fix(model-picker): surface the current custom/uncurated model in picker rows (#53457)

A model selected via the CLI (e.g. /model openrouter/<uncurated-name>) was
absent from every model picker — the main picker AND the MoA reference/
aggregator slot pickers — because each provider row only carried its curated
catalog. Inject the current model at the front of its provider's row so it is
selectable and shown everywhere.
This commit is contained in:
Teknium 2026-06-27 00:06:34 -07:00 committed by GitHub
parent fbf748b282
commit d712a7fd73
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 78 additions and 0 deletions

View file

@ -2253,6 +2253,24 @@ def list_authenticated_providers(
seen_slugs.add(slug.lower())
_section4_emitted_slugs.add(slug.lower())
# Surface a custom / uncurated model the user selected via the CLI.
# Each row's model list is its curated/live catalog, so a model the user set
# with `/model <provider>/<uncurated-name>` would otherwise be invisible in
# every picker — the main model picker AND the MoA reference/aggregator slot
# pickers, which read these same rows. Inject it at the front of the current
# provider's row (matched by slug) so it is selectable and shown. Done as a
# post-pass so it covers every provider section uniformly, regardless of
# which branch emitted the row.
if current_model:
for _row in results:
if not _row.get("is_current"):
continue
_models = _row.get("models") or []
if current_model not in _models:
_row["models"] = [current_model, *_models]
_row["total_models"] = _row.get("total_models", len(_models)) + 1
break
# Sort: current provider first, then by model count descending
results.sort(key=lambda r: (not r["is_current"], -r["total_models"]))

View file

@ -1122,3 +1122,63 @@ def test_section3_skips_probe_when_no_key_but_explicit_models(monkeypatch):
row = next(p for p in providers if p["slug"] == "public-subset")
assert row["models"] == ["only-a", "only-b"]
assert row["total_models"] == 2
def test_current_custom_model_is_surfaced_in_builtin_provider_row(monkeypatch):
"""A custom/uncurated model selected via the CLI must appear in its
provider's picker row.
Regression: selecting `/model openrouter/<uncurated-name>` left the model
invisible in every picker (main model picker AND the MoA reference/aggregator
slot pickers, which read these rows), because the row only carried the
curated catalog. The current model is now injected at the front of the
current provider's list.
"""
monkeypatch.setattr("agent.models_dev.fetch_models_dev", lambda: {})
monkeypatch.setattr("hermes_cli.providers.HERMES_OVERLAYS", {})
monkeypatch.setenv("OPENROUTER_API_KEY", "sk-test")
# Pin a small curated catalog so the assertion is deterministic.
monkeypatch.setattr(
"hermes_cli.models.cached_provider_model_ids",
lambda slug, **kw: ["anthropic/claude-opus-4.8", "openai/gpt-5.5"]
if slug == "openrouter"
else [],
)
custom = "some-vendor/totally-custom-model-v9"
providers = list_authenticated_providers(
current_provider="openrouter",
current_model=custom,
user_providers={},
custom_providers=[],
)
row = next(p for p in providers if p["slug"] == "openrouter")
assert custom in row["models"], row["models"]
assert row["models"][0] == custom # injected at the front
assert row["total_models"] == 3
def test_current_custom_model_not_leaked_into_other_provider_rows(monkeypatch):
"""The current model is only injected into the CURRENT provider's row,
never into other providers (which can't serve it)."""
monkeypatch.setattr("agent.models_dev.fetch_models_dev", lambda: {})
monkeypatch.setattr("hermes_cli.providers.HERMES_OVERLAYS", {})
monkeypatch.setenv("OPENROUTER_API_KEY", "sk-test")
monkeypatch.setenv("NOUS_API_KEY", "sk-test")
monkeypatch.setattr(
"hermes_cli.models.cached_provider_model_ids",
lambda slug, **kw: ["curated/one"],
)
custom = "some-vendor/totally-custom-model-v9"
providers = list_authenticated_providers(
current_provider="openrouter",
current_model=custom,
user_providers={},
custom_providers=[],
)
for row in providers:
if row["slug"] != "openrouter" and not row.get("is_current"):
assert custom not in row.get("models", []), f"leaked into {row['slug']}"