From 930be347f1e3efefae0aa2f98219b3d126abf0ce Mon Sep 17 00:00:00 2001 From: Teknium <127238744+teknium1@users.noreply.github.com> Date: Fri, 21 Aug 2026 00:08:23 -0700 Subject: [PATCH] =?UTF-8?q?feat:=20keyless=20flag=20on=20the=20provider=20?= =?UTF-8?q?catalog=20=E2=80=94=20GUI=20contract=20tests=20exempt=20anonymo?= =?UTF-8?q?us=20providers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit opencode-free broke two provider-surface contract tests: 'api_key providers must expose a credential env var' and 'GUI ⊇ hermes model universe'. Both premises assume a credential exists. Add a keyless flag to HermesOverlay + ProviderDescriptor (same derived-exemption pattern as virtual providers) so any future anonymous provider is covered without hardcoded slugs. Nothing to configure = no Providers-tab card, by design; the model picker remains the selection surface. --- hermes_cli/provider_catalog.py | 5 +++++ hermes_cli/providers.py | 2 ++ tests/hermes_cli/test_provider_catalog.py | 9 +++++---- tests/hermes_cli/test_provider_parity.py | 6 +++++- 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/hermes_cli/provider_catalog.py b/hermes_cli/provider_catalog.py index a164ac84ce..b7323894d1 100644 --- a/hermes_cli/provider_catalog.py +++ b/hermes_cli/provider_catalog.py @@ -66,6 +66,7 @@ class ProviderDescriptor: base_url_env_var: str # base-URL override env var (may be "") signup_url: str # signup / console URL (may be "") order: int # CANONICAL_PROVIDERS index — mirrors `hermes model` + keyless: bool = False # served anonymously — no credential exists to configure def tab_for_auth_type(auth_type: str) -> str: @@ -171,6 +172,10 @@ def provider_catalog() -> list[ProviderDescriptor]: base_url_env_var=base_url_var, signup_url=signup_url, order=order, + # Keyless providers (e.g. opencode-free) are served + # anonymously: there is no credential to configure, so the + # GUI renders no key card and contract tests exempt them. + keyless=bool(getattr(overlay, "keyless", False)), ) ) return out diff --git a/hermes_cli/providers.py b/hermes_cli/providers.py index 2533afdcde..d8b8e28774 100644 --- a/hermes_cli/providers.py +++ b/hermes_cli/providers.py @@ -41,6 +41,7 @@ class HermesOverlay: extra_env_vars: Tuple[str, ...] = () # env vars models.dev doesn't list base_url_override: str = "" # override if models.dev URL is wrong/missing base_url_env_var: str = "" # env var for user-custom base URL + keyless: bool = False # served anonymously — no credential exists to configure HERMES_OVERLAYS: Dict[str, HermesOverlay] = { @@ -160,6 +161,7 @@ HERMES_OVERLAYS: Dict[str, HermesOverlay] = { transport="openai_chat", is_aggregator=True, base_url_override="https://opencode.ai/zen/v1", + keyless=True, ), "kilo": HermesOverlay( transport="openai_chat", diff --git a/tests/hermes_cli/test_provider_catalog.py b/tests/hermes_cli/test_provider_catalog.py index aff6e550e7..89fe2a31f6 100644 --- a/tests/hermes_cli/test_provider_catalog.py +++ b/tests/hermes_cli/test_provider_catalog.py @@ -57,13 +57,14 @@ def test_api_key_providers_expose_a_credential_env_var(): surface at least one env var to write the key into (otherwise the GUI can't configure it). - Exemptions: ``aws_sdk`` (bedrock — uses AWS_REGION/AWS_PROFILE) and the - ``custom`` bring-your-own-endpoint pseudo-provider, which is configured - inline via the local-endpoint flow rather than a fixed env var. + Exemptions: ``aws_sdk`` (bedrock — uses AWS_REGION/AWS_PROFILE), the + ``custom`` bring-your-own-endpoint pseudo-provider (configured inline via + the local-endpoint flow), and keyless providers (``d.keyless`` — e.g. + opencode-free, served anonymously: there is no credential to write). """ exempt = {"custom"} for d in provider_catalog(): - if d.auth_type == "api_key" and d.slug not in exempt: + if d.auth_type == "api_key" and d.slug not in exempt and not d.keyless: assert d.api_key_env_vars, f"{d.slug} is api_key but exposes no env var" diff --git a/tests/hermes_cli/test_provider_parity.py b/tests/hermes_cli/test_provider_parity.py index 017c46b88b..f5961184cd 100644 --- a/tests/hermes_cli/test_provider_parity.py +++ b/tests/hermes_cli/test_provider_parity.py @@ -31,7 +31,11 @@ HEADERS = {"X-Hermes-Session-Token": _SESSION_TOKEN} # derived from the catalog so any future virtual provider is covered without a # hardcoded slug. _VIRTUAL = {d.slug for d in provider_catalog() if d.auth_type == "virtual"} -_EXEMPT = {"custom"} | _VIRTUAL +# Keyless providers (opencode-free) are served anonymously: no credential +# exists, so there is nothing to configure on either Providers tab. Derived +# from the catalog flag so any future keyless provider is covered. +_KEYLESS = {d.slug for d in provider_catalog() if d.keyless} +_EXEMPT = {"custom"} | _VIRTUAL | _KEYLESS # Providers that legitimately offer BOTH auth methods and so intentionally # appear on both desktop tabs (an API-key card AND an account sign-in card).