pub enum UiEvent {
Show 26 variants
AgentTurnStarted,
AgentThinking,
AgentTextDelta(String),
AgentThinkingDelta(String),
ThinkingComplete {
text: String,
},
AgentMessageComplete(String),
ToolCallStarted {
id: String,
name: String,
args: Value,
},
ToolCallProgress {
id: String,
chunk: ProgressChunk,
},
ToolCallCompleted {
id: String,
result: UiToolResult,
},
AgentTurnComplete,
TurnStats {
input_tokens: u64,
output_tokens: u64,
cumulative_input: u64,
cumulative_output: u64,
model: String,
},
PermissionRequested {
tool: String,
args: Value,
resolver: Sender<Decision>,
},
PermissionModeChanged {
mode: PermissionMode,
},
InlineBashOutput {
command: String,
output: String,
},
SessionReplaced {
session_id: String,
history: Vec<Message>,
},
ModelSwitched(ModelId),
ForkCandidates(Vec<(String, String)>),
BranchTree(BranchTree),
MessagesSnapshot(Vec<Message>),
StateSnapshot {
session_id: String,
model: String,
active_turn: bool,
},
ExtensionList {
extensions: Vec<ExtensionInfo>,
},
SettingsSnapshot {
settings: Settings,
},
Error(String),
AttachmentError {
kind: AttachmentErrorKind,
message: String,
},
ExtensionCancelled {
extension_name: String,
reason: Option<String>,
},
Notice {
title: String,
body: String,
},
}Variants§
AgentTurnStarted
AgentThinking
AgentTextDelta(String)
AgentThinkingDelta(String)
Mid-stream extended-thinking delta from the LLM. Anthropic-only
at the wire level (motosan-ai 0.15.4 emits thinking events for
the Anthropic provider only). Each delta is a partial chunk; the
TUI accumulates them into an InFlight::StreamingThinking block
and finalizes on the matching UiEvent::ThinkingComplete. A
turn may emit zero or more AgentThinkingDeltas before a single
ThinkingComplete; deltas always precede any AgentTextDelta
for the same turn.
ThinkingComplete
v0.9 Phase A: emitted by capo-agent after each AssistantContent::Reasoning
(thinking/chain-of-thought) ContentPart is observed in a completed
assistant Message. Fires BEFORE AgentMessageComplete for the same
turn so the TUI’s transcript order is: thinking → text. Multiple
thinking phases per turn produce multiple events in stream order.
See spec §3.5.
Dual source (since v0.11): this variant has two emitters in
capo-agent::app::run_turn:
- Streaming path —
CoreEvent::ThinkingDonemaps directly toThinkingCompleteviamap_event(Anthropic-only). When live this is preceded by zero or moreAgentThinkingDeltas. - Post-turn walker path —
extract_new_thinking_eventswalksAssistantContent::Reasoningin the just-finished turn’s messages and emits oneThinkingCompleteper part. Used for backends that don’t stream thinking (everything non-Anthropic under motosan-ai 0.15.4 today).
A per-turn streamed_thinking_seen flag ensures only one of the two
paths fires for a given turn. The TUI distinguishes the two sources
implicitly: if in_flight is StreamingThinking when this event
arrives, it’s streamed (collapse default = true); otherwise it’s
walker-sourced (collapse default = false, preserving pre-v0.11 UX
for non-Anthropic users).
AgentMessageComplete(String)
ToolCallStarted
ToolCallProgress
ToolCallCompleted
AgentTurnComplete
TurnStats
Token-count summary emitted after each LLM chat call. Cumulative
fields carry the running total for this session. Per-turn deltas
(input_tokens / output_tokens) are the increment from THIS
turn — 0 if the provider didn’t surface counts (CLI shells may
not). See spec §3.1.
Fields
PermissionRequested
PermissionModeChanged
v0.10 Phase A: permission mode changed (Shift+Tab in TUI, –mode CLI flag at startup, or Command::SetPermissionMode RPC). RPC clients with strict UiEvent dispatchers need a new arm.
Fields
mode: PermissionModeInlineBashOutput
Output of a !!cmd inline-bash run, for transcript display.
SessionReplaced
The session was replaced (/new cleared it, or /resume loaded a
stored one). Carries the new session ID + transcript so the TUI can
rebuild state.messages and detect same-session rebuilds.
v0.10 Phase B-2: BREAKING wire change from payload [...] to
payload { "session_id": "...", "history": [...] }.
ModelSwitched(ModelId)
The active model changed successfully.
ForkCandidates(Vec<(String, String)>)
Refreshed /fork candidate list (active-branch user messages,
newest first) — (EntryId, preview) pairs. The binary emits this
at startup and after every turn so the picker is never stale.
BranchTree(BranchTree)
Refreshed session branch tree — the binary emits this at startup
and after every turn so the /tree view is never stale.
MessagesSnapshot(Vec<Message>)
Reply to Command::GetMessages — the session’s persisted message
history. RPC clients use this to snapshot transcript state.
StateSnapshot
Reply to Command::GetState — a small status snapshot for RPC
clients (the TUI holds these in AppState so does not need it).
ExtensionList
Reply to Command::ListExtensions — the registered extensions
- per-extension health status.
Fields
extensions: Vec<ExtensionInfo>SettingsSnapshot
Snapshot of the current settings. Emitted by the binary at
startup and after every successful ApplySettings / ReloadSettings
so the TUI can update state.settings_snapshot. RPC clients
can also consume this to observe live settings changes.
Error(String)
AttachmentError
Emitted when an attachment in a UserMessage failed validation
(path missing, unsupported extension, oversize, unreadable). No turn
is started; the agent stays in Idle. See spec §3 / §4.4.
ExtensionCancelled
An extension cancelled a before_user_message or
session_before_switch hook. The TUI rolls back any optimistic
transcript push (via state.pending_turn_submit) and restores
the composer buffer. See spec §4.4.
Notice
Surface a transcript notice from an extension reply action,
/image errors, or other non-fatal informational events.