@travisennis/acai 0.0.11 → 0.0.12
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/README.md +2 -3
- package/dist/commands/init-project/utils.d.ts.map +1 -1
- package/dist/commands/init-project/utils.js +0 -11
- package/dist/commands/manager.d.ts.map +1 -1
- package/dist/commands/manager.js +6 -1
- package/dist/commands/resources/index.d.ts.map +1 -1
- package/dist/commands/resources/index.js +4 -1
- package/dist/commands/session/index.d.ts.map +1 -1
- package/dist/commands/session/index.js +6 -0
- package/dist/commands/session/types.d.ts +1 -0
- package/dist/commands/session/types.d.ts.map +1 -1
- package/dist/commands/tools/index.d.ts +3 -0
- package/dist/commands/tools/index.d.ts.map +1 -0
- package/dist/commands/tools/index.js +190 -0
- package/dist/commands/tools/templates.d.ts +6 -0
- package/dist/commands/tools/templates.d.ts.map +1 -0
- package/dist/commands/tools/templates.js +97 -0
- package/dist/config/index.d.ts +5 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +41 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -3
- package/dist/models/anthropic-provider.d.ts +1 -1
- package/dist/models/deepseek-provider.d.ts +3 -3
- package/dist/models/deepseek-provider.js +17 -17
- package/dist/models/google-provider.d.ts +2 -4
- package/dist/models/google-provider.d.ts.map +1 -1
- package/dist/models/google-provider.js +2 -17
- package/dist/models/groq-provider.d.ts +2 -4
- package/dist/models/groq-provider.d.ts.map +1 -1
- package/dist/models/groq-provider.js +3 -21
- package/dist/models/opencode-go-provider.d.ts +11 -1
- package/dist/models/opencode-go-provider.d.ts.map +1 -1
- package/dist/models/opencode-go-provider.js +136 -0
- package/dist/models/opencode-zen-provider.d.ts +3 -3
- package/dist/models/opencode-zen-provider.d.ts.map +1 -1
- package/dist/models/opencode-zen-provider.js +26 -32
- package/dist/models/openrouter-provider.d.ts +4 -15
- package/dist/models/openrouter-provider.d.ts.map +1 -1
- package/dist/models/openrouter-provider.js +26 -169
- package/dist/models/providers.d.ts +1 -1
- package/dist/models/providers.d.ts.map +1 -1
- package/dist/models/xai-provider.d.ts +1 -2
- package/dist/models/xai-provider.d.ts.map +1 -1
- package/dist/models/xai-provider.js +0 -13
- package/dist/prompts/manager.d.ts.map +1 -1
- package/dist/prompts/manager.js +5 -1
- package/dist/prompts/system-prompt.d.ts +1 -0
- package/dist/prompts/system-prompt.d.ts.map +1 -1
- package/dist/prompts/system-prompt.js +20 -5
- package/dist/repl/index.d.ts +1 -2
- package/dist/repl/index.d.ts.map +1 -1
- package/dist/repl/index.js +5 -52
- package/dist/skills/activated-tracker.d.ts +11 -0
- package/dist/skills/activated-tracker.d.ts.map +1 -0
- package/dist/skills/activated-tracker.js +16 -0
- package/dist/skills/index.d.ts +1 -1
- package/dist/skills/index.d.ts.map +1 -1
- package/dist/skills/index.js +7 -1
- package/dist/tools/bash.d.ts +4 -4
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash.js +17 -6
- package/dist/tools/directory-tree.d.ts +4 -4
- package/dist/tools/directory-tree.d.ts.map +1 -1
- package/dist/tools/directory-tree.js +2 -0
- package/dist/tools/dynamic-tool-loader.d.ts +11 -2
- package/dist/tools/dynamic-tool-loader.d.ts.map +1 -1
- package/dist/tools/dynamic-tool-loader.js +299 -39
- package/dist/tools/edit-file.d.ts +2 -2
- package/dist/tools/glob.d.ts +16 -16
- package/dist/tools/glob.d.ts.map +1 -1
- package/dist/tools/glob.js +9 -1
- package/dist/tools/grep.d.ts +14 -14
- package/dist/tools/grep.d.ts.map +1 -1
- package/dist/tools/grep.js +7 -0
- package/dist/tools/index.d.ts +42 -36
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +16 -1
- package/dist/tools/ls.d.ts +2 -2
- package/dist/tools/ls.d.ts.map +1 -1
- package/dist/tools/ls.js +1 -0
- package/dist/tools/read-file.d.ts +8 -8
- package/dist/tools/save-file.d.ts +4 -4
- package/dist/tools/skill.d.ts +2 -1
- package/dist/tools/skill.d.ts.map +1 -1
- package/dist/tools/skill.js +55 -12
- package/dist/tools/types.d.ts +8 -2
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/web-fetch.d.ts +6 -6
- package/dist/tools/web-fetch.d.ts.map +1 -1
- package/dist/tools/web-fetch.js +27 -8
- package/dist/tools/web-search.d.ts +4 -4
- package/dist/tools/web-search.js +1 -1
- package/dist/tui/components/footer.d.ts +0 -2
- package/dist/tui/components/footer.d.ts.map +1 -1
- package/dist/tui/components/footer.js +1 -17
- package/dist/utils/binary-output.d.ts +32 -0
- package/dist/utils/binary-output.d.ts.map +1 -0
- package/dist/utils/binary-output.js +127 -0
- package/dist/utils/command-protection.d.ts.map +1 -1
- package/dist/utils/command-protection.js +92 -9
- package/dist/utils/parsing.d.ts +1 -1
- package/dist/utils/parsing.d.ts.map +1 -1
- package/package.json +27 -25
- package/dist/modes/manager.d.ts +0 -24
- package/dist/modes/manager.d.ts.map +0 -1
- package/dist/modes/manager.js +0 -77
- package/dist/modes/prompts.d.ts +0 -2
- package/dist/modes/prompts.d.ts.map +0 -1
- package/dist/modes/prompts.js +0 -142
|
@@ -18,6 +18,156 @@ const toolMetadataSchema = z.object({
|
|
|
18
18
|
})),
|
|
19
19
|
needsApproval: z.boolean().default(true),
|
|
20
20
|
});
|
|
21
|
+
const KNOWN_EXTENSIONS = [
|
|
22
|
+
".js",
|
|
23
|
+
".mjs",
|
|
24
|
+
".cjs",
|
|
25
|
+
".sh",
|
|
26
|
+
".bash",
|
|
27
|
+
".zsh",
|
|
28
|
+
".py",
|
|
29
|
+
".rb",
|
|
30
|
+
".tool",
|
|
31
|
+
];
|
|
32
|
+
const EXTENSION_INTERPRETER_MAP = {
|
|
33
|
+
".js": process.execPath,
|
|
34
|
+
".mjs": process.execPath,
|
|
35
|
+
".cjs": process.execPath,
|
|
36
|
+
".sh": "/bin/bash",
|
|
37
|
+
".bash": "/bin/bash",
|
|
38
|
+
".zsh": "/bin/zsh",
|
|
39
|
+
".py": "python3",
|
|
40
|
+
".rb": "ruby",
|
|
41
|
+
};
|
|
42
|
+
export function getShebang(scriptPath) {
|
|
43
|
+
try {
|
|
44
|
+
const fd = fs.openSync(scriptPath, "r");
|
|
45
|
+
const buffer = Buffer.alloc(256);
|
|
46
|
+
const bytesRead = fs.readSync(fd, buffer, 0, 256, 0);
|
|
47
|
+
fs.closeSync(fd);
|
|
48
|
+
const content = buffer.toString("utf8", 0, bytesRead);
|
|
49
|
+
if (content.startsWith("#!")) {
|
|
50
|
+
return content.slice(2).trim().split("\n")[0].trim();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
// Can't read file, skip
|
|
55
|
+
}
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
export function parseShebang(shebang, scriptPath) {
|
|
59
|
+
if (shebang.startsWith("/usr/bin/env ")) {
|
|
60
|
+
const interpreter = shebang
|
|
61
|
+
.slice("/usr/bin/env ".length)
|
|
62
|
+
.trim()
|
|
63
|
+
.split(" ")[0];
|
|
64
|
+
return { command: interpreter, args: [scriptPath] };
|
|
65
|
+
}
|
|
66
|
+
const parts = shebang.split(" ");
|
|
67
|
+
return { command: parts[0], args: [...parts.slice(1), scriptPath] };
|
|
68
|
+
}
|
|
69
|
+
export function resolveToolInterpreter(scriptPath) {
|
|
70
|
+
// 1. Check shebang
|
|
71
|
+
const shebang = getShebang(scriptPath);
|
|
72
|
+
if (shebang) {
|
|
73
|
+
return parseShebang(shebang, scriptPath);
|
|
74
|
+
}
|
|
75
|
+
// 2. Check extension
|
|
76
|
+
const ext = path.extname(scriptPath).toLowerCase();
|
|
77
|
+
if (EXTENSION_INTERPRETER_MAP[ext]) {
|
|
78
|
+
return { command: EXTENSION_INTERPRETER_MAP[ext], args: [scriptPath] };
|
|
79
|
+
}
|
|
80
|
+
// 3. Extensionless executable
|
|
81
|
+
if (!ext) {
|
|
82
|
+
try {
|
|
83
|
+
const stats = fs.statSync(scriptPath);
|
|
84
|
+
if (stats.mode & 0o111) {
|
|
85
|
+
return { command: scriptPath, args: [] };
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
// File doesn't exist or can't stat, skip
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
export function parseTextSchema(content) {
|
|
95
|
+
const lines = content
|
|
96
|
+
.trim()
|
|
97
|
+
.split("\n")
|
|
98
|
+
.map((l) => l.trim())
|
|
99
|
+
.filter((l) => l && !l.startsWith("#") && !l.startsWith("//"));
|
|
100
|
+
let name;
|
|
101
|
+
let description;
|
|
102
|
+
const parameters = [];
|
|
103
|
+
for (const line of lines) {
|
|
104
|
+
if (line.startsWith("name:")) {
|
|
105
|
+
name = line.slice(5).trim();
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
if (line.startsWith("description:")) {
|
|
109
|
+
description = line.slice(12).trim();
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
// Parse parameters: "paramName: type [optional|required] description text"
|
|
113
|
+
const paramMatch = line.match(/^(\w+):\s*(string|number|boolean)\s+(optional|required)?\s*(.*)$/);
|
|
114
|
+
if (paramMatch) {
|
|
115
|
+
const [, paramName, paramType, requirement, paramDescription] = paramMatch;
|
|
116
|
+
parameters.push({
|
|
117
|
+
name: paramName,
|
|
118
|
+
type: paramType,
|
|
119
|
+
description: paramDescription || `Parameter ${paramName}`,
|
|
120
|
+
required: requirement !== "optional",
|
|
121
|
+
});
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
// Handle params without type keyword (default to string)
|
|
125
|
+
const simpleMatch = line.match(/^(\w+):\s*(.*)$/);
|
|
126
|
+
if (simpleMatch &&
|
|
127
|
+
!line.startsWith("name:") &&
|
|
128
|
+
!line.startsWith("description:")) {
|
|
129
|
+
const [, paramName, rest] = simpleMatch;
|
|
130
|
+
const typeMatch = rest.match(/^(string|number|boolean)\s*(.*)$/);
|
|
131
|
+
if (typeMatch) {
|
|
132
|
+
const [, paramType, afterType] = typeMatch;
|
|
133
|
+
const optMatch = afterType.match(/^(optional|required)\s*(.*)$/);
|
|
134
|
+
parameters.push({
|
|
135
|
+
name: paramName,
|
|
136
|
+
type: paramType,
|
|
137
|
+
description: optMatch
|
|
138
|
+
? optMatch[2] || `Parameter ${paramName}`
|
|
139
|
+
: afterType || `Parameter ${paramName}`,
|
|
140
|
+
required: !optMatch || optMatch[1] !== "optional",
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
const optMatch = rest.match(/^(optional|required)\s*(.*)$/);
|
|
145
|
+
parameters.push({
|
|
146
|
+
name: paramName,
|
|
147
|
+
type: "string",
|
|
148
|
+
description: optMatch
|
|
149
|
+
? optMatch[2] || rest
|
|
150
|
+
: rest || `Parameter ${paramName}`,
|
|
151
|
+
required: !optMatch || optMatch[1] !== "optional",
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
if (!name || !description) {
|
|
157
|
+
logger.warn("Text schema missing required name or description");
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
if (!/^[a-zA-Z_][a-zA-Z0-9_-]*$/.test(name)) {
|
|
161
|
+
logger.warn(`Invalid tool name: ${name}`);
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
return {
|
|
165
|
+
name,
|
|
166
|
+
description,
|
|
167
|
+
parameters,
|
|
168
|
+
needsApproval: true,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
21
171
|
export function parseToolMetadata(output) {
|
|
22
172
|
try {
|
|
23
173
|
const parsed = JSON.parse(output.trim());
|
|
@@ -58,20 +208,29 @@ function generateZodSchema(parameters) {
|
|
|
58
208
|
}
|
|
59
209
|
return z.object(fields);
|
|
60
210
|
}
|
|
61
|
-
async function getMetadata(scriptPath) {
|
|
211
|
+
async function getMetadata(scriptPath, sessionContext) {
|
|
212
|
+
const interpreter = resolveToolInterpreter(scriptPath);
|
|
213
|
+
if (!interpreter) {
|
|
214
|
+
logger.warn(`No valid interpreter for ${scriptPath}, skipping.`);
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
62
217
|
return new Promise((resolve) => {
|
|
63
218
|
let child;
|
|
64
219
|
try {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
220
|
+
const env = {
|
|
221
|
+
...process.env,
|
|
222
|
+
// biome-ignore lint/style/useNamingConvention: Environment variables are conventionally uppercase
|
|
223
|
+
TOOL_ACTION: "describe",
|
|
224
|
+
// biome-ignore lint/style/useNamingConvention: Environment variables are conventionally uppercase
|
|
225
|
+
NODE_ENV: "production",
|
|
226
|
+
};
|
|
227
|
+
if (sessionContext) {
|
|
228
|
+
env["ACAI_SESSION_ID"] = sessionContext.sessionId;
|
|
229
|
+
env["ACAI_PROJECT_DIR"] = sessionContext.projectDir;
|
|
230
|
+
env["ACAI_AGENT_NAME"] = sessionContext.agentName;
|
|
231
|
+
}
|
|
232
|
+
child = spawn(interpreter.command, interpreter.args, {
|
|
233
|
+
env,
|
|
75
234
|
stdio: ["ignore", "pipe", "pipe"],
|
|
76
235
|
});
|
|
77
236
|
}
|
|
@@ -96,11 +255,18 @@ async function getMetadata(scriptPath) {
|
|
|
96
255
|
}
|
|
97
256
|
try {
|
|
98
257
|
const metadata = parseToolMetadata(stdout);
|
|
99
|
-
resolve(metadata);
|
|
258
|
+
resolve({ ...metadata, format: "json" });
|
|
100
259
|
}
|
|
101
|
-
catch
|
|
102
|
-
|
|
103
|
-
|
|
260
|
+
catch {
|
|
261
|
+
// JSON parse failed, try text format
|
|
262
|
+
const textMetadata = parseTextSchema(stdout);
|
|
263
|
+
if (textMetadata) {
|
|
264
|
+
resolve({ ...textMetadata, format: "text" });
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
logger.error(`Failed to parse metadata from ${scriptPath}: not valid JSON or text format`);
|
|
268
|
+
resolve(null);
|
|
269
|
+
}
|
|
104
270
|
}
|
|
105
271
|
});
|
|
106
272
|
child.on("error", (err) => {
|
|
@@ -109,22 +275,40 @@ async function getMetadata(scriptPath) {
|
|
|
109
275
|
});
|
|
110
276
|
});
|
|
111
277
|
}
|
|
112
|
-
async function spawnChildProcess(scriptPath, params, abortSignal) {
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
117
|
-
|
|
278
|
+
async function spawnChildProcess(scriptPath, params, abortSignal, sessionContext, format = "json") {
|
|
279
|
+
const interpreter = resolveToolInterpreter(scriptPath);
|
|
280
|
+
if (!interpreter) {
|
|
281
|
+
throw new Error(`No valid interpreter for ${scriptPath}`);
|
|
282
|
+
}
|
|
283
|
+
let paramsInput;
|
|
284
|
+
if (format === "text") {
|
|
285
|
+
paramsInput = `${Object.entries(params)
|
|
286
|
+
.map(([key, value]) => `${key}=${value}`)
|
|
287
|
+
.join("\n")}\n`;
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
290
|
+
const paramsArray = Object.entries(params).map(([name, value]) => ({
|
|
291
|
+
name,
|
|
292
|
+
value,
|
|
293
|
+
}));
|
|
294
|
+
paramsInput = `${JSON.stringify(paramsArray)}\n`;
|
|
295
|
+
}
|
|
296
|
+
const env = {
|
|
297
|
+
...process.env,
|
|
298
|
+
// biome-ignore lint/style/useNamingConvention: Environment variables are conventionally uppercase
|
|
299
|
+
TOOL_ACTION: "execute",
|
|
300
|
+
// biome-ignore lint/style/useNamingConvention: Environment variables are conventionally uppercase
|
|
301
|
+
NODE_ENV: "production",
|
|
302
|
+
};
|
|
303
|
+
if (sessionContext) {
|
|
304
|
+
env["ACAI_SESSION_ID"] = sessionContext.sessionId;
|
|
305
|
+
env["ACAI_PROJECT_DIR"] = sessionContext.projectDir;
|
|
306
|
+
env["ACAI_AGENT_NAME"] = sessionContext.agentName;
|
|
307
|
+
}
|
|
118
308
|
return new Promise((resolve, reject) => {
|
|
119
|
-
const child = spawn(
|
|
309
|
+
const child = spawn(interpreter.command, interpreter.args, {
|
|
120
310
|
cwd: path.dirname(scriptPath),
|
|
121
|
-
env
|
|
122
|
-
...process.env,
|
|
123
|
-
// biome-ignore lint/style/useNamingConvention: Environment variables are conventionally uppercase
|
|
124
|
-
TOOL_ACTION: "execute",
|
|
125
|
-
// biome-ignore lint/style/useNamingConvention: Environment variables are conventionally uppercase
|
|
126
|
-
NODE_ENV: "production",
|
|
127
|
-
},
|
|
311
|
+
env,
|
|
128
312
|
stdio: ["pipe", "pipe", "pipe"],
|
|
129
313
|
});
|
|
130
314
|
let stdout = "";
|
|
@@ -135,7 +319,7 @@ async function spawnChildProcess(scriptPath, params, abortSignal) {
|
|
|
135
319
|
child.kill();
|
|
136
320
|
reject(new Error("Execution timed out after 30 seconds"));
|
|
137
321
|
}, 30000);
|
|
138
|
-
child.stdin.write(
|
|
322
|
+
child.stdin.write(paramsInput);
|
|
139
323
|
child.stdin.end();
|
|
140
324
|
child.stdout.on("data", (data) => {
|
|
141
325
|
stdout += data.toString();
|
|
@@ -181,9 +365,10 @@ async function spawnChildProcess(scriptPath, params, abortSignal) {
|
|
|
181
365
|
}
|
|
182
366
|
});
|
|
183
367
|
}
|
|
184
|
-
function createDynamicTool(scriptPath, metadata) {
|
|
368
|
+
function createDynamicTool(scriptPath, metadata, sessionContext) {
|
|
185
369
|
const inputSchema = generateZodSchema(metadata.parameters);
|
|
186
370
|
const toolName = metadata.name;
|
|
371
|
+
const format = metadata.format;
|
|
187
372
|
return {
|
|
188
373
|
[toolName]: {
|
|
189
374
|
toolDef: {
|
|
@@ -193,7 +378,7 @@ function createDynamicTool(scriptPath, metadata) {
|
|
|
193
378
|
display() {
|
|
194
379
|
return "running";
|
|
195
380
|
},
|
|
196
|
-
async execute(input, { abortSignal }) {
|
|
381
|
+
async execute(input, { abortSignal, sessionContext: executionContext }) {
|
|
197
382
|
if (abortSignal?.aborted) {
|
|
198
383
|
throw new Error("Execution aborted");
|
|
199
384
|
}
|
|
@@ -203,12 +388,36 @@ function createDynamicTool(scriptPath, metadata) {
|
|
|
203
388
|
catch (e) {
|
|
204
389
|
throw new Error(`Invalid parameters for tool ${metadata.name}: ${e.message}`);
|
|
205
390
|
}
|
|
206
|
-
|
|
391
|
+
// Prefer execution-time context over load-time context
|
|
392
|
+
const context = executionContext ?? sessionContext;
|
|
393
|
+
return spawnChildProcess(scriptPath, input, abortSignal, context, format);
|
|
207
394
|
},
|
|
208
395
|
},
|
|
209
396
|
};
|
|
210
397
|
}
|
|
211
|
-
|
|
398
|
+
function findCompanion(dir, baseName) {
|
|
399
|
+
const companionExtensions = [
|
|
400
|
+
".sh",
|
|
401
|
+
".bash",
|
|
402
|
+
".zsh",
|
|
403
|
+
".py",
|
|
404
|
+
".rb",
|
|
405
|
+
".js",
|
|
406
|
+
".mjs",
|
|
407
|
+
".cjs",
|
|
408
|
+
"",
|
|
409
|
+
];
|
|
410
|
+
for (const ext of companionExtensions) {
|
|
411
|
+
const candidate = path.join(dir, baseName + ext);
|
|
412
|
+
if (fs.existsSync(candidate)) {
|
|
413
|
+
const interpreter = resolveToolInterpreter(candidate);
|
|
414
|
+
if (interpreter)
|
|
415
|
+
return candidate;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
return null;
|
|
419
|
+
}
|
|
420
|
+
export async function loadDynamicTools({ baseDir, existingToolNames = [], sessionContext, }) {
|
|
212
421
|
const projectConfig = await config.getConfig();
|
|
213
422
|
const dynamicConfig = projectConfig.tools.dynamicTools;
|
|
214
423
|
if (!dynamicConfig.enabled) {
|
|
@@ -222,13 +431,32 @@ export async function loadDynamicTools({ baseDir, existingToolNames = [], }) {
|
|
|
222
431
|
if (!fs.existsSync(dir))
|
|
223
432
|
return;
|
|
224
433
|
try {
|
|
225
|
-
const files = fs
|
|
226
|
-
|
|
227
|
-
.
|
|
434
|
+
const files = fs.readdirSync(dir).filter((f) => {
|
|
435
|
+
// Known extensions
|
|
436
|
+
if (KNOWN_EXTENSIONS.some((ext) => f.endsWith(ext))) {
|
|
437
|
+
return true;
|
|
438
|
+
}
|
|
439
|
+
// Extensionless files that are executable
|
|
440
|
+
if (!path.extname(f)) {
|
|
441
|
+
const fullPath = path.join(dir, f);
|
|
442
|
+
try {
|
|
443
|
+
const stats = fs.statSync(fullPath);
|
|
444
|
+
if (stats.mode & 0o111)
|
|
445
|
+
return true;
|
|
446
|
+
}
|
|
447
|
+
catch {
|
|
448
|
+
// Can't stat, skip
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
return false;
|
|
452
|
+
});
|
|
228
453
|
for (const file of files) {
|
|
454
|
+
// Skip .tool files, they are handled separately
|
|
455
|
+
if (file.endsWith(".tool"))
|
|
456
|
+
continue;
|
|
229
457
|
const scriptPath = path.join(dir, file);
|
|
230
458
|
try {
|
|
231
|
-
const metadata = await getMetadata(scriptPath);
|
|
459
|
+
const metadata = await getMetadata(scriptPath, sessionContext);
|
|
232
460
|
if (metadata) {
|
|
233
461
|
toolMap.set(metadata.name, { path: scriptPath, metadata });
|
|
234
462
|
logger.info(`Loaded ${isProject ? "project" : "user"} tool: ${metadata.name}`);
|
|
@@ -241,6 +469,38 @@ export async function loadDynamicTools({ baseDir, existingToolNames = [], }) {
|
|
|
241
469
|
logger.error(`Error scanning ${file}: ${e}`);
|
|
242
470
|
}
|
|
243
471
|
}
|
|
472
|
+
// Scan for .tool files (text schema with companion executable)
|
|
473
|
+
const allDirFiles = fs.readdirSync(dir);
|
|
474
|
+
const allToolFiles = allDirFiles.filter((f) => f.endsWith(".tool"));
|
|
475
|
+
for (const toolFile of allToolFiles) {
|
|
476
|
+
const toolPath = path.join(dir, toolFile);
|
|
477
|
+
try {
|
|
478
|
+
const content = fs.readFileSync(toolPath, "utf8");
|
|
479
|
+
const metadata = parseTextSchema(content);
|
|
480
|
+
if (!metadata) {
|
|
481
|
+
logger.warn(`Failed to parse .tool file: ${toolFile}`);
|
|
482
|
+
continue;
|
|
483
|
+
}
|
|
484
|
+
const baseName = toolFile.slice(0, -5); // Remove .tool extension
|
|
485
|
+
const companionPath = findCompanion(dir, baseName);
|
|
486
|
+
if (!companionPath) {
|
|
487
|
+
logger.warn(`No companion executable found for ${toolFile}`);
|
|
488
|
+
continue;
|
|
489
|
+
}
|
|
490
|
+
const metadataWithFormat = {
|
|
491
|
+
...metadata,
|
|
492
|
+
format: "text",
|
|
493
|
+
};
|
|
494
|
+
toolMap.set(metadata.name, {
|
|
495
|
+
path: companionPath,
|
|
496
|
+
metadata: metadataWithFormat,
|
|
497
|
+
});
|
|
498
|
+
logger.info(`Loaded ${isProject ? "project" : "user"} tool: ${metadata.name} (from .tool file)`);
|
|
499
|
+
}
|
|
500
|
+
catch (e) {
|
|
501
|
+
logger.error(`Error reading .tool file ${toolFile}: ${e}`);
|
|
502
|
+
}
|
|
503
|
+
}
|
|
244
504
|
}
|
|
245
505
|
catch (e) {
|
|
246
506
|
logger.error(`Error reading dir ${dir}: ${e}`);
|
|
@@ -274,7 +534,7 @@ export async function loadDynamicTools({ baseDir, existingToolNames = [], }) {
|
|
|
274
534
|
logger.warn(`Duplicate dynamic tool name '${toolName}' found. Skipping duplicate.`);
|
|
275
535
|
continue;
|
|
276
536
|
}
|
|
277
|
-
Object.assign(tools, createDynamicTool(path, metadata));
|
|
537
|
+
Object.assign(tools, createDynamicTool(path, metadata, sessionContext));
|
|
278
538
|
}
|
|
279
539
|
if (conflictingTools.length > 0) {
|
|
280
540
|
logger.warn(`Warning: ${conflictingTools.length} dynamic tool(s) skipped due to name conflicts: ${conflictingTools.join(", ")}`);
|
|
@@ -6,7 +6,7 @@ export declare const EditFileTool: {
|
|
|
6
6
|
};
|
|
7
7
|
declare const inputSchema: z.ZodObject<{
|
|
8
8
|
path: z.ZodString;
|
|
9
|
-
edits: z.
|
|
9
|
+
edits: z.ZodPreprocess<z.ZodArray<z.ZodObject<{
|
|
10
10
|
oldText: z.ZodString;
|
|
11
11
|
newText: z.ZodString;
|
|
12
12
|
}, z.core.$strip>>>;
|
|
@@ -19,7 +19,7 @@ export declare const createEditFileTool: (options: {
|
|
|
19
19
|
description: string;
|
|
20
20
|
inputSchema: z.ZodObject<{
|
|
21
21
|
path: z.ZodString;
|
|
22
|
-
edits: z.
|
|
22
|
+
edits: z.ZodPreprocess<z.ZodArray<z.ZodObject<{
|
|
23
23
|
oldText: z.ZodString;
|
|
24
24
|
newText: z.ZodString;
|
|
25
25
|
}, z.core.$strip>>>;
|
package/dist/tools/glob.d.ts
CHANGED
|
@@ -4,28 +4,28 @@ export declare const GlobTool: {
|
|
|
4
4
|
name: "Glob";
|
|
5
5
|
};
|
|
6
6
|
export declare const inputSchema: z.ZodObject<{
|
|
7
|
-
patterns: z.
|
|
8
|
-
path: z.
|
|
9
|
-
gitignore: z.
|
|
10
|
-
recursive: z.
|
|
11
|
-
expandDirectories: z.
|
|
12
|
-
ignoreFiles: z.
|
|
13
|
-
cwd: z.
|
|
14
|
-
maxResults: z.
|
|
7
|
+
patterns: z.ZodDefault<z.ZodPreprocess<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>>;
|
|
8
|
+
path: z.ZodDefault<z.ZodPreprocess<z.ZodString>>;
|
|
9
|
+
gitignore: z.ZodDefault<z.ZodPreprocess<z.ZodNullable<z.ZodCoercedBoolean<unknown>>>>;
|
|
10
|
+
recursive: z.ZodDefault<z.ZodPreprocess<z.ZodNullable<z.ZodCoercedBoolean<unknown>>>>;
|
|
11
|
+
expandDirectories: z.ZodDefault<z.ZodPreprocess<z.ZodNullable<z.ZodCoercedBoolean<unknown>>>>;
|
|
12
|
+
ignoreFiles: z.ZodDefault<z.ZodPreprocess<z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>>>;
|
|
13
|
+
cwd: z.ZodDefault<z.ZodPreprocess<z.ZodNullable<z.ZodCoercedString<unknown>>>>;
|
|
14
|
+
maxResults: z.ZodDefault<z.ZodPreprocess<z.ZodNullable<z.ZodCoercedNumber<unknown>>>>;
|
|
15
15
|
}, z.core.$strip>;
|
|
16
16
|
type GlobInputSchema = z.infer<typeof inputSchema>;
|
|
17
17
|
export declare const createGlobTool: () => {
|
|
18
18
|
toolDef: {
|
|
19
19
|
description: string;
|
|
20
20
|
inputSchema: z.ZodObject<{
|
|
21
|
-
patterns: z.
|
|
22
|
-
path: z.
|
|
23
|
-
gitignore: z.
|
|
24
|
-
recursive: z.
|
|
25
|
-
expandDirectories: z.
|
|
26
|
-
ignoreFiles: z.
|
|
27
|
-
cwd: z.
|
|
28
|
-
maxResults: z.
|
|
21
|
+
patterns: z.ZodDefault<z.ZodPreprocess<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>>;
|
|
22
|
+
path: z.ZodDefault<z.ZodPreprocess<z.ZodString>>;
|
|
23
|
+
gitignore: z.ZodDefault<z.ZodPreprocess<z.ZodNullable<z.ZodCoercedBoolean<unknown>>>>;
|
|
24
|
+
recursive: z.ZodDefault<z.ZodPreprocess<z.ZodNullable<z.ZodCoercedBoolean<unknown>>>>;
|
|
25
|
+
expandDirectories: z.ZodDefault<z.ZodPreprocess<z.ZodNullable<z.ZodCoercedBoolean<unknown>>>>;
|
|
26
|
+
ignoreFiles: z.ZodDefault<z.ZodPreprocess<z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>>>;
|
|
27
|
+
cwd: z.ZodDefault<z.ZodPreprocess<z.ZodNullable<z.ZodCoercedString<unknown>>>>;
|
|
28
|
+
maxResults: z.ZodDefault<z.ZodPreprocess<z.ZodNullable<z.ZodCoercedNumber<unknown>>>>;
|
|
29
29
|
}, z.core.$strip>;
|
|
30
30
|
};
|
|
31
31
|
display({ patterns, path }: GlobInputSchema): string;
|
package/dist/tools/glob.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"glob.d.ts","sourceRoot":"","sources":["../../source/tools/glob.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AA6EvD,eAAO,MAAM,QAAQ;;CAEpB,CAAC;AAEF,eAAO,MAAM,WAAW;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"glob.d.ts","sourceRoot":"","sources":["../../source/tools/glob.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AA6EvD,eAAO,MAAM,QAAQ;;CAEpB,CAAC;AAEF,eAAO,MAAM,WAAW;;;;;;;;;iBAkFtB,CAAC;AAEH,KAAK,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEnD,eAAO,MAAM,cAAc;;;;;;;;;;;;;;gCAMK,eAAe;wGAmBtC,eAAe,mBACD,oBAAoB,GACpC,OAAO,CAAC,MAAM,CAAC;CAuCrB,CAAC"}
|
package/dist/tools/glob.js
CHANGED
|
@@ -81,18 +81,23 @@ export const inputSchema = z.object({
|
|
|
81
81
|
}
|
|
82
82
|
return val;
|
|
83
83
|
}, z.union([z.string(), z.array(z.string())]))
|
|
84
|
+
.default("**/*")
|
|
84
85
|
.describe("Glob patterns to search for (e.g., '*.ts', '**/*.test.ts', 'src/**/*.js')"),
|
|
85
86
|
path: z
|
|
86
87
|
.preprocess((val) => (val === null || val === undefined ? process.cwd() : val), z.string())
|
|
88
|
+
.default(process.cwd())
|
|
87
89
|
.describe("Base directory to search in"),
|
|
88
90
|
gitignore: z
|
|
89
91
|
.preprocess((val) => convertNullString(val), z.coerce.boolean().nullable())
|
|
92
|
+
.default(null)
|
|
90
93
|
.describe("Respect ignore patterns in .gitignore files. (default: true)"),
|
|
91
94
|
recursive: z
|
|
92
95
|
.preprocess((val) => convertNullString(val), z.coerce.boolean().nullable())
|
|
96
|
+
.default(null)
|
|
93
97
|
.describe("Search recursively. (default: true)"),
|
|
94
98
|
expandDirectories: z
|
|
95
99
|
.preprocess((val) => convertNullString(val), z.coerce.boolean().nullable())
|
|
100
|
+
.default(null)
|
|
96
101
|
.describe("Automatically expand directories to files. (default: true)"),
|
|
97
102
|
ignoreFiles: z
|
|
98
103
|
.preprocess((val) => {
|
|
@@ -116,12 +121,15 @@ export const inputSchema = z.object({
|
|
|
116
121
|
}
|
|
117
122
|
return converted;
|
|
118
123
|
}, z.union([z.string(), z.array(z.string())]).nullable())
|
|
124
|
+
.default(null)
|
|
119
125
|
.describe("Glob patterns to look for ignore files (e.g., '.gitignore'). Pass null to use default behavior."),
|
|
120
126
|
cwd: z
|
|
121
127
|
.preprocess((val) => convertNullString(val), z.coerce.string().nullable())
|
|
128
|
+
.default(null)
|
|
122
129
|
.describe("Current working directory override. (default: process.cwd())"),
|
|
123
130
|
maxResults: z
|
|
124
131
|
.preprocess((val) => convertNullString(val), z.coerce.number().nullable())
|
|
132
|
+
.default(null)
|
|
125
133
|
.describe("Maximum number of files to return. Set to 0 for no limit. (Default: 100)"),
|
|
126
134
|
});
|
|
127
135
|
export const createGlobTool = () => {
|
|
@@ -145,7 +153,7 @@ export const createGlobTool = () => {
|
|
|
145
153
|
const effectivePath = typeof path === "string" && path.trim() !== "" ? path : process.cwd();
|
|
146
154
|
const patternArray = normalizePatternArray(patterns);
|
|
147
155
|
const effectiveMaxResults = maxResults ?? DEFAULT_MAX_RESULTS;
|
|
148
|
-
const globOptions = buildGlobOptions(effectivePath, gitignore, recursive, expandDirectories, ignoreFiles, cwd);
|
|
156
|
+
const globOptions = buildGlobOptions(effectivePath, gitignore ?? null, recursive ?? null, expandDirectories ?? null, ignoreFiles ?? null, cwd ?? null);
|
|
149
157
|
const matchingFiles = await glob(patternArray, globOptions);
|
|
150
158
|
const filesToStat = matchingFiles.length > MAX_STAT_FILES
|
|
151
159
|
? matchingFiles.slice(0, MAX_STAT_FILES)
|
package/dist/tools/grep.d.ts
CHANGED
|
@@ -6,13 +6,13 @@ export declare const GrepTool: {
|
|
|
6
6
|
declare const inputSchema: z.ZodObject<{
|
|
7
7
|
pattern: z.ZodString;
|
|
8
8
|
path: z.ZodString;
|
|
9
|
-
recursive: z.
|
|
10
|
-
ignoreCase: z.
|
|
11
|
-
filePattern: z.
|
|
12
|
-
contextLines: z.
|
|
13
|
-
searchIgnored: z.
|
|
14
|
-
literal: z.
|
|
15
|
-
maxResults: z.
|
|
9
|
+
recursive: z.ZodDefault<z.ZodPreprocess<z.ZodNullable<z.ZodCoercedBoolean<unknown>>>>;
|
|
10
|
+
ignoreCase: z.ZodDefault<z.ZodPreprocess<z.ZodNullable<z.ZodCoercedBoolean<unknown>>>>;
|
|
11
|
+
filePattern: z.ZodDefault<z.ZodPreprocess<z.ZodNullable<z.ZodCoercedString<unknown>>>>;
|
|
12
|
+
contextLines: z.ZodDefault<z.ZodPreprocess<z.ZodNullable<z.ZodCoercedNumber<unknown>>>>;
|
|
13
|
+
searchIgnored: z.ZodDefault<z.ZodPreprocess<z.ZodNullable<z.ZodCoercedBoolean<unknown>>>>;
|
|
14
|
+
literal: z.ZodDefault<z.ZodPreprocess<z.ZodNullable<z.ZodCoercedBoolean<unknown>>>>;
|
|
15
|
+
maxResults: z.ZodDefault<z.ZodPreprocess<z.ZodNullable<z.ZodCoercedNumber<unknown>>>>;
|
|
16
16
|
}, z.core.$strip>;
|
|
17
17
|
type GrepInputSchema = z.infer<typeof inputSchema>;
|
|
18
18
|
export declare const createGrepTool: () => {
|
|
@@ -21,13 +21,13 @@ export declare const createGrepTool: () => {
|
|
|
21
21
|
inputSchema: z.ZodObject<{
|
|
22
22
|
pattern: z.ZodString;
|
|
23
23
|
path: z.ZodString;
|
|
24
|
-
recursive: z.
|
|
25
|
-
ignoreCase: z.
|
|
26
|
-
filePattern: z.
|
|
27
|
-
contextLines: z.
|
|
28
|
-
searchIgnored: z.
|
|
29
|
-
literal: z.
|
|
30
|
-
maxResults: z.
|
|
24
|
+
recursive: z.ZodDefault<z.ZodPreprocess<z.ZodNullable<z.ZodCoercedBoolean<unknown>>>>;
|
|
25
|
+
ignoreCase: z.ZodDefault<z.ZodPreprocess<z.ZodNullable<z.ZodCoercedBoolean<unknown>>>>;
|
|
26
|
+
filePattern: z.ZodDefault<z.ZodPreprocess<z.ZodNullable<z.ZodCoercedString<unknown>>>>;
|
|
27
|
+
contextLines: z.ZodDefault<z.ZodPreprocess<z.ZodNullable<z.ZodCoercedNumber<unknown>>>>;
|
|
28
|
+
searchIgnored: z.ZodDefault<z.ZodPreprocess<z.ZodNullable<z.ZodCoercedBoolean<unknown>>>>;
|
|
29
|
+
literal: z.ZodDefault<z.ZodPreprocess<z.ZodNullable<z.ZodCoercedBoolean<unknown>>>>;
|
|
30
|
+
maxResults: z.ZodDefault<z.ZodPreprocess<z.ZodNullable<z.ZodCoercedNumber<unknown>>>>;
|
|
31
31
|
}, z.core.$strip>;
|
|
32
32
|
};
|
|
33
33
|
display({ pattern, path, filePattern, recursive, ignoreCase, contextLines, }: GrepInputSchema): string;
|
package/dist/tools/grep.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grep.d.ts","sourceRoot":"","sources":["../../source/tools/grep.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAKvD,eAAO,MAAM,QAAQ;;CAEpB,CAAC;AAEF,QAAA,MAAM,WAAW;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"grep.d.ts","sourceRoot":"","sources":["../../source/tools/grep.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAKvD,eAAO,MAAM,QAAQ;;CAEpB,CAAC;AAEF,QAAA,MAAM,WAAW;;;;;;;;;;iBA2Cf,CAAC;AAEH,KAAK,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEnD,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;kFAapB,eAAe;sHAoCb,eAAe,mBACD,oBAAoB,GACpC,OAAO,CAAC,MAAM,CAAC;CAkErB,CAAC;AAEF,UAAU,WAAW;IACnB,SAAS,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC3B,UAAU,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,aAAa,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC/B,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAuMD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CA8B9D;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,WAAgB,GACxB,MAAM,EAAE,CAgEV;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,KAAK,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;KACd,CAAC,CAAC;CACJ;AAED,UAAU,UAAU;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,WAAW,EAAE,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,EAAE,CAqDrE;AA8BD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,CAEhE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,CAE/D;AAyBD;;GAEG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,WAAW,EAAE,EACtB,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACpC;IAAE,SAAS,EAAE,WAAW,EAAE,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,CAoDpD;AAED,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,WAAgB,EACzB,WAAW,CAAC,EAAE,WAAW,GAAG,IAAI,GAC/B,OAAO,CAAC,UAAU,CAAC,CAgGrB"}
|
package/dist/tools/grep.js
CHANGED
|
@@ -16,24 +16,31 @@ const inputSchema = z.object({
|
|
|
16
16
|
path: z.string().describe("The path to search in"),
|
|
17
17
|
recursive: z
|
|
18
18
|
.preprocess((val) => convertNullString(val), z.coerce.boolean().nullable())
|
|
19
|
+
.default(null)
|
|
19
20
|
.describe("Search recursively. (default: true))"),
|
|
20
21
|
ignoreCase: z
|
|
21
22
|
.preprocess((val) => convertNullString(val), z.coerce.boolean().nullable())
|
|
23
|
+
.default(null)
|
|
22
24
|
.describe("Use case-sensitive search. (default: false)"),
|
|
23
25
|
filePattern: z
|
|
24
26
|
.preprocess((val) => convertNullString(val), z.coerce.string().nullable())
|
|
27
|
+
.default(null)
|
|
25
28
|
.describe("Glob pattern to filter files (e.g., '*.ts', '**/*.test.js'). (Default: no filtering)"),
|
|
26
29
|
contextLines: z
|
|
27
30
|
.preprocess((val) => convertNullString(val), z.coerce.number().nullable())
|
|
31
|
+
.default(null)
|
|
28
32
|
.describe("The number of context lines needed in search results. (Default: 0)"),
|
|
29
33
|
searchIgnored: z
|
|
30
34
|
.preprocess((val) => convertNullString(val), z.coerce.boolean().nullable())
|
|
35
|
+
.default(null)
|
|
31
36
|
.describe("Search ignored files. (Default: false)"),
|
|
32
37
|
literal: z
|
|
33
38
|
.preprocess((val) => convertNullString(val), z.coerce.boolean().nullable())
|
|
39
|
+
.default(null)
|
|
34
40
|
.describe("Pass true for fixed-string search (-F), false for regex, (Default: auto-detects unbalanced patterns like mismatched parentheses/brackets.)"),
|
|
35
41
|
maxResults: z
|
|
36
42
|
.preprocess((val) => convertNullString(val), z.coerce.number().nullable())
|
|
43
|
+
.default(null)
|
|
37
44
|
.describe("Maximum number of matches to return. Set to 0 for no limit. (Default: 100)"),
|
|
38
45
|
});
|
|
39
46
|
export const createGrepTool = () => {
|