feat: keyless flag on the provider catalog — GUI contract tests exempt anonymous providers

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.
This commit is contained in:
Teknium
2026-08-21 00:08:23 -07:00
parent a63da06340
commit 930be347f1
4 changed files with 17 additions and 5 deletions

View File

@@ -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

View File

@@ -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",

View File

@@ -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"

View File

@@ -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).