Skip to content

fix(model-picker): require real credentials in section 1 (api_key path)#20705

Closed
tymrtn wants to merge 1 commit into
NousResearch:mainfrom
tymrtn:fix/picker-empty-pool-section1
Closed

fix(model-picker): require real credentials in section 1 (api_key path)#20705
tymrtn wants to merge 1 commit into
NousResearch:mainfrom
tymrtn:fix/picker-empty-pool-section1

Conversation

@tymrtn

@tymrtn tymrtn commented May 6, 2026

Copy link
Copy Markdown
Contributor

Summary

Section 1 of list_authenticated_providers (the api_key auth path in hermes_cli/model_switch.py) was checking:

if store and hermes_id in store.get("credential_pool", {}):
    has_creds = True

This gave false positives for entries whose value is an empty list — a state that occurs naturally after credential rotation or partial seeding. The picker therefore surfaced providers the user never authenticated to (huggingface, opencode-go, minimax / minimax-cn, zai, …). Selecting one of those routes every turn at a dead endpoint and 401s.

Sister fix 46072425f closed the same class of bug in sections 2 and 2b but missed section 1. (PR #20703 tried to paper over the symptom with a config-side allowlist; that's been closed in favor of this focused fix.)

Fix

Drop the key-presence test on the auth store and use the same pattern already used elsewhere in the function:

from agent.credential_pool import load_pool
pool = load_pool(hermes_id)
if pool.has_credentials():
    has_creds = True

load_pool().has_credentials() checks that real credentials exist (env vars, singletons, and pool entries, with the usual seeding paths) — empty lists no longer leak through.

Tests

  • New: tests/hermes_cli/test_picker_empty_credential_pool.py
    • Empty credential_pool['huggingface'] = [] ⇒ NOT in returned slugs.
    • Pool reports real creds ⇒ row appears.
  • Updated test_mapped_provider_credential_pool_visibility (in test_overlay_slug_resolution.py) to validate via the new pool path instead of the leaky bandaid it previously asserted.
  • Full target run: tests/hermes_cli/ -k 'model_switch or picker or list_auth or overlay'185 passed.

Scope

  • No new public APIs.
  • Single-function change inside list_authenticated_providers.
  • Mirrors the approach already shipped in sections 2 / 2b.

Section 1 of list_authenticated_providers checked

    hermes_id in store.get('credential_pool', {})

which gave false positives for entries with empty list values, surfacing
providers (e.g. huggingface, opencode-go, minimax(-cn), zai) in the
/model picker that the user never authenticated to. Selecting one
routed every turn to a dead endpoint and 401'd.

Sister fix 4607242 closed this same class of bug in sections 2 and
2b but missed section 1. This patch mirrors that approach: drop the
key-presence test on the auth store and use
agent.credential_pool.load_pool(hermes_id).has_credentials() — which
verifies real credentials exist (env, singletons, pool entries).

Adds a regression test (tests/hermes_cli/test_picker_empty_credential_pool.py)
covering the empty-list pathological case and the positive path.

Updates one existing overlay test that relied on the leaky behavior to
use the same load_pool stub pattern instead.

No new public APIs. Safe minimal change.
@teknium1

Copy link
Copy Markdown
Contributor

Closing as already fixed on main.

Triage notes (medium confidence):
origin/main:hermes_cli/model_switch.py:1235 already uses store.get('credential_pool', {}).get(hermes_id) which is falsy for empty list values — the exact bug the PR description targets. The PR's switch to load_pool().has_credentials() is a refactor not a fix.

If you still see this on the latest version, please reopen with reproduction steps.

(Bulk-closed during a CLI triage sweep.)

@teknium1 teknium1 closed this May 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/auth Authentication, OAuth, credential pools comp/cli CLI entry point, hermes_cli/, setup wizard P2 Medium — degraded but workaround exists type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants