fix(desktop): stop a session's effort and fast mode moving the composer pick - #322
Merged
OmarB97 merged 1 commit intoAug 2, 2026
Merged
Conversation
…er pick #318 stopped a spawned session's MODEL from overwriting the composer's persisted selection. Reasoning effort and fast mode are sticky in exactly the same way and were left with exactly the same bug. Both persist to localStorage, and `desktopSessionCreateParams` reads both as what the NEXT new chat runs — so writing a session's runtime values into them re-aims every chat the user starts afterwards. Four paths did that, all with the persisting setters: `syncRuntimeMetadataToView` on every state flush, `applyRuntimeInfo` at session create, `applyStoredSessionPreviewRuntimeInfo` on a sidebar preview, and the `session.info` handler in gateway-event.ts. That last one is worth a reviewer's attention: it sits inside the `if (apply)` block whose own comment explains why model/provider must not be written there, and `apply` is also true for a global broadcast when NO session is active — so a heartbeat could rewrite the stored effort while the user sat on a fresh draft, with no session on screen to explain it. The fix is #318's, applied to its two remaining fields: $activeSessionReasoningEffort / $activeSessionFastMode hold what the open session runs, `$primaryReasoningEffort` / `$primaryFastMode` compute `live ?? picked` for the primary chat surface, and only a deliberate pick (model menu, presets, Settings) or the profile-default seed still writes $currentReasoningEffort / $currentFastMode. `clearActiveSessionModel` became `clearActiveSessionRuntime` since it now hands back all four. Two existing state-cache assertions moved from $currentReasoningEffort to $primaryReasoningEffort. They are testing what the composer DISPLAYS, and the atom holding that answer changed identity — the same edit #318 made to the model assertions beside them. Their meaning is unchanged: a background session's metadata still must not paint the foreground. Proven both ways rather than assumed. Reverting just the state-cache swap fails three tests (`expected 'high' to be 'low'`); reverting just the gateway-event swap fails two (`expected 'low' to be 'high'`). End to end: with a stored pick of effort=high/fast=true, a session reporting low/false leaves the next chat's session.create params on high/true. Co-Authored-By: Claude Fable 5 <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.
What this is
#318 stopped a spawned session's model from overwriting the composer's persisted selection. Reasoning effort and fast mode are sticky in exactly the same way, are read by the same function for the same purpose, and were left with exactly the same bug. This is that fix, applied to the two remaining fields.
I found this while fixing the context meter (#316) and originally wrote the model half too — #318 landed first and did it better, so this keeps only what is still missing and follows #318's pattern rather than competing with it.
The bug
$currentReasoningEffortand$currentFastModepersist to localStorage, anddesktopSessionCreateParamsreads both as what the next new chat runs. Four paths wrote session runtime values into them using the persisting setters, so whatever session you had open silently became your stored default:syncRuntimeMetadataToViewapplyRuntimeInfoapplyStoredSessionPreviewRuntimeInfosession.infohandler ingateway-event.tsThe last one deserves a look. It sits inside the
if (apply)block whose own comment explains why model/provider must not be written there — the guard was placed and then walked around by the lines below it. Andapplyis also true for a global broadcast when no session is active, so a heartbeat could rewrite the user's stored effort while they sat on a fresh draft, with nothing on screen to explain it.The fix
Straight from #318:
$activeSessionReasoningEffort/$activeSessionFastModehold what the open session runs (unpersisted,null= no session owns the display),$primaryReasoningEffort/$primaryFastModecomputelive ?? pickedfor the primary chat surface, andsession-view.tsxdisplays those. Only a deliberate pick — model menu, presets, Settings — or the profile-default seed still writes$currentReasoningEffort/$currentFastMode.clearActiveSessionModelbecameclearActiveSessionRuntime, since it now hands back all four mirrors.desktopSessionCreateParamsis untouched and still reads the stored pick, which is the point.One thing to check me on
Two existing assertions in
use-session-state-cache.test.tsxmoved from$currentReasoningEffortto$primaryReasoningEffort. That is not a failing test being edited into submission: those assertions test what the composer displays, and the atom holding that answer changed identity — the identical edit #318 made to the model assertions sitting beside them. Their meaning is unchanged, and the test still proves a background session's metadata does not paint the foreground.Evidence
Proven both directions rather than assumed:
use-session-state-cache.tsswap → 3 tests fail (expected 'high' to be 'low').gateway-event.tsswap → 2 tests fail (expected 'low' to be 'high').effort=high/fast=true, after a session reportinglow/false, the next chat'ssession.createparams still carryreasoning_effort: 'high'andfast: true.Checks
npm run test:ui— 1954 passed, 1 skipped, 0 failures (rebased onto fix(goals): make the goal store's launch-home scope deliberate, not accidental #320).npm run typecheck(app + electron + e2e) — clean.npx eslint src/ electron/— 9 errors, matching the pre-existing baseline onmainexactly; both errors in files this PR touches were confirmed viagit stashto pre-date it.🤖 Generated with Claude Code