//! History blocks: the unit of the TUI's stored display model. //! //! The TUI holds a flat `Vec` and re-renders it every frame. //! Streaming events mutate the most recent matching block instead of //! queuing a new line, so one logical thing (a tool call, an assistant //! reply) stays visually coherent as updates arrive. #![allow(dead_code)] // Phase 5 will consume `output` in detail mode. use std::time::Instant; use protocol::{AlertLevel, AlertSource, Greeting, PodEvent, Segment}; pub enum Block { Greeting(Greeting), TurnHeader { turn: usize, }, UserMessage { segments: Vec, }, /// Persisted `role:system` history item rendered as an ordinary log /// element. File refs, auto-read snippets, workflow bodies, and future /// system-message injections all share this lane. SystemMessage { text: String, }, /// Echo of `Method::Notify` received by this Pod, surfaced as a log /// element so subscribers see the external input that drove any /// following auto-kicked turn. Notify { message: String, }, /// Echo of `Method::PodEvent` received by this Pod. Same role as /// `Notify` — an input log element, not a turn-control signal. PodEvent { event: PodEvent, }, AssistantText { text: String, }, Thinking(ThinkingBlock), ToolCall(ToolCallBlock), Alert { level: AlertLevel, source: AlertSource, message: String, }, Compact(CompactEvent), TurnStats { requests: usize, /// Net tokens uploaded across the turn's LLM requests /// (cache reads excluded; cache writes included). Same value /// the status line accumulates while the turn is in flight. upload_tokens: u64, output_tokens: u64, }, } pub struct ThinkingBlock { /// Accumulated reasoning body. Empty for providers that emit only /// metadata (no plaintext deltas). pub text: String, pub state: ThinkingState, } pub enum ThinkingState { /// Live block: actively streaming. `started_at` powers the /// `Thinking... (Xs)` live timer. History-restored blocks never /// enter this state — they materialise as `Finished { elapsed_secs: /// None }` since the original duration is not persisted. Streaming { started_at: Instant }, /// Block ended cleanly with `ThinkingDone`. Finished { elapsed_secs: Option }, /// `TurnEnd` arrived before `ThinkingDone`. Elapsed time is frozen /// at the last observed instant. Incomplete { elapsed_secs: Option }, } pub enum CompactEvent { /// Live block: compaction worker is running. `started_at` powers the /// `Compacting... (Xs)` live timer. Streaming { started_at: Instant }, /// Compaction ended cleanly with `CompactDone`. Done { new_session_id: uuid::Uuid, elapsed_secs: Option, }, /// Compaction ended with `CompactFailed`. Failed { error: String, elapsed_secs: Option, }, /// The TUI stopped observing events before a terminal compact event. Incomplete { elapsed_secs: Option }, } pub struct ToolCallBlock { pub id: String, pub name: String, /// Raw JSON fragments accumulated from `ToolCallArgsDelta`. pub args_stream: String, /// Final arguments text once `ToolCallDone` lands. pub arguments: Option, pub state: ToolCallState, /// For Edit tool calls: snapshot of the file content *before* the /// edit was applied to the cache. Captured at result time so the /// diff renderer can reproduce the old-content context even after /// subsequent mutations have rolled the cache forward. pub edit_snapshot: Option, } pub enum ToolCallState { /// `ToolCallStart` received, nothing else yet. Pending, /// At least one `ToolCallArgsDelta` has arrived. Streaming, /// `ToolCallDone` received, waiting on the tool result. Executing, /// `ToolResult { is_error: false, .. }` received. Done { summary: String, output: Option, }, /// `ToolResult { is_error: true, .. }` received. Error { summary: String, output: Option, }, /// Turn ended before a matching `ToolResult` arrived. Incomplete, }