mod approval_recorder;
mod assembly;
mod availability_facade;
mod builder;
mod builtins;
mod cache;
mod catalog_facade;
mod cgp_facade;
mod circuit_breaker;
mod commands_facade;
mod config_helpers;
mod distributed;
mod dual_output;
mod error;
mod execution_facade;
mod execution_history;
mod execution_kernel;
mod execution_request;
mod execution_stages;
mod executors;
pub mod file_helpers;
mod file_monitor_facade;
mod harness;
mod harness_facade;
mod history_facade;
pub mod interfaces;
mod inventory;
mod inventory_facade;
mod justification;
mod justification_extractor;
pub mod labels;
mod maintenance;
mod mcp_facade;
mod mcp_helpers;
mod metrics_facade;
mod optimization_facade;
mod output_processing;
mod pack;
mod pack_impls;
mod planning_workflow_checks;
mod planning_workflow_facade;
mod policy;
mod policy_facade;
mod progress_facade;
mod pty;
mod pty_facade;
mod registration;
mod registration_facade;
mod resiliency;
mod resiliency_facade;
mod risk_scorer;
mod runtime_config_facade;
mod sandbox_facade;
mod scheduler_facade;
mod search_runtime_facade;
mod shell_policy;
mod shell_policy_facade;
mod spooler_facade;
mod subagent_facade;
mod telemetry;
mod timeout;
mod timeout_category;
mod timeout_facade;
mod tool_catalog_facade;
mod tool_executor_impl;
mod tool_search_index;
mod trait_impls;
mod unified_actions;
mod utils;
pub use approval_recorder::ApprovalRecorder;
pub use cgp_facade::CgpRuntimeMode;
pub use cgp_facade::native_cgp_tool_factory;
pub use cgp_facade::wrap_registered_native_tool;
pub use error::{ToolErrorType, ToolExecutionError};
pub use execution_history::{
HarnessContextSnapshot, ToolExecutionHistory, ToolExecutionRecord, ToolTaskTelemetrySnapshot,
};
pub use execution_kernel::ToolPreflightOutcome;
pub use execution_request::{ExecSettlementMode, ExecutionPolicySnapshot, ToolExecutionOutcome, ToolExecutionRequest};
pub use harness::HarnessContext;
pub use justification::{ApprovalPattern, JustificationManager, ToolJustification};
pub use justification_extractor::JustificationExtractor;
pub use pty::{PtySessionGuard, PtySessionManager};
pub use registration::{
NativeCgpToolFactory, ToolCatalogSource, ToolExecutorFn, ToolHandler, ToolRegistration,
ToolRegistrationSpec as ToolMetadata,
};
pub use resiliency::{ResiliencyContext, ToolFailureTracker};
pub use risk_scorer::{RiskLevel, ToolRiskContext, ToolRiskScorer, ToolSource, WorkspaceTrust};
pub use shell_policy::ShellPolicyChecker;
pub use telemetry::ToolTelemetryEvent;
pub use timeout::{AdaptiveTimeoutTuning, ToolLatencyStats, ToolTimeoutCategory, ToolTimeoutPolicy};
pub use tool_catalog_facade::{SessionToolCatalogState, ToolGroup, tool_groups};
pub use interfaces::{
McpBridge, PtySessionControl, SharedRegistry, ToolCatalog, ToolMetrics, ToolRegistryApi, ToolResilience,
ToolSecurity,
};
use assembly::ToolAssembly;
use inventory::ToolInventory;
use policy::ToolPolicyGateway;
use utils::normalize_tool_output;
use crate::tools::exec_session::ExecSessionManager;
use crate::tools::handlers::PlanningWorkflowState;
pub(super) use crate::tools::pty::PtyManager;
use crate::tools::result::ToolResult as SplitToolResult;
use crate::tools::safety_gateway::SafetyGateway;
use parking_lot::Mutex; use rustc_hash::FxHashMap;
use std::sync::{Arc, Weak};
use crate::exec::code_executor::{BuiltinToolExecutor, BuiltinToolInfo};
use crate::mcp::McpClient;
use crate::subagents::SubagentController;
use crate::tools::edited_file_monitor::EditedFileMonitor;
use async_trait::async_trait;
use std::sync::RwLock;
pub type SessionModelTools = Arc<tokio::sync::RwLock<Vec<crate::llm::provider::ToolDefinition>>>;
pub type ToolProgressCallback = Arc<dyn Fn(&str, &str) + Send + Sync>;
use super::traits::Tool;
#[cfg(test)]
use crate::config::types::CapabilityLevel;
const DEFAULT_LOOP_DETECT_WINDOW: usize = 5;
#[derive(Clone)]
pub struct ToolRegistry {
inventory: ToolInventory,
edited_file_monitor: Arc<EditedFileMonitor>,
policy_gateway: Arc<ToolPolicyGateway>,
pty_sessions: PtySessionManager,
exec_sessions: ExecSessionManager,
mcp_client: Arc<parking_lot::RwLock<Option<Arc<McpClient>>>>,
mcp_tool_index: Arc<tokio::sync::RwLock<FxHashMap<String, Vec<String>>>>,
mcp_reverse_index: Arc<tokio::sync::RwLock<FxHashMap<String, String>>>,
timeout_policy: Arc<parking_lot::RwLock<ToolTimeoutPolicy>>,
execution_history: ToolExecutionHistory,
harness_context: HarnessContext,
resiliency: Arc<Mutex<ResiliencyContext>>,
mcp_circuit_breaker: Arc<circuit_breaker::McpCircuitBreaker>,
shared_circuit_breaker: Arc<RwLock<Option<Arc<crate::tools::circuit_breaker::CircuitBreaker>>>>,
initialized: Arc<std::sync::atomic::AtomicBool>,
shell_policy: Arc<RwLock<ShellPolicyChecker>>,
runtime_sandbox_config: Arc<RwLock<vtcode_config::SandboxConfig>>,
agent_type: Arc<RwLock<String>>,
active_pty_sessions: Arc<RwLock<Option<Arc<std::sync::atomic::AtomicUsize>>>>,
cached_available_tools: Arc<parking_lot::RwLock<Option<Vec<String>>>>,
active_tool_profile: Arc<RwLock<crate::config::ToolProfile>>,
progress_callback: Arc<RwLock<Option<ToolProgressCallback>>>,
pub(crate) tool_call_counter: Arc<std::sync::atomic::AtomicU64>,
pub(crate) pty_poll_counter: Arc<std::sync::atomic::AtomicU64>,
metrics: Arc<crate::metrics::MetricsCollector>,
memory_pool: Arc<crate::core::memory_pool::MemoryPool>,
hot_tool_cache: Arc<parking_lot::RwLock<lru::LruCache<String, Arc<dyn Tool>>>>,
optimization_config: vtcode_config::OptimizationConfig,
middleware: crate::tools::tool_middleware::MiddlewareChain,
output_spooler: Arc<super::output_spooler::ToolOutputSpooler>,
planning_workflow_state: PlanningWorkflowState,
safety_gateway: Arc<SafetyGateway>,
cgp_runtime_mode: Arc<RwLock<Option<CgpRuntimeMode>>>,
tool_assembly: Arc<RwLock<ToolAssembly>>,
tool_catalog_state: Arc<SessionToolCatalogState>,
subagent_controller: Arc<RwLock<Option<Arc<SubagentController>>>>,
session_scheduler: Arc<tokio::sync::Mutex<crate::scheduler::SessionScheduler>>,
session_model_tools: Arc<RwLock<Option<SessionModelTools>>>,
self_ref: Arc<RwLock<Option<Weak<ToolRegistry>>>>,
}
const BUILTIN_CODE_TOOLS: &[&str] = &[
crate::config::constants::tools::UNIFIED_FILE,
crate::config::constants::tools::CODE_SEARCH,
crate::config::constants::tools::WEB_FETCH,
crate::config::constants::tools::WEB_SEARCH,
crate::config::constants::tools::CRON,
crate::config::constants::tools::MEMORY,
crate::config::constants::tools::TASK_TRACKER,
];
fn builtin_code_tool_description(name: &str) -> String {
match name {
n if n == crate::config::constants::tools::UNIFIED_FILE => "Read, write, edit, move, copy, or delete files.",
n if n == crate::config::constants::tools::CODE_SEARCH => {
"Search code by query, with optional path, file_types, result_types, and max_results."
}
n if n == crate::config::constants::tools::WEB_FETCH => {
"Fetch a URL and return an analysed summary or markdown."
}
n if n == crate::config::constants::tools::WEB_SEARCH => "Run a web search and return ranked results.",
n if n == crate::config::constants::tools::CRON => "Manage scheduled prompts.",
n if n == crate::config::constants::tools::MEMORY => "Read or update persistent project memory.",
n if n == crate::config::constants::tools::TASK_TRACKER => "Track multi-step task checklists.",
_ => "Built-in VT Code tool.",
}
.to_string()
}
impl ToolRegistry {
pub fn set_self_ref(&self, registry: Arc<ToolRegistry>) {
*self.self_ref.write().unwrap_or_else(std::sync::PoisonError::into_inner) = Some(Arc::downgrade(®istry));
}
pub(crate) fn builtin_executor_for_code(&self) -> Option<Arc<dyn BuiltinToolExecutor>> {
self.self_ref
.read()
.unwrap_or_else(std::sync::PoisonError::into_inner)
.as_ref()
.and_then(Weak::upgrade)
.map(|registry| registry as Arc<dyn BuiltinToolExecutor>)
}
}
#[async_trait]
impl BuiltinToolExecutor for ToolRegistry {
async fn execute_builtin_tool(
&self,
tool_name: &str,
args: &serde_json::Value,
) -> anyhow::Result<serde_json::Value> {
if !BUILTIN_CODE_TOOLS.contains(&tool_name) {
anyhow::bail!("tool '{tool_name}' is not exposed to code snippets");
}
self.execute_tool(tool_name, args.clone()).await
}
fn list_builtin_tools(&self) -> anyhow::Result<Vec<BuiltinToolInfo>> {
Ok(BUILTIN_CODE_TOOLS
.iter()
.map(|name| BuiltinToolInfo {
name: (*name).to_string(),
description: builtin_code_tool_description(name),
})
.collect())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ToolPermissionDecision {
Allow,
Deny,
Prompt,
}
#[cfg(test)]
mod tests;