1use indexmap::IndexMap;
2use serde::{Deserialize, Serialize};
3
4use crate::constants::{defaults, tools};
5use crate::core::plugins::PluginRuntimeConfig;
6
7#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
9#[derive(Debug, Clone, Deserialize, Serialize)]
10pub struct ToolsConfig {
11 #[serde(default = "default_tool_policy")]
13 pub default_policy: ToolPolicy,
14
15 #[serde(default)]
17 #[cfg_attr(
18 feature = "schema",
19 schemars(with = "std::collections::BTreeMap<String, ToolPolicy>")
20 )]
21 pub policies: IndexMap<String, ToolPolicy>,
22
23 #[serde(default = "default_max_tool_loops")]
30 pub max_tool_loops: usize,
31
32 #[serde(default = "default_max_repeated_tool_calls")]
35 pub max_repeated_tool_calls: usize,
36
37 #[serde(default = "default_max_tool_rate_per_second")]
40 pub max_tool_rate_per_second: Option<usize>,
41
42 #[serde(default)]
44 pub web_fetch: WebFetchConfig,
45
46 #[serde(default)]
48 pub plugins: PluginRuntimeConfig,
49
50 #[serde(default)]
54 pub loop_thresholds: IndexMap<String, usize>,
55}
56
57#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
59#[derive(Debug, Clone, Deserialize, Serialize)]
60pub struct WebFetchConfig {
61 #[serde(default = "default_web_fetch_mode")]
63 pub mode: String,
64
65 #[serde(default)]
67 pub dynamic_blocklist_enabled: bool,
68
69 #[serde(default)]
71 pub dynamic_blocklist_path: String,
72
73 #[serde(default)]
75 pub dynamic_whitelist_enabled: bool,
76
77 #[serde(default)]
79 pub dynamic_whitelist_path: String,
80
81 #[serde(default)]
83 pub blocked_domains: Vec<String>,
84
85 #[serde(default)]
87 pub allowed_domains: Vec<String>,
88
89 #[serde(default)]
91 pub blocked_patterns: Vec<String>,
92
93 #[serde(default)]
95 pub enable_audit_logging: bool,
96
97 #[serde(default)]
99 pub audit_log_path: String,
100
101 #[serde(default = "default_strict_https")]
103 pub strict_https_only: bool,
104}
105
106impl Default for ToolsConfig {
107 fn default() -> Self {
108 let policies = DEFAULT_TOOL_POLICIES
109 .iter()
110 .map(|(tool, policy)| ((*tool).into(), *policy))
111 .collect::<IndexMap<_, _>>();
112 Self {
113 default_policy: default_tool_policy(),
114 policies,
115 max_tool_loops: default_max_tool_loops(),
116 max_repeated_tool_calls: default_max_repeated_tool_calls(),
117 max_tool_rate_per_second: default_max_tool_rate_per_second(),
118 web_fetch: WebFetchConfig::default(),
119 plugins: PluginRuntimeConfig::default(),
120 loop_thresholds: IndexMap::new(),
121 }
122 }
123}
124
125const DEFAULT_BLOCKLIST_PATH: &str = "~/.vtcode/web_fetch_blocklist.json";
126const DEFAULT_WHITELIST_PATH: &str = "~/.vtcode/web_fetch_whitelist.json";
127const DEFAULT_AUDIT_LOG_PATH: &str = "~/.vtcode/web_fetch_audit.log";
128
129impl Default for WebFetchConfig {
130 fn default() -> Self {
131 Self {
132 mode: default_web_fetch_mode(),
133 dynamic_blocklist_enabled: false,
134 dynamic_blocklist_path: DEFAULT_BLOCKLIST_PATH.into(),
135 dynamic_whitelist_enabled: false,
136 dynamic_whitelist_path: DEFAULT_WHITELIST_PATH.into(),
137 blocked_domains: Vec::new(),
138 allowed_domains: Vec::new(),
139 blocked_patterns: Vec::new(),
140 enable_audit_logging: false,
141 audit_log_path: DEFAULT_AUDIT_LOG_PATH.into(),
142 strict_https_only: true,
143 }
144 }
145}
146
147#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
149#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq)]
150#[serde(rename_all = "lowercase")]
151pub enum ToolPolicy {
152 Allow,
154 Prompt,
156 Deny,
158}
159
160#[inline]
161const fn default_tool_policy() -> ToolPolicy {
162 ToolPolicy::Prompt
163}
164
165#[inline]
166const fn default_max_tool_loops() -> usize {
167 defaults::DEFAULT_MAX_TOOL_LOOPS
168}
169
170#[inline]
171const fn default_max_repeated_tool_calls() -> usize {
172 defaults::DEFAULT_MAX_REPEATED_TOOL_CALLS
173}
174
175#[inline]
176const fn default_max_tool_rate_per_second() -> Option<usize> {
177 None
178}
179
180#[inline]
181fn default_web_fetch_mode() -> String {
182 "restricted".into()
183}
184
185fn default_strict_https() -> bool {
186 true
187}
188
189const DEFAULT_TOOL_POLICIES: &[(&str, ToolPolicy)] = &[
190 (tools::LIST_FILES, ToolPolicy::Allow),
192 (tools::GREP_FILE, ToolPolicy::Allow),
193 (tools::READ_FILE, ToolPolicy::Allow),
194 (tools::WRITE_FILE, ToolPolicy::Allow),
196 (tools::EDIT_FILE, ToolPolicy::Allow),
197 (tools::CREATE_FILE, ToolPolicy::Allow),
198 (tools::DELETE_FILE, ToolPolicy::Prompt),
200 (tools::APPLY_PATCH, ToolPolicy::Prompt),
201 (tools::SEARCH_REPLACE, ToolPolicy::Prompt),
202 (tools::RUN_PTY_CMD, ToolPolicy::Prompt),
204 (tools::CREATE_PTY_SESSION, ToolPolicy::Allow),
205 (tools::READ_PTY_SESSION, ToolPolicy::Allow),
206 (tools::LIST_PTY_SESSIONS, ToolPolicy::Allow),
207 (tools::RESIZE_PTY_SESSION, ToolPolicy::Allow),
208 (tools::SEND_PTY_INPUT, ToolPolicy::Prompt),
209 (tools::CLOSE_PTY_SESSION, ToolPolicy::Allow),
210 (tools::EXECUTE_CODE, ToolPolicy::Prompt),
212 (tools::SEARCH_TOOLS, ToolPolicy::Allow),
214 (tools::SKILL, ToolPolicy::Allow),
215 (tools::WEB_FETCH, ToolPolicy::Prompt),
218];