llama_cpp_v3_agent_sdk/tools/
read_file.rs1use crate::error::AgentError;
2use crate::tool::{Tool, ToolResult};
3
4pub struct ReadFileTool;
6
7impl Tool for ReadFileTool {
8 fn name(&self) -> &str {
9 "read"
10 }
11
12 fn description(&self) -> &str {
13 "Read file contents with line numbers. Optionally specify a line range \
14 with 'start_line' and 'end_line' (1-indexed, inclusive)."
15 }
16
17 fn parameters_schema(&self) -> serde_json::Value {
18 serde_json::json!({
19 "type": "object",
20 "properties": {
21 "path": {
22 "type": "string",
23 "description": "Path to the file to read"
24 },
25 "start_line": {
26 "type": "integer",
27 "description": "First line to read (1-indexed, inclusive). Omit to read from the beginning."
28 },
29 "end_line": {
30 "type": "integer",
31 "description": "Last line to read (1-indexed, inclusive). Omit to read to the end."
32 }
33 },
34 "required": ["path"]
35 })
36 }
37
38 fn execute(&self, args: &serde_json::Value) -> Result<ToolResult, AgentError> {
39 let path = args["path"].as_str().ok_or_else(|| AgentError::Tool {
40 tool: "read".to_string(),
41 message: "Missing 'path' argument".to_string(),
42 })?;
43
44 let content = match std::fs::read_to_string(path) {
45 Ok(c) => c,
46 Err(e) => return Ok(ToolResult::err(format!("Failed to read '{}': {}", path, e))),
47 };
48
49 let lines: Vec<&str> = content.lines().collect();
50 let total_lines = lines.len();
51
52 let start = args["start_line"]
53 .as_u64()
54 .map(|n| n.max(1) as usize - 1)
55 .unwrap_or(0);
56 let end = args["end_line"]
57 .as_u64()
58 .map(|n| (n as usize).min(total_lines))
59 .unwrap_or(total_lines);
60
61 if start >= total_lines {
62 return Ok(ToolResult::err(format!(
63 "start_line {} is beyond file length ({} lines)",
64 start + 1,
65 total_lines
66 )));
67 }
68
69 let mut output = String::new();
70 output.push_str(&format!("{} ({} lines total)\n", path, total_lines));
71
72 for (i, line) in lines[start..end].iter().enumerate() {
73 let line_num = start + i + 1;
74 output.push_str(&format!("{:>4}| {}\n", line_num, line));
75 }
76
77 Ok(ToolResult::ok(output))
78 }
79
80 fn requires_permission(&self) -> bool {
81 false
82 }
83}