Skip to main content

deepseek/agent/builtin_tools/
write.rs

1use 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}