fix(model): prefer live models for user providers

This commit is contained in:
Dejie Guo 2026-04-28 08:48:58 +08:00 committed by Teknium
parent 69b8fa65d4
commit 8cced33784
2 changed files with 66 additions and 2 deletions

View file

@ -1346,8 +1346,23 @@ def list_authenticated_providers(
if fb:
models_list = list(fb)
# Try to probe /v1/models if URL is set (but don't block on it)
# For now just show what we know from config
# Prefer the endpoint's live /models list when credentials are
# available. This keeps OpenAI-compatible relays (for example CRS)
# in sync when the server catalog changes without requiring the
# user to mirror every model into config.yaml.
api_key = str(ep_cfg.get("api_key", "") or "").strip()
if not api_key:
key_env = str(ep_cfg.get("key_env", "") or "").strip()
api_key = os.environ.get(key_env, "").strip() if key_env else ""
if api_url and api_key:
try:
from hermes_cli.models import fetch_api_models
live_models = fetch_api_models(api_key, api_url)
if live_models:
models_list = live_models
except Exception:
pass
results.append({
"slug": ep_name,
"name": display_name,

View file

@ -131,6 +131,55 @@ def test_list_authenticated_providers_enumerates_dict_format_models(monkeypatch)
]
def test_list_authenticated_providers_uses_live_models_for_user_provider(monkeypatch):
"""User-defined OpenAI-compatible providers should prefer live /models.
Regression: CRS-style providers with a stale config ``models:`` dict kept
showing only the configured subset in the /model picker, even though their
/v1/models endpoint exposed newly added models.
"""
monkeypatch.setattr("agent.models_dev.fetch_models_dev", lambda: {})
monkeypatch.setattr("hermes_cli.providers.HERMES_OVERLAYS", {})
monkeypatch.setenv("CRS_TEST_KEY", "sk-test")
calls = []
def fake_fetch_api_models(api_key, base_url):
calls.append((api_key, base_url))
return ["old-configured-model", "new-live-model"]
monkeypatch.setattr("hermes_cli.models.fetch_api_models", fake_fetch_api_models)
user_providers = {
"crs-henkee": {
"name": "CRS Henkee",
"base_url": "http://127.0.0.1:3000/api/v1",
"key_env": "CRS_TEST_KEY",
"model": "old-configured-model",
"models": {
"old-configured-model": {"context_length": 200000},
},
}
}
providers = list_authenticated_providers(
current_provider="crs-henkee",
user_providers=user_providers,
custom_providers=[],
max_models=50,
)
user_prov = next(
(p for p in providers if p.get("is_user_defined") and p["slug"] == "crs-henkee"),
None,
)
assert user_prov is not None
assert calls == [("sk-test", "http://127.0.0.1:3000/api/v1")]
assert user_prov["models"] == ["old-configured-model", "new-live-model"]
assert user_prov["total_models"] == 2
def test_list_authenticated_providers_dict_models_without_default_model(monkeypatch):
"""Dict-format ``models:`` without a ``default_model`` must still expose
every dict key, not collapse to an empty list."""