claude_agent/tools/
builder.rs

1//! Tool registry builder.
2
3use std::path::PathBuf;
4use std::sync::Arc;
5
6use super::ProcessManager;
7use super::access::ToolAccess;
8use super::context::ExecutionContext;
9use super::env::ToolExecutionEnv;
10use super::registry::ToolRegistry;
11use super::traits::Tool;
12use crate::agent::{TaskOutputTool, TaskRegistry, TaskTool};
13use crate::common::IndexRegistry;
14use crate::permissions::PermissionPolicy;
15use crate::session::session_state::ToolState;
16use crate::session::{MemoryPersistence, SessionId};
17use crate::subagents::SubagentIndex;
18
19pub struct ToolRegistryBuilder {
20    access: ToolAccess,
21    working_dir: Option<PathBuf>,
22    task_registry: Option<TaskRegistry>,
23    skill_executor: Option<crate::skills::SkillExecutor>,
24    subagent_registry: Option<IndexRegistry<SubagentIndex>>,
25    policy: Option<PermissionPolicy>,
26    sandbox_config: Option<crate::security::SandboxConfig>,
27    tool_state: Option<ToolState>,
28    session_id: Option<SessionId>,
29}
30
31impl ToolRegistryBuilder {
32    pub fn new() -> Self {
33        Self {
34            access: ToolAccess::default(),
35            working_dir: None,
36            task_registry: None,
37            skill_executor: None,
38            subagent_registry: None,
39            policy: None,
40            sandbox_config: None,
41            tool_state: None,
42            session_id: None,
43        }
44    }
45
46    pub fn access(mut self, access: ToolAccess) -> Self {
47        self.access = access;
48        self
49    }
50
51    pub fn working_dir(mut self, dir: impl Into<PathBuf>) -> Self {
52        self.working_dir = Some(dir.into());
53        self
54    }
55
56    pub fn task_registry(mut self, registry: TaskRegistry) -> Self {
57        self.task_registry = Some(registry);
58        self
59    }
60
61    pub fn skill_executor(mut self, executor: crate::skills::SkillExecutor) -> Self {
62        self.skill_executor = Some(executor);
63        self
64    }
65
66    pub fn subagent_registry(mut self, registry: IndexRegistry<SubagentIndex>) -> Self {
67        self.subagent_registry = Some(registry);
68        self
69    }
70
71    pub fn policy(mut self, policy: PermissionPolicy) -> Self {
72        self.policy = Some(policy);
73        self
74    }
75
76    pub fn sandbox_config(mut self, config: crate::security::SandboxConfig) -> Self {
77        self.sandbox_config = Some(config);
78        self
79    }
80
81    pub fn tool_state(mut self, state: ToolState) -> Self {
82        self.tool_state = Some(state);
83        self
84    }
85
86    pub fn session_id(mut self, id: SessionId) -> Self {
87        self.session_id = Some(id);
88        self
89    }
90
91    pub fn build(self) -> ToolRegistry {
92        let access = &self.access;
93        let wd = self
94            .working_dir
95            .unwrap_or_else(|| std::env::current_dir().unwrap_or_default());
96        let permission_policy = self.policy.unwrap_or_default();
97
98        let sandbox_config = self.sandbox_config.unwrap_or_else(|| {
99            crate::security::SandboxConfig::disabled().with_working_dir(wd.clone())
100        });
101
102        let security = crate::security::SecurityContext::builder()
103            .root(&wd)
104            .sandbox(sandbox_config)
105            .build()
106            .map(|mut security| {
107                security.policy = crate::security::SecurityPolicy::new(permission_policy);
108                security
109            })
110            .unwrap_or_else(|_| crate::security::SecurityContext::permissive());
111
112        let context = ExecutionContext::new(security);
113        let task_registry = self
114            .task_registry
115            .unwrap_or_else(|| TaskRegistry::new(Arc::new(MemoryPersistence::new())));
116        let process_manager = Arc::new(ProcessManager::new());
117
118        let session_id = self.session_id.unwrap_or_default();
119        let tool_state = self
120            .tool_state
121            .unwrap_or_else(|| ToolState::new(session_id));
122
123        let task_tool: Arc<dyn Tool> = match self.subagent_registry {
124            Some(sr) => Arc::new(TaskTool::new(task_registry.clone()).with_subagent_registry(sr)),
125            None => Arc::new(TaskTool::new(task_registry.clone())),
126        };
127
128        let skill_tool: Arc<dyn Tool> = match self.skill_executor {
129            Some(executor) => Arc::new(crate::skills::SkillTool::new(executor)),
130            None => Arc::new(crate::skills::SkillTool::with_defaults()),
131        };
132
133        let all_tools: Vec<Arc<dyn Tool>> = vec![
134            Arc::new(super::ReadTool),
135            Arc::new(super::WriteTool),
136            Arc::new(super::EditTool),
137            Arc::new(super::GlobTool),
138            Arc::new(super::GrepTool),
139            Arc::new(super::BashTool::with_process_manager(
140                process_manager.clone(),
141            )),
142            Arc::new(super::KillShellTool::with_process_manager(
143                process_manager.clone(),
144            )),
145            task_tool,
146            Arc::new(TaskOutputTool::new(task_registry.clone())),
147            Arc::new(super::TodoWriteTool::new(tool_state.clone(), session_id)),
148            Arc::new(super::PlanTool::new(tool_state.clone())),
149            skill_tool,
150        ];
151
152        let env = ToolExecutionEnv {
153            context,
154            tool_state: Some(tool_state),
155            process_manager: Some(process_manager),
156        };
157
158        let mut registry = ToolRegistry::with_env(task_registry, env);
159
160        for tool in all_tools {
161            if access.is_allowed(tool.name()) {
162                registry.register(tool);
163            }
164        }
165
166        registry
167    }
168}
169
170impl Default for ToolRegistryBuilder {
171    fn default() -> Self {
172        Self::new()
173    }
174}