From 523a64a726b66d04e239d2a8b6de60b945222667 Mon Sep 17 00:00:00 2001 From: nnnet Date: Tue, 2 Jun 2026 14:47:21 +0300 Subject: [PATCH] feat(providers): post-filter picker by ``enabled: false`` for built-ins MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sections 1-2 of ``list_authenticated_providers`` emit rows directly from ``PROVIDER_REGISTRY`` (auth-driven built-ins) before reaching the per-section gate I added for section 3 (user-config providers). That means flipping ``providers.openrouter.enabled: false`` hid OpenRouter from a user-config block but the built-in OpenRouter row still showed because its row came from section 1's auth-status path. Add a single post-filter at the end of ``list_authenticated_providers`` that drops every row whose ``provider_id`` or ``slug`` matches a disabled name in ``providers``. Same source of truth, applied once at the end, covers all four sections in one pass. Wrapped in ``try/except`` so a degraded config can't break the picker — if anything fails reading the config, the filter no-ops and the picker shows the un-filtered list (same as before this PR). --- hermes_cli/model_switch.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/hermes_cli/model_switch.py b/hermes_cli/model_switch.py index f7009a38edabc..a054fced7f8f8 100644 --- a/hermes_cli/model_switch.py +++ b/hermes_cli/model_switch.py @@ -2701,6 +2701,28 @@ def list_authenticated_providers( seen_slugs.add(slug.lower()) _section4_emitted_slugs.add(slug.lower()) + # Apply final ``providers..enabled: false`` post-filter — covers + # built-in PROVIDER_REGISTRY rows (sections 1-2) which would otherwise + # bypass the per-section gate. Indexed by lowercase slug AND by + # ``provider_id`` so PROVIDER_REGISTRY entries that match user-config + # blocks are filtered consistently. + try: + from hermes_cli.config import is_provider_enabled + if isinstance(user_providers, dict): + _disabled_slugs = { + str(name).strip().lower() + for name, cfg in user_providers.items() + if isinstance(cfg, dict) and not is_provider_enabled(cfg) + } + if _disabled_slugs: + results = [ + r for r in results + if str(r.get("provider_id", "")).strip().lower() not in _disabled_slugs + and str(r.get("slug", "")).strip().lower() not in _disabled_slugs + ] + except Exception: + pass + # 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 /` would otherwise be invisible in