Skip to content

Interface: AgentPaneState

agentmux


agentmux / agent-pane-state-store / AgentPaneState

Defined in: agent-pane-state/types.ts:318

The reducer’s state. Each field maps 1:1 to a Solid signal that the agent pane projects from. The reducer enforces invariants ACROSS fields (e.g. a turn can’t enter Submitting/Streaming while the stream is unsubscribed — see the TurnStart arm).

PR G cleanup: turnActive / stopping (top-level) and active (on streaming) have all been removed. state.turnPhase.kind is the sole working-state encoding; “is the stream subscribed?” is now derived from state.lastEventMs !== null (cleared atomically with the stream on StreamSubscribe / StreamUnsubscribe).

activity: ActivityState

Defined in: agent-pane-state/types.ts:353

What the agent is doing right now (see ActivityState).


attachedTask: AttachedTaskState

Defined in: agent-pane-state/types.ts:493

Live “attached long-running task” state, or null — see AttachedTaskState. Deliberately NOT cleared by any TurnPhase transition (TurnEnd/TurnReset/etc.): a task attached in one turn can legitimately survive into later turns, so only its own two commands (AttachedTaskObserved/AttachedTaskCleared) ever touch this field.


compacting: CompactionState

Defined in: agent-pane-state/types.ts:485

Live “compaction in progress” state, or null. See CompactionState.


context: ContextReading

Defined in: agent-pane-state/types.ts:452

The context meter’s reading: tokens in context, the model’s window, and where each came from — see store/agent-pane-state/context-reading.ts. Set by TokensIn (live) and ReconcileContextFromHistory (the restored transcript, only while contextSeedable). Unlike turnTokens it is NOT cleared at TurnEnd, so the meter shows the last known fill between turns. Cleared on TurnReset (session wipe), ContextInvalidated (the conversation was replaced) and CompactionBoundary (it no longer measures anything until the next call). Displays read it through plausibleReading, never directly.


contextSeedable: boolean

Defined in: agent-pane-state/types.ts:460

True until something more current than the restored transcript has spoken: a live reading, an invalidation, a compaction or a reset. ReconcileContextFromHistory seeds only while it holds — context being null can’t tell “nothing yet” from “invalidated while history was still loading”, and seeding the latter restores a dead conversation.


currentTool: string

Defined in: agent-pane-state/types.ts:329


currentToolArg: string

Defined in: agent-pane-state/types.ts:332

First significant argument of the active tool (file path, command, etc.). Cleared alongside currentTool on ToolEnd / TurnEnd / TurnReset.


detailsOpen: boolean

Defined in: agent-pane-state/types.ts:423

Whether the composer details panel — the Shell drawer, holding the interactive terminal — is open. Default false. Persists across renders within a pane lifetime; resets to false on pane unmount (because a new pane gets a fresh state via initialState()). Not persisted to backend — a per-session ephemeral preference.

It used to host the session banners and the Archive/Export/Restore actions as well; those moved to AgentSessionNotices (above the composer) and the AgentSessionStats popover respectively, and the runtime dropdowns moved to the strip before that — leaving the drawer to the shell alone. See SPEC_AGENT_SHELL_DRAWER_INFO_PANEL_2026_09_19.md §3.

SPEC_AGENT_COMPOSER_SLIM_STATUS_2026_05_26.md §5.4. Previously auto-collapsed on TurnStart; removed once the panel started hosting a live interactive shell (AgentShellSubblock) that needs to survive sending more messages, not close on every send.


failure: PaneFailure

Defined in: agent-pane-state/types.ts:483

Active classified failure for this pane, or null. Set by FailureObserved (which also force-ends a working turn — see the command’s reducer case), cleared by FailureCleared or implicitly by the next TurnStart (a fresh turn always ends the failure episode). See PaneFailure.


initPhase: InitPhase

Defined in: agent-pane-state/types.ts:383

Init phase — InitPending until history fetch resolves (or fails). Discriminated union; failure reason lives in the InitFailed variant’s reason payload — no separate initError field.


