Skip to main content

vtcode_acp/tooling/
schemas.rs

1use std::path::Path;
2
3use serde_json::json;
4
5use vtcode_core::config::constants::tools;
6use vtcode_core::llm::provider::ToolDefinition;
7
8pub const TOOL_READ_FILE_DESCRIPTION: &str = "Read the contents of a text or source file accessible to the IDE workspace. Returns file content with line numbers. For binary files or very large files, consider shell-based inspection via exec_command instead.";
9pub const TOOL_READ_FILE_URI_ARG: &str = "uri";
10pub const TOOL_READ_FILE_PATH_ARG: &str = "path";
11pub const TOOL_READ_FILE_LINE_ARG: &str = "line";
12pub const TOOL_READ_FILE_LIMIT_ARG: &str = "limit";
13
14pub const TOOL_LIST_FILES_DESCRIPTION: &str = "Explore workspace files in a SUBDIRECTORY (root path is blocked). Requires path like 'src/' or 'vtcode-core/'. For root overview, use shell commands via exec_command.";
15pub const TOOL_LIST_FILES_PATH_ARG: &str = "path";
16pub const TOOL_LIST_FILES_MODE_ARG: &str = "mode";
17pub const TOOL_LIST_FILES_PAGE_ARG: &str = "page";
18pub const TOOL_LIST_FILES_PER_PAGE_ARG: &str = "per_page";
19pub const TOOL_LIST_FILES_MAX_ITEMS_ARG: &str = "max_items";
20pub const TOOL_LIST_FILES_INCLUDE_HIDDEN_ARG: &str = "include_hidden";
21pub const TOOL_LIST_FILES_RESPONSE_FORMAT_ARG: &str = "response_format";
22pub const TOOL_LIST_FILES_URI_ARG: &str = "uri";
23pub const TOOL_LIST_FILES_NAME_PATTERN_ARG: &str = "name_pattern";
24pub const TOOL_LIST_FILES_CONTENT_PATTERN_ARG: &str = "content_pattern";
25pub const TOOL_LIST_FILES_FILE_EXTENSIONS_ARG: &str = "file_extensions";
26pub const TOOL_LIST_FILES_CASE_SENSITIVE_ARG: &str = "case_sensitive";
27pub const TOOL_LIST_FILES_ITEMS_KEY: &str = "items";
28pub const TOOL_LIST_FILES_MESSAGE_KEY: &str = "message";
29pub const TOOL_LIST_FILES_RESULT_KEY: &str = "result";
30pub const TOOL_LIST_FILES_SUMMARY_MAX_ITEMS: usize = 20;
31
32pub(super) fn build_read_file_definition(workspace_root: &Path) -> ToolDefinition {
33    let workspace_display = workspace_root.display().to_string();
34    let sample_path = workspace_root.join("README.md");
35    let sample_path_string = sample_path.to_string_lossy().into_owned();
36    let sample_uri = format!("file://{sample_path_string}");
37    let description = format!(
38        "{TOOL_READ_FILE_DESCRIPTION}. Workspace root: {workspace_display}. Provide {TOOL_READ_FILE_PATH_ARG} or {TOOL_READ_FILE_URI_ARG} inside the workspace. Paths must be absolute (see ACP file system spec). Optional {TOOL_READ_FILE_LINE_ARG} and {TOOL_READ_FILE_LIMIT_ARG} control slicing.",
39    );
40    let examples = vec![
41        json!({
42            TOOL_READ_FILE_PATH_ARG: &sample_path_string,
43        }),
44        json!({
45            TOOL_READ_FILE_PATH_ARG: &sample_path_string,
46            TOOL_READ_FILE_LINE_ARG: 1,
47            TOOL_READ_FILE_LIMIT_ARG: 200,
48        }),
49        json!({
50            TOOL_READ_FILE_URI_ARG: sample_uri,
51        }),
52    ];
53    let schema = json!({
54        "type": "object",
55        "minProperties": 1,
56        "properties": {
57            TOOL_READ_FILE_PATH_ARG: {
58                "type": "string",
59                "description": "Absolute path to the file within the workspace",
60                "minLength": 1,
61            },
62            TOOL_READ_FILE_URI_ARG: {
63                "type": "string",
64                "description": "File URI using file:// or editor-specific schemes",
65                "minLength": 1,
66            },
67            TOOL_READ_FILE_LINE_ARG: {
68                "type": "integer",
69                "minimum": 1,
70                "description": "1-based line number to start reading from",
71            },
72            TOOL_READ_FILE_LIMIT_ARG: {
73                "type": "integer",
74                "minimum": 1,
75                "description": "Maximum number of lines to read",
76            }
77        },
78        "additionalProperties": false,
79        "description": description,
80        "examples": examples,
81    });
82
83    ToolDefinition::function(tools::READ_FILE.to_string(), description, schema)
84}
85
86pub(super) fn build_list_files_definition(workspace_root: &Path) -> ToolDefinition {
87    let description = format!(
88        "{TOOL_LIST_FILES_DESCRIPTION}. Workspace root: {}. Provide {path} (relative) or {uri} inside the workspace. Defaults to '.' when omitted.",
89        workspace_root.display(),
90        path = TOOL_LIST_FILES_PATH_ARG,
91        uri = TOOL_LIST_FILES_URI_ARG,
92    );
93    let workspace_display = workspace_root.display().to_string();
94    let examples = vec![
95        json!({
96            TOOL_LIST_FILES_MODE_ARG: "list",
97        }),
98        json!({
99            TOOL_LIST_FILES_PATH_ARG: "src",
100            TOOL_LIST_FILES_MODE_ARG: "recursive",
101            TOOL_LIST_FILES_PER_PAGE_ARG: 100,
102        }),
103        json!({
104            TOOL_LIST_FILES_URI_ARG: format!("file://{}/src", workspace_display),
105        }),
106    ];
107    let schema = json!({
108        "type": "object",
109        "properties": {
110            TOOL_LIST_FILES_PATH_ARG: {
111                "type": "string",
112                "description": "Directory or file path relative to the workspace root",
113                "default": ".",
114            },
115            TOOL_LIST_FILES_MODE_ARG: {
116                "type": "string",
117                "enum": ["list", "recursive", "find_name", "find_content"],
118                "description": "Listing mode: list (default), recursive, find_name, or find_content",
119            },
120            TOOL_LIST_FILES_PAGE_ARG: {
121                "type": "integer",
122                "minimum": 1,
123                "description": "Page number to return (1-based)",
124            },
125            TOOL_LIST_FILES_PER_PAGE_ARG: {
126                "type": "integer",
127                "minimum": 1,
128                "description": "Items per page (default 50)",
129            },
130            TOOL_LIST_FILES_MAX_ITEMS_ARG: {
131                "type": "integer",
132                "minimum": 1,
133                "description": "Maximum number of items to scan before truncation",
134            },
135            TOOL_LIST_FILES_INCLUDE_HIDDEN_ARG: {
136                "type": "boolean",
137                "description": "Whether to include dotfiles and ignored entries",
138            },
139            TOOL_LIST_FILES_RESPONSE_FORMAT_ARG: {
140                "type": "string",
141                "enum": ["concise", "detailed"],
142                "description": "Choose concise (default) or detailed metadata",
143            },
144            TOOL_LIST_FILES_NAME_PATTERN_ARG: {
145                "type": "string",
146                "description": "Optional filename pattern used by recursive or find_name modes",
147            },
148            TOOL_LIST_FILES_CONTENT_PATTERN_ARG: {
149                "type": "string",
150                "description": "Pattern to search within files when using find_content mode",
151            },
152            TOOL_LIST_FILES_FILE_EXTENSIONS_ARG: {
153                "type": "array",
154                "items": {"type": "string"},
155                "description": "Restrict results to files matching any extension",
156            },
157            TOOL_LIST_FILES_CASE_SENSITIVE_ARG: {
158                "type": "boolean",
159                "description": "Enable case sensitive matching for patterns",
160            },
161        },
162        "additionalProperties": false,
163        "description": description,
164        "examples": examples,
165    });
166
167    ToolDefinition::function(tools::LIST_FILES.to_string(), description, schema)
168}