vtcode_core/tools/registry/
mod.rs1mod approval_recorder;
4mod assembly;
5mod availability_facade;
6mod builder;
7mod builtins;
8mod cache;
9mod catalog_facade;
10mod cgp_facade;
11mod circuit_breaker;
12mod commands_facade;
13mod config_helpers;
14mod distributed;
15mod dual_output;
16mod error;
17mod execution_attempts;
18mod execution_facade;
19mod execution_handlers;
20mod execution_history;
21mod execution_kernel;
22mod execution_request;
23mod execution_results;
24mod execution_stages;
25mod executors;
26pub mod file_helpers;
27mod file_monitor_facade;
28mod harness;
29mod harness_facade;
30mod history_facade;
31pub mod interfaces;
32mod inventory;
33mod inventory_facade;
34mod justification;
35mod justification_extractor;
36pub mod labels;
37mod maintenance;
38mod mcp_facade;
39mod mcp_helpers;
40mod metrics_facade;
41mod optimization_facade;
42mod output_processing;
43mod pack;
44mod pack_impls;
45mod patch_recovery;
46mod planning_workflow_checks;
47mod planning_workflow_facade;
48mod policy;
49mod policy_facade;
50mod progress_facade;
51mod pty;
52mod pty_facade;
53mod reentrancy;
54mod registration;
55mod registration_facade;
56mod resiliency;
57mod resiliency_facade;
58mod risk_scorer;
59mod runtime_config_facade;
60mod sandbox_facade;
61mod scheduler_facade;
62mod search_runtime_facade;
63mod shell_policy;
64mod shell_policy_facade;
65mod spool_processing;
66mod spooler_facade;
67mod subagent_facade;
68mod telemetry;
69mod timeout;
70mod timeout_category;
71mod timeout_facade;
72mod tool_catalog_facade;
73mod tool_executor_impl;
74mod tool_search_index;
75mod trait_impls;
76mod unified_actions;
77mod utils;
78
79pub use approval_recorder::ApprovalRecorder;
80pub use cgp_facade::CgpRuntimeMode;
81pub use cgp_facade::native_cgp_tool_factory;
82pub use cgp_facade::wrap_registered_native_tool;
83pub use error::{ToolErrorType, ToolExecutionError};
84pub use execution_history::{
85 HarnessContextSnapshot, ToolExecutionHistory, ToolExecutionRecord, ToolTaskTelemetrySnapshot,
86};
87pub use execution_kernel::ToolPreflightOutcome;
88pub use execution_request::{ExecSettlementMode, ExecutionPolicySnapshot, ToolExecutionOutcome, ToolExecutionRequest};
89pub use executors::sandbox_policy_from_runtime_config;
90pub use harness::HarnessContext;
91pub use justification::{ApprovalPattern, JustificationManager, ToolJustification};
92pub use justification_extractor::JustificationExtractor;
93pub use pty::{PtySessionGuard, PtySessionManager};
94pub use registration::{
95 NativeCgpToolFactory, ToolCatalogSource, ToolExecutorFn, ToolHandler, ToolNetworkAccess, ToolRegistration,
96 ToolRegistrationSpec as ToolMetadata,
97};
98pub use resiliency::{ResiliencyContext, ToolFailureTracker};
99pub use risk_scorer::{RiskLevel, ToolRiskContext, ToolRiskScorer, ToolSource, WorkspaceTrust};
100pub use shell_policy::ShellPolicyChecker;
101pub use telemetry::ToolTelemetryEvent;
102pub use timeout::{AdaptiveTimeoutTuning, ToolLatencyStats, ToolTimeoutCategory, ToolTimeoutPolicy};
103pub use tool_catalog_facade::{SessionToolCatalogState, ToolGroup, tool_groups};
104
105pub use interfaces::{
107 McpBridge, PtySessionControl, SharedRegistry, ToolCatalog, ToolMetrics, ToolRegistryApi, ToolResilience,
108 ToolSecurity,
109};
110
111use assembly::ToolAssembly;
112use inventory::ToolInventory;
113use policy::ToolPolicyGateway;
114use utils::normalize_tool_output;
115
116use crate::tool_policy::ToolPolicy;
117use crate::tools::exec_session::ExecSessionManager;
118use crate::tools::handlers::PlanningWorkflowState;
119pub(super) use crate::tools::pty::PtyManager;
120use crate::tools::result::ToolResult as SplitToolResult;
121use crate::tools::safety_gateway::SafetyGateway;
122use indexmap::IndexMap;
123use parking_lot::Mutex; use rustc_hash::FxHashMap;
125use std::sync::{Arc, Weak};
126
127use crate::exec::code_executor::{BuiltinToolExecutor, BuiltinToolInfo};
128use crate::mcp::McpClient;
129use crate::subagents::SubagentController;
130use crate::tools::edited_file_monitor::EditedFileMonitor;
131use async_trait::async_trait;
132use std::sync::RwLock;
133
134pub type SessionModelTools = Arc<tokio::sync::RwLock<Vec<crate::llm::provider::ToolDefinition>>>;
135
136pub type ToolProgressCallback = Arc<dyn Fn(&str, &str) + Send + Sync>;
138
139use super::traits::Tool;
140
141#[cfg(test)]
142use crate::config::types::CapabilityLevel;
143
144const DEFAULT_LOOP_DETECT_WINDOW: usize = 5;
146
147#[derive(Clone)]
148pub struct ToolRegistry {
149 inventory: ToolInventory,
150 persistent_memory_config: Arc<crate::config::PersistentMemoryConfig>,
152 persistent_memory_enabled: bool,
153 edited_file_monitor: Arc<EditedFileMonitor>,
154 policy_gateway: Arc<ToolPolicyGateway>,
155 pty_sessions: PtySessionManager,
156 exec_sessions: ExecSessionManager,
157 mcp_client: Arc<parking_lot::RwLock<Option<Arc<McpClient>>>>,
158 mcp_tool_index: Arc<tokio::sync::RwLock<FxHashMap<String, Vec<String>>>>,
159 mcp_reverse_index: Arc<tokio::sync::RwLock<FxHashMap<String, String>>>,
160 timeout_policy: Arc<parking_lot::RwLock<ToolTimeoutPolicy>>,
161 execution_history: ToolExecutionHistory,
162 patch_recovery_reads: Arc<Mutex<patch_recovery::PatchRecoveryReads>>,
163 harness_context: HarnessContext,
164
165 resiliency: Arc<Mutex<ResiliencyContext>>,
167
168 mcp_circuit_breaker: Arc<circuit_breaker::McpCircuitBreaker>,
170 shared_circuit_breaker: Arc<RwLock<Option<Arc<crate::tools::circuit_breaker::CircuitBreaker>>>>,
172 initialized: Arc<std::sync::atomic::AtomicBool>,
173 shell_policy: Arc<RwLock<ShellPolicyChecker>>,
175 runtime_sandbox_config: Arc<RwLock<vtcode_config::SandboxConfig>>,
176 agent_type: Arc<RwLock<String>>,
177 active_pty_sessions: Arc<RwLock<Option<Arc<std::sync::atomic::AtomicUsize>>>>,
179
180 cached_available_tools: Arc<parking_lot::RwLock<Option<Vec<String>>>>,
182 active_tool_profile: Arc<RwLock<crate::config::ToolProfile>>,
184 progress_callback: Arc<RwLock<Option<ToolProgressCallback>>>,
186 tool_call_counter: Arc<std::sync::atomic::AtomicU64>,
189 pty_poll_counter: Arc<std::sync::atomic::AtomicU64>,
191 canonical_plans_dir: Arc<std::sync::OnceLock<std::path::PathBuf>>,
194 metrics: Arc<crate::metrics::MetricsCollector>,
196
197 memory_pool: Arc<crate::core::memory_pool::MemoryPool>,
200 hot_tool_cache: Arc<parking_lot::RwLock<lru::LruCache<String, Arc<dyn Tool>>>>,
202 optimization_config: vtcode_config::OptimizationConfig,
204
205 middleware: crate::tools::tool_middleware::MiddlewareChain,
207
208 output_spooler: Arc<super::output_spooler::ToolOutputSpooler>,
210
211 planning_workflow_state: PlanningWorkflowState,
215 planning_mode_policy_overrides: Arc<parking_lot::RwLock<Option<IndexMap<String, ToolPolicy>>>>,
219 safety_gateway: Arc<SafetyGateway>,
221 cgp_runtime_mode: Arc<RwLock<Option<CgpRuntimeMode>>>,
223 tool_assembly: Arc<RwLock<ToolAssembly>>,
225 tool_catalog_state: Arc<SessionToolCatalogState>,
227 subagent_controller: Arc<RwLock<Option<Arc<SubagentController>>>>,
229 matrix_worker: Arc<parking_lot::RwLock<Option<crate::subagents::matrix::MatrixWorkerContext>>>,
230 matrix_coordinator: Arc<std::sync::atomic::AtomicBool>,
231 session_scheduler: Arc<tokio::sync::Mutex<crate::scheduler::SessionScheduler>>,
233 session_model_tools: Arc<RwLock<Option<SessionModelTools>>>,
235 self_ref: Arc<RwLock<Option<Weak<ToolRegistry>>>>,
237}
238
239const BUILTIN_CODE_TOOLS: &[&str] = &[
240 crate::config::constants::tools::UNIFIED_FILE,
241 crate::config::constants::tools::CODE_SEARCH,
242 crate::config::constants::tools::WEB_FETCH,
243 crate::config::constants::tools::WEB_SEARCH,
244 crate::config::constants::tools::CRON,
245 crate::config::constants::tools::MEMORY,
246 crate::config::constants::tools::TASK_TRACKER,
247];
248
249fn builtin_code_tool_description(name: &str) -> String {
250 match name {
251 n if n == crate::config::constants::tools::UNIFIED_FILE => "Read, write, edit, move, copy, or delete files.",
252 n if n == crate::config::constants::tools::CODE_SEARCH => {
253 "Search code by query, with optional path, file_types, result_types, and max_results."
254 }
255 n if n == crate::config::constants::tools::WEB_FETCH => {
256 "Fetch a URL and return an analysed summary or markdown."
257 }
258 n if n == crate::config::constants::tools::WEB_SEARCH => "Run a web search and return ranked results.",
259 n if n == crate::config::constants::tools::CRON => "Manage scheduled prompts.",
260 n if n == crate::config::constants::tools::MEMORY => "Read or update persistent project memory.",
261 n if n == crate::config::constants::tools::TASK_TRACKER => "Track multi-step task checklists.",
262 _ => "Built-in VT Code tool.",
263 }
264 .to_string()
265}
266
267impl ToolRegistry {
268 pub fn set_self_ref(&self, registry: Arc<ToolRegistry>) {
269 *self.self_ref.write().unwrap_or_else(std::sync::PoisonError::into_inner) = Some(Arc::downgrade(®istry));
270 }
271
272 fn builtin_executor_for_code(&self) -> Option<Arc<dyn BuiltinToolExecutor>> {
273 self.self_ref
274 .read()
275 .unwrap_or_else(std::sync::PoisonError::into_inner)
276 .as_ref()
277 .and_then(Weak::upgrade)
278 .map(|registry| registry as Arc<dyn BuiltinToolExecutor>)
279 }
280}
281
282#[async_trait]
283impl BuiltinToolExecutor for ToolRegistry {
284 async fn execute_builtin_tool(
285 &self,
286 tool_name: &str,
287 args: &serde_json::Value,
288 ) -> anyhow::Result<serde_json::Value> {
289 if !BUILTIN_CODE_TOOLS.contains(&tool_name) {
290 anyhow::bail!("tool '{tool_name}' is not exposed to code snippets");
291 }
292 self.execute_tool(tool_name, args.clone()).await
293 }
294
295 fn list_builtin_tools(&self) -> anyhow::Result<Vec<BuiltinToolInfo>> {
296 Ok(BUILTIN_CODE_TOOLS
297 .iter()
298 .map(|name| BuiltinToolInfo {
299 name: (*name).to_string(),
300 description: builtin_code_tool_description(name),
301 })
302 .collect())
303 }
304}
305
306#[derive(Debug, Clone, Copy, PartialEq, Eq)]
307pub enum ToolPermissionDecision {
308 Allow,
309 Deny,
310 Prompt,
311}
312
313#[cfg(test)]
314mod tests;