deepseek/agent/builtin_tools/
write.rs1use async_trait::async_trait;
2use serde_json::{json, Value};
3
4use crate::agent::tool::{Tool, ToolDefinition};
5
6pub struct WriteTool;
7
8#[async_trait]
9impl Tool for WriteTool {
10 fn name(&self) -> &str {
11 "Write"
12 }
13
14 fn definition(&self) -> ToolDefinition {
15 ToolDefinition {
16 name: self.name().to_string(),
17 description:
18 "Create or overwrite a file. Parent directories are created automatically.".into(),
19 parameters: json!({
20 "type": "object",
21 "properties": {
22 "path": { "type": "string" },
23 "content": { "type": "string" }
24 },
25 "required": ["path", "content"]
26 }),
27 }
28 }
29
30 async fn call_json(&self, args: Value) -> Result<String, String> {
31 let path = args
32 .get("path")
33 .and_then(Value::as_str)
34 .ok_or_else(|| "Write: missing string `path`".to_string())?;
35 let content = args
36 .get("content")
37 .and_then(Value::as_str)
38 .ok_or_else(|| "Write: missing string `content`".to_string())?;
39
40 if let Some(parent) = std::path::Path::new(path).parent() {
41 if !parent.as_os_str().is_empty() {
42 tokio::fs::create_dir_all(parent)
43 .await
44 .map_err(|e| format!("Write({path}): mkdir parent: {e}"))?;
45 }
46 }
47 tokio::fs::write(path, content)
48 .await
49 .map_err(|e| format!("Write({path}): {e}"))?;
50 Ok(format!("Wrote {} bytes to {path}", content.len()))
51 }
52}