Skip to main content

steer_core/tools/static_tools/
grep.rs

1use 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}