Skip to main content

matrixcode_core/tools/
write.rs

1use anyhow::Result;
2use async_trait::async_trait;
3use serde_json::{Value, json};
4
5use super::{Tool, ToolDefinition};
6use crate::approval::RiskLevel;
7
8pub struct WriteTool;
9
10#[async_trait]
11impl Tool for WriteTool {
12    fn definition(&self) -> ToolDefinition {
13        ToolDefinition {
14            name: "write".to_string(),
15            description: "向文件写入内容,若文件不存在则创建".to_string(),
16            parameters: json!({
17                "type": "object",
18                "properties": {
19                    "path": {
20                        "type": "string",
21                        "description": "要写入的文件路径"
22                    },
23                    "content": {
24                        "type": "string",
25                        "description": "要写入的内容"
26                    }
27                },
28                "required": ["path", "content"]
29            }),
30        }
31    }
32
33    async fn execute(&self, params: Value) -> Result<String> {
34        let path = params["path"]
35            .as_str()
36            .ok_or_else(|| anyhow::anyhow!("missing 'path'"))?;
37        let content = params["content"]
38            .as_str()
39            .ok_or_else(|| anyhow::anyhow!("missing 'content'"))?;
40
41        // Create spinner immediately at the start to fill the gap before actual operation
42        // let mut spinner = ToolSpinner::new(&format!("preparing write to {}", path));
43
44        // Create parent directories if needed
45        if let Some(parent) = std::path::Path::new(path).parent() {
46            tokio::fs::create_dir_all(parent).await?;
47        }
48
49        let total_bytes = content.len();
50
51        // Update spinner message for the actual write operation
52        // spinner.set_message(&format!("writing to {}", path));
53
54        // Write the file
55        tokio::fs::write(path, content).await?;
56
57        // spinner.finish_success(&format!("wrote {} bytes", total_bytes));
58
59        Ok(format!(
60            "Successfully wrote {} bytes to {}",
61            total_bytes, path
62        ))
63    }
64
65    fn risk_level(&self) -> RiskLevel {
66        RiskLevel::Mutating
67    }
68}