from dataclasses import dataclass from collections.abc import Mapping from typing import Any from app.config import Settings def _configured(value: str) -> bool: return bool(value) and not value.startswith("replace_with_") @dataclass(frozen=True) class ProviderCapability: provider: str configured: bool strengths: tuple[str, ...] class ModelRouter: def __init__(self, settings: Settings | Mapping[str, Any]) -> None: self.settings = settings def _value(self, key: str, default: str = "") -> str: if isinstance(self.settings, Mapping): return str(self.settings.get(key, default) or "") return str(getattr(self.settings, key, default) or "") def capabilities(self) -> list[ProviderCapability]: return [ ProviderCapability( provider=self._value("ai_provider", "custom"), configured=_configured(self._value("ai_api_key")) and bool(self._value("ai_base_url")) and bool(self._value("image_model")), strengths=("统一模型网关", "空间理解", "图像生成与编辑"), ), ] def choose_image_provider(self, task: str) -> str: configured = [item.provider for item in self.capabilities() if item.configured] if configured: return configured[0] raise RuntimeError("No image provider is configured.")