vtcode_config/core/
tools.rs

1use indexmap::IndexMap;
2use serde::{Deserialize, Serialize};
3
4use crate::constants::{defaults, tools};
5
6/// Tools configuration
7#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
8#[derive(Debug, Clone, Deserialize, Serialize)]
9pub struct ToolsConfig {
10    /// Default policy for tools not explicitly listed
11    #[serde(default = "default_tool_policy")]
12    pub default_policy: ToolPolicy,
13
14    /// Specific tool policies
15    #[serde(default)]
16    #[cfg_attr(
17        feature = "schema",
18        schemars(with = "std::collections::BTreeMap<String, ToolPolicy>")
19    )]
20    pub policies: IndexMap<String, ToolPolicy>,
21
22    /// Maximum inner tool-call loops per user turn
23    ///
24    /// Prevents infinite tool-calling cycles in interactive chat. This limits how
25    /// many back-and-forths the agent will perform executing tools and
26    /// re-asking the model before returning a final answer.
27    ///
28    #[serde(default = "default_max_tool_loops")]
29    pub max_tool_loops: usize,
30
31    /// Maximum number of times the same tool invocation can be retried with the
32    /// identical arguments within a single turn.
33    #[serde(default = "default_max_repeated_tool_calls")]
34    pub max_repeated_tool_calls: usize,
35
36    /// Web Fetch tool security configuration
37    #[serde(default)]
38    pub web_fetch: WebFetchConfig,
39}
40
41/// Web Fetch tool security configuration
42#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
43#[derive(Debug, Clone, Deserialize, Serialize)]
44pub struct WebFetchConfig {
45    /// Security mode: "restricted" (blocklist) or "whitelist" (allowlist)
46    #[serde(default = "default_web_fetch_mode")]
47    pub mode: String,
48
49    /// Enable dynamic blocklist loading from external file
50    #[serde(default)]
51    pub dynamic_blocklist_enabled: bool,
52
53    /// Path to dynamic blocklist file
54    #[serde(default)]
55    pub dynamic_blocklist_path: String,
56
57    /// Enable dynamic whitelist loading from external file
58    #[serde(default)]
59    pub dynamic_whitelist_enabled: bool,
60
61    /// Path to dynamic whitelist file
62    #[serde(default)]
63    pub dynamic_whitelist_path: String,
64
65    /// Inline blocklist - Additional domains to block
66    #[serde(default)]
67    pub blocked_domains: Vec<String>,
68
69    /// Inline whitelist - Domains to allow in restricted mode
70    #[serde(default)]
71    pub allowed_domains: Vec<String>,
72
73    /// Additional blocked patterns
74    #[serde(default)]
75    pub blocked_patterns: Vec<String>,
76
77    /// Enable audit logging of URL validation decisions
78    #[serde(default)]
79    pub enable_audit_logging: bool,
80
81    /// Path to audit log file
82    #[serde(default)]
83    pub audit_log_path: String,
84
85    /// Strict HTTPS-only mode
86    #[serde(default = "default_strict_https")]
87    pub strict_https_only: bool,
88}
89
90impl Default for ToolsConfig {
91    fn default() -> Self {
92        let policies = DEFAULT_TOOL_POLICIES
93            .iter()
94            .map(|(tool, policy)| ((*tool).to_string(), *policy))
95            .collect::<IndexMap<_, _>>();
96        Self {
97            default_policy: default_tool_policy(),
98            policies,
99            max_tool_loops: default_max_tool_loops(),
100            max_repeated_tool_calls: default_max_repeated_tool_calls(),
101            web_fetch: WebFetchConfig::default(),
102        }
103    }
104}
105
106impl Default for WebFetchConfig {
107    fn default() -> Self {
108        Self {
109            mode: default_web_fetch_mode(),
110            dynamic_blocklist_enabled: false,
111            dynamic_blocklist_path: "~/.vtcode/web_fetch_blocklist.json".to_string(),
112            dynamic_whitelist_enabled: false,
113            dynamic_whitelist_path: "~/.vtcode/web_fetch_whitelist.json".to_string(),
114            blocked_domains: Vec::new(),
115            allowed_domains: Vec::new(),
116            blocked_patterns: Vec::new(),
117            enable_audit_logging: false,
118            audit_log_path: "~/.vtcode/web_fetch_audit.log".to_string(),
119            strict_https_only: true,
120        }
121    }
122}
123
124/// Tool execution policy
125#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
126#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq)]
127#[serde(rename_all = "lowercase")]
128pub enum ToolPolicy {
129    /// Allow execution without confirmation
130    Allow,
131    /// Prompt user for confirmation
132    Prompt,
133    /// Deny execution
134    Deny,
135}
136
137fn default_tool_policy() -> ToolPolicy {
138    ToolPolicy::Prompt
139}
140
141fn default_max_tool_loops() -> usize {
142    defaults::DEFAULT_MAX_TOOL_LOOPS
143}
144
145fn default_max_repeated_tool_calls() -> usize {
146    defaults::DEFAULT_MAX_REPEATED_TOOL_CALLS
147}
148
149fn default_web_fetch_mode() -> String {
150    "restricted".to_string()
151}
152
153fn default_strict_https() -> bool {
154    true
155}
156
157const DEFAULT_TOOL_POLICIES: &[(&str, ToolPolicy)] = &[
158    // File operations (non-destructive)
159    (tools::LIST_FILES, ToolPolicy::Allow),
160    (tools::GREP_FILE, ToolPolicy::Allow),
161    (tools::READ_FILE, ToolPolicy::Allow),
162    // File operations (write/create)
163    (tools::WRITE_FILE, ToolPolicy::Allow),
164    (tools::EDIT_FILE, ToolPolicy::Allow),
165    (tools::CREATE_FILE, ToolPolicy::Allow),
166    // File operations (destructive - require confirmation)
167    (tools::DELETE_FILE, ToolPolicy::Prompt),
168    (tools::APPLY_PATCH, ToolPolicy::Prompt),
169    // PTY/Terminal operations
170    (tools::RUN_PTY_CMD, ToolPolicy::Allow),
171    (tools::CREATE_PTY_SESSION, ToolPolicy::Allow),
172    (tools::READ_PTY_SESSION, ToolPolicy::Allow),
173    (tools::LIST_PTY_SESSIONS, ToolPolicy::Allow),
174    (tools::RESIZE_PTY_SESSION, ToolPolicy::Allow),
175    (tools::SEND_PTY_INPUT, ToolPolicy::Prompt),
176    (tools::CLOSE_PTY_SESSION, ToolPolicy::Allow),
177    // Code execution (requires confirmation)
178    (tools::EXECUTE_CODE, ToolPolicy::Prompt),
179    // Planning and meta tools
180    (tools::UPDATE_PLAN, ToolPolicy::Allow),
181    (tools::SEARCH_TOOLS, ToolPolicy::Allow),
182    // Skill management (non-destructive)
183    (tools::SAVE_SKILL, ToolPolicy::Allow),
184    (tools::LOAD_SKILL, ToolPolicy::Allow),
185    (tools::LIST_SKILLS, ToolPolicy::Allow),
186    (tools::SEARCH_SKILLS, ToolPolicy::Allow),
187    // Diagnostic and introspection tools
188    // GET_ERRORS: Requires session state inspection (diagnostic, low risk)
189    (tools::GET_ERRORS, ToolPolicy::Allow),
190    // DEBUG_AGENT: Low-level agent state inspection (diagnostic, read-only)
191    (tools::DEBUG_AGENT, ToolPolicy::Allow),
192    // ANALYZE_AGENT: Analyzes agent behavior patterns (diagnostic, read-only)
193    (tools::ANALYZE_AGENT, ToolPolicy::Allow),
194    // Web operations (requires confirmation)
195    (tools::WEB_FETCH, ToolPolicy::Prompt),
196];