fix(state): persist mid-session model switch to database (#34850) - #35256
Merged
Conversation
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
Contributor
🔎 Lint report:
|
…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
force-pushed
the
hermes/hermes-b520738f
branch
from
May 30, 2026 08:57
0832c61 to
01d8b8e
Compare
Collaborator
This was referenced May 30, 2026
1 task
sam7894604
pushed a commit
to sam7894604/hermes-agent
that referenced
this pull request
Jun 25, 2026
Split the session row when the model changes mid-session (/model command or provider failover), so token counts and costs are attributed to the correct model. Follows the same session-rotation pattern used by compression: end old session (end_reason=model_switch) -> create child with parent_session_id -> rotate agent.session_id. Fixes NousResearch#28637, NousResearch#48248, NousResearch#34850 Supersedes NousResearch#35256 Co-Authored-By: Claude <noreply@anthropic.com>
sam7894604
pushed a commit
to sam7894604/hermes-agent
that referenced
this pull request
Jul 5, 2026
Split the session row when the model changes mid-session (/model command or provider failover), so token counts and costs are attributed to the correct model. Follows the same session-rotation pattern used by compression: end old session (end_reason=model_switch) -> create child with parent_session_id -> rotate agent.session_id. Fixes NousResearch#28637, NousResearch#48248, NousResearch#34850 Supersedes NousResearch#35256 Co-Authored-By: Claude <noreply@anthropic.com>
sam7894604
pushed a commit
to sam7894604/hermes-agent
that referenced
this pull request
Jul 9, 2026
Split the session row when the model changes mid-session (/model command or provider failover), so token counts and costs are attributed to the correct model. Follows the same session-rotation pattern used by compression: end old session (end_reason=model_switch) -> create child with parent_session_id -> rotate agent.session_id. Fixes NousResearch#28637, NousResearch#48248, NousResearch#34850 Supersedes NousResearch#35256 Co-Authored-By: Claude <noreply@anthropic.com>
sam7894604
pushed a commit
to sam7894604/hermes-agent
that referenced
this pull request
Jul 22, 2026
Split the session row when the model changes mid-session (/model command or provider failover), so token counts and costs are attributed to the correct model. Follows the same session-rotation pattern used by compression: end old session (end_reason=model_switch) -> create child with parent_session_id -> rotate agent.session_id. Fixes NousResearch#28637, NousResearch#48248, NousResearch#34850 Supersedes NousResearch#35256 Co-Authored-By: Claude <noreply@anthropic.com>
sam7894604
pushed a commit
to sam7894604/hermes-agent
that referenced
this pull request
Jul 22, 2026
Split the session row when the model changes mid-session (/model command or provider failover), so token counts and costs are attributed to the correct model. Follows the same session-rotation pattern used by compression: end old session (end_reason=model_switch) -> create child with parent_session_id -> rotate agent.session_id. Fixes NousResearch#28637, NousResearch#48248, NousResearch#34850 Supersedes NousResearch#35256 Co-Authored-By: Claude <noreply@anthropic.com>
sam7894604
pushed a commit
to sam7894604/hermes-agent
that referenced
this pull request
Jul 22, 2026
Split the session row when the model changes mid-session (/model command or provider failover), so token counts and costs are attributed to the correct model. Follows the same session-rotation pattern used by compression: end old session (end_reason=model_switch) -> create child with parent_session_id -> rotate agent.session_id. Fixes NousResearch#28637, NousResearch#48248, NousResearch#34850 Supersedes NousResearch#35256 Co-Authored-By: Claude <noreply@anthropic.com>
3 tasks
sam7894604
pushed a commit
to sam7894604/hermes-agent
that referenced
this pull request
Aug 9, 2026
Split the session row when the model changes mid-session (/model command or provider failover), so token counts and costs are attributed to the correct model. Follows the same session-rotation pattern used by compression: end old session (end_reason=model_switch) -> create child with parent_session_id -> rotate agent.session_id. Fixes NousResearch#28637, NousResearch#48248, NousResearch#34850 Supersedes NousResearch#35256 Co-Authored-By: Claude <noreply@anthropic.com>
sam7894604
pushed a commit
to sam7894604/hermes-agent
that referenced
this pull request
Aug 11, 2026
Split the session row when the model changes mid-session (/model command or provider failover), so token counts and costs are attributed to the correct model. Follows the same session-rotation pattern used by compression: end old session (end_reason=model_switch) -> create child with parent_session_id -> rotate agent.session_id. Fixes NousResearch#28637, NousResearch#48248, NousResearch#34850 Supersedes NousResearch#35256 Co-Authored-By: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The dashboard Models page now reflects the model a session actually switched to, not the one it was created with. A mid-session
/modelswitch in the gateway updated the cached agent and the in-memory override but never wrote the new model to the DB —update_token_counts()usesmodel = COALESCE(model, ?)(first-writer-wins), so thesessions.modelcolumn kept the original value forever.Salvages #35181 by @LengR (cherry-picked, authorship preserved). Closes #34850, also fixes #28637 (duplicate root cause).
Changes
update_session_model(session_id, model)— unconditionalUPDATE sessions SET model = ?(vs the COALESCE backfill inupdate_token_counts)./modelswitch sites (interactive picker callback + text path) now resolve the session_id viasession_store.get_or_create_session(source)and callupdate_session_model. Text path usesgetattr(self, "_session_db", None)to match the picker path and stay safe under theobject.__new__()gateway test pattern.update_session_modeloverwrites the COALESCE-pinned model AND that a subsequent token update doesn't revert it.Validation
/modelswitch to Btests/test_hermes_state.py -k model→ 3 passed. E2E with real SessionDB I/O in isolated HERMES_HOME confirms the dashboardSELECT model FROM sessionsreflects B after a switch and stays B across later token updates.Infographic