hermes - ✅(Solved) Fix [Bug]: Gateway /model switch leaves stale base_url and does not persist api_mode [4 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
NousResearch/hermes-agent#25107Fetched 2026-05-14 03:48:53
View on GitHub
Comments
0
Participants
1
Timeline
9
Reactions
0
Author
Participants
Timeline (top)
labeled ×5cross-referenced ×4

Root Cause

Gateway /model persists only a subset of switch_model(...) result fields and treats empty base_url as "do not update" instead of "clear stale value".

Fix Action

Fixed

PR fix notes

PR #25131: fix(agent): persist complete model runtime state on /model switch

Description (problem / solution / changelog)

Summary

Both gateway /model and CLI /model --global now persist the complete runtime tuple to config.yaml:

model.default
model.provider
model.base_url      # NEW: was missing or conditionally written
model.api_mode      # NEW: was never persisted

Before

Gateway /model (gateway/run.py):

model_cfg["default"] = result.new_model
model_cfg["provider"] = result.target_provider
if result.base_url:                    # ← only writes when truthy
    model_cfg["base_url"] = result.base_url
# api_mode: never persisted

CLI /model --global (cli.py, 2 locations):

save_config_value("model.default", result.new_model)
if result.provider_changed:
    save_config_value("model.provider", result.target_provider)
# base_url: never persisted
# api_mode: never persisted

After

Gateway — unconditional with empty-string clearing:

model_cfg["base_url"] = result.base_url or ""
model_cfg["api_mode"] = result.api_mode or ""

CLI — two additional save_config_value calls:

save_config_value("model.base_url", result.base_url or "")
save_config_value("model.api_mode", result.api_mode or "")

Impact

Fixes the class of bugs where switching models leaves stale endpoint/protocol state:

ScenarioBeforeAfter
Switch from custom → built-in providerOld base_url survivesCleared to ""
Switch from anthropic_messages → openaiOld api_mode survivesCleared to ""
Switch to a provider with explicit base_urlNot persisted (CLI)Persisted correctly
Restart gateway after /model switchMay use stale endpointUses correct state

Testing

  • 5 new tests covering all persistence paths
  • 29 existing model-switch tests passing (0 regressions)

Files changed

FileChange
gateway/run.pyPersist base_url + api_mode unconditionally
cli.pyAdd save_config_value for base_url + api_mode (2 locations)
tests/gateway/test_model_switch_config_persistence.pyNew: 5 tests

Closes #25107 Closes #25106 See also #25105 (kimi-for-coding alias normalization — separate issue)

Changed files

  • cli.py (modified, +6/-0)
  • gateway/run.py (modified, +3/-2)
  • tests/gateway/test_model_switch_config_persistence.py (added, +209/-0)

PR #25138: fix: persist gateway model runtime state

Description (problem / solution / changelog)

Bug

Gateway /model --global persisted model.default/provider and sometimes base_url, but omitted api_mode and left stale base_url/api_mode values in config.yaml when switching providers.

Fixes #25107

Summary

Update gateway /model --global persistence to write default/provider/base_url/api_mode and remove stale base_url/api_mode when the resolved switch has empty runtime fields. This keeps gateway config aligned with the actual session override.

TDD / ATDD coverage

  • Added a focused regression test that reproduces the reported behavior.
  • Implemented the minimal production change needed to satisfy the regression.
  • Re-ran the targeted test file to guard nearby behavior.

Test plan

  • /Users/mudrii/src/hermes/hermes-agent/venv/bin/python -m pytest tests/gateway/test_model_command_persistence.py tests/gateway/test_session_model_reset.py -q -o 'addopts=' -> 5 passed

Review notes

  • Kept the change scoped to the issue-specific runtime path.
  • No secrets are persisted or logged.

Changed files

  • gateway/run.py (modified, +9/-0)
  • tests/gateway/test_model_command_persistence.py (added, +122/-0)

PR #25148: fix(tui): persist api_mode in _persist_model_switch()

Description (problem / solution / changelog)

What does this PR do?

Root cause: _persist_model_switch() in tui_gateway/server.py writes model.default, model.provider, and model.base_url to config.yaml on a --global /model switch but never writes model.api_mode. When a user switches away from a provider that requires a non-default api_mode (e.g. OpenCode → codex_responses, Kimi Coding → custom mode), the stale value survives in config.yaml. The next TUI session restores the old api_mode and routes the new model through the wrong protocol/endpoint.

Fix: mirror the existing base_url pop-or-write pattern for api_mode — write when truthy, pop when empty. No other behavior changes. gateway/run.py and cli.py already received the equivalent fix via PRs #25131 / #25138; this closes the third persist path that both missed.

Related Issue

Fixes #25107

Type of Change

  • 🐛 Bug fix

Changes Made

  • tui_gateway/server.py: add 4-line api_mode persist block in _persist_model_switch() (+4 lines)
  • tests/test_tui_gateway_server.py: add api_mode assertion to existing test_config_set_model_global_persists; add new test_config_set_model_global_clears_stale_api_mode (+67 lines)

How to Test

python3.11 -m pytest tests/test_tui_gateway_server.py::test_config_set_model_global_persists tests/test_tui_gateway_server.py::test_config_set_model_global_clears_stale_api_mode -v --override-ini="addopts="

Checklist

  • Contributing Guide okundu | Conventional Commits | Duplicate PR yok
  • Sadece bu fix | Tests eklendi | Platform: macOS
  • Docs — N/A | Cross-platform — N/A

Changed files

  • tests/test_tui_gateway_server.py (modified, +63/-0)
  • tui_gateway/server.py (modified, +4/-0)

PR #25137: fix: persist CLI model runtime state

Description (problem / solution / changelog)

Bug

CLI /model --global only persisted model.default and sometimes model.provider. It did not persist the resolved model.base_url/model.api_mode, and it did not clear stale runtime fields after switching away from custom/Anthropic-compatible providers.

Fixes #25106

Summary

Persist the complete CLI model runtime state via a config read-modify-write: default, provider, base_url, and api_mode. Empty base_url/api_mode now remove stale values. The success message is only printed after save_config succeeds.

TDD / ATDD coverage

  • Added a focused regression test that reproduces the reported behavior.
  • Implemented the minimal production change needed to satisfy the regression.
  • Re-ran the targeted test file to guard nearby behavior.

Test plan

  • /Users/mudrii/src/hermes/hermes-agent/venv/bin/python -m pytest tests/hermes_cli/test_apply_model_switch_result_context.py -q -o 'addopts=' -> 6 passed

Review notes

  • Kept the change scoped to the issue-specific runtime path.
  • No secrets are persisted or logged.

Changed files

  • cli.py (modified, +52/-10)
  • tests/hermes_cli/test_apply_model_switch_result_context.py (modified, +183/-0)

Code Example

model_cfg["default"] = result.new_model
model_cfg["provider"] = result.target_provider
if result.base_url:
    model_cfg["base_url"] = result.base_url

---

model.default
model.provider
model.base_url
model.api_mode

---

model_cfg["base_url"] = result.base_url or ""
model_cfg["api_mode"] = result.api_mode or ""
RAW_BUFFERClick to expand / collapse

Bug Description

The gateway /model switch handler persists an incomplete model runtime state.

Current behavior in gateway/run.py updates:

model_cfg["default"] = result.new_model
model_cfg["provider"] = result.target_provider
if result.base_url:
    model_cfg["base_url"] = result.base_url

but this has two bugs:

  1. base_url is only written when truthy, so switching to a provider with no explicit base URL leaves the old provider's base_url in config.
  2. api_mode is not persisted at all, so the previous provider's api_mode can remain or the new provider's required protocol can be lost.

Expected Behavior

Gateway /model should persist or clear the complete runtime tuple:

model.default
model.provider
model.base_url
model.api_mode

If result.base_url or result.api_mode is empty, the corresponding config field should be cleared instead of preserving stale state.

Actual Behavior

A gateway model switch can leave stale model.base_url and stale/missing model.api_mode in config.yaml.

This can cause future gateway sessions or restarted gateway processes to route a model through the wrong endpoint/protocol.

Examples:

  • switch from a custom/OpenAI-compatible endpoint to a native provider: old custom base_url remains
  • switch from an Anthropic Messages-routed provider to a chat-completions provider: old api_mode remains
  • switch to Kimi Coding: required Kimi api_mode / normalized base URL may not be persisted consistently

Reproduction

  1. Configure Hermes gateway with a provider that has explicit model.base_url and/or non-default model.api_mode.
  2. Use gateway /model to switch to another provider/model.
  3. Inspect ~/.hermes/config.yaml.
  4. Observe model.default / model.provider update, but stale model.base_url may remain and model.api_mode is not saved from the switch result.
  5. Restart gateway or start a new session and observe stale runtime config can affect routing.

Root Cause

Gateway /model persists only a subset of switch_model(...) result fields and treats empty base_url as "do not update" instead of "clear stale value".

Suggested Fix

Persist both fields unconditionally with empty-string clearing semantics:

model_cfg["base_url"] = result.base_url or ""
model_cfg["api_mode"] = result.api_mode or ""

This should mirror the CLI global model-switch persistence behavior.

Related Existing Reports / PRs

Related historical work:

  • #2078: /model command — provider switching, stale endpoints, custom display
  • #3685: stale api_mode class of bug
  • #6551: full model triple persistence hardening

This report tracks the remaining current-main gateway /model persistence gap explicitly.

Environment

  • Hermes Agent current main around commit 4fdfdf674
  • Surface: gateway /model
  • Config file: ~/.hermes/config.yaml

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

hermes - ✅(Solved) Fix [Bug]: Gateway /model switch leaves stale base_url and does not persist api_mode [4 pull requests, 1 participants]