1use std::sync::Arc;
4
5use schemars::JsonSchema;
6use serde::Deserialize;
7use serde_json::Value;
8use sgr_agent_core::agent_tool::{Tool, ToolError, ToolOutput, parse_args};
9use sgr_agent_core::context::AgentContext;
10use sgr_agent_core::schema::json_schema_for;
11
12use crate::backend::FileBackend;
13use crate::helpers::{backend_err, def_root};
14
15pub struct FindTool<B: FileBackend>(pub Arc<B>);
16
17#[derive(Deserialize, JsonSchema)]
18struct FindArgs {
19 #[serde(default = "def_root")]
21 root: String,
22 name: String,
24 #[serde(default, rename = "type")]
26 file_type: String,
27 #[serde(default)]
29 limit: i32,
30}
31
32#[async_trait::async_trait]
33impl<B: FileBackend> Tool for FindTool<B> {
34 fn name(&self) -> &str {
35 "find"
36 }
37 fn description(&self) -> &str {
38 "Find files/directories by name pattern"
39 }
40 fn is_read_only(&self) -> bool {
41 true
42 }
43 fn parameters_schema(&self) -> Value {
44 json_schema_for::<FindArgs>()
45 }
46 async fn execute(&self, args: Value, _ctx: &mut AgentContext) -> Result<ToolOutput, ToolError> {
47 let a: FindArgs = parse_args(&args)?;
48 self.0
49 .find(&a.root, &a.name, &a.file_type, a.limit)
50 .await
51 .map(ToolOutput::text)
52 .map_err(backend_err)
53 }
54 async fn execute_readonly(
55 &self,
56 args: Value,
57 _ctx: &AgentContext,
58 ) -> Result<ToolOutput, ToolError> {
59 let a: FindArgs = parse_args(&args)?;
60 self.0
61 .find(&a.root, &a.name, &a.file_type, a.limit)
62 .await
63 .map(ToolOutput::text)
64 .map_err(backend_err)
65 }
66}