Skip to main content

UiState

Struct UiState 

Source
pub struct UiState {
Show 31 fields pub phase: UiPhase, pub agent_mode: AgentMode, pub spinner_label: String, pub spinner_frame: usize, pub unicode_symbols: bool, pub total_tokens: usize, pub prompt_tokens: usize, pub completion_tokens: usize, pub cached_tokens: usize, pub prior_phase: Option<UiPhase>, pub prior_spinner_label: Option<String>, pub thinking_idx: usize, pub turn_started_at: Option<Instant>, pub phase_started_at: Option<Instant>, pub last_context: Option<ContextSnapshot>, pub last_submitted_message: Option<String>, pub pending_context_render: Option<bool>, pub pending_images: Vec<ImagePart>, pub pending_image_hashes: Vec<u64>, pub pending_image_markers: Vec<usize>, pub pending_recalled_attachments: Vec<HistoryImageRef>, pub session_image_count: usize, pub show_tool_output: bool, pub show_reasoning: bool, pub sub_agent_total: usize, pub sub_agent_done: usize, pub sub_agent_tasks: Vec<SubAgentTaskInfo>, pub sub_agent_failed: usize, pub sub_agent_started_at: Option<Instant>, pub active_tool_batches: HashMap<String, ActiveToolBatch>, pub call_id_to_batch: HashMap<String, String>,
}

Fields§

§phase: UiPhase§agent_mode: AgentMode§spinner_label: String§spinner_frame: usize§unicode_symbols: bool

Mirrors TerminalCaps::unicode_symbols — frozen at construction. When false, tick_spinner and the spinner-label ellipsis fall back to ASCII so terminals whose font lacks / (notably Windows legacy conhost) don’t show tofu.

§total_tokens: usize§prompt_tokens: usize§completion_tokens: usize§cached_tokens: usize§prior_phase: Option<UiPhase>

When Suspended, holds the phase to restore on resume.

§prior_spinner_label: Option<String>

While waiting on a tool approval, holds the "Running {Tool}" label that was active before the prompt opened. on_approval_needed stashes it here and swaps spinner_label to “Waiting approval”; on_approval_resolved restores it. Without this, the spinner kept saying “Running Bash… · 273s” while the agent was actually blocked on permission.decide().await — looked identical to a real tool hang.

§thinking_idx: usize

Round-robin index into THINKING_LABELS; bumped on each on_submit.

§turn_started_at: Option<Instant>

When the current turn started. Set by on_submit, cleared on turn-complete / turn-cancelled / error. Used to surface the total wall-clock duration in the TurnComplete event payload.

§phase_started_at: Option<Instant>

When the current phase began. Reset on every phase transition (on_submit, on_thinking, on_tool_call_streaming, on_tool_call_started) so the spinner shows time spent on the CURRENT operation — Pondering… 12s, Running ReadFile… 4s — instead of accumulating over the whole turn. Cleared on turn-complete / turn-cancelled / error so the idle spinner (rare) doesn’t tick a stale duration.

§last_context: Option<ContextSnapshot>

Last observed context breakdown. Populated from AgentEvent::ContextStats/context renders this. None before the first turn completes.

§last_submitted_message: Option<String>

Verbatim text of the message that is currently running. Set on every submit, cleared on turn-complete. When the user hits Ctrl+C / Esc mid-stream the streaming-key handler takes this and restores it to the input buffer so the cancelled message can be edited + resent without re-typing. None between turns and after any successful completion.

§pending_context_render: Option<bool>

/context dispatched a RefreshContextStats command and is waiting for the resulting rich ContextStats event to render the report. Some(show_prompt) until the next rich emission lands; cleared after the render fires. Prevents stale-cache renders without forcing /context to block synchronously on the agent loop. The bool is the prompt sub-arg (include full system prompt body).

§pending_images: Vec<ImagePart>

Images pasted from clipboard (Ctrl+V) waiting to be sent with the next user message. Drained on submit.

§pending_image_hashes: Vec<u64>

