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