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}