lastCompactionBoundaryAt: number

Defined in: agent-pane-state/types.ts:532

Wall-clock ms of the most recent REAL CompactionBoundary event (backend-sourced, exact — not the ≥50%-drop heuristic below). The TokensIn heuristic checks this before firing its own synthetic context-compacted event, so a Claude session that just got a real boundary doesn’t also get a duplicate heuristic-sourced one for the very next turn’s token drop. Providers without a structured signal (codex/gemini/copilot) never set this, so the heuristic remains their only detection path. See docs/specs/SPEC_COMPACTION_DETECTION_AND_HANDLING_2026_07_31.md §4.3.


lastContextModel: string

Defined in: agent-pane-state/types.ts:475

Resolved model id of the main agent’s latest reply (message.model). The Runtime menu shows it; the context reading is measured on it.


lastEventMs: number

Defined in: agent-pane-state/types.ts:394

Wall-clock ms of the last observable stream activity (subscribe, flush, tool, tokens). Drives the stuck-stream watchdog.

Doubles as the “is the stream subscribed?” gate since PR G: lastEventMs !== null ⇔ the pane has seen a StreamSubscribe that no subsequent StreamUnsubscribe has cleared. Both fields always moved in lockstep when the legacy streaming.active boolean existed, so the substitution is exact.


learnedContextWindows: ContextWindowMap

Defined in: agent-pane-state/types.ts:472

Context windows proven per model by an accepted prompt larger than the window we had (context-reading.ts learnedWindowsAfter). Outlive TurnReset for the same reason as reportedContextWindows.


pending: PendingMessage[]

Defined in: agent-pane-state/types.ts:377


pendingCompactionPing: object

Defined in: agent-pane-state/types.ts:548

A compaction_started ping the reducer rejected because turnPhase wasn’t (yet) working, but which arrived on a phase a LATER authoritative signal could still legitimately promote for THIS SAME turn — ReconcileTurnActive(active: true) or StreamFlushObserved’s own promotion arm, both of which retroactively apply it into compacting on promotion. Cleared whenever that promotion happens, whenever an authoritative signal proves the turn is genuinely NOT running (ReconcileTurnActive(active: false), even when that’s a same-ref no-op for turnPhase itself), by a fresh unrelated TurnStart (not the turn this ping was about), or by any of the other “whatever compaction was in flight is now moot” terminal transitions compacting itself already clears on. See docs/specs/SPEC_COMPACTION_STARTED_RECONCILIATION_RACE_2026_09_02.md.

startedAt: number

trigger: "manual" | "auto"


pendingCompactTurn: boolean

Defined in: agent-pane-state/types.ts:376

True for the duration of a turn started specifically to send a manual “/compact” (the composer’s “Compact now” button, or a user typing it) — set on TurnStart when command.content === "/compact", consumed and reset by CompactionBoundary. Exists because a manual CompactionBoundary.trigger alone is NOT a safe signal that THIS pane’s currently-working turn is the synthetic one that action opened: the reducer’s own tests deliberately model a manual boundary landing while an unrelated real turn is already streaming (compaction_started/compact_boundary travel over independent transports with no ordering guarantee against the primary NDJSON stream — see the CompactionStarted race-guard tests). Only end the turn when we know FOR THIS PANE that its own working turn is the one the manual compact opened. codex P1 on PR #2659.


reconnecting: ResumeRetryState

Defined in: agent-pane-state/types.ts:500

Live “reconnecting after a stale --resume session id” state, or null — see ResumeRetryState. Owned exclusively by ResumeRetryStarted/ResumeRetryResolved, dispatched from useResumeRetryStream.ts.


registryAttachedTaskSince: number

Defined in: agent-pane-state/types.ts:520

