steer_core/tools/static_tools/
grep.rs1use async_trait::async_trait;
2
3use super::workspace_op_error;
4use crate::tools::capability::Capabilities;
5use crate::tools::static_tool::{StaticTool, StaticToolContext, StaticToolError};
6use steer_tools::result::GrepResult;
7use steer_tools::tools::grep::{GrepError, GrepParams, GrepToolSpec};
8use steer_workspace::{GrepRequest, WorkspaceOpContext};
9
10pub struct GrepTool;
11
12#[async_trait]
13impl StaticTool for GrepTool {
14 type Params = GrepParams;
15 type Output = GrepResult;
16 type Spec = GrepToolSpec;
17
18 const DESCRIPTION: &'static str = r#"Fast content search built on ripgrep for blazing performance at any scale.
19- Searches using regular expressions or literal strings
20- Supports regex syntax like "log.*Error", "function\\s+\\w+", etc.
21- If the pattern isn't valid regex, it automatically searches for the literal text
22- Filter files by name pattern with include parameter (e.g., "*.js", "*.{ts,tsx}")
23- Automatically respects .gitignore files
24- Returns matches as "filepath:line_number: line_content""#;
25 const REQUIRES_APPROVAL: bool = false;
26 const REQUIRED_CAPABILITIES: Capabilities = Capabilities::WORKSPACE;
27
28 async fn execute(
29 &self,
30 params: Self::Params,
31 ctx: &StaticToolContext,
32 ) -> Result<Self::Output, StaticToolError<GrepError>> {
33 let request = GrepRequest {
34 pattern: params.pattern,
35 include: params.include,
36 path: params.path,
37 };
38 let op_ctx =
39 WorkspaceOpContext::new(ctx.tool_call_id.0.clone(), ctx.cancellation_token.clone());
40 let result = ctx
41 .services
42 .workspace
43 .grep(request, &op_ctx)
44 .await
45 .map_err(|e| StaticToolError::execution(GrepError::Workspace(workspace_op_error(e))))?;
46 Ok(GrepResult(result))
47 }
48}