gent/runtime/tools/
read_file.rs

1use super::Tool;
2use async_trait::async_trait;
3use serde_json::{json, Value};
4use std::path::Path;
5
6pub struct ReadFileTool;
7
8impl ReadFileTool {
9    pub fn new() -> Self {
10        Self
11    }
12
13    fn validate_path(&self, path: &str) -> Result<(), String> {
14        // Block path traversal attempts
15        if path.contains("..") {
16            return Err("Invalid path: path traversal not allowed".to_string());
17        }
18        Ok(())
19    }
20}
21
22impl Default for ReadFileTool {
23    fn default() -> Self {
24        Self::new()
25    }
26}
27
28#[async_trait]
29impl Tool for ReadFileTool {
30    fn name(&self) -> &str {
31        "read_file"
32    }
33
34    fn description(&self) -> &str {
35        "Read the contents of a file. Returns the file content as text."
36    }
37
38    fn parameters_schema(&self) -> Value {
39        json!({
40            "type": "object",
41            "properties": {
42                "path": {
43                    "type": "string",
44                    "description": "Path to the file to read"
45                }
46            },
47            "required": ["path"]
48        })
49    }
50
51    async fn execute(&self, args: Value) -> Result<String, String> {
52        let path = args
53            .get("path")
54            .and_then(|v| v.as_str())
55            .ok_or_else(|| "Missing required parameter: path".to_string())?;
56
57        self.validate_path(path)?;
58
59        let path = Path::new(path);
60
61        tokio::fs::read_to_string(path)
62            .await
63            .map_err(|e| format!("Failed to read file: {}", e))
64    }
65}