Parallel to pending_images — content fingerprint of each pasted image’s raw RGBA bytes. Used by the right-aligned status hint to suppress Image in clipboard · ctrl+v to paste once the clipboard content matches an already-attached image (avoids dup paste prompts), while still surfacing the hint when the user copies a new image after pasting an earlier one. Cleared together with pending_images on submit.

§pending_image_markers: Vec<usize>

Parallel to pending_images — the marker number N originally printed for each image at paste time. Submit-time matching does line.contains("[Image #N]") against this number to decide whether the image survived editing. Must NOT be i + 1 from the vec position — once session_image_count became monotonic across turns, paste-time numbers diverge from positional indices, and using the index dropped images on every retry that wasn’t the first paste of the session.

§pending_recalled_attachments: Vec<HistoryImageRef>

Image attachments to re-attach when the user submits a recalled history entry. Populated by the up-arrow handler from the recalled HistoryEntry::images; drained on submit by the hydrate prelude in event_loop/mod.rs. Lazy by design — disk reads happen at submit time, not on every navigation.

§session_image_count: usize

Monotonic counter for the [Image #N] marker shown in the input buffer + scrollback. Incremented on every paste and NEVER reset across turns — so two images pasted in different turns get distinct labels (e.g. [Image #1] in turn 1, [Image #2] in turn 2). Without this, both turns’ first paste would both render as [Image #1], making it ambiguous which image a later reference points at when scrolling back.

§show_tool_output: bool

Whether to show real-time tool output (e.g., bash stdout/stderr). Toggled by Ctrl+O. When false (default), tool output is hidden during execution and only shown in the final result.

§show_reasoning: bool

Whether to show LLM reasoning/thinking content (e.g., DeepSeek-R1, MiniMax-M2.7). Toggled by Ctrl+O together with show_tool_output. When false (default), reasoning content is hidden during streaming.

§sub_agent_total: usize

Number of fork sub-agents currently dispatched. While > 0, the foreground turn is blocked awaiting pool.execute_all — there’s no fresh tool / think event to update the spinner, so without an override the label stays frozen on the last tool name (e.g. “Running ReadFile… 82s”) for the entire pool duration. Cleared on SubAgentDispatchEnd.

§sub_agent_done: usize

How many sub-agents in the current dispatch have reported a terminal status (done / failed / timeout). Updated by on_sub_agent_settled. Reset to 0 on each new dispatch.

§sub_agent_tasks: Vec<SubAgentTaskInfo>

Per-task descriptors (path + dedup suffix) for the active dispatch. Indexed identically to the tasks field on AgentEvent::SubAgentDispatchStart so the UI can look up a child’s display path from the index field on Started/Done/ Failed events. Cleared on on_sub_agent_dispatch_end.

§sub_agent_failed: usize

Number of failed sub-agents in the current dispatch — tracked separately from sub_agent_done so the aggregate summary can distinguish “6/7 ok · 1 fail” from “7/7 ok”. Reset on each new dispatch.

§sub_agent_started_at: Option<Instant>

Wall-clock start of the current dispatch. Used to render the elapsed-time figure on the SubAgentDispatchEnd aggregate summary line. Cleared with the rest of the dispatch state.

§active_tool_batches: HashMap<String, ActiveToolBatch>

Active tool batches, keyed by batch_id. Populated on ToolBatchStarted and cleared on ToolBatchCompleted. Used by per-call event handlers to detect “this ToolCallStarted/Result belongs to an active batch” and skip the standalone row render (the batch header already represents it).

§call_id_to_batch: HashMap<String, String>

Reverse map call_id → batch_id for O(1) lookup when a per-call event arrives. Mirrors active_tool_batches membership; cleared together.

Implementations§

Source§

impl UiState

Source

pub fn new() -> Self

Source

pub fn with_unicode(unicode_symbols: bool) -> Self

Construct a UiState with an explicit Unicode capability. Production code calls this from App::new with the value the terminal-capability probe produced; tests stick with new().

Source

pub fn ellipsis(&self) -> &'static str

Single-character horizontal ellipsis (, U+2026) when Unicode is available, three ASCII dots (...) otherwise. Used by the spinner label and any other “still working…” suffix.

Source

pub fn on_context_stats( &mut self, system_tokens: usize, sent_tokens: usize, tool_defs_tokens: usize, cold_zone_tokens: usize, total_messages: usize, ctx_window: usize, ctx_name: &str, system_prompt: &str, )

Merge one AgentEvent::ContextStats emission into the cached snapshot. The agent side fires two emissions per turn: one narrow (from TurnRunner) and one rich (from handle_send_message). Each leaves the fields it doesn’t know at 0 / empty — we keep the most-recent non-zero value per field so either order works.

Source

pub fn turn_elapsed(&self) -> Option<Duration>

Elapsed wall time since the current turn began, if a turn is active. Returns None when idle.

Source

pub fn phase_elapsed(&self) -> Option<Duration>

Elapsed wall time since the current phase began. The spinner uses this so its · 12s suffix shows time on the current operation (LLM round-trip / tool execution), not cumulative turn time. Falls back to turn_elapsed() when no phase transition has fired yet — defensive, should not normally happen since on_submit seeds both.

Source

pub fn on_submit(&mut self)

Source

pub fn on_turn_complete(&mut self)

Source

pub fn on_turn_cancelled(&mut self)

Source

pub fn on_error(&mut self)

Source

pub fn on_tool_call_started(&mut self, name: &str)

Set the spinner label to "Running {name}" (no trailing ellipsis — the renderer appends ... uniformly so it looks right even when the elapsed-time suffix is appended). Resets the phase clock so the spinner timer starts fresh on this tool execution.

Source

pub fn on_tool_call_streaming(&mut self, name: &str)

Source

pub fn on_thinking(&mut self)

Source

pub fn on_sub_agent_dispatch_start(&mut self, tasks: Vec<SubAgentTaskInfo>)

Begin a fork dispatch. Stores the per-task descriptors so the UI can look up each child’s display path + dedup-suffix by index when a SubAgentTaskStarted/Done/Failed event arrives — the previous flow flattened identical basenames (tunnel.rs × 3) into indistinguishable rows. Also overrides the foreground spinner label since pool.execute_all blocks the loop.

Source

pub fn on_sub_agent_task_done(&mut self)

Mark one sub-agent as completed (success). Late events after on_sub_agent_dispatch_end are no-ops — sub_agent_total == 0 is the gate.

Source

pub fn on_sub_agent_task_failed(&mut self)

Mark one sub-agent as failed (error / timeout / no-edit). Increments BOTH the done and failed counters — for the spinner label done is “settled” regardless of outcome, but the aggregate emitted on dispatch_end needs the success/fail split.

Source

pub fn on_sub_agent_dispatch_end(&mut self)

End the dispatch — clears descriptors so subsequent thinks/tools resume normal label behaviour. The next on_thinking / on_tool_call_started will overwrite spinner_label; we leave it alone here so the final “N/N” stays visible until the next phase. The success/fail split is preserved long enough for the event loop to render the aggregate summary line, then cleared.

Source

pub fn on_approval_needed(&mut self, display_tool: &str)

display_tool is the already-PascalCased name (e.g. "Bash", "ReadFile") — same form on_tool_call_started writes into spinner_label. Stashed so on_approval_resolved can put the label back when execution resumes.

Source

pub fn on_approval_resolved(&mut self)

Source

pub fn on_suspend(&mut self)

Source

pub fn on_resume(&mut self)

Source

pub fn next_done_label(&mut self) -> &'static str

Pick (and advance) a playful “done” phrase for the turn separator.

Source

pub fn toggle_tool_output(&mut self)

Toggle real-time tool output and reasoning visibility. Both are controlled by Ctrl+O (verbose mode).

Source

pub fn toggle_verbose(&mut self)

Toggle verbose mode (alias for toggle_tool_output). Shows/hides both tool output and reasoning content.

Source

pub fn tick_spinner(&mut self) -> &'static str

Trait Implementations§

Source§

impl Default for UiState

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more