Skip to main content

vtcode_config/constants/
tools.rs

1// ============================================================
2// MODEL-FACING TOOLS
3// ============================================================
4/// Canonical shell execution tool exposed to the model.
5pub const EXEC_COMMAND: &str = "exec_command";
6/// Canonical stdin writer for active execution sessions.
7pub const WRITE_STDIN: &str = "write_stdin";
8/// Canonical patch application tool exposed to the model.
9pub const APPLY_PATCH: &str = "apply_patch";
10/// Optional public rationale recording within the canonical current task.
11pub const RECORD_DECISION: &str = "record_decision";
12/// Advanced bounded syntactic code search tool for VTCode-specific profiles.
13pub const CODE_SEARCH: &str = "code_search";
14
15// ============================================================
16// LEGACY INTERNAL DISPATCHERS
17// ============================================================
18/// Internal search and discovery dispatcher retained behind public tools.
19pub const UNIFIED_SEARCH: &str = "search_dispatch_internal";
20/// Internal shell execution and code execution dispatcher retained behind public tools.
21pub const UNIFIED_EXEC: &str = "command_session_internal";
22/// Internal file operations dispatcher retained behind public tools.
23pub const UNIFIED_FILE: &str = "file_operation_internal";
24
25// ============================================================
26// TOOL IDS
27// ============================================================
28pub const THINK: &str = "think";
29pub const SEARCH_TOOLS: &str = "search_tools";
30/// Unified MCP tool (action: search_tools | get_tool_details | list_servers |
31/// connect | disconnect). `connect`/`disconnect` are config-gated lifecycle
32/// ops evaluated under the action-qualified policy keys `mcp:connect` /
33/// `mcp:disconnect` (default Prompt) so they keep their human-in-the-loop
34/// confirmation even though the base `mcp` tool is `ToolPolicy::Allow`.
35pub const MCP: &str = "mcp";
36pub const MCP_SEARCH_TOOLS: &str = "mcp_search_tools";
37pub const MCP_GET_TOOL_DETAILS: &str = "mcp_get_tool_details";
38pub const MCP_LIST_SERVERS: &str = "mcp_list_servers";
39pub const MCP_CONNECT_SERVER: &str = "mcp_connect_server";
40pub const MCP_DISCONNECT_SERVER: &str = "mcp_disconnect_server";
41pub const WEB_SEARCH: &str = "web_search";
42pub const WEB_FETCH: &str = "web_fetch";
43pub const FETCH_URL: &str = "fetch_url";
44/// Defuddle-backed markdown extraction for a single URL. The hosted
45/// `defuddle.md/{link}` service is rate-limited, so this tool is hard-capped
46/// at one call per tool instance (treat one tool instance as one session).
47pub const DEFUDDLE_FETCH: &str = "defuddle_fetch";
48pub const LIST: &str = "list";
49pub const GREP: &str = "grep";
50pub const FETCH: &str = "fetch";
51pub const EXEC_PTY_CMD: &str = "exec_pty_cmd";
52pub const SHELL: &str = "shell";
53pub const GREP_FILE: &str = "grep_file";
54pub const LIST_FILES: &str = "list_files";
55
56// ============================================================
57// SKILL MANAGEMENT TOOLS (Progressive Disclosure)
58// ============================================================
59/// List all available skills (local and dormant system utilities)
60pub const LIST_SKILLS: &str = "list_skills";
61/// Load a skill's instructions and activate its tools
62pub const LOAD_SKILL: &str = "load_skill";
63/// Load resources from a skill (scripts, templates, docs)
64pub const LOAD_SKILL_RESOURCE: &str = "load_skill_resource";
65
66// ============================================================
67// INTERNAL EXECUTION HELPERS
68// ============================================================
69pub const RUN_PTY_CMD: &str = "run_pty_cmd";
70pub const CREATE_PTY_SESSION: &str = "create_pty_session";
71pub const LIST_PTY_SESSIONS: &str = "list_pty_sessions";
72pub const CLOSE_PTY_SESSION: &str = "close_pty_session";
73pub const SEND_PTY_INPUT: &str = "send_pty_input";
74pub const READ_PTY_SESSION: &str = "read_pty_session";
75pub const RESIZE_PTY_SESSION: &str = "resize_pty_session";
76pub const EXECUTE_CODE: &str = "execute_code";
77
78// ============================================================
79// INTERNAL FILE OPERATION HELPERS
80// ============================================================
81pub const READ_FILE: &str = "read_file";
82pub const WRITE_FILE: &str = "write_file";
83pub const EDIT_FILE: &str = "edit_file";
84pub const DELETE_FILE: &str = "delete_file";
85pub const CREATE_FILE: &str = "create_file";
86pub const SEARCH_REPLACE: &str = "search_replace";
87pub const FILE_OP: &str = "file_op";
88pub const MOVE_FILE: &str = "move_file";
89pub const COPY_FILE: &str = "copy_file";
90
91// ============================================================
92// ERROR & DIAGNOSTICS
93// ============================================================
94pub const GET_ERRORS: &str = "get_errors";
95
96// ============================================================
97// HUMAN-IN-THE-LOOP (HITL)
98// ============================================================
99/// Canonical HITL tool name for structured user input.
100pub const REQUEST_USER_INPUT: &str = "request_user_input";
101/// Canonical memory tool name for Anthropic native memory sessions.
102pub const MEMORY: &str = "memory";
103/// Legacy alias routed to `request_user_input`.
104pub const ASK_QUESTIONS: &str = "ask_questions";
105/// Legacy alias routed to `request_user_input` (deprecated tabbed shape).
106pub const ASK_USER_QUESTION: &str = "ask_user_question";
107/// Durable scheduler control for coordinators and assignment-owned worker reports.
108pub const MATRIX: &str = "matrix";
109/// Unified subagent lifecycle tool (action: spawn | spawn_subprocess |
110/// send_input | resume | wait | close). `wait_agent`/`close_agent` are now
111/// aliases routed to `agent` (action='wait'/'close'); `LIFECYCLE_CLEANUP_TOOLS`
112/// still lists their names so the policy layer keeps treating them as
113/// always-allowed cleanup calls regardless of the active primary agent's
114/// restricted tool policy.
115pub const AGENT: &str = "agent";
116/// Unified scheduled-prompt tool (action: create | list | delete).
117pub const CRON: &str = "cron";
118/// Legacy alias for `cron` action=create.
119pub const CRON_CREATE: &str = "cron_create";
120/// List session-scoped scheduled tasks.
121pub const CRON_LIST: &str = "cron_list";
122/// Delete a session-scoped scheduled task by id.
123pub const CRON_DELETE: &str = "cron_delete";
124
125// ============================================================
126// PLANNING WORKFLOW
127// ============================================================
128/// Start planning - enables read-only tools and planning workflow.
129pub const START_PLANNING: &str = "start_planning";
130/// Task tracker / plan manager - tracks checklist progress during complex tasks.
131pub const TASK_TRACKER: &str = "task_tracker";
132
133// ============================================================
134// SUBAGENT COLLABORATION
135// ============================================================
136/// Spawn a delegated child agent.
137pub const SPAWN_AGENT: &str = "spawn_agent";
138/// Launch a managed background subprocess that hosts a background-enabled subagent.
139pub const SPAWN_BACKGROUND_SUBPROCESS: &str = "spawn_background_subprocess";
140/// Send follow-up input to a delegated child agent.
141pub const SEND_INPUT: &str = "send_input";
142/// Wait for one or more delegated child agents to finish.
143pub const WAIT_AGENT: &str = "wait_agent";
144/// Resume a delegated child agent without sending a message.
145pub const RESUME_AGENT: &str = "resume_agent";
146/// Close a delegated child agent.
147pub const CLOSE_AGENT: &str = "close_agent";
148
149/// Cleanup-only child-agent tools that must remain available regardless of the
150/// active primary agent's tool policy, so restricted primaries can still join or
151/// close already-running child work. Add new lifecycle-only cleanup tools here.
152pub const LIFECYCLE_CLEANUP_TOOLS: &[&str] = &[WAIT_AGENT, CLOSE_AGENT];
153
154/// Workflow-coordination tools that must remain available regardless of the
155/// `[automation.full_auto].allowed_tools` allow-list, so planning, checklist,
156/// and interview coordination keep working in Auto mode and other full-auto
157/// runs. These are control-plane (not execution blast radius): `task_tracker`
158/// owns only its session tracker file, `start_planning` only flips the
159/// planning-workflow state, and `request_user_input` still resolves through
160/// the interactive-session gate at execution time. Callers must pass the
161/// canonical tool name (see `canonical_tool_name`); matching is exact.
162pub const ALWAYS_AVAILABLE_WORKFLOW_TOOLS: &[&str] = &[TASK_TRACKER, START_PLANNING, REQUEST_USER_INPUT, MATRIX];
163
164/// Returns `true` for workflow-coordination tools that bypass the full-auto
165/// allow-list (see [`ALWAYS_AVAILABLE_WORKFLOW_TOOLS`]).
166#[inline]
167pub fn is_workflow_coordination_tool(canonical_name: &str) -> bool {
168    ALWAYS_AVAILABLE_WORKFLOW_TOOLS.contains(&canonical_name)
169}
170
171// Special wildcard for full access
172pub const WILDCARD_ALL: &str = "*";
173
174// ===========================================================================
175// Compile-time validation
176//
177// All tool name constants are validated at compile time. These assertions
178// ensure every name is non-empty, uses only [a-z0-9_], and contains no
179// leading/trailing underscores (which would signal a naming convention
180// violation). The wildcard "*" is exempt from character checks.
181// ===========================================================================
182
183const _: () = {
184    /// Validate a tool name at compile time. Panics with a clear message
185    /// if the name is empty, contains invalid characters, or has leading/
186    /// trailing underscores (except for the wildcard "*").
187    const fn validate_tool_name(name: &str) {
188        assert!(!name.is_empty(), "tool name must not be empty");
189        let bytes = name.as_bytes();
190        // Wildcard "*" is the only name allowed to bypass character checks
191        if bytes.len() == 1 && bytes[0] == b'*' {
192            return;
193        }
194        assert!(
195            bytes[0] != b'_' && bytes[bytes.len() - 1] != b'_',
196            "tool name must not have leading/trailing underscores"
197        );
198        let mut i = 0;
199        while i < bytes.len() {
200            let b = bytes[i];
201            assert!(b.is_ascii_lowercase() || b.is_ascii_digit() || b == b'_', "tool name must contain only [a-z0-9_]");
202            i += 1;
203        }
204    }
205
206    // Model-facing tools
207    validate_tool_name(EXEC_COMMAND);
208    validate_tool_name(WRITE_STDIN);
209    validate_tool_name(APPLY_PATCH);
210    validate_tool_name(CODE_SEARCH);
211
212    // Internal unified tools
213    validate_tool_name(UNIFIED_SEARCH);
214    validate_tool_name(UNIFIED_EXEC);
215    validate_tool_name(UNIFIED_FILE);
216
217    // Tool IDs
218    validate_tool_name(THINK);
219    validate_tool_name(SEARCH_TOOLS);
220    validate_tool_name(MCP);
221    validate_tool_name(MCP_SEARCH_TOOLS);
222    validate_tool_name(MCP_GET_TOOL_DETAILS);
223    validate_tool_name(MCP_LIST_SERVERS);
224    validate_tool_name(MCP_CONNECT_SERVER);
225    validate_tool_name(MCP_DISCONNECT_SERVER);
226    validate_tool_name(WEB_SEARCH);
227    validate_tool_name(WEB_FETCH);
228    validate_tool_name(FETCH_URL);
229    validate_tool_name(DEFUDDLE_FETCH);
230    validate_tool_name(LIST);
231    validate_tool_name(GREP);
232    validate_tool_name(FETCH);
233    validate_tool_name(EXEC_PTY_CMD);
234    validate_tool_name(SHELL);
235    validate_tool_name(GREP_FILE);
236    validate_tool_name(LIST_FILES);
237
238    // Skill management
239    validate_tool_name(LIST_SKILLS);
240    validate_tool_name(LOAD_SKILL);
241    validate_tool_name(LOAD_SKILL_RESOURCE);
242
243    // Internal execution helpers
244    validate_tool_name(RUN_PTY_CMD);
245    validate_tool_name(CREATE_PTY_SESSION);
246    validate_tool_name(LIST_PTY_SESSIONS);
247    validate_tool_name(CLOSE_PTY_SESSION);
248    validate_tool_name(SEND_PTY_INPUT);
249    validate_tool_name(READ_PTY_SESSION);
250    validate_tool_name(RESIZE_PTY_SESSION);
251    validate_tool_name(EXECUTE_CODE);
252
253    // Internal file operation helpers
254    validate_tool_name(READ_FILE);
255    validate_tool_name(WRITE_FILE);
256    validate_tool_name(EDIT_FILE);
257    validate_tool_name(DELETE_FILE);
258    validate_tool_name(CREATE_FILE);
259    validate_tool_name(SEARCH_REPLACE);
260    validate_tool_name(FILE_OP);
261    validate_tool_name(MOVE_FILE);
262    validate_tool_name(COPY_FILE);
263
264    // Error & diagnostics
265    validate_tool_name(GET_ERRORS);
266
267    // HITL
268    validate_tool_name(REQUEST_USER_INPUT);
269    validate_tool_name(MEMORY);
270    validate_tool_name(ASK_QUESTIONS);
271    validate_tool_name(ASK_USER_QUESTION);
272    validate_tool_name(AGENT);
273    validate_tool_name(CRON);
274    validate_tool_name(CRON_CREATE);
275    validate_tool_name(CRON_LIST);
276    validate_tool_name(CRON_DELETE);
277
278    // Planning workflow
279    validate_tool_name(START_PLANNING);
280    validate_tool_name(TASK_TRACKER);
281
282    // Subagent collaboration
283    validate_tool_name(SPAWN_AGENT);
284    validate_tool_name(SPAWN_BACKGROUND_SUBPROCESS);
285    validate_tool_name(SEND_INPUT);
286    validate_tool_name(WAIT_AGENT);
287    validate_tool_name(RESUME_AGENT);
288    validate_tool_name(CLOSE_AGENT);
289
290    // Wildcard
291    validate_tool_name(WILDCARD_ALL);
292};
293
294#[cfg(test)]
295mod tests {
296    use super::*;
297
298    #[test]
299    fn workflow_coordination_tools_bypass_the_full_auto_allow_list() {
300        for tool in [TASK_TRACKER, START_PLANNING, REQUEST_USER_INPUT] {
301            assert!(is_workflow_coordination_tool(tool), "{tool} must bypass the allow-list");
302        }
303    }
304
305    #[test]
306    fn execution_tools_do_not_bypass_the_full_auto_allow_list() {
307        for tool in [
308            EXEC_COMMAND,
309            WRITE_STDIN,
310            APPLY_PATCH,
311            CODE_SEARCH,
312            WEB_FETCH,
313            "not_a_tool",
314        ] {
315            assert!(!is_workflow_coordination_tool(tool), "{tool} must stay allow-list gated");
316        }
317    }
318}