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