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}