refactor(webui): derive provider model catalog kind
This commit is contained in:
@@ -32,6 +32,7 @@ class ProviderSpec:
|
||||
keywords: tuple[str, ...] # model-name keywords for matching (lowercase)
|
||||
env_key: str # env var for API key, e.g. "DASHSCOPE_API_KEY"
|
||||
display_name: str = "" # shown in `nanobot status`
|
||||
model_catalog: str = "auto" # WebUI model-list source
|
||||
|
||||
# which provider implementation to use
|
||||
# "openai_compat" | "anthropic" | "azure_openai" | "openai_codex" | "github_copilot" | "bedrock"
|
||||
@@ -221,6 +222,7 @@ PROVIDERS: tuple[ProviderSpec, ...] = (
|
||||
keywords=("skywork", "skyclaw", "apifree"),
|
||||
env_key="SKYWORK_API_KEY",
|
||||
display_name="Skywork",
|
||||
model_catalog="official",
|
||||
backend="openai_compat",
|
||||
env_extras=(("APIFREE_API_KEY", "{api_key}"),),
|
||||
is_gateway=True,
|
||||
|
||||
@@ -99,47 +99,6 @@ _CONTEXT_WINDOW_TOKEN_OPTIONS = {65_536, 200_000, 262_144}
|
||||
_MODEL_CONFIGURATION_SLUG_RE = re.compile(r"[^a-z0-9_-]+")
|
||||
_ENV_REF_RE = re.compile(r"\$\{([A-Za-z_][A-Za-z0-9_]*)\}")
|
||||
|
||||
_MODEL_LIST_UNSUPPORTED_BACKENDS = {
|
||||
"anthropic",
|
||||
"azure_openai",
|
||||
"bedrock",
|
||||
"github_copilot",
|
||||
"openai_codex",
|
||||
}
|
||||
|
||||
_MODEL_LIST_CATALOG_PROVIDERS = {
|
||||
"aihubmix",
|
||||
"byteplus",
|
||||
"byteplus_coding_plan",
|
||||
"huggingface",
|
||||
"novita",
|
||||
"openrouter",
|
||||
"siliconflow",
|
||||
"volcengine",
|
||||
"volcengine_coding_plan",
|
||||
}
|
||||
|
||||
_MODEL_LIST_OFFICIAL_PROVIDERS = {
|
||||
"ant_ling",
|
||||
"dashscope",
|
||||
"deepseek",
|
||||
"gemini",
|
||||
"groq",
|
||||
"longcat",
|
||||
"minimax",
|
||||
"minimax_anthropic",
|
||||
"mistral",
|
||||
"moonshot",
|
||||
"nvidia",
|
||||
"openai",
|
||||
"qianfan",
|
||||
"skywork",
|
||||
"stepfun",
|
||||
"xiaomi_mimo",
|
||||
"zhipu",
|
||||
}
|
||||
|
||||
|
||||
class WebUISettingsError(ValueError):
|
||||
"""User-facing settings validation failure."""
|
||||
|
||||
@@ -394,10 +353,13 @@ def _provider_settings_row(
|
||||
|
||||
|
||||
def _model_catalog_kind(spec: Any) -> str:
|
||||
if spec.name in _MODEL_LIST_CATALOG_PROVIDERS:
|
||||
return "catalog"
|
||||
if spec.name in _MODEL_LIST_OFFICIAL_PROVIDERS:
|
||||
return "official"
|
||||
catalog = getattr(spec, "model_catalog", "auto")
|
||||
if catalog != "auto":
|
||||
return catalog
|
||||
if spec.is_transcription_only or spec.is_oauth:
|
||||
return "unsupported"
|
||||
if spec.backend != "openai_compat" and spec.name != "minimax_anthropic":
|
||||
return "unsupported"
|
||||
if spec.is_local:
|
||||
return "local"
|
||||
if spec.is_direct:
|
||||
@@ -490,27 +452,20 @@ def provider_models_payload(query: QueryParams) -> dict[str, Any]:
|
||||
raise WebUISettingsError("unknown provider")
|
||||
spec, provider_key, provider_config = resolved_provider
|
||||
|
||||
catalog_kind = _model_catalog_kind(spec)
|
||||
base_payload: dict[str, Any] = {
|
||||
"provider": provider_key,
|
||||
"label": spec.label,
|
||||
"catalog_kind": _model_catalog_kind(spec),
|
||||
"catalog_kind": catalog_kind,
|
||||
"models": [],
|
||||
"model_count": 0,
|
||||
"message": None,
|
||||
"fetched_at": time.time(),
|
||||
}
|
||||
if (
|
||||
spec.is_transcription_only
|
||||
or (
|
||||
spec.backend in _MODEL_LIST_UNSUPPORTED_BACKENDS
|
||||
and spec.name != "minimax_anthropic"
|
||||
)
|
||||
or spec.is_oauth
|
||||
):
|
||||
if catalog_kind == "unsupported":
|
||||
return {
|
||||
**base_payload,
|
||||
"status": "unsupported",
|
||||
"catalog_kind": "unsupported",
|
||||
"message": "Model list is not available for this provider. Type a model ID manually.",
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ from nanobot.config.schema import Config, ModelPresetConfig
|
||||
from nanobot.providers.registry import find_by_name
|
||||
from nanobot.webui.settings_api import (
|
||||
WebUISettingsError,
|
||||
_model_catalog_kind,
|
||||
_oauth_provider_status,
|
||||
create_model_configuration,
|
||||
login_oauth_provider,
|
||||
@@ -998,9 +999,16 @@ def test_provider_models_payload_requires_gateway_key(
|
||||
payload = provider_models_payload({"provider": ["openrouter"]})
|
||||
|
||||
assert payload["status"] == "not_configured"
|
||||
assert payload["catalog_kind"] == "catalog"
|
||||
assert payload["models"] == []
|
||||
|
||||
|
||||
def test_model_catalog_kind_uses_provider_spec_metadata() -> None:
|
||||
assert _model_catalog_kind(find_by_name("skywork")) == "official"
|
||||
assert _model_catalog_kind(find_by_name("anthropic")) == "unsupported"
|
||||
assert _model_catalog_kind(find_by_name("openrouter")) == "catalog"
|
||||
|
||||
|
||||
def test_create_model_configuration_accepts_configured_oauth_provider(
|
||||
tmp_path,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
|
||||
Reference in New Issue
Block a user