Skip to main content

mermaid_model/
action.rs

1//! Value types describing one tool action's display.
2//!
3//! These ride alongside `ChatMessage::actions` — the chat renderer
4//! paints one per tool call attached to an assistant message. Pure
5//! data; no runtime, no I/O.
6//!
7//! Lives in `mermaid-model` because `models::ChatMessage` embeds a
8//! `Vec<ActionDisplay>`; the wire type owning display data is a wart, but it is
9//! serialized into every saved conversation, so the type moves down rather than
10//! the field going away.
11//!
12//! New tool executions land here via `domain::transition::
13//! action_display_for`, which reads the `PendingToolCall` and
14//! `ToolOutcome` produced by the reducer. The chat widget then
15//! paints the `ActionDetails` variant's specific layout.
16
17use serde::{Deserialize, Serialize};
18
19use crate::tool_run::ToolRunMetadata;
20
21/// Result shape carried on an `ActionDisplay`. Discriminates the
22/// success/error path; the chat widget colors them differently and
23/// `Success` may carry image data for multimodal tools.
24#[derive(Debug, Clone, Serialize, Deserialize)]
25#[must_use]
26pub enum ActionResult {
27    Success {
28        output: String,
29        #[serde(default)]
30        images: Option<Vec<String>>,
31    },
32    Error {
33        error: String,
34    },
35    /// Call is still in flight. Only ever synthesized by the render layer
36    /// for the live transcript view (the chat widget blinks the header dot);
37    /// never committed to the message log, so it never reaches disk.
38    Running,
39}
40
41/// Attached to a committed assistant `ChatMessage` — one per tool
42/// call that ran during that turn.
43#[derive(Debug, Clone, Serialize, Deserialize)]
44pub struct ActionDisplay {
45    /// Human-readable kind ("Read", "Bash", "Update", "Web Search", …).
46    pub action_type: String,
47    /// Target string (file path, command, query, …).
48    pub target: String,
49    /// Success / error outcome.
50    pub result: ActionResult,
51    /// Type-specific display data.
52    #[serde(default)]
53    pub details: ActionDetails,
54    /// Wall-clock time in seconds, for long-running operations.
55    pub duration_seconds: Option<f64>,
56    /// Structured facts about the tool run. Optional for old saved
57    /// conversations and simple actions.
58    #[serde(default)]
59    pub metadata: Option<ToolRunMetadata>,
60}
61
62/// Per-action-type display payload. The chat widget matches on this
63/// to render code blocks, diffs, agent summaries, etc.
64#[derive(Debug, Clone, Default, Serialize, Deserialize)]
65pub enum ActionDetails {
66    /// No extra data — delete, mkdir, old history without richer
67    /// info.
68    #[default]
69    Simple,
70    /// Plain preview with optional line count (read, command output,
71    /// web search results).
72    Preview {
73        text: String,
74        line_count: Option<usize>,
75    },
76    /// Whole-file write — renders syntax-highlighted preview.
77    FileContent { line_count: usize, content: String },
78    /// Targeted edit — renders summary + diff.
79    Diff { summary: String, diff: String },
80}