Skip to content

fix(state): persist mid-session model switch to database (#34850)#35256

Merged
teknium1 merged 2 commits into
mainfrom
hermes/hermes-b520738f
May 30, 2026
Merged

fix(state): persist mid-session model switch to database (#34850)#35256
teknium1 merged 2 commits into
mainfrom
hermes/hermes-b520738f

Conversation

@teknium1

Copy link
Copy Markdown
Contributor

Summary

The dashboard Models page now reflects the model a session actually switched to, not the one it was created with. A mid-session /model switch in the gateway updated the cached agent and the in-memory override but never wrote the new model to the DB — update_token_counts() uses model = COALESCE(model, ?) (first-writer-wins), so the sessions.model column kept the original value forever.

Salvages #35181 by @LengR (cherry-picked, authorship preserved). Closes #34850, also fixes #28637 (duplicate root cause).

Changes

  • hermes_state.py: new update_session_model(session_id, model) — unconditional UPDATE sessions SET model = ? (vs the COALESCE backfill in update_token_counts).
  • gateway/run.py: both /model switch sites (interactive picker callback + text path) now resolve the session_id via session_store.get_or_create_session(source) and call update_session_model. Text path uses getattr(self, "_session_db", None) to match the picker path and stay safe under the object.__new__() gateway test pattern.
  • tests/test_hermes_state.py: asserts update_session_model overwrites the COALESCE-pinned model AND that a subsequent token update doesn't revert it.

Validation

Before After
create(model=A) → token updates A A
/model switch to B A (stale) B
token update after switch A B (stable)

tests/test_hermes_state.py -k model → 3 passed. E2E with real SessionDB I/O in isolated HERMES_HOME confirms the dashboard SELECT model FROM sessions reflects B after a switch and stays B across later token updates.

Infographic

mid-session-model-switch-persists

When a user switches models mid-session via /model, the gateway updates
the in-memory agent and session overrides, but the database was never
updated. The COALESCE(model, ?) in update_token_counts() only fills NULL
values, so the dashboard always showed the original model.

Fix: Add SessionDB.update_session_model() that unconditionally sets the
model column, and call it from both the interactive picker and direct
/model command paths in the gateway.

Fixes #34850
@github-actions

github-actions Bot commented May 30, 2026

Copy link
Copy Markdown
Contributor

🔎 Lint report: hermes/hermes-b520738f 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: 9498 on HEAD, 9498 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 4925 pre-existing issues carried over.

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

…t path

Follow-up to LengR's #35181 salvage:
- gateway text-path uses getattr(self, '_session_db', None) to match the
  picker callback path (defensive for object.__new__() gateway test pattern).
- add SessionDB.update_session_model test asserting it overwrites the
  COALESCE-pinned model and survives subsequent token updates (#34850).
@teknium1 teknium1 force-pushed the hermes/hermes-b520738f branch from 0832c61 to 01d8b8e Compare May 30, 2026 08:57
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/gateway Gateway runner, session dispatch, delivery comp/agent Core agent loop, run_agent.py, prompt builder labels May 30, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Salvage of #35181 (@LengR). Fixes #34850 (duplicate of #28637). If this merges, #35181, #28677, and #28842 should be closed as superseded.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent loop, run_agent.py, prompt builder 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.

Bug: Model switch mid-session not persisted to database (dashboard shows stale model) Per-model token usage is lost during mid-session model switches

3 participants