Skip to content

fix(gateway): clear last-resolved-model cache on 3 more conversation-boundary resets - #58906

Merged
teknium1 merged 1 commit into
NousResearch:mainfrom
srojk34:fix/session-expiry-model-cache-stale
Jul 5, 2026
Merged

fix(gateway): clear last-resolved-model cache on 3 more conversation-boundary resets#58906
teknium1 merged 1 commit into
NousResearch:mainfrom
srojk34:fix/session-expiry-model-cache-stale

Conversation

@srojk34

@srojk34 srojk34 commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

11b4a21a5 cleared the per-session _last_resolved_model cache on /new and the compression-exhausted auto-reset, so a reset conversation resolves the model from current config instead of a stale cached value (#58403 — a transient config-cache miss otherwise serves the old model back even after an explicit reset/config change).

Auditing every other site documented as the same "full conversation boundary — drop every session-scoped transient state" treatment (they all pop _session_model_overrides, clear the reasoning override, and pop _pending_model_notes) turned up three more that still missed _last_resolved_model:

  • _session_expiry_watcher's permanent finalization block (gateway/run.py) — a session that goes idle and gets finalized, then later resumed, could serve a model cached from before it went idle on a transient config-cache miss.
  • The daily/idle/suspended auto-reset cleanup (_was_auto_reset handling, gateway/run.py) — same failure mode, different trigger; its own comment says "drop every session-scoped transient state."
  • /resume (gateway/slash_commands.py) — its own comment already says "conversation boundary just like /new" for the sibling dicts it clears, but _last_resolved_model wasn't among them.

(I also checked the /moa <prompt> one-shot-override revert and the /reasoning command's reasoning-only reset — both are legitimately out of scope: neither is a full conversation-boundary reset, so clearing the model-resolution cache there would be wrong.)

Related Issue

Same underlying issue as 11b4a21a5: #58403 (three additional sites of the same class, not yet covered by that fix).

Type of Change

  • 🐛 Bug fix (stale-cache class, same as 11b4a21a5)

Changes Made

  • gateway/run.py: pop _last_resolved_model[key] in the session-expiry finalization block and the _was_auto_reset cleanup block (+14 lines)
  • gateway/slash_commands.py: pop _last_resolved_model[session_key] in /resume's conversation-boundary cleanup (+7 lines)
  • tests/gateway/test_session_boundary_hooks.py: new behavioral regression test driving _session_expiry_watcher end-to-end
  • tests/gateway/test_10710_auto_reset_evicts_cached_agent.py: new AST-invariant test, mirroring this file's existing pattern for pinning the auto-reset cleanup block's contents
  • tests/gateway/test_resume_command.py: new test extending the existing test_resume_clears_session_model_overrides pattern

How to Test

pytest tests/gateway/test_resume_command.py tests/gateway/test_session_boundary_hooks.py tests/gateway/test_10710_auto_reset_evicts_cached_agent.py tests/gateway/test_48031_model_switch_after_auto_reset.py tests/gateway/test_new_clears_last_resolved_model.py tests/gateway/test_session_boundary_security_state.py -v

Mutation-verified: all 3 new tests fail against the pre-fix code.

Checklist

  • Contributing Guide read | Conventional Commits | No duplicate PR found (searched _last_resolved_model session_expiry auto_reset resume, resume clears last resolved model, was_auto_reset last_resolved_model)
  • Scoped to this one cache/pattern | Tests added | Platform: macOS
  • Docs — N/A | Cross-platform — N/A (pure Python dict handling)

…boundary resets

11b4a21 cleared the per-session _last_resolved_model cache on /new and
the compression-exhausted auto-reset, so a resumed/reset conversation
resolves the model from current config instead of a stale cached value
(NousResearch#58403). Three other sites documented as the same "full conversation
boundary" treatment — pop _session_model_overrides, clear the reasoning
override, pop _pending_model_notes — still missed _last_resolved_model:

- _session_expiry_watcher's permanent finalization block (gateway/run.py):
  a session that goes idle and is finalized, then resumed, could serve a
  model cached before it went idle on a transient config-cache miss.
- The daily/idle/suspended auto-reset cleanup (_was_auto_reset handling,
  gateway/run.py): same failure mode, different trigger.
- /resume (gateway/slash_commands.py), whose own comment already says
  "conversation boundary just like /new" for the sibling dicts it clears.

Fix: pop the session's _last_resolved_model entry in all three, mirroring
the exact pattern 11b4a21 established.
@alt-glitch alt-glitch added type/bug Something isn't working comp/gateway Gateway runner, session dispatch, delivery sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state P2 Medium — degraded but workaround exists labels Jul 5, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Related: #58829 (open) clears _last_resolved_model only on the daily/idle/suspended _was_auto_reset cleanup block; this PR is a superset -- it covers that same site plus the _session_expiry_watcher finalization block and /resume. Both descend from 11b4a21 / #58403 (salvaged in merged #58503). Not a duplicate (superset); maintainer picks the broader fix.

@teknium1
teknium1 merged commit cdcbc3a into NousResearch:main Jul 5, 2026
31 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/gateway Gateway runner, session dispatch, delivery P2 Medium — degraded but workaround exists sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants