code-ollama 0.23.2 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +287 -49
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { appendFileSync, existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, rmSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { appendFileSync, existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, rmdirSync, statSync, writeFileSync } from "node:fs";
|
|
3
3
|
import cac from "cac";
|
|
4
4
|
import { homedir, tmpdir } from "node:os";
|
|
5
5
|
import { join } from "node:path";
|
|
@@ -50,7 +50,7 @@ var LIST$1 = [
|
|
|
50
50
|
//#endregion
|
|
51
51
|
//#region package.json
|
|
52
52
|
var name = "code-ollama";
|
|
53
|
-
var version = "0.
|
|
53
|
+
var version = "0.24.0";
|
|
54
54
|
//#endregion
|
|
55
55
|
//#region src/constants/package.ts
|
|
56
56
|
var NAME = name;
|
|
@@ -107,13 +107,16 @@ var BACK = {
|
|
|
107
107
|
//#endregion
|
|
108
108
|
//#region src/constants/tool.ts
|
|
109
109
|
var tool_exports = /* @__PURE__ */ __exportAll({
|
|
110
|
+
CREATE_DIRECTORY: () => CREATE_DIRECTORY,
|
|
111
|
+
DELETE_PATH: () => DELETE_PATH,
|
|
110
112
|
EDIT_FILE: () => EDIT_FILE,
|
|
113
|
+
FIND_FILES: () => FIND_FILES,
|
|
111
114
|
GREP_SEARCH: () => GREP_SEARCH,
|
|
112
115
|
LIST_DIR: () => LIST_DIR,
|
|
113
116
|
READ_FILE: () => READ_FILE,
|
|
114
117
|
READ_TOOL_NAMES: () => READ_TOOL_NAMES,
|
|
118
|
+
RENAME_PATH: () => RENAME_PATH,
|
|
115
119
|
RUN_SHELL: () => RUN_SHELL,
|
|
116
|
-
VIEW_RANGE: () => VIEW_RANGE,
|
|
117
120
|
WEB_FETCH: () => WEB_FETCH,
|
|
118
121
|
WEB_SEARCH: () => WEB_SEARCH,
|
|
119
122
|
WRITE_FILE: () => WRITE_FILE,
|
|
@@ -122,23 +125,29 @@ var tool_exports = /* @__PURE__ */ __exportAll({
|
|
|
122
125
|
var READ_FILE = "read_file";
|
|
123
126
|
var WRITE_FILE = "write_file";
|
|
124
127
|
var EDIT_FILE = "edit_file";
|
|
128
|
+
var CREATE_DIRECTORY = "create_directory";
|
|
129
|
+
var RENAME_PATH = "rename_path";
|
|
130
|
+
var DELETE_PATH = "delete_path";
|
|
125
131
|
var RUN_SHELL = "run_shell";
|
|
126
132
|
var LIST_DIR = "list_dir";
|
|
133
|
+
var FIND_FILES = "find_files";
|
|
127
134
|
var GREP_SEARCH = "grep_search";
|
|
128
|
-
var VIEW_RANGE = "view_range";
|
|
129
135
|
var WEB_SEARCH = "web_search";
|
|
130
136
|
var WEB_FETCH = "web_fetch";
|
|
131
137
|
var READ_TOOL_NAMES = [
|
|
132
138
|
READ_FILE,
|
|
133
139
|
LIST_DIR,
|
|
140
|
+
FIND_FILES,
|
|
134
141
|
GREP_SEARCH,
|
|
135
|
-
VIEW_RANGE,
|
|
136
142
|
WEB_SEARCH,
|
|
137
143
|
WEB_FETCH
|
|
138
144
|
];
|
|
139
145
|
var WRITE_TOOL_NAMES = [
|
|
140
146
|
WRITE_FILE,
|
|
141
147
|
EDIT_FILE,
|
|
148
|
+
CREATE_DIRECTORY,
|
|
149
|
+
RENAME_PATH,
|
|
150
|
+
DELETE_PATH,
|
|
142
151
|
RUN_SHELL
|
|
143
152
|
];
|
|
144
153
|
//#endregion
|
|
@@ -157,10 +166,14 @@ Follow these rules:
|
|
|
157
166
|
|
|
158
167
|
When tools return results, incorporate them into your response naturally`;
|
|
159
168
|
var TOOL_INSTRUCTIONS = `Available tools:
|
|
160
|
-
- read_file: Read file contents at a path
|
|
169
|
+
- read_file: Read file contents at a path; supports startLine, endLine, and maxLines options
|
|
161
170
|
- write_file: Write content to a file (requires approval)
|
|
162
171
|
- edit_file: Replace one exact text match in a file (requires approval)
|
|
172
|
+
- create_directory: Create a directory and missing parent directories (requires approval)
|
|
173
|
+
- rename_path: Rename or move a file or directory without overwriting existing destinations (requires approval)
|
|
174
|
+
- delete_path: Delete a file or directory; non-empty directories require recursive=true (requires approval)
|
|
163
175
|
- list_dir: List files in a directory
|
|
176
|
+
- find_files: Recursively find files by optional substring or wildcard path pattern; supports includeHidden and ignoredDirs options
|
|
164
177
|
- grep_search: Search code with regex
|
|
165
178
|
- web_search: Search the web for current or external information
|
|
166
179
|
- run_shell: Execute shell commands (requires approval)
|
|
@@ -815,10 +828,24 @@ function defineTool(name, description, params, required) {
|
|
|
815
828
|
* Tool definitions for Ollama API
|
|
816
829
|
*/
|
|
817
830
|
var TOOLS = [
|
|
818
|
-
defineTool(READ_FILE, "Read the contents of a file at the specified path
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
831
|
+
defineTool(READ_FILE, "Read the contents of a file at the specified path, optionally limited by line range", {
|
|
832
|
+
path: {
|
|
833
|
+
type: "string",
|
|
834
|
+
description: "The path to the file to read"
|
|
835
|
+
},
|
|
836
|
+
startLine: {
|
|
837
|
+
type: "number",
|
|
838
|
+
description: "Optional starting line number to read from (1-indexed)"
|
|
839
|
+
},
|
|
840
|
+
endLine: {
|
|
841
|
+
type: "number",
|
|
842
|
+
description: "Optional ending line number to read through (inclusive)"
|
|
843
|
+
},
|
|
844
|
+
maxLines: {
|
|
845
|
+
type: "number",
|
|
846
|
+
description: "Optional maximum number of lines to read; cannot be combined with endLine"
|
|
847
|
+
}
|
|
848
|
+
}, ["path"]),
|
|
822
849
|
defineTool(WRITE_FILE, "Write content to a file at the specified path", {
|
|
823
850
|
path: {
|
|
824
851
|
type: "string",
|
|
@@ -847,6 +874,30 @@ var TOOLS = [
|
|
|
847
874
|
"oldText",
|
|
848
875
|
"newText"
|
|
849
876
|
]),
|
|
877
|
+
defineTool(CREATE_DIRECTORY, "Create a directory and any missing parent directories at the specified path", { path: {
|
|
878
|
+
type: "string",
|
|
879
|
+
description: "The directory path to create"
|
|
880
|
+
} }, ["path"]),
|
|
881
|
+
defineTool(RENAME_PATH, "Rename or move an existing file or directory to a new path", {
|
|
882
|
+
from: {
|
|
883
|
+
type: "string",
|
|
884
|
+
description: "The existing file or directory path to rename or move"
|
|
885
|
+
},
|
|
886
|
+
to: {
|
|
887
|
+
type: "string",
|
|
888
|
+
description: "The destination path for the renamed or moved item"
|
|
889
|
+
}
|
|
890
|
+
}, ["from", "to"]),
|
|
891
|
+
defineTool(DELETE_PATH, "Delete a file or directory at the specified path", {
|
|
892
|
+
path: {
|
|
893
|
+
type: "string",
|
|
894
|
+
description: "The file or directory path to delete"
|
|
895
|
+
},
|
|
896
|
+
recursive: {
|
|
897
|
+
type: "boolean",
|
|
898
|
+
description: "Whether to delete non-empty directories recursively; use false for files and empty directories"
|
|
899
|
+
}
|
|
900
|
+
}, ["path", "recursive"]),
|
|
850
901
|
defineTool(RUN_SHELL, "Execute a shell command", { command: {
|
|
851
902
|
type: "string",
|
|
852
903
|
description: "The shell command to execute"
|
|
@@ -855,6 +906,28 @@ var TOOLS = [
|
|
|
855
906
|
type: "string",
|
|
856
907
|
description: "The path to the directory to list"
|
|
857
908
|
} }, ["path"]),
|
|
909
|
+
defineTool(FIND_FILES, "Recursively find files under a directory, optionally matching a simple substring or wildcard pattern", {
|
|
910
|
+
path: {
|
|
911
|
+
type: "string",
|
|
912
|
+
description: "The directory path to search in"
|
|
913
|
+
},
|
|
914
|
+
pattern: {
|
|
915
|
+
type: "string",
|
|
916
|
+
description: "Optional case-insensitive substring or wildcard pattern to match against file paths"
|
|
917
|
+
},
|
|
918
|
+
includeHidden: {
|
|
919
|
+
type: "boolean",
|
|
920
|
+
description: "Whether to include hidden files and directories; defaults to false"
|
|
921
|
+
},
|
|
922
|
+
ignoredDirs: {
|
|
923
|
+
type: "array",
|
|
924
|
+
description: "Optional directory names or simple wildcard patterns to skip instead of the default ignored directory list; .git is always skipped",
|
|
925
|
+
items: {
|
|
926
|
+
type: "string",
|
|
927
|
+
description: "Directory name or wildcard pattern to skip"
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
}, ["path"]),
|
|
858
931
|
defineTool(GREP_SEARCH, "Search files within a directory; multi-word queries also match common code identifier forms", {
|
|
859
932
|
pattern: {
|
|
860
933
|
type: "string",
|
|
@@ -865,24 +938,6 @@ var TOOLS = [
|
|
|
865
938
|
description: "The directory path to search in"
|
|
866
939
|
}
|
|
867
940
|
}, ["pattern", "path"]),
|
|
868
|
-
defineTool(VIEW_RANGE, "View a specific range of lines from a file", {
|
|
869
|
-
path: {
|
|
870
|
-
type: "string",
|
|
871
|
-
description: "The path to the file"
|
|
872
|
-
},
|
|
873
|
-
start: {
|
|
874
|
-
type: "number",
|
|
875
|
-
description: "The starting line number (1-indexed)"
|
|
876
|
-
},
|
|
877
|
-
end: {
|
|
878
|
-
type: "number",
|
|
879
|
-
description: "The ending line number (inclusive)"
|
|
880
|
-
}
|
|
881
|
-
}, [
|
|
882
|
-
"path",
|
|
883
|
-
"start",
|
|
884
|
-
"end"
|
|
885
|
-
]),
|
|
886
941
|
defineTool(WEB_SEARCH, "Search the web for external or current information", { query: {
|
|
887
942
|
type: "string",
|
|
888
943
|
description: "The search query to look up"
|
|
@@ -926,6 +981,17 @@ async function runShell(command) {
|
|
|
926
981
|
var DIFF_CONTEXT_LINES = 3;
|
|
927
982
|
var DIFF_MAX_LINES = 120;
|
|
928
983
|
var DIFF_MAX_CHARS = 12e3;
|
|
984
|
+
var DEFAULT_FIND_FILES_IGNORED_DIRS = [
|
|
985
|
+
"node_modules",
|
|
986
|
+
"__pycache__",
|
|
987
|
+
".*cache",
|
|
988
|
+
".tox",
|
|
989
|
+
".venv",
|
|
990
|
+
"venv",
|
|
991
|
+
"dist",
|
|
992
|
+
"build",
|
|
993
|
+
"coverage"
|
|
994
|
+
];
|
|
929
995
|
function splitLines(content) {
|
|
930
996
|
return content.split("\n");
|
|
931
997
|
}
|
|
@@ -993,16 +1059,63 @@ function buildSearchPatterns(pattern) {
|
|
|
993
1059
|
function capitalize(value) {
|
|
994
1060
|
return value.charAt(0).toUpperCase() + value.slice(1);
|
|
995
1061
|
}
|
|
1062
|
+
function escapeRegExp(value) {
|
|
1063
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1064
|
+
}
|
|
1065
|
+
function fileMatchesPattern(filePath, pattern) {
|
|
1066
|
+
const trimmedPattern = pattern?.trim();
|
|
1067
|
+
if (!trimmedPattern) return true;
|
|
1068
|
+
const normalizedPath = filePath.toLowerCase();
|
|
1069
|
+
const normalizedFileName = normalizedPath.slice(Math.max(normalizedPath.lastIndexOf("/"), normalizedPath.lastIndexOf("\\")) + 1);
|
|
1070
|
+
const normalizedPattern = trimmedPattern.toLowerCase();
|
|
1071
|
+
if (!normalizedPattern.includes("*") && !normalizedPattern.includes("?")) return normalizedPath.includes(normalizedPattern);
|
|
1072
|
+
const regexPattern = normalizedPattern.split("").map((char) => {
|
|
1073
|
+
if (char === "*") return ".*";
|
|
1074
|
+
if (char === "?") return ".";
|
|
1075
|
+
return escapeRegExp(char);
|
|
1076
|
+
}).join("");
|
|
1077
|
+
const regex = new RegExp(`^${regexPattern}$`);
|
|
1078
|
+
return regex.test(normalizedPath) || regex.test(normalizedFileName);
|
|
1079
|
+
}
|
|
1080
|
+
function valueMatchesWildcardPattern(value, pattern) {
|
|
1081
|
+
const normalizedValue = value.toLowerCase();
|
|
1082
|
+
const normalizedPattern = pattern.trim().toLowerCase();
|
|
1083
|
+
if (!normalizedPattern.includes("*") && !normalizedPattern.includes("?")) return normalizedValue === normalizedPattern;
|
|
1084
|
+
const regexPattern = normalizedPattern.split("").map((char) => {
|
|
1085
|
+
if (char === "*") return ".*";
|
|
1086
|
+
if (char === "?") return ".";
|
|
1087
|
+
return escapeRegExp(char);
|
|
1088
|
+
}).join("");
|
|
1089
|
+
return new RegExp(`^${regexPattern}$`).test(normalizedValue);
|
|
1090
|
+
}
|
|
1091
|
+
function directoryMatchesIgnoredPattern(dirName, ignoredDirs) {
|
|
1092
|
+
for (const ignoredDir of ignoredDirs) if (valueMatchesWildcardPattern(dirName, ignoredDir)) return true;
|
|
1093
|
+
return false;
|
|
1094
|
+
}
|
|
1095
|
+
function formatNumberedLines(lines, startLine) {
|
|
1096
|
+
return lines.map((line, index) => `${String(startLine + index)}: ${line}`).join("\n");
|
|
1097
|
+
}
|
|
996
1098
|
/**
|
|
997
1099
|
* Read file contents
|
|
998
1100
|
*/
|
|
999
|
-
function readFile(filePath) {
|
|
1101
|
+
function readFile(filePath, options = {}) {
|
|
1000
1102
|
try {
|
|
1001
1103
|
if (!existsSync(filePath)) return {
|
|
1002
1104
|
content: "",
|
|
1003
1105
|
error: `File not found: ${filePath}`
|
|
1004
1106
|
};
|
|
1005
|
-
|
|
1107
|
+
const content = readFileSync(filePath, "utf8");
|
|
1108
|
+
if (!(options.startLine !== void 0 || options.endLine !== void 0 || options.maxLines !== void 0)) return { content };
|
|
1109
|
+
const lines = content.split("\n");
|
|
1110
|
+
const startLine = options.startLine ?? 1;
|
|
1111
|
+
const endLine = options.endLine ?? startLine + (options.maxLines ?? lines.length) - 1;
|
|
1112
|
+
const startIndex = startLine - 1;
|
|
1113
|
+
const endIndex = Math.min(lines.length, endLine);
|
|
1114
|
+
if (startIndex >= lines.length) return {
|
|
1115
|
+
content: "",
|
|
1116
|
+
error: "Invalid line range"
|
|
1117
|
+
};
|
|
1118
|
+
return { content: formatNumberedLines(lines.slice(startIndex, endIndex), startLine) };
|
|
1006
1119
|
} catch (error) {
|
|
1007
1120
|
return {
|
|
1008
1121
|
content: "",
|
|
@@ -1067,26 +1180,73 @@ function editFile(filePath, oldText, newText) {
|
|
|
1067
1180
|
}
|
|
1068
1181
|
}
|
|
1069
1182
|
/**
|
|
1070
|
-
*
|
|
1183
|
+
* Create a directory and any missing parent directories
|
|
1071
1184
|
*/
|
|
1072
|
-
function
|
|
1185
|
+
function createDirectory(dirPath) {
|
|
1073
1186
|
try {
|
|
1074
|
-
if (
|
|
1187
|
+
if (existsSync(dirPath)) {
|
|
1188
|
+
if (statSync(dirPath).isDirectory()) return { content: `Directory already exists: ${dirPath}` };
|
|
1189
|
+
return {
|
|
1190
|
+
content: "",
|
|
1191
|
+
error: `Path already exists and is not a directory: ${dirPath}`
|
|
1192
|
+
};
|
|
1193
|
+
}
|
|
1194
|
+
mkdirSync(dirPath, { recursive: true });
|
|
1195
|
+
return { content: `Directory created successfully: ${dirPath}` };
|
|
1196
|
+
} catch (error) {
|
|
1197
|
+
return {
|
|
1075
1198
|
content: "",
|
|
1076
|
-
error: `
|
|
1199
|
+
error: `Failed to create directory: ${error instanceof Error ? error.message : String(error)}`
|
|
1077
1200
|
};
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
/**
|
|
1204
|
+
* Rename or move an existing file or directory
|
|
1205
|
+
*/
|
|
1206
|
+
function renamePath(fromPath, toPath) {
|
|
1207
|
+
try {
|
|
1208
|
+
if (!existsSync(fromPath)) return {
|
|
1082
1209
|
content: "",
|
|
1083
|
-
error:
|
|
1210
|
+
error: `Source path not found: ${fromPath}`
|
|
1211
|
+
};
|
|
1212
|
+
if (existsSync(toPath)) return {
|
|
1213
|
+
content: "",
|
|
1214
|
+
error: `Destination path already exists: ${toPath}`
|
|
1084
1215
|
};
|
|
1085
|
-
|
|
1216
|
+
renameSync(fromPath, toPath);
|
|
1217
|
+
return { content: `Path renamed successfully: ${fromPath} -> ${toPath}` };
|
|
1086
1218
|
} catch (error) {
|
|
1087
1219
|
return {
|
|
1088
1220
|
content: "",
|
|
1089
|
-
error: `Failed to
|
|
1221
|
+
error: `Failed to rename path: ${error instanceof Error ? error.message : String(error)}`
|
|
1222
|
+
};
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
/**
|
|
1226
|
+
* Delete a file or directory
|
|
1227
|
+
*/
|
|
1228
|
+
function deletePath(path, recursive) {
|
|
1229
|
+
try {
|
|
1230
|
+
if (!existsSync(path)) return {
|
|
1231
|
+
content: "",
|
|
1232
|
+
error: `Path not found: ${path}`
|
|
1233
|
+
};
|
|
1234
|
+
if (statSync(path).isDirectory()) {
|
|
1235
|
+
if (readdirSync(path).length > 0 && !recursive) return {
|
|
1236
|
+
content: "",
|
|
1237
|
+
error: `Directory is not empty; set recursive to true to delete: ${path}`
|
|
1238
|
+
};
|
|
1239
|
+
if (recursive) rmSync(path, {
|
|
1240
|
+
recursive: true,
|
|
1241
|
+
force: false
|
|
1242
|
+
});
|
|
1243
|
+
else rmdirSync(path);
|
|
1244
|
+
} else rmSync(path, { force: false });
|
|
1245
|
+
return { content: `Path deleted successfully: ${path}` };
|
|
1246
|
+
} catch (error) {
|
|
1247
|
+
return {
|
|
1248
|
+
content: "",
|
|
1249
|
+
error: `Failed to delete path: ${error instanceof Error ? error.message : String(error)}`
|
|
1090
1250
|
};
|
|
1091
1251
|
}
|
|
1092
1252
|
}
|
|
@@ -1110,6 +1270,40 @@ function listDir(dirPath) {
|
|
|
1110
1270
|
}
|
|
1111
1271
|
}
|
|
1112
1272
|
/**
|
|
1273
|
+
* Recursively find files by path
|
|
1274
|
+
*/
|
|
1275
|
+
function findFiles(dirPath, options = {}) {
|
|
1276
|
+
try {
|
|
1277
|
+
if (!existsSync(dirPath)) return {
|
|
1278
|
+
content: "",
|
|
1279
|
+
error: `Directory not found: ${dirPath}`
|
|
1280
|
+
};
|
|
1281
|
+
if (!statSync(dirPath).isDirectory()) return {
|
|
1282
|
+
content: "",
|
|
1283
|
+
error: `Path is not a directory: ${dirPath}`
|
|
1284
|
+
};
|
|
1285
|
+
const results = [];
|
|
1286
|
+
const includeHidden = options.includeHidden ?? false;
|
|
1287
|
+
const ignoredDirs = new Set(options.ignoredDirs ?? DEFAULT_FIND_FILES_IGNORED_DIRS);
|
|
1288
|
+
function searchDirectory(currentPath) {
|
|
1289
|
+
const entries = readdirSync(currentPath, { withFileTypes: true });
|
|
1290
|
+
for (const entry of entries) {
|
|
1291
|
+
const fullPath = join(currentPath, entry.name);
|
|
1292
|
+
if (entry.isDirectory()) {
|
|
1293
|
+
if (entry.name !== ".git" && !directoryMatchesIgnoredPattern(entry.name, ignoredDirs) && (includeHidden || !entry.name.startsWith("."))) searchDirectory(fullPath);
|
|
1294
|
+
} else if (entry.isFile() && (includeHidden || !entry.name.startsWith(".")) && fileMatchesPattern(fullPath, options.pattern)) results.push(fullPath);
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
searchDirectory(dirPath);
|
|
1298
|
+
return { content: results.join("\n") };
|
|
1299
|
+
} catch (error) {
|
|
1300
|
+
return {
|
|
1301
|
+
content: "",
|
|
1302
|
+
error: `Failed to find files: ${error instanceof Error ? error.message : String(error)}`
|
|
1303
|
+
};
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
/**
|
|
1113
1307
|
* Search for pattern in files using ripgrep if available, fallback to Node.js
|
|
1114
1308
|
*/
|
|
1115
1309
|
async function grepSearch(pattern, dirPath) {
|
|
@@ -1333,10 +1527,13 @@ var REQUIRED_STRING_ARGS = {
|
|
|
1333
1527
|
"oldText",
|
|
1334
1528
|
"newText"
|
|
1335
1529
|
],
|
|
1530
|
+
[CREATE_DIRECTORY]: ["path"],
|
|
1531
|
+
[RENAME_PATH]: ["from", "to"],
|
|
1532
|
+
[DELETE_PATH]: ["path"],
|
|
1336
1533
|
[RUN_SHELL]: ["command"],
|
|
1337
1534
|
[LIST_DIR]: ["path"],
|
|
1535
|
+
[FIND_FILES]: ["path"],
|
|
1338
1536
|
[GREP_SEARCH]: ["pattern", "path"],
|
|
1339
|
-
[VIEW_RANGE]: ["path"],
|
|
1340
1537
|
[WEB_SEARCH]: ["query"],
|
|
1341
1538
|
[WEB_FETCH]: ["url"]
|
|
1342
1539
|
};
|
|
@@ -1351,14 +1548,44 @@ function validateArgs(name, args) {
|
|
|
1351
1548
|
content: "",
|
|
1352
1549
|
error: `Missing required argument: ${key} (received keys: ${received})`
|
|
1353
1550
|
};
|
|
1354
|
-
if (name === "
|
|
1355
|
-
|
|
1551
|
+
if (name === "read_file") {
|
|
1552
|
+
for (const key of [
|
|
1553
|
+
"startLine",
|
|
1554
|
+
"endLine",
|
|
1555
|
+
"maxLines"
|
|
1556
|
+
]) if (args[key] !== void 0 && !Number.isInteger(args[key])) return {
|
|
1557
|
+
content: "",
|
|
1558
|
+
error: `Invalid optional numeric argument: ${key} (received keys: ${received})`
|
|
1559
|
+
};
|
|
1560
|
+
if (typeof args.startLine === "number" && args.startLine < 1 || typeof args.endLine === "number" && args.endLine < 1 || typeof args.maxLines === "number" && args.maxLines < 1) return {
|
|
1561
|
+
content: "",
|
|
1562
|
+
error: "Invalid read range: startLine, endLine, and maxLines must be >= 1"
|
|
1563
|
+
};
|
|
1564
|
+
if (args.endLine !== void 0 && args.maxLines !== void 0) return {
|
|
1356
1565
|
content: "",
|
|
1357
|
-
error:
|
|
1566
|
+
error: "Invalid read range: endLine cannot be combined with maxLines"
|
|
1358
1567
|
};
|
|
1359
|
-
if (args.
|
|
1568
|
+
if (typeof args.startLine === "number" && typeof args.endLine === "number" && args.endLine < args.startLine) return {
|
|
1569
|
+
content: "",
|
|
1570
|
+
error: "Invalid read range: endLine must be >= startLine"
|
|
1571
|
+
};
|
|
1572
|
+
}
|
|
1573
|
+
if (name === "delete_path" && typeof args.recursive !== "boolean") return {
|
|
1574
|
+
content: "",
|
|
1575
|
+
error: `Missing required boolean argument: recursive (received keys: ${received})`
|
|
1576
|
+
};
|
|
1577
|
+
if (name === "find_files" && args.pattern !== void 0 && typeof args.pattern !== "string") return {
|
|
1578
|
+
content: "",
|
|
1579
|
+
error: `Invalid optional argument: pattern must be a string (received keys: ${received})`
|
|
1580
|
+
};
|
|
1581
|
+
if (name === "find_files" && args.includeHidden !== void 0 && typeof args.includeHidden !== "boolean") return {
|
|
1582
|
+
content: "",
|
|
1583
|
+
error: `Invalid optional argument: includeHidden must be a boolean (received keys: ${received})`
|
|
1584
|
+
};
|
|
1585
|
+
if (name === "find_files" && args.ignoredDirs !== void 0) {
|
|
1586
|
+
if (!Array.isArray(args.ignoredDirs) || !args.ignoredDirs.every((value) => typeof value === "string")) return {
|
|
1360
1587
|
content: "",
|
|
1361
|
-
error:
|
|
1588
|
+
error: `Invalid optional argument: ignoredDirs must be an array of strings (received keys: ${received})`
|
|
1362
1589
|
};
|
|
1363
1590
|
}
|
|
1364
1591
|
if (name === "web_fetch") try {
|
|
@@ -1435,13 +1662,24 @@ async function executeTool(name, args, options) {
|
|
|
1435
1662
|
if (invalid) return invalid;
|
|
1436
1663
|
const stringArgs = args;
|
|
1437
1664
|
switch (name) {
|
|
1438
|
-
case READ_FILE: return readFile(stringArgs.path
|
|
1665
|
+
case READ_FILE: return readFile(stringArgs.path, {
|
|
1666
|
+
endLine: args.endLine,
|
|
1667
|
+
maxLines: args.maxLines,
|
|
1668
|
+
startLine: args.startLine
|
|
1669
|
+
});
|
|
1439
1670
|
case WRITE_FILE: return writeFile(stringArgs.path, stringArgs.content);
|
|
1440
1671
|
case EDIT_FILE: return editFile(stringArgs.path, stringArgs.oldText, stringArgs.newText);
|
|
1672
|
+
case CREATE_DIRECTORY: return createDirectory(stringArgs.path);
|
|
1673
|
+
case RENAME_PATH: return renamePath(stringArgs.from, stringArgs.to);
|
|
1674
|
+
case DELETE_PATH: return deletePath(stringArgs.path, args.recursive);
|
|
1441
1675
|
case RUN_SHELL: return runShell(stringArgs.command);
|
|
1442
1676
|
case LIST_DIR: return listDir(stringArgs.path);
|
|
1677
|
+
case FIND_FILES: return findFiles(stringArgs.path, {
|
|
1678
|
+
ignoredDirs: args.ignoredDirs,
|
|
1679
|
+
includeHidden: args.includeHidden,
|
|
1680
|
+
pattern: stringArgs.pattern
|
|
1681
|
+
});
|
|
1443
1682
|
case GREP_SEARCH: return await grepSearch(stringArgs.pattern, stringArgs.path);
|
|
1444
|
-
case VIEW_RANGE: return viewRange(stringArgs.path, args.start, args.end);
|
|
1445
1683
|
case WEB_SEARCH: return await webSearch(stringArgs.query);
|
|
1446
1684
|
case WEB_FETCH: return await webFetch(stringArgs.url);
|
|
1447
1685
|
// v8 ignore next 2
|