Skip to content

fix(model): clear stale endpoint credentials across all provider switches - #49380

Merged
teknium1 merged 2 commits into
mainfrom
hermes/hermes-cc985345
Jun 20, 2026
Merged

fix(model): clear stale endpoint credentials across all provider switches#49380
teknium1 merged 2 commits into
mainfrom
hermes/hermes-cc985345

Conversation

@teknium1

Copy link
Copy Markdown
Contributor

Summary

Switching away from a custom provider no longer leaves a stale model.api_key (or legacy model.api / model.api_mode) sitting in config.yaml to override the new provider's credential resolution.

Root cause: the custom-endpoint flow persists model.api_key to config.yaml. Every other provider-switch path then wrote provider/base_url back without clearing it, so the old custom key survived and contaminated the new provider — which resolves credentials from env/auth.json/credential pool, not inline config.

Changes

  • hermes_cli/config.py: new shared helper clear_model_endpoint_credentials() (toggles for api_key/api_mode, also clears legacy api).
  • hermes_cli/model_setup_flows.py: apply the helper across all provider-switch flows — nous, openrouter, api_key_provider, azure_foundry, copilot, copilot_acp, kimi, stepfun, bedrock, bedrock_api_key, anthropic. Nous also reloads config after the auth helper writes provider state so the stale in-memory copy can't clobber it.
  • hermes_cli/auth.py: _update_config_for_provider() now uses the shared helper (also picks up the legacy model.api field it previously missed).
  • hermes_cli/web_server.py: Desktop/web main + auxiliary model assignment clear stale endpoint creds + base_url on provider change (guarded so custom keeps its key).
  • gateway/slash_commands.py: both /model --global persistence sites clear stale creds on a non-custom switch.

The Bedrock Mantle custom flow is included — it previously saved provider: custom with a changed endpoint while leaving the prior custom key, which could route Bedrock with the wrong credential.

Validation

Before After
switch custom → nous / openrouter / deepseek / anthropic / etc. stale model.api_key persists cleared
Bedrock Mantle custom re-point old key could route new endpoint cleared/replaced
same-provider re-pick n/a key preserved (guard)
custom-provider switch n/a key intentionally kept

336 targeted tests pass (tests/cli/test_cli_provider_resolution.py, tests/hermes_cli/test_update_config_clears_custom_fields.py, tests/gateway/test_model_picker_persist.py, tests/hermes_cli/test_web_server.py).

Credit

Salvage of #49360 by @helix4u, who triaged the report, found the root cause, and authored the comprehensive shared-helper fix (both commits preserved via rebase-merge). Supersedes #49362 by @infinitycrew39, who correctly extended the original Nous fix to the three main CLI flows and prompted the wider audit — credited there.

Closes #49360.

Infographic

stale-key-purge

@github-actions

Copy link
Copy Markdown
Contributor

🔎 Lint report: hermes/hermes-cc985345 vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 11225 on HEAD, 11222 on base (🆕 +3)

🆕 New issues (4):

Rule Count
unsupported-operator 2
not-subscriptable 1
invalid-assignment 1
First entries
tests/cli/test_cli_provider_resolution.py:376: [not-subscriptable] not-subscriptable: Cannot subscript object of type `None` with no `__getitem__` method
tests/cli/test_cli_provider_resolution.py:378: [unsupported-operator] unsupported-operator: Operator `not in` is not supported between objects of type `Literal["api_mode"]` and `Unknown | None`
tests/run_agent/test_credits_notices_toggle.py:76: [invalid-assignment] invalid-assignment: Object of type `None` is not assignable to attribute `_credits_session_start_micros` of type `int`
tests/cli/test_cli_provider_resolution.py:377: [unsupported-operator] unsupported-operator: Operator `not in` is not supported between objects of type `Literal["api_key"]` and `Unknown | None`

✅ Fixed issues (2):

Rule Count
unresolved-attribute 2
First entries
run_agent.py:2984: [unresolved-attribute] unresolved-attribute: Object of type `Self@get_credits_spent_micros` has no attribute `_credits_session_start_micros`
tests/run_agent/test_credits_notices_toggle.py:76: [unresolved-attribute] unresolved-attribute: Unresolved attribute `_credits_session_start_micros` on type `AIAgent`

Unchanged: 5881 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

@alt-glitch alt-glitch added type/bug Something isn't working comp/cli CLI entry point, hermes_cli/, setup wizard comp/gateway Gateway runner, session dispatch, delivery area/auth Authentication, OAuth, credential pools area/config Config system, migrations, profiles P2 Medium — degraded but workaround exists labels Jun 20, 2026
@teknium1
teknium1 merged commit c253b07 into main Jun 20, 2026
35 checks passed
@teknium1
teknium1 deleted the hermes/hermes-cc985345 branch June 20, 2026 02:58
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 area/config Config system, migrations, profiles comp/cli CLI entry point, hermes_cli/, setup wizard comp/gateway Gateway runner, session dispatch, delivery 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