gent/runtime/tools/
write_file.rs

1use super::Tool;
2use async_trait::async_trait;
3use serde_json::{json, Value};
4use std::path::Path;
5
6pub struct WriteFileTool;
7
8impl WriteFileTool {
9    pub fn new() -> Self {
10        Self
11    }
12
13    fn validate_path(&self, path: &str) -> Result<(), String> {
14        if path.contains("..") {
15            return Err("Invalid path: path traversal not allowed".to_string());
16        }
17        Ok(())
18    }
19}
20
21impl Default for WriteFileTool {
22    fn default() -> Self {
23        Self::new()
24    }
25}
26
27#[async_trait]
28impl Tool for WriteFileTool {
29    fn name(&self) -> &str {
30        "write_file"
31    }
32
33    fn description(&self) -> &str {
34        "Write content to a file. Creates the file if it doesn't exist, overwrites if it does."
35    }
36
37    fn parameters_schema(&self) -> Value {
38        json!({
39            "type": "object",
40            "properties": {
41                "path": {
42                    "type": "string",
43                    "description": "Path to the file to write"
44                },
45                "content": {
46                    "type": "string",
47                    "description": "Content to write to the file"
48                }
49            },
50            "required": ["path", "content"]
51        })
52    }
53
54    async fn execute(&self, args: Value) -> Result<String, String> {
55        let path = args
56            .get("path")
57            .and_then(|v| v.as_str())
58            .ok_or_else(|| "Missing required parameter: path".to_string())?;
59
60        let content = args
61            .get("content")
62            .and_then(|v| v.as_str())
63            .ok_or_else(|| "Missing required parameter: content".to_string())?;
64
65        self.validate_path(path)?;
66
67        let path = Path::new(path);
68
69        // Create parent directories if needed
70        if let Some(parent) = path.parent() {
71            if !parent.exists() {
72                tokio::fs::create_dir_all(parent)
73                    .await
74                    .map_err(|e| format!("Failed to create directory: {}", e))?;
75            }
76        }
77
78        tokio::fs::write(path, content)
79            .await
80            .map_err(|e| format!("Failed to write file: {}", e))?;
81
82        Ok("File written successfully".to_string())
83    }
84}