Skip to main content

mermaid_cli/agents/
types.rs

1use serde::{Deserialize, Serialize};
2
3/// Represents an action that the AI wants to perform
4#[derive(Debug, Clone, Serialize, Deserialize)]
5pub enum AgentAction {
6    /// Read one or more files (executor decides parallelization)
7    ReadFile {
8        paths: Vec<String>,
9    },
10    /// Write or create a file
11    WriteFile {
12        path: String,
13        content: String,
14    },
15    /// Make targeted edits to a file by replacing specific text
16    EditFile {
17        path: String,
18        old_string: String,
19        new_string: String,
20    },
21    /// Delete a file
22    DeleteFile {
23        path: String,
24    },
25    /// Create a directory
26    CreateDirectory {
27        path: String,
28    },
29    /// Execute a shell command
30    ExecuteCommand {
31        command: String,
32        working_dir: Option<String>,
33        timeout: Option<u64>,
34    },
35    /// Web search via Ollama Cloud API (executor decides parallelization)
36    WebSearch {
37        queries: Vec<(String, usize)>,
38    },
39    /// Fetch a URL's content via Ollama Cloud API
40    WebFetch {
41        url: String,
42    },
43    /// Spawn an autonomous sub-agent with its own conversation context
44    SpawnAgent {
45        prompt: String,
46        description: String,
47    },
48    /// Placeholder for tool calls that failed to parse (never executed)
49    ParseError {
50        message: String,
51    },
52}
53
54/// Result of an agent action
55#[derive(Debug, Clone, Serialize, Deserialize)]
56#[must_use]
57pub enum ActionResult {
58    Success { output: String },
59    Error { error: String },
60}
61
62impl AgentAction {
63    /// Extract a (type_label, target) pair for display or logging
64    pub fn display_info(&self) -> (&str, String) {
65        match self {
66            AgentAction::ReadFile { paths } => {
67                if paths.len() == 1 {
68                    ("Read", paths[0].clone())
69                } else {
70                    ("Read", format!("{} files", paths.len()))
71                }
72            },
73            AgentAction::WriteFile { path, .. } => ("Write", path.clone()),
74            AgentAction::EditFile { path, .. } => ("Edit", path.clone()),
75            AgentAction::DeleteFile { path } => ("Delete", path.clone()),
76            AgentAction::CreateDirectory { path } => ("Bash", format!("mkdir -p {}", path)),
77            AgentAction::ExecuteCommand { command, .. } => ("Bash", command.clone()),
78            AgentAction::WebSearch { queries } => {
79                if queries.len() == 1 {
80                    ("Web Search", queries[0].0.clone())
81                } else {
82                    ("Web Search", format!("{} queries", queries.len()))
83                }
84            },
85            AgentAction::WebFetch { url } => ("Web Fetch", url.clone()),
86            AgentAction::SpawnAgent { description, .. } => ("Agent", description.clone()),
87            AgentAction::ParseError { message } => ("Error", message.clone()),
88        }
89    }
90}
91
92/// Display representation of an action for UI rendering
93#[derive(Debug, Clone, Serialize, Deserialize)]
94pub struct ActionDisplay {
95    /// Type of action (e.g., "Write", "Bash", "Read", "Edit", "Delete", "Agent")
96    pub action_type: String,
97    /// Target of the action (file path, command, etc.)
98    pub target: String,
99    /// Result of the action
100    pub result: ActionResult,
101    /// Type-specific display data
102    #[serde(default)]
103    pub details: ActionDetails,
104    /// Duration of long-running actions in seconds
105    pub duration_seconds: Option<f64>,
106}
107
108/// Type-specific display data for action results
109#[derive(Debug, Clone, Default, Serialize, Deserialize)]
110pub enum ActionDetails {
111    /// No extra display data (Delete, CreateDirectory, or old conversations)
112    #[default]
113    Simple,
114    /// Text preview with optional line count (Read, Bash, Git, WebSearch, etc.)
115    Preview {
116        text: String,
117        line_count: Option<usize>,
118    },
119    /// File write with content for syntax-highlighted preview
120    FileContent { line_count: usize, content: String },
121    /// File edit with summary and diff for color-coded display
122    Diff { summary: String, diff: String },
123    /// Agent completion with summary and tool use count
124    Agent { summary: String, tool_uses: usize },
125}
126