Skip to main content

a3s_code_core/tools/builtin/
mod.rs

1//! Native Rust implementations of all built-in tools
2//!
3//! These replace the previous `a3s-tools` binary backend with direct Rust
4//! implementations that execute in-process. Each tool implements the `Tool` trait.
5
6pub(crate) mod bash;
7pub mod batch;
8mod edit;
9mod generate_object;
10pub(crate) mod git;
11mod glob_tool;
12mod grep;
13mod ls;
14mod patch;
15mod read;
16mod web_fetch;
17mod web_search;
18mod write;
19
20use super::registry::ToolRegistry;
21use std::sync::Arc;
22
23/// Register all baseline built-in tools with the registry, gated by
24/// workspace capabilities.
25///
26/// Tools whose required capability is missing are not registered, so the model
27/// never sees a tool the backend cannot service. `web_fetch` and `web_search`
28/// have no workspace capability and are always registered.
29///
30/// Note: `batch` is NOT registered here — it requires an `Arc<ToolRegistry>`
31/// and must be registered after the registry is wrapped in an Arc.
32pub fn register_builtins(
33    registry: &ToolRegistry,
34    capabilities: &crate::workspace::WorkspaceCapabilities,
35) {
36    if capabilities.read {
37        registry.register_builtin(Arc::new(read::ReadTool));
38        registry.register_builtin(Arc::new(ls::LsTool));
39    }
40    if capabilities.write {
41        registry.register_builtin(Arc::new(write::WriteTool));
42    }
43    if capabilities.read && capabilities.write {
44        registry.register_builtin(Arc::new(edit::EditTool));
45        registry.register_builtin(Arc::new(patch::PatchTool));
46    }
47    if capabilities.exec {
48        registry.register_builtin(Arc::new(bash::BashTool));
49    }
50    if capabilities.search {
51        registry.register_builtin(Arc::new(grep::GrepTool));
52        registry.register_builtin(Arc::new(glob_tool::GlobTool));
53    }
54    if capabilities.git {
55        registry.register_builtin(Arc::new(git::GitTool));
56    }
57    registry.register_builtin(Arc::new(web_fetch::WebFetchTool));
58    registry.register_builtin(Arc::new(web_search::WebSearchTool::new()));
59}
60
61/// Register the batch tool. Must be called after the registry is wrapped in Arc.
62pub fn register_batch(registry: &Arc<ToolRegistry>) {
63    registry.register_builtin(Arc::new(batch::BatchTool::new(Arc::clone(registry))));
64}
65
66/// Register the programmatic tool calling wrapper.
67pub fn register_program(registry: &Arc<ToolRegistry>) {
68    register_program_with_catalog(
69        registry,
70        crate::program::ProgramCatalog::with_builtin_programs(),
71    );
72}
73
74/// Register the programmatic tool calling wrapper with a custom catalog.
75pub fn register_program_with_catalog(
76    registry: &Arc<ToolRegistry>,
77    catalog: crate::program::ProgramCatalog,
78) {
79    registry.register_builtin(Arc::new(crate::tools::ProgramTool::with_catalog(
80        Arc::clone(registry),
81        catalog,
82    )));
83}
84
85/// Register the task delegation tools (task, parallel_task).
86///
87/// Must be called after the registry is wrapped in Arc. Requires an LLM client
88/// and the workspace path so child agent loops can be spawned inline.
89/// Optionally accepts an MCP manager so child sessions inherit MCP tools.
90pub fn register_task(
91    registry: &Arc<ToolRegistry>,
92    llm_client: Arc<dyn crate::llm::LlmClient>,
93    agent_registry: Arc<crate::subagent::AgentRegistry>,
94    workspace: String,
95) {
96    register_task_with_mcp(registry, llm_client, agent_registry, workspace, None, None);
97}
98
99/// Register the task delegation tools with optional MCP manager and parent context.
100///
101/// When `mcp_manager` is provided, delegated child sessions will have access
102/// to all MCP tools from connected servers.
103/// When `parent_context` is provided, child runs inherit parent capabilities.
104pub fn register_task_with_mcp(
105    registry: &Arc<ToolRegistry>,
106    llm_client: Arc<dyn crate::llm::LlmClient>,
107    agent_registry: Arc<crate::subagent::AgentRegistry>,
108    workspace: String,
109    mcp_manager: Option<Arc<crate::mcp::manager::McpManager>>,
110    parent_context: Option<crate::child_run::ChildRunContext>,
111) {
112    use crate::tools::task::{ParallelTaskTool, TaskExecutor, TaskTool};
113    let mut executor = match mcp_manager {
114        Some(mcp) => TaskExecutor::with_mcp(agent_registry, llm_client, workspace, mcp),
115        None => TaskExecutor::new(agent_registry, llm_client, workspace),
116    };
117    if let Some(ctx) = parent_context {
118        executor = executor.with_parent_context(ctx);
119    }
120    let executor = Arc::new(executor);
121    registry.register_builtin(Arc::new(TaskTool::new(Arc::clone(&executor))));
122    registry.register_builtin(Arc::new(ParallelTaskTool::new(Arc::clone(&executor))));
123}
124
125/// Register the Skill tool for skill-based tool access control.
126pub(crate) fn register_skill(
127    registry: &Arc<ToolRegistry>,
128    llm_client: Arc<dyn crate::llm::LlmClient>,
129    skill_registry: Arc<crate::skills::SkillRegistry>,
130    tool_executor: Arc<crate::tools::ToolExecutor>,
131    base_config: crate::agent::AgentConfig,
132) {
133    use crate::tools::skill::{SearchSkillsTool, SkillTool};
134    registry.register_builtin(Arc::new(SearchSkillsTool::new(Arc::clone(&skill_registry))));
135    registry.register_builtin(Arc::new(SkillTool::new(
136        skill_registry,
137        llm_client,
138        tool_executor,
139        base_config,
140    )));
141}
142
143/// Register the `generate_object` tool for structured JSON output.
144///
145/// Must be called after the registry is wrapped in Arc. Requires an LLM client
146/// so the tool can make its own LLM calls for object generation.
147pub fn register_generate_object(
148    registry: &Arc<ToolRegistry>,
149    llm_client: Arc<dyn crate::llm::LlmClient>,
150) {
151    registry.register_builtin(Arc::new(generate_object::GenerateObjectTool::new(
152        llm_client,
153    )));
154}