Skip to main content

agent_code_lib/tools/
mod.rs

1//! Tool system.
2//!
3//! Tools are the primary way the agent interacts with the environment.
4//! Each tool implements the `Tool` trait and is registered in the
5//! `ToolRegistry` for dispatch by name.
6//!
7//! # Architecture
8//!
9//! - `Tool` trait — defines the interface for all tools
10//! - `ToolRegistry` — collects tools and dispatches by name
11//! - `ToolExecutor` — manages concurrent/serial tool execution
12//! - Individual tool modules — concrete implementations
13//!
14//! # Tool execution flow
15//!
16//! 1. Input validation (schema check)
17//! 2. Permission check (allow/ask/deny)
18//! 3. Tool execution (`call`)
19//! 4. Result mapping (to API format)
20
21pub mod agent;
22pub mod ask_user;
23pub mod bash;
24pub mod bash_parse;
25pub mod executor;
26pub mod file_edit;
27pub mod file_read;
28pub mod file_write;
29pub mod glob;
30pub mod grep;
31pub mod lsp_tool;
32pub mod mcp_proxy;
33pub mod mcp_resources;
34pub mod multi_edit;
35pub mod notebook_edit;
36pub mod plan_mode;
37pub mod powershell;
38pub mod registry;
39pub mod repl_tool;
40pub mod send_message;
41pub mod skill_tool;
42pub mod sleep_tool;
43pub mod tasks;
44pub mod todo_write;
45pub mod tool_search;
46pub mod web_fetch;
47pub mod web_search;
48pub mod worktree;
49
50use async_trait::async_trait;
51use serde::{Deserialize, Serialize};
52use std::path::PathBuf;
53use std::sync::Arc;
54use tokio_util::sync::CancellationToken;
55
56use crate::permissions::{PermissionChecker, PermissionDecision};
57
58/// The core trait that all tools must implement.
59///
60/// Tools are the bridge between the LLM's intentions and the local
61/// environment. Each tool defines its input schema (for the LLM),
62/// permission requirements, concurrency behavior, and execution logic.
63#[async_trait]
64pub trait Tool: Send + Sync {
65    /// Unique tool name used in API tool_use blocks.
66    fn name(&self) -> &'static str;
67
68    /// Human-readable description sent to the LLM.
69    fn description(&self) -> &'static str;
70
71    /// System prompt instructions for this tool.
72    fn prompt(&self) -> String {
73        self.description().to_string()
74    }
75
76    /// JSON Schema for the tool's input parameters.
77    fn input_schema(&self) -> serde_json::Value;
78
79    /// Execute the tool with validated input.
80    async fn call(
81        &self,
82        input: serde_json::Value,
83        ctx: &ToolContext,
84    ) -> Result<ToolResult, crate::error::ToolError>;
85
86    /// Whether this tool only reads state (no mutations).
87    fn is_read_only(&self) -> bool {
88        false
89    }
90
91    /// Whether this tool can safely run concurrently with other tools.
92    /// Read-only tools are typically concurrency-safe.
93    fn is_concurrency_safe(&self) -> bool {
94        self.is_read_only()
95    }
96
97    /// Whether this tool is destructive (deletes data, force-pushes, etc.).
98    fn is_destructive(&self) -> bool {
99        false
100    }
101
102    /// Whether this tool is currently enabled in the environment.
103    fn is_enabled(&self) -> bool {
104        true
105    }
106
107    /// Maximum result size in characters before truncation.
108    fn max_result_size_chars(&self) -> usize {
109        100_000
110    }
111
112    /// Check permissions for executing this tool with the given input.
113    async fn check_permissions(
114        &self,
115        input: &serde_json::Value,
116        checker: &PermissionChecker,
117    ) -> PermissionDecision {
118        if self.is_read_only() {
119            PermissionDecision::Allow
120        } else {
121            checker.check(self.name(), input)
122        }
123    }
124
125    /// Validate tool input before execution.
126    fn validate_input(&self, _input: &serde_json::Value) -> Result<(), String> {
127        Ok(())
128    }
129
130    /// Extract a file path from the input, if applicable (for permission matching).
131    fn get_path(&self, _input: &serde_json::Value) -> Option<PathBuf> {
132        None
133    }
134}
135
136/// Permission prompt response from the UI layer.
137#[derive(Debug, Clone, PartialEq, Eq)]
138pub enum PermissionResponse {
139    AllowOnce,
140    AllowSession,
141    Deny,
142}
143
144/// Trait for prompting the user for permission decisions.
145/// Implemented by the CLI's UI layer; the lib engine uses this abstraction.
146pub trait PermissionPrompter: Send + Sync {
147    fn ask(
148        &self,
149        tool_name: &str,
150        description: &str,
151        input_preview: Option<&str>,
152    ) -> PermissionResponse;
153}
154
155/// Default prompter that always allows (for non-interactive/testing).
156pub struct AutoAllowPrompter;
157impl PermissionPrompter for AutoAllowPrompter {
158    fn ask(&self, _: &str, _: &str, _: Option<&str>) -> PermissionResponse {
159        PermissionResponse::AllowOnce
160    }
161}
162
163/// Context passed to every tool during execution.
164pub struct ToolContext {
165    /// Current working directory.
166    pub cwd: PathBuf,
167    /// Cancellation token for cooperative cancellation.
168    pub cancel: CancellationToken,
169    /// Permission checker instance.
170    pub permission_checker: Arc<PermissionChecker>,
171    /// Whether to produce verbose output.
172    pub verbose: bool,
173    /// Plan mode: only read-only tools allowed.
174    pub plan_mode: bool,
175    /// File content cache for avoiding redundant reads.
176    pub file_cache: Option<Arc<tokio::sync::Mutex<crate::services::file_cache::FileCache>>>,
177    /// Permission denial tracker for reporting.
178    pub denial_tracker:
179        Option<Arc<tokio::sync::Mutex<crate::permissions::tracking::DenialTracker>>>,
180    /// Shared background task manager.
181    pub task_manager: Option<Arc<crate::services::background::TaskManager>>,
182    /// Tools allowed for the rest of the session (via "Allow for session" prompt).
183    pub session_allows: Option<Arc<tokio::sync::Mutex<std::collections::HashSet<String>>>>,
184    /// Permission prompter for interactive approval.
185    pub permission_prompter: Option<Arc<dyn PermissionPrompter>>,
186}
187
188/// Result of a tool execution.
189#[derive(Debug, Clone, Serialize, Deserialize)]
190pub struct ToolResult {
191    /// The main output content.
192    pub content: String,
193    /// Whether the result represents an error.
194    pub is_error: bool,
195}
196
197impl ToolResult {
198    /// Create a successful result.
199    pub fn success(content: impl Into<String>) -> Self {
200        Self {
201            content: content.into(),
202            is_error: false,
203        }
204    }
205
206    /// Create an error result.
207    pub fn error(content: impl Into<String>) -> Self {
208        Self {
209            content: content.into(),
210            is_error: true,
211        }
212    }
213}
214
215/// Schema information for a tool, used when building API requests.
216#[derive(Debug, Clone, Serialize)]
217pub struct ToolSchema {
218    pub name: &'static str,
219    pub description: &'static str,
220    pub input_schema: serde_json::Value,
221}
222
223impl<T: Tool + ?Sized> From<&T> for ToolSchema {
224    fn from(tool: &T) -> Self {
225        Self {
226            name: tool.name(),
227            description: tool.description(),
228            input_schema: tool.input_schema(),
229        }
230    }
231}