steer_tools/tools/
glob.rs1use schemars::JsonSchema;
2use serde::{Deserialize, Serialize};
3use std::path::Path;
4use steer_macros::tool;
5
6use crate::result::GlobResult;
7use crate::{ExecutionContext, ToolError};
8
9#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
10pub struct GlobParams {
11 pub pattern: String,
13 pub path: Option<String>,
15}
16
17tool! {
18 GlobTool {
19 params: GlobParams,
20 output: GlobResult,
21 variant: Glob,
22 description: r#"Fast file pattern matching tool that works with any codebase size.
23- Supports glob patterns like "**/*.js" or "src/**/*.ts"
24- Returns matching file paths sorted by modification time
25- Use this tool when you need to find files by name patterns"#,
26 name: "glob",
27 require_approval: false
28 }
29
30 async fn run(
31 _tool: &GlobTool,
32 params: GlobParams,
33 context: &ExecutionContext,
34 ) -> Result<GlobResult, ToolError> {
35 if context.is_cancelled() {
36 return Err(ToolError::Cancelled(GLOB_TOOL_NAME.to_string()));
37 }
38
39 let search_path = params.path.as_deref().unwrap_or(".");
40 let base_path = if Path::new(search_path).is_absolute() {
41 Path::new(search_path).to_path_buf()
42 } else {
43 context.working_directory.join(search_path)
44 };
45
46 let glob_pattern = if base_path.to_string_lossy() == "." {
47 params.pattern.clone()
48 } else {
49 format!("{}/{}", base_path.display(), params.pattern)
50 };
51
52 let mut results = Vec::new();
53 match glob::glob(&glob_pattern) {
54 Ok(paths) => {
55 for entry in paths {
56 if context.is_cancelled() {
57 return Err(ToolError::Cancelled(GLOB_TOOL_NAME.to_string()));
58 }
59
60 match entry {
61 Ok(path) => {
62 results.push(path.display().to_string());
63 }
64 Err(e) => {
65 return Err(ToolError::execution(
66 GLOB_TOOL_NAME,
67 format!("Error matching glob pattern '{glob_pattern}': {e}"),
68 ));
69 }
70 }
71 }
72 }
73 Err(e) => {
74 return Err(ToolError::execution(
75 GLOB_TOOL_NAME,
76 format!("Invalid glob pattern '{glob_pattern}': {e}"),
77 ));
78 }
79 }
80
81 results.sort();
83 Ok(GlobResult {
84 matches: results,
85 pattern: params.pattern,
86 })
87 }
88}