import json import os from dataclasses import dataclass, field from pathlib import Path from typing import Any, Dict, Mapping, Optional OPENROUTER_BASE_URL = "https://openrouter.ai/api/v1" @dataclass(frozen=True) class ProviderConfig: name: str provider: str model: str base_url: str api_key_env: str router_options: Dict[str, Any] = field(default_factory=dict) @property def api_key(self) -> str: return os.environ.get(self.api_key_env, "") DEFAULT_PROFILES: Dict[str, ProviderConfig] = { "default": ProviderConfig( name="default", provider="openrouter", model=os.environ.get("OPENROUTER_MODEL", "openai/gpt-5.6-sol"), base_url=OPENROUTER_BASE_URL, api_key_env="OPENROUTER_API_KEY", ), "best_value": ProviderConfig( name="best_value", provider="openrouter", model=os.environ.get("OPENROUTER_BEST_VALUE_MODEL", "openai/gpt-5.6-terra"), base_url=OPENROUTER_BASE_URL, api_key_env="OPENROUTER_API_KEY", ), "paper_openai": ProviderConfig( name="paper_openai", provider="openrouter", model="openai/gpt-4o-2024-08-06", base_url=OPENROUTER_BASE_URL, api_key_env="OPENROUTER_API_KEY", ), "paper_claude": ProviderConfig( name="paper_claude", provider="openrouter", model="anthropic/claude-3.5-sonnet", base_url=OPENROUTER_BASE_URL, api_key_env="OPENROUTER_API_KEY", ), "paper_gemini": ProviderConfig( name="paper_gemini", provider="openrouter", model="google/gemini-pro-1.5", base_url=OPENROUTER_BASE_URL, api_key_env="OPENROUTER_API_KEY", ), "fastuse_experimental": ProviderConfig( name="fastuse_experimental", provider="openrouter", model=os.environ.get("OPENROUTER_FASTUSE_MODEL", "google/gemini-3.1-pro-preview"), base_url=OPENROUTER_BASE_URL, api_key_env="OPENROUTER_API_KEY", ), } PROFILE_ALIASES = { "openrouter": "default", "gpt4v": "paper_openai", "gpt4v_abl": "paper_openai", "claude35sonnet": "paper_claude", "gemini15pro": "paper_gemini", "gemini31pro": "fastuse_experimental", "gemini-3-flash-preview-nothinking": "default", "gemini-3-flash-preview-nothinking_abl": "default", } def _load_yaml_or_json(path: Path) -> Mapping[str, Any]: text = path.read_text() if path.suffix.lower() == ".json": return json.loads(text) try: import yaml except ImportError as exc: raise RuntimeError("Install PyYAML or use a JSON config file.") from exc loaded = yaml.safe_load(text) return loaded or {} def _profile_from_mapping(name: str, values: Mapping[str, Any]) -> ProviderConfig: return ProviderConfig( name=name, provider=values["provider"], model=values["model"], base_url=values.get("base_url", OPENROUTER_BASE_URL), api_key_env=values.get("api_key_env", "OPENROUTER_API_KEY"), router_options=dict(values.get("router_options", {})), ) def load_profiles(path: Optional[str] = None) -> Dict[str, ProviderConfig]: profiles = dict(DEFAULT_PROFILES) if not path: return profiles raw = _load_yaml_or_json(Path(path)) raw_profiles = raw.get("profiles", raw) for name, values in raw_profiles.items(): profiles[name] = _profile_from_mapping(name, values) return profiles def get_model_profile(name: str = "default", config_path: Optional[str] = None) -> ProviderConfig: profile_name = PROFILE_ALIASES.get(name, name) profiles = load_profiles(config_path) if profile_name not in profiles: valid = ", ".join(sorted(profiles)) raise ValueError(f"Unknown model profile '{name}'. Valid profiles: {valid}") return profiles[profile_name] def validate_model_available(profile: ProviderConfig, models_catalog: Optional[Any] = None) -> bool: if models_catalog is None: return True if isinstance(models_catalog, Mapping): models_catalog = models_catalog.get("data", models_catalog.keys()) model_ids = { entry.get("id") if isinstance(entry, Mapping) else str(entry) for entry in models_catalog } if profile.model not in model_ids: raise ValueError(f"Model {profile.model!r} was not found in the supplied catalog.") return True def sanitize_manifest( profile: ProviderConfig, request_payload: Mapping[str, Any], response_payload: Optional[Mapping[str, Any]] = None, ) -> Dict[str, Any]: response_payload = response_payload or {} return { "provider": profile.provider, "profile": profile.name, "request_model": request_payload.get("model"), "response_model": response_payload.get("model"), "base_url": profile.base_url, "api_key_env": profile.api_key_env, "router_options": dict(profile.router_options), "usage": response_payload.get("usage", {}), }