free-claude-code/api/dependencies.py
2026-02-27 19:50:21 -08:00

113 lines
4.3 KiB
Python

"""Dependency injection for FastAPI."""
from fastapi import HTTPException
from loguru import logger
from config.settings import NVIDIA_NIM_BASE_URL, Settings
from config.settings import get_settings as _get_settings
from providers.base import BaseProvider, ProviderConfig
# Global provider instance (singleton)
_provider: BaseProvider | None = None
def get_settings() -> Settings:
"""Get application settings via dependency injection."""
return _get_settings()
def _create_provider(settings: Settings) -> BaseProvider:
"""Construct and return a new provider instance from settings."""
if settings.provider_type == "nvidia_nim":
if not settings.nvidia_nim_api_key or not settings.nvidia_nim_api_key.strip():
raise HTTPException(
status_code=503,
detail=(
"NVIDIA_NIM_API_KEY is not set. Add it to your .env file. "
"Get a key at https://build.nvidia.com/settings/api-keys"
),
)
from providers.nvidia_nim import NvidiaNimProvider
config = ProviderConfig(
api_key=settings.nvidia_nim_api_key,
base_url=NVIDIA_NIM_BASE_URL,
rate_limit=settings.provider_rate_limit,
rate_window=settings.provider_rate_window,
max_concurrency=settings.provider_max_concurrency,
http_read_timeout=settings.http_read_timeout,
http_write_timeout=settings.http_write_timeout,
http_connect_timeout=settings.http_connect_timeout,
)
provider = NvidiaNimProvider(config, nim_settings=settings.nim)
elif settings.provider_type == "open_router":
if not settings.open_router_api_key or not settings.open_router_api_key.strip():
raise HTTPException(
status_code=503,
detail=(
"OPENROUTER_API_KEY is not set. Add it to your .env file. "
"Get a key at https://openrouter.ai/keys"
),
)
from providers.open_router import OpenRouterProvider
config = ProviderConfig(
api_key=settings.open_router_api_key,
base_url="https://openrouter.ai/api/v1",
rate_limit=settings.provider_rate_limit,
rate_window=settings.provider_rate_window,
max_concurrency=settings.provider_max_concurrency,
http_read_timeout=settings.http_read_timeout,
http_write_timeout=settings.http_write_timeout,
http_connect_timeout=settings.http_connect_timeout,
)
provider = OpenRouterProvider(config)
elif settings.provider_type == "lmstudio":
from providers.lmstudio import LMStudioProvider
config = ProviderConfig(
api_key="lm-studio",
base_url=settings.lm_studio_base_url,
rate_limit=settings.provider_rate_limit,
rate_window=settings.provider_rate_window,
max_concurrency=settings.provider_max_concurrency,
http_read_timeout=settings.http_read_timeout,
http_write_timeout=settings.http_write_timeout,
http_connect_timeout=settings.http_connect_timeout,
)
provider = LMStudioProvider(config)
else:
logger.error(
"Unknown provider_type: '%s'. Supported: 'nvidia_nim', 'open_router', 'lmstudio'",
settings.provider_type,
)
raise ValueError(
f"Unknown provider_type: '{settings.provider_type}'. "
f"Supported: 'nvidia_nim', 'open_router', 'lmstudio'"
)
logger.info("Provider initialized: %s", settings.provider_type)
return provider
def get_provider() -> BaseProvider:
"""Get or create the provider instance based on settings.provider_type."""
global _provider
if _provider is None:
_provider = _create_provider(get_settings())
return _provider
async def cleanup_provider():
"""Cleanup provider resources."""
global _provider
if _provider:
client = getattr(_provider, "_client", None)
if client and hasattr(client, "aclose"):
await client.aclose()
elif client:
logger.warning(
"Provider client %r has no aclose(); skipping async cleanup",
type(client).__name__,
)
_provider = None
logger.debug("Provider cleanup completed")