Skip to content

fix(session): persist the model across resume - #343

Open
danielkov wants to merge 4 commits into
mainfrom
fix/acp-resume-model-persistence
Open

danielkov wants to merge 4 commits into
mainfrom
fix/acp-resume-model-persistence

Conversation

@danielkov

@danielkov danielkov commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Durable sessions now remember their model and restore it on session/load and session/resume, falling back to the configured default when the model is provably unusable. An explicit --model or --provider overrides and replaces the remembered model. Kit also reports recorded context usage after restoring a session.

Motivation

A resumed session started on the configured default, so an ACP client that restored its own saved model looked like it was switching models. Above 80% occupancy the context guard rejected that switch with a bare Internal error, and Paseo treats that as fatal, which made the thread impossible to reopen. Clients also showed no context data after a resume until the next model response.

Impact

  • Threads that failed to reopen this way can resume again, including existing transcripts with no model record.
  • Sessions no longer silently change model when the configured default changes.
  • Switching to a window at least as large as the one recorded with the latest usage no longer asks for confirmation, in the TUI as well as over ACP.
  • The confirmation error changes from -32603 to -31050 and now carries its explanation in message. The kit.model_switch data is unchanged.
  • New sessions write transcript schema 7, which older Kit versions reject.

Technical details

Evidence required for fallback

Only missing provider credentials, an unparseable id, a successful listing that omits the model, or a 404 for an Anthropic id missing from the listing count as unusable; aliases resolve through the retrieve endpoint. A failed listing keeps the remembered model. The check reads the raw listing because the advertised catalog always adds the current model. A fallback lasts for that attachment only: the record is kept, so the model returns once it is available again.

Telling explicit flags from defaults

The TUI always forwards its resolved model to kit serve, so --model alone cannot signal intent. It now passes the hidden --prefer-session-model flag when the user did not choose a model on the command line. Subagent harness launches keep their explicit model.

Existing transcripts

These have no model record and items do not record their model, so there is nothing to restore. The guard exemption compares the target window with the window recorded on the latest usage, which frees these threads without knowing the previous model. The client's first successful selection then writes the record.

Usage update timing

The usage update is sent after activation instead of during replay, because Paseo discards non-transcript updates while replaying. A model change also refreshes the update using the new model's advertised window, and the recorded window is used only when it belongs to the selected model. Each usage now records its producing model as kit.model metadata for that check.

Child sessions

Inherited child transcripts deliberately do not copy the parent's model, since a child's model is chosen when it is spawned.

Resumed sessions started on the configured default, so a client restoring its own model tripped the context guard and could not reopen the thread. Record the model in transcript schema 7, restore it on load and resume, and fall back to the default only when it is provably unusable. An explicit --model or --provider overrides and replaces it. Exempt switches to a window at least as large as the recorded one, return a distinct confirmation error with its explanation, and report recorded context usage after restoring.

@kit-code-agent kit-code-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Model restoration can reject valid Anthropic aliases and hidden subscription models, while headless prompt resumes bypass restoration entirely. Explicit ACP overrides can also publish a previous model's context capacity. The new confirmation code uses an ACP-reserved range, and OpenRouter/Speakeasy restoration adds a duplicate serialized catalog request.

Took 20 min

Comment thread src/provider/adapter.rs Resolved
Comment thread src/provider/adapter.rs Resolved
Comment thread src/protocols/acp.rs Resolved
Comment thread src/main.rs Resolved
Comment thread src/protocols/acp/model_switch.rs Resolved
Comment thread src/provider/adapter.rs Resolved
Apply restoration and explicit overrides to persistent prompts, confirm Anthropic aliases through the retrieve endpoint, keep hidden subscription models in catalog membership, ignore a recorded window that belongs to another model, and move the confirmation code out of the ranges ACP reserves.

@kit-code-agent kit-code-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recorded usage-window eligibility is not preserved across model-only changes, so a subsequent attachment can advertise another model's capacity.

Took 10 min

Comment thread src/runtime.rs Resolved
A model change without a new response left the previous model's window on the latest usage, so a later attachment could report it as the selected model's capacity. Derive attribution from record order and stop trusting the recorded window for forks.

@kit-code-agent kit-code-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A response generated during a temporary fallback can make the fallback model's recorded context capacity appear attributable to the remembered model on a later attachment.

Took 7 min 56 sec

Comment thread src/session.rs Resolved
Inferring a recorded window's model from transcript record order could not see responses produced during a temporary fallback. Stamp each usage with its producing model and trust the recorded window only when it matches the selection, which also covers overrides, switches, and forks.

@kit-code-agent kit-code-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found. The changes look good to merge.

Took 8 min 45 sec

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant