You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The TUI statusline ctx used/window pct% segment only updates once per turn, when the turn fully ends:
contextRemaining is computed and emitted with the token_usage event in the Final usage event block, after the agent loop breaks (packages/runtime/src/ai-sdk-backend.ts, ~L2761).
Mid-turn, each step-finish boundary already captures lastStepInputTokens (~L2190), but it only feeds the end-of-turn computation and the durable recordUsageCheckpoint hook — nothing reaches the live event stream.
The TUI's only live update path is applyMakaSessionEventToTranscript's case 'token_usage' (packages/cli/src/pi-transcript.ts), and /context is midTurn: 'refuse'.
During a long agentic turn (dozens of tool steps, minutes) — exactly when the context grows fastest and the user most needs the signal to /compact or wrap up — the indicator sits stale at the previous turn's value.
Prior art: desktop already does better
The desktop session inspector shows a context bar that updates per settled provider request, mid-turn:
The Host commits a latest-context snapshot at every request settlement (packages/runtime/src/provider-request-telemetry.ts: finalize → emitModelCallAttempt → accounting.record({ attempt, latestContext })).
The inspector subscribes to the live session event stream; trace-relevant events (tool_start, tool_result, token_usage, …) trigger a 400 ms-debounced re-read of context.diagnostics.query (apps/desktop/src/renderer/features/workbar/tools/inspector/use-session-trace.ts, session-trace-refresh.ts).
Proposal: reuse the desktop pull model in the TUI
Verified feasible with no protocol changes:
context.diagnostics.query is a plain read (packages/runtime-host/src/server/context-coordinator.ts#queryDiagnostics): header snapshot + run-store read, no execution authority, no busy gate.
The TUI driver already exposes it: runtime-host-session-driver.tsgetContextDiagnostics() (L1117). The /context mid-turn refusal is the TUI's own runControl serial lock (pi-tui-runner.ts L882), not a protocol constraint — a refresh hook can call the driver directly.
Hook point exists: onEvent in pi-tui-runner.ts (L1455) sees every live event mid-turn. Attach a debounced refresh on the trace-relevant event set.
No race: the finish part's finalize() (snapshot commit) is awaited beforecontroller.enqueue in the telemetry stream wrapper, so by the time tool_start reaches the UI the snapshot is durable.
Semantics line up: diagnostics.inputTokens is "used"; contextRemaining = contextWindow - inputTokens matches the existing statusline formula. The end-of-turn token_usage stays the authoritative persisted record; the pull only enriches the live turn.
Why pull over a new push event
Zero protocol surface: no core event schema, backend emission, host mapper, or persistence-semantics changes.
Single source of truth: TUI and desktop read the same latest-context snapshot row — no second derivation path to drift on resume/backfill/compact edges.
All changes contained in the CLI package.
Free follow-up: /context could become mid-turn-capable over the same query path.
Scope
Debounced getContextDiagnostics() refresh on trace-relevant live events; update the statusline ctx segment (used/window/pct) mid-turn.
Prefer the diagnostics' contextWindow (measured at settlement) over the catalog value when present.
Reuse or share the refresh-coalescer policy with desktop's session-trace-refresh.ts.
Non-goals
Token-level "real-time" during a single streaming request — impossible exactly (providers report input tokens at completion); a pre-dispatch bytes/4 estimate is too rough (base64 attachments) to be worth it.
Problem
The TUI statusline
ctx used/window pct%segment only updates once per turn, when the turn fully ends:contextRemainingis computed and emitted with thetoken_usageevent in the Final usage event block, after the agent loop breaks (packages/runtime/src/ai-sdk-backend.ts, ~L2761).step-finishboundary already captureslastStepInputTokens(~L2190), but it only feeds the end-of-turn computation and the durablerecordUsageCheckpointhook — nothing reaches the live event stream.applyMakaSessionEventToTranscript'scase 'token_usage'(packages/cli/src/pi-transcript.ts), and/contextismidTurn: 'refuse'.During a long agentic turn (dozens of tool steps, minutes) — exactly when the context grows fastest and the user most needs the signal to
/compactor wrap up — the indicator sits stale at the previous turn's value.Prior art: desktop already does better
The desktop session inspector shows a context bar that updates per settled provider request, mid-turn:
packages/runtime/src/provider-request-telemetry.ts:finalize→emitModelCallAttempt→accounting.record({ attempt, latestContext })).tool_start,tool_result,token_usage, …) trigger a 400 ms-debounced re-read ofcontext.diagnostics.query(apps/desktop/src/renderer/features/workbar/tools/inspector/use-session-trace.ts,session-trace-refresh.ts).Proposal: reuse the desktop pull model in the TUI
Verified feasible with no protocol changes:
context.diagnostics.queryis a plain read (packages/runtime-host/src/server/context-coordinator.ts#queryDiagnostics): header snapshot + run-store read, no execution authority, no busy gate.runtime-host-session-driver.tsgetContextDiagnostics()(L1117). The/contextmid-turn refusal is the TUI's ownrunControlserial lock (pi-tui-runner.tsL882), not a protocol constraint — a refresh hook can call the driver directly.onEventinpi-tui-runner.ts(L1455) sees every live event mid-turn. Attach a debounced refresh on the trace-relevant event set.finishpart'sfinalize()(snapshot commit) is awaited beforecontroller.enqueuein the telemetry stream wrapper, so by the timetool_startreaches the UI the snapshot is durable.Semantics line up:
diagnostics.inputTokensis "used";contextRemaining = contextWindow - inputTokensmatches the existing statusline formula. The end-of-turntoken_usagestays the authoritative persisted record; the pull only enriches the live turn.Why pull over a new push event
/contextcould become mid-turn-capable over the same query path.Scope
getContextDiagnostics()refresh on trace-relevant live events; update the statusline ctx segment (used/window/pct) mid-turn.contextWindow(measured at settlement) over the catalog value when present.session-trace-refresh.ts.Non-goals
token_usagepersistence or billing semantics (fix(headless): harden real-provider smoke reliability #972: incomplete usage is no usage).Refs: #1053 #1064 #1067 #3371 #4019 (per-turn behavior, all closed), desktop pull model #1625 #2323.