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/// Ask a peer CLI session in this workspace a question.
149pub const ASK_SESSION: &str = "ask_session";
150/// Answer a question received from a peer CLI session.
151pub const ANSWER_SESSION: &str = "answer_session";
152/// List live peer CLI sessions in this workspace.
153pub const LIST_SESSIONS: &str = "list_sessions";
154
155/// Cleanup-only child-agent tools that must remain available regardless of the
156/// active primary agent's tool policy, so restricted primaries can still join or
157/// close already-running child work. Add new lifecycle-only cleanup tools here.
158pub const LIFECYCLE_CLEANUP_TOOLS: &[&str] = &[WAIT_AGENT, CLOSE_AGENT];
159
160/// Workflow-coordination tools that must remain available regardless of the
161/// `[automation.full_auto].allowed_tools` allow-list, so planning, checklist,
162/// and interview coordination keep working in Auto mode and other full-auto
163/// runs. These are control-plane (not execution blast radius): `task_tracker`
164/// owns only its session tracker file, `start_planning` only flips the
165/// planning-workflow state, and `request_user_input` still resolves through
166/// the interactive-session gate at execution time. Callers must pass the
167/// canonical tool name (see `canonical_tool_name`); matching is exact.
168pub const ALWAYS_AVAILABLE_WORKFLOW_TOOLS: &[&str] = &[TASK_TRACKER, START_PLANNING, REQUEST_USER_INPUT, MATRIX];
169
170/// Returns `true` for workflow-coordination tools that bypass the full-auto
171/// allow-list (see [`ALWAYS_AVAILABLE_WORKFLOW_TOOLS`]).
172#[inline]
173pub fn is_workflow_coordination_tool(canonical_name: &str) -> bool {
174    ALWAYS_AVAILABLE_WORKFLOW_TOOLS.contains(&canonical_name)
175}
176
177/// Canonical command-session tool name for a possibly-aliased tool name.
178///
179/// Maps every exec/PTY alias (plus the `"bash"`, `"exec"`, and
180/// `"container.exec"` spellings transcript layers emit) to [`UNIFIED_EXEC`].
181/// Pure string match living next to the constants so lower layers (e.g.
182/// transcript normalization) can use it without depending on the classifier.
183#[inline]
184pub fn canonical_command_session_tool_name(tool_name: &str) -> Option<&'static str> {
185    match tool_name {
186        UNIFIED_EXEC | RUN_PTY_CMD | SEND_PTY_INPUT | CREATE_PTY_SESSION | READ_PTY_SESSION | LIST_PTY_SESSIONS
187        | CLOSE_PTY_SESSION | EXECUTE_CODE | EXEC_PTY_CMD | EXEC_COMMAND | WRITE_STDIN | SHELL | "bash" | "exec"
188        | "container.exec" => Some(UNIFIED_EXEC),
189        _ => None,
190    }
191}
192
193/// Returns `true` if `tool_name` is any alias of the unified command-session tool.
194#[must_use]
195#[inline]
196pub fn is_command_session_tool(tool_name: &str) -> bool {
197    canonical_command_session_tool_name(tool_name).is_some()
198}
199
200// Special wildcard for full access
201pub const WILDCARD_ALL: &str = "*";
202
203// ===========================================================================
204// Compile-time validation
205//
206// All tool name constants are validated at compile time. These assertions
207// ensure every name is non-empty, uses only [a-z0-9_], and contains no
208// leading/trailing underscores (which would signal a naming convention
209// violation). The wildcard "*" is exempt from character checks.
210// ===========================================================================
211
212const _: () = {
213    /// Validate a tool name at compile time. Panics with a clear message
214    /// if the name is empty, contains invalid characters, or has leading/
215    /// trailing underscores (except for the wildcard "*").
216    const fn validate_tool_name(name: &str) {
217        assert!(!name.is_empty(), "tool name must not be empty");
218        let bytes = name.as_bytes();
219        // Wildcard "*" is the only name allowed to bypass character checks
220        if bytes.len() == 1 && bytes[0] == b'*' {
221            return;
222        }
223        assert!(
224            bytes[0] != b'_' && bytes[bytes.len() - 1] != b'_',
225            "tool name must not have leading/trailing underscores"
226        );
227        let mut i = 0;
228        while i < bytes.len() {
229            let b = bytes[i];
230            assert!(b.is_ascii_lowercase() || b.is_ascii_digit() || b == b'_', "tool name must contain only [a-z0-9_]");
231            i += 1;
232        }
233    }
234
235    // Model-facing tools
236    validate_tool_name(EXEC_COMMAND);
237    validate_tool_name(WRITE_STDIN);
238    validate_tool_name(APPLY_PATCH);
239    validate_tool_name(CODE_SEARCH);
240
241    // Internal unified tools
242    validate_tool_name(UNIFIED_SEARCH);
243    validate_tool_name(UNIFIED_EXEC);
244    validate_tool_name(UNIFIED_FILE);
245
246    // Tool IDs
247    validate_tool_name(THINK);
248    validate_tool_name(SEARCH_TOOLS);
249    validate_tool_name(MCP);
250    validate_tool_name(MCP_SEARCH_TOOLS);
251    validate_tool_name(MCP_GET_TOOL_DETAILS);
252    validate_tool_name(MCP_LIST_SERVERS);
253    validate_tool_name(MCP_CONNECT_SERVER);
254    validate_tool_name(MCP_DISCONNECT_SERVER);
255    validate_tool_name(WEB_SEARCH);
256    validate_tool_name(WEB_FETCH);
257    validate_tool_name(FETCH_URL);
258    validate_tool_name(DEFUDDLE_FETCH);
259    validate_tool_name(LIST);
260    validate_tool_name(GREP);
261    validate_tool_name(FETCH);
262    validate_tool_name(EXEC_PTY_CMD);
263    validate_tool_name(SHELL);
264    validate_tool_name(GREP_FILE);
265    validate_tool_name(LIST_FILES);
266
267    // Skill management
268    validate_tool_name(LIST_SKILLS);
269    validate_tool_name(LOAD_SKILL);
270    validate_tool_name(LOAD_SKILL_RESOURCE);
271
272    // Internal execution helpers
273    validate_tool_name(RUN_PTY_CMD);
274    validate_tool_name(CREATE_PTY_SESSION);
275    validate_tool_name(LIST_PTY_SESSIONS);
276    validate_tool_name(CLOSE_PTY_SESSION);
277    validate_tool_name(SEND_PTY_INPUT);
278    validate_tool_name(READ_PTY_SESSION);
279    validate_tool_name(RESIZE_PTY_SESSION);
280    validate_tool_name(EXECUTE_CODE);
281
282    // Internal file operation helpers
283    validate_tool_name(READ_FILE);
284    validate_tool_name(WRITE_FILE);
285    validate_tool_name(EDIT_FILE);
286    validate_tool_name(DELETE_FILE);
287    validate_tool_name(CREATE_FILE);
288    validate_tool_name(SEARCH_REPLACE);
289    validate_tool_name(FILE_OP);
290    validate_tool_name(MOVE_FILE);
291    validate_tool_name(COPY_FILE);
292
293    // Error & diagnostics
294    validate_tool_name(GET_ERRORS);
295
296    // HITL
297    validate_tool_name(REQUEST_USER_INPUT);
298    validate_tool_name(MEMORY);
299    validate_tool_name(ASK_QUESTIONS);
300    validate_tool_name(ASK_USER_QUESTION);
301    validate_tool_name(AGENT);
302    validate_tool_name(CRON);
303    validate_tool_name(CRON_CREATE);
304    validate_tool_name(CRON_LIST);
305    validate_tool_name(CRON_DELETE);
306
307    // Planning workflow
308    validate_tool_name(START_PLANNING);
309    validate_tool_name(TASK_TRACKER);
310
311    // Subagent collaboration
312    validate_tool_name(SPAWN_AGENT);
313    validate_tool_name(SPAWN_BACKGROUND_SUBPROCESS);
314    validate_tool_name(SEND_INPUT);
315    validate_tool_name(WAIT_AGENT);
316    validate_tool_name(RESUME_AGENT);
317    validate_tool_name(CLOSE_AGENT);
318
319    // Wildcard
320    validate_tool_name(WILDCARD_ALL);
321};
322
323#[cfg(test)]
324mod tests {
325    use super::*;
326
327    #[test]
328    fn workflow_coordination_tools_bypass_the_full_auto_allow_list() {
329        for tool in [TASK_TRACKER, START_PLANNING, REQUEST_USER_INPUT] {
330            assert!(is_workflow_coordination_tool(tool), "{tool} must bypass the allow-list");
331        }
332    }
333
334    #[test]
335    fn execution_tools_do_not_bypass_the_full_auto_allow_list() {
336        for tool in [
337            EXEC_COMMAND,
338            WRITE_STDIN,
339            APPLY_PATCH,
340            CODE_SEARCH,
341            WEB_FETCH,
342            "not_a_tool",
343        ] {
344            assert!(!is_workflow_coordination_tool(tool), "{tool} must stay allow-list gated");
345        }
346    }
347}