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