From 9aaa71367b7c54cd06745fee5bfd56fd8f4bf2e3 Mon Sep 17 00:00:00 2001 From: teknium1 <127238744+teknium1@users.noreply.github.com> Date: Tue, 15 Sep 2026 14:28:19 -0700 Subject: [PATCH] fix(catalog): apply the opencode free exclusion on the live-first keyed Zen/Go picker --- hermes_cli/models.py | 4 ++++ .../hermes_cli/test_opencode_free_live_catalog.py | 14 ++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/hermes_cli/models.py b/hermes_cli/models.py index 364629ec55..626e6daf41 100644 --- a/hermes_cli/models.py +++ b/hermes_cli/models.py @@ -1456,6 +1456,10 @@ def _profile_live_catalog(normalized: str) -> Optional[list[str]]: return None api_key, base_url = _api_key_credentials(normalized) live = profile.fetch_models(api_key=api_key, base_url=base_url or profile.base_url or None) if api_key else None + if live and normalized in _LIVE_FIRST_PICKER_PROVIDERS: + # The relay still LISTS delisted ids it no longer serves; the keyed Zen/Go picker is + # live-first, so it takes the same exclusion as the keyless catalog (#111749). + live = [m for m in live if str(m).lower() not in _OPENCODE_FREE_EXCLUDED_MODELS] if not live: return list(profile.fallback_models) if profile.fallback_models else None curated = list(_PROVIDER_MODELS.get(normalized, [])) or list(profile.fallback_models or ()) diff --git a/tests/hermes_cli/test_opencode_free_live_catalog.py b/tests/hermes_cli/test_opencode_free_live_catalog.py index b704c58c70..cb226c1c2b 100644 --- a/tests/hermes_cli/test_opencode_free_live_catalog.py +++ b/tests/hermes_cli/test_opencode_free_live_catalog.py @@ -214,6 +214,20 @@ class TestOpencodeFreeFollowUps: assert "ox-alpha-free" not in live assert "mimo-v2.5-free" in live # control: a servable free model survives the filter + def test_keyed_zen_live_first_picker_drops_delisted_model(self, monkeypatch): + """The keyed opencode-zen picker is live-first over GET /zen/v1/models, which still lists + deepseek-v4-flash-free; it must take the same exclusion as the keyless catalog (#111749).""" + import hermes_cli.models as mod + from providers import get_provider_profile + + prof = get_provider_profile("opencode-zen") + monkeypatch.setenv("OPENCODE_ZEN_API_KEY", "sk-zen-fake") + with patch.object(type(prof), "fetch_models", lambda self, **kw: list(_LIVE_RAW_IDS)): + zen = mod._profile_live_catalog("opencode-zen") + assert zen is not None + assert "deepseek-v4-flash-free" not in zen + assert "mimo-v2.5-free" in zen # control: a servable live model still leads + def test_heal_union_includes_live_only_model(self): """A newly-live free model absent from the static floor must still heal opencode-go/zen selections to the keyless Zen relay (sibling-site widen: