gent/runtime/tools/
write_file.rs1use 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 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}