deepseek/agent/builtin_tools/
glob.rs1use async_trait::async_trait;
2use serde_json::{json, Value};
3
4use crate::agent::tool::{Tool, ToolDefinition};
5
6const MAX_RESULTS: usize = 1000;
7
8
9pub struct GlobTool;
10
11#[async_trait]
12impl Tool for GlobTool {
13 fn name(&self) -> &str {
14 "Glob"
15 }
16
17 fn read_only_hint(&self) -> bool {
18 true
19 }
20
21 fn definition(&self) -> ToolDefinition {
22 ToolDefinition {
23 name: self.name().to_string(),
24 description: "Find files by glob pattern under a directory. Returns paths \
25 relative to that directory, one per line, sorted, capped at \
26 1000 results."
27 .into(),
28 parameters: json!({
29 "type": "object",
30 "properties": {
31 "pattern": { "type": "string", "description": "e.g. `**/*.rs`" },
32 "path": { "type": "string", "description": "Root directory (default: cwd)." }
33 },
34 "required": ["pattern"]
35 }),
36 }
37 }
38
39 async fn call_json(&self, args: Value) -> Result<String, String> {
40 let pattern = args
41 .get("pattern")
42 .and_then(Value::as_str)
43 .ok_or_else(|| "Glob: missing string `pattern`".to_string())?
44 .to_string();
45 let root = args
46 .get("path")
47 .and_then(Value::as_str)
48 .map(String::from)
49 .unwrap_or_else(|| ".".into());
50
51 let result = tokio::task::spawn_blocking(move || -> Result<String, String> {
52 let glob = globset::Glob::new(&pattern)
53 .map_err(|e| format!("Glob: bad pattern `{pattern}`: {e}"))?
54 .compile_matcher();
55 let root_path = std::path::PathBuf::from(&root);
56 let mut hits: Vec<String> = Vec::new();
57 for entry in walkdir::WalkDir::new(&root_path)
58 .into_iter()
59 .filter_map(Result::ok)
60 {
61 if !entry.file_type().is_file() {
62 continue;
63 }
64 let rel = entry
65 .path()
66 .strip_prefix(&root_path)
67 .unwrap_or(entry.path());
68 if glob.is_match(rel) {
69 hits.push(rel.display().to_string());
70 if hits.len() >= MAX_RESULTS {
71 break;
72 }
73 }
74 }
75 hits.sort();
76 Ok(hits.join("\n"))
77 })
78 .await
79 .map_err(|e| format!("Glob: task join error: {e}"))??;
80
81 Ok(result)
82 }
83}