133 lines
4.3 KiB
Rust
133 lines
4.3 KiB
Rust
//! History blocks: the unit of the TUI's stored display model.
|
|
//!
|
|
//! The TUI holds a flat `Vec<Block>` 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<Segment>,
|
|
},
|
|
/// 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<u64> },
|
|
/// `TurnEnd` arrived before `ThinkingDone`. Elapsed time is frozen
|
|
/// at the last observed instant.
|
|
Incomplete { elapsed_secs: Option<u64> },
|
|
}
|
|
|
|
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<u64>,
|
|
},
|
|
/// Compaction ended with `CompactFailed`.
|
|
Failed {
|
|
error: String,
|
|
elapsed_secs: Option<u64>,
|
|
},
|
|
/// The TUI stopped observing events before a terminal compact event.
|
|
Incomplete { elapsed_secs: Option<u64> },
|
|
}
|
|
|
|
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<String>,
|
|
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<String>,
|
|
}
|
|
|
|
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<String>,
|
|
},
|
|
/// `ToolResult { is_error: true, .. }` received.
|
|
Error {
|
|
summary: String,
|
|
output: Option<String>,
|
|
},
|
|
/// Turn ended before a matching `ToolResult` arrived.
|
|
Incomplete,
|
|
}
|