|
|
"""
|
|
|
Providers API
|
|
|
Endpoints for provider registry and status
|
|
|
"""
|
|
|
|
|
|
from fastapi import APIRouter, HTTPException, Query
|
|
|
from fastapi.responses import JSONResponse
|
|
|
from typing import Optional, Dict, Any
|
|
|
from datetime import datetime, timezone
|
|
|
import logging
|
|
|
|
|
|
from backend.services.provider_registry_service import get_registry_service
|
|
|
from backend.services.registry_loader import get_registry_loader
|
|
|
from backend.services.provider_fallback_manager import fallback_manager
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
router = APIRouter(
|
|
|
prefix="/api/providers",
|
|
|
tags=["Providers API"]
|
|
|
)
|
|
|
|
|
|
registry_service = get_registry_service()
|
|
|
registry_loader = get_registry_loader()
|
|
|
|
|
|
|
|
|
@router.get("")
|
|
|
async def get_providers(
|
|
|
show_sources: bool = Query(False, description="Show source file information"),
|
|
|
category: Optional[str] = Query(None, description="Filter by category")
|
|
|
):
|
|
|
"""
|
|
|
Get list of all providers
|
|
|
Built from /mnt/data/all_apis_merged_2025.json and /mnt/data/api-config-complete.txt
|
|
|
"""
|
|
|
|
|
|
providers = registry_loader.providers
|
|
|
|
|
|
|
|
|
registry = registry_service.build_registry()
|
|
|
registry_providers = registry.get("providers", [])
|
|
|
|
|
|
|
|
|
seen_urls = set()
|
|
|
all_providers = []
|
|
|
|
|
|
|
|
|
for provider in providers:
|
|
|
url_key = provider.get("base_url", "").lower().rstrip("/")
|
|
|
if url_key and url_key not in seen_urls:
|
|
|
seen_urls.add(url_key)
|
|
|
all_providers.append(provider)
|
|
|
|
|
|
|
|
|
for provider in registry_providers:
|
|
|
url_key = provider.get("base_url", "").lower().rstrip("/")
|
|
|
if url_key and url_key not in seen_urls:
|
|
|
seen_urls.add(url_key)
|
|
|
all_providers.append(provider)
|
|
|
|
|
|
|
|
|
if category:
|
|
|
all_providers = [
|
|
|
p for p in all_providers
|
|
|
if category in p.get("categories", []) or p.get("category") == category
|
|
|
]
|
|
|
|
|
|
|
|
|
safe_providers = []
|
|
|
for provider in all_providers:
|
|
|
safe_provider = {
|
|
|
"name": provider.get("name", "unknown"),
|
|
|
"base_url": provider.get("base_url", ""),
|
|
|
"category": provider.get("category", "generic"),
|
|
|
"categories": provider.get("categories", [provider.get("category", "generic")]),
|
|
|
"endpoints": provider.get("endpoints", {}),
|
|
|
"free": provider.get("free", False),
|
|
|
"priority": provider.get("priority", 10),
|
|
|
"docs_url": provider.get("docs_url"),
|
|
|
"has_api_key": bool(provider.get("api_key") or provider.get("auth_value")),
|
|
|
"key_inline": bool(provider.get("auth_value"))
|
|
|
}
|
|
|
|
|
|
if show_sources:
|
|
|
safe_provider["source_file"] = provider.get("source_file", "/mnt/data/all_apis_merged_2025.json")
|
|
|
safe_provider["notes"] = provider.get("notes")
|
|
|
|
|
|
safe_providers.append(safe_provider)
|
|
|
|
|
|
return {
|
|
|
"data": safe_providers,
|
|
|
"meta": {
|
|
|
"source": "registry",
|
|
|
"generated_at": datetime.now(timezone.utc).isoformat(),
|
|
|
"total_count": len(safe_providers),
|
|
|
"free_count": sum(1 for p in safe_providers if p["free"]),
|
|
|
"categories": list(set(
|
|
|
cat for p in safe_providers
|
|
|
for cat in p.get("categories", [p.get("category", "generic")])
|
|
|
)),
|
|
|
"registry_files": [
|
|
|
"/mnt/data/all_apis_merged_2025.json",
|
|
|
"/mnt/data/api-config-complete.txt"
|
|
|
]
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
@router.get("/status")
|
|
|
async def get_providers_status():
|
|
|
"""Get status of all providers (circuit breakers, health, etc.)"""
|
|
|
status = fallback_manager.get_provider_status()
|
|
|
|
|
|
return {
|
|
|
"data": status,
|
|
|
"meta": {
|
|
|
"source": "fallback_manager",
|
|
|
"generated_at": datetime.now(timezone.utc).isoformat()
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
@router.get("/health")
|
|
|
async def get_providers_health():
|
|
|
"""Get health check for all providers"""
|
|
|
status = fallback_manager.get_provider_status()
|
|
|
|
|
|
healthy = sum(1 for p in status["providers"] if p["is_available"])
|
|
|
total = status["total_providers"]
|
|
|
|
|
|
return {
|
|
|
"data": {
|
|
|
"healthy": healthy,
|
|
|
"total": total,
|
|
|
"health_percentage": (healthy / total * 100) if total > 0 else 0,
|
|
|
"providers": status["providers"]
|
|
|
},
|
|
|
"meta": {
|
|
|
"source": "fallback_manager",
|
|
|
"generated_at": datetime.now(timezone.utc).isoformat()
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|