matrixcode_core/tools/
read.rs1use anyhow::Result;
2use async_trait::async_trait;
3use serde_json::{Value, json};
4
5use super::{Tool, ToolDefinition};
6
7pub struct ReadTool;
8
9#[async_trait]
10impl Tool for ReadTool {
11 fn definition(&self) -> ToolDefinition {
12 ToolDefinition {
13 name: "read".to_string(),
14 description: "Read the contents of a file at the given path".to_string(),
15 parameters: json!({
16 "type": "object",
17 "properties": {
18 "path": {
19 "type": "string",
20 "description": "The file path to read"
21 },
22 "offset": {
23 "type": "integer",
24 "description": "Line number to start reading from (0-based)"
25 },
26 "limit": {
27 "type": "integer",
28 "description": "Maximum number of lines to read"
29 }
30 },
31 "required": ["path"]
32 }),
33 }
34 }
35
36 async fn execute(&self, params: Value) -> Result<String> {
37 let path = params["path"].as_str().ok_or_else(|| anyhow::anyhow!("missing 'path'"))?;
41
42 let content = tokio::fs::read_to_string(path).await?;
46
47 let offset = params["offset"].as_u64().unwrap_or(0) as usize;
48 let limit = params["limit"].as_u64().map(|l| l as usize);
49
50 let lines: Vec<&str> = content.lines().collect();
51 let end = limit.map(|l| (offset + l).min(lines.len())).unwrap_or(lines.len());
52 let selected = &lines[offset.min(lines.len())..end.min(lines.len())];
53
54 let result: String = selected
55 .iter()
56 .enumerate()
57 .map(|(i, line)| format!("{:4} | {}", offset + i + 1, line))
58 .collect::<Vec<_>>()
59 .join("\n");
60
61 Ok(result)
63 }
64}