Persist the context gauge per session and restore it on switch - #320
Merged
Conversation
The composer's context chip was computed only from the live turn's prompt_built event, so it vanished on relaunch and — worse — switching threads kept the previous thread's numbers on screen until the next turn ran. - Move the ContextUsageState shape + contextUsageFromPrompt projection from the TUI into src/session/context-usage.ts (TUI paths re-export) so the runtime can use them without a TUI dependency. - executeTurn now stamps the turn's window occupancy (prompt_built estimate, refined by the provider's real promptTokens) onto SessionState before the post-turn save — every origin funnels through it. - session_switched carries the stored snapshot; the reducer restores the chip from it and resets to empty when the target session has none, fixing the stale-gauge-on-switch bug.
This was referenced Sep 2, 2026
praxstack
pushed a commit
to praxstack/AtomicBot-ai-atomic-agent
that referenced
this pull request
Sep 4, 2026
Conflict resolutions against the context-usage work already on the rc branch: - runtime/bootstrap.ts: one save at the end of a turn now stamps both the turn's context usage (AtomicBot-ai#320) and the provider/model it ran on (AtomicBot-ai#321). Two PRs rewrote the same choke point; keeping either alone silently dropped the other's stamp. - session/index.ts: both barrels re-exported. - bootstrap.test.ts: the two near-identical turn-stamp tests folded into one that asserts both stamps, returned and reloaded. Also fixes merge-caused breakage between AtomicBot-ai#309 and AtomicBot-ai#315: AtomicBot-ai#309 made `OpenAiToolCallDelta.index` optional, so the contract probe's accumulator no longer type-checks and would have keyed every index-less call into slot 0. It now resolves call identity the way the stream consumer does — index > id > the call currently open.
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.
Problem
The composer's context chip lives only in TUI memory, computed from the live turn's
prompt_builtevent. Two consequences:session_switchednever touchedcontextUsage), claiming the new thread is exactly as full as the one you just left.Change
ContextUsageState+contextUsageFromPromptmove from the TUI intosrc/session/context-usage.ts; the old TUI import paths re-export, so panels/reducers/tests are untouched.executeTurnstamps the turn's window occupancy ontoSessionState.contextUsageright before the post-turn save. Every origin (TUI, scheduler, Telegram, HTTP) funnels through it, and the snapshot is theprompt_builtestimate refined by the provider's realpromptTokenswhen the completion reports one — the same reduction the chip itself does.session_switchednow carries the target session's stored snapshot; the reducer restores the gauge from it, and resets to empty when the session has none (fresh thread, or one written before this field existed).Sessions serialize as whole-state JSON blobs, so the new optional field needs no migration; old rows just load without it.
Tests