Earliest started_at_ms among this block’s currently-Running db_background_tasks rows (Phase A/B of docs/specs/SPEC_BACKGROUND_TASK_DASHBOARD_INTELLIGENCE_2026_08_20.md), or null. A SEPARATE floor signal, not a duplicate of attachedTask above: the durable registry can know about a task the live transcript has no record of at all (e.g. it survived a session restart under a fresh controller generation — Phase B). Deliberately owned EXCLUSIVELY by its own two commands (RegistryAttachedTaskObserved/RegistryAttachedTaskCleared, dispatched only from useBackgroundTaskRegistry.ts) — no other command touches it, specifically so the transcript-derived attachedTask axis’s own independent recompute-and-clear effect (agent-view.tsx’s attached-task effect) can never stomp on it. The effect instead READS this field and combines it with its own transcript-derived value (registry ∪ transcript, earliest start wins) rather than treating either source as sole truth. See the Codex P1 finding on PR #2685 this was written to address.


reportedContextWindows: ReportedContextWindows

Defined in: agent-pane-state/types.ts:466

Context windows Claude Code reported in result.modelUsage, per model id. They outrank the model-name table for any reading on that model, and outlive TurnReset: a model’s window is a fact about the model.


sessionStats: SessionStats

Defined in: agent-pane-state/types.ts:320


sessionTotals: SessionStats

Defined in: agent-pane-state/types.ts:328

Cumulative cost/tokens/duration across every completed turn in this pane’s lifetime — unlike sessionStats (which is replaced, not accumulated, on each TurnEnd), this sums into the previous value. Feeds the composer-strip “totals” display near the input. Cleared only on TurnReset. See SPEC_AGENT_SESSION_COST_TOTALS_2026_07_02.md.


stashOpen: boolean

Defined in: agent-pane-state/types.ts:440

Whether the Stash drawer (the per-agent Accounts/Memory/MCP/Skills/ Startup/Registration surface) is open, top-anchored under the pane header — SPEC_AGENT_STASH_PANE_MIGRATION_2026_09_22.md §3.3.

A SEPARATE axis from detailsOpen (the bottom-anchored shell drawer), deliberately: the two are independent surfaces a user can have open at once, and mutual exclusion would silently close a live shell holding real terminal state (§6 open question 1, answered in favor of independence). The transcript is protected from being squeezed by a CSS max-height on the Stash drawer, not by forcing one of the two closed.

Like detailsOpen, NOT auto-collapsed on TurnStart — sending a message must not yank a surface the user deliberately opened.


streaming: StreamingState

Defined in: agent-pane-state/types.ts:319


turnCarry: TurnCarry

Defined in: agent-pane-state/types.ts:360

Each pass’s own figures (its TurnEnd stats), summed over the turn srv reported it in. For providers whose passes srv doesn’t count (ACP, App Server, one-shot subprocess: no result usage reaches the ledger), the Worked line reports the turn from this.


turnLedger: TurnLedger

Defined in: agent-pane-state/types.ts:351

The turn as the user sees it, over however many CLI passes: srv’s agentturn event, verbatim (turn-ledger.ts). Null until srv has published one for this block. The working row runs its clock and counter from it; turnPhase and turnTokens stay per pass.


turnPhase: TurnPhase

Defined in: agent-pane-state/types.ts:402

Single-source-of-truth turn phase. PR A added it with dual-write against the legacy turnActive / stopping / streaming.active booleans; PR B migrated every view consumer onto it via isWorking(state) / isDisconnected(state) / state.turnPhase.kind; PR G removed the legacy fields.


turnTokens: TurnTokens

Defined in: agent-pane-state/types.ts:344

The current turn’s live usage, from the stream. Its lifetime follows the stream’s own order: set by TokensIn, cleared by that turn’s TurnEnd, or by StreamSessionStarted when the process died before a result. Nothing outside the stream clears it on a normal turn end: ReconcileTurnActive, the liveness recovery and TurnStart all leave it alone, because srv sends the turn-ended push before it forwards the result line, so the turn’s session_end (and sometimes earlier calls) still follow, and a queued message or the next turn can start in that gap. Hard ends (disconnect, failure, timeouts, reset) clear it.