wave-agent-sdk 0.2.1 → 0.5.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/agent.d.ts +66 -20
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +156 -83
- package/dist/constants/prompts.d.ts +7 -2
- package/dist/constants/prompts.d.ts.map +1 -1
- package/dist/constants/prompts.js +41 -5
- package/dist/constants/tools.d.ts +2 -2
- package/dist/constants/tools.js +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/managers/MemoryRuleManager.d.ts.map +1 -1
- package/dist/managers/MemoryRuleManager.js +16 -2
- package/dist/managers/aiManager.d.ts +14 -4
- package/dist/managers/aiManager.d.ts.map +1 -1
- package/dist/managers/aiManager.js +61 -9
- package/dist/managers/backgroundBashManager.d.ts.map +1 -1
- package/dist/managers/backgroundBashManager.js +1 -0
- package/dist/managers/backgroundTaskManager.d.ts +35 -0
- package/dist/managers/backgroundTaskManager.d.ts.map +1 -0
- package/dist/managers/backgroundTaskManager.js +249 -0
- package/dist/managers/bashManager.d.ts.map +1 -1
- package/dist/managers/bashManager.js +0 -3
- package/dist/managers/foregroundTaskManager.d.ts +9 -0
- package/dist/managers/foregroundTaskManager.d.ts.map +1 -0
- package/dist/managers/foregroundTaskManager.js +20 -0
- package/dist/managers/liveConfigManager.d.ts +1 -1
- package/dist/managers/liveConfigManager.d.ts.map +1 -1
- package/dist/managers/lspManager.d.ts.map +1 -1
- package/dist/managers/lspManager.js +3 -1
- package/dist/managers/messageManager.d.ts +34 -4
- package/dist/managers/messageManager.d.ts.map +1 -1
- package/dist/managers/messageManager.js +104 -13
- package/dist/managers/permissionManager.d.ts.map +1 -1
- package/dist/managers/permissionManager.js +11 -13
- package/dist/managers/pluginManager.d.ts.map +1 -1
- package/dist/managers/pluginManager.js +3 -2
- package/dist/managers/pluginScopeManager.d.ts +13 -2
- package/dist/managers/pluginScopeManager.d.ts.map +1 -1
- package/dist/managers/pluginScopeManager.js +38 -0
- package/dist/managers/reversionManager.d.ts +39 -0
- package/dist/managers/reversionManager.d.ts.map +1 -0
- package/dist/managers/reversionManager.js +118 -0
- package/dist/managers/slashCommandManager.d.ts +4 -1
- package/dist/managers/slashCommandManager.d.ts.map +1 -1
- package/dist/managers/slashCommandManager.js +16 -6
- package/dist/managers/subagentManager.d.ts +13 -2
- package/dist/managers/subagentManager.d.ts.map +1 -1
- package/dist/managers/subagentManager.js +144 -35
- package/dist/managers/toolManager.d.ts +11 -1
- package/dist/managers/toolManager.d.ts.map +1 -1
- package/dist/managers/toolManager.js +11 -3
- package/dist/services/GitService.d.ts.map +1 -1
- package/dist/services/GitService.js +6 -2
- package/dist/services/MarketplaceService.d.ts +14 -1
- package/dist/services/MarketplaceService.d.ts.map +1 -1
- package/dist/services/MarketplaceService.js +72 -4
- package/dist/services/MemoryRuleService.d.ts +1 -1
- package/dist/services/MemoryRuleService.d.ts.map +1 -1
- package/dist/services/MemoryRuleService.js +13 -2
- package/dist/services/aiService.js +1 -1
- package/dist/services/configurationService.d.ts +18 -2
- package/dist/services/configurationService.d.ts.map +1 -1
- package/dist/services/configurationService.js +62 -0
- package/dist/services/fileWatcher.d.ts +0 -5
- package/dist/services/fileWatcher.d.ts.map +1 -1
- package/dist/services/fileWatcher.js +0 -11
- package/dist/services/memory.js +1 -1
- package/dist/services/pluginLoader.d.ts.map +1 -1
- package/dist/services/pluginLoader.js +6 -1
- package/dist/services/reversionService.d.ts +24 -0
- package/dist/services/reversionService.d.ts.map +1 -0
- package/dist/services/reversionService.js +76 -0
- package/dist/services/session.d.ts +7 -0
- package/dist/services/session.d.ts.map +1 -1
- package/dist/services/session.js +126 -3
- package/dist/tools/bashTool.d.ts +0 -8
- package/dist/tools/bashTool.d.ts.map +1 -1
- package/dist/tools/bashTool.js +52 -174
- package/dist/tools/deleteFileTool.d.ts.map +1 -1
- package/dist/tools/deleteFileTool.js +9 -0
- package/dist/tools/editTool.d.ts.map +1 -1
- package/dist/tools/editTool.js +15 -4
- package/dist/tools/multiEditTool.d.ts.map +1 -1
- package/dist/tools/multiEditTool.js +16 -5
- package/dist/tools/taskOutputTool.d.ts +3 -0
- package/dist/tools/taskOutputTool.d.ts.map +1 -0
- package/dist/tools/taskOutputTool.js +149 -0
- package/dist/tools/taskStopTool.d.ts +3 -0
- package/dist/tools/taskStopTool.d.ts.map +1 -0
- package/dist/tools/taskStopTool.js +65 -0
- package/dist/tools/taskTool.d.ts.map +1 -1
- package/dist/tools/taskTool.js +105 -63
- package/dist/tools/types.d.ts +7 -0
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/writeTool.d.ts.map +1 -1
- package/dist/tools/writeTool.js +9 -0
- package/dist/types/commands.d.ts +1 -0
- package/dist/types/commands.d.ts.map +1 -1
- package/dist/types/configuration.d.ts +3 -0
- package/dist/types/configuration.d.ts.map +1 -1
- package/dist/types/environment.d.ts +2 -1
- package/dist/types/environment.d.ts.map +1 -1
- package/dist/types/environment.js +0 -6
- package/dist/types/history.d.ts +5 -0
- package/dist/types/history.d.ts.map +1 -0
- package/dist/types/history.js +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -0
- package/dist/types/marketplace.d.ts +4 -0
- package/dist/types/marketplace.d.ts.map +1 -1
- package/dist/types/messaging.d.ts +7 -1
- package/dist/types/messaging.d.ts.map +1 -1
- package/dist/types/processes.d.ts +24 -4
- package/dist/types/processes.d.ts.map +1 -1
- package/dist/types/reversion.d.ts +29 -0
- package/dist/types/reversion.d.ts.map +1 -0
- package/dist/types/reversion.js +1 -0
- package/dist/utils/builtinSubagents.d.ts.map +1 -1
- package/dist/utils/builtinSubagents.js +16 -0
- package/dist/utils/constants.d.ts +2 -2
- package/dist/utils/constants.d.ts.map +1 -1
- package/dist/utils/constants.js +2 -2
- package/dist/utils/editUtils.d.ts +4 -9
- package/dist/utils/editUtils.d.ts.map +1 -1
- package/dist/utils/editUtils.js +54 -55
- package/dist/utils/messageOperations.d.ts +3 -1
- package/dist/utils/messageOperations.d.ts.map +1 -1
- package/dist/utils/messageOperations.js +8 -1
- package/dist/utils/openaiClient.d.ts.map +1 -1
- package/dist/utils/openaiClient.js +56 -26
- package/dist/utils/promptHistory.d.ts +20 -0
- package/dist/utils/promptHistory.d.ts.map +1 -0
- package/dist/utils/promptHistory.js +117 -0
- package/package.json +5 -3
- package/src/agent.ts +193 -109
- package/src/constants/prompts.ts +45 -5
- package/src/constants/tools.ts +2 -2
- package/src/index.ts +1 -1
- package/src/managers/MemoryRuleManager.ts +18 -2
- package/src/managers/aiManager.ts +87 -18
- package/src/managers/backgroundBashManager.ts +1 -0
- package/src/managers/backgroundTaskManager.ts +306 -0
- package/src/managers/bashManager.ts +0 -4
- package/src/managers/foregroundTaskManager.ts +26 -0
- package/src/managers/liveConfigManager.ts +2 -1
- package/src/managers/lspManager.ts +3 -1
- package/src/managers/messageManager.ts +136 -18
- package/src/managers/permissionManager.ts +11 -13
- package/src/managers/pluginManager.ts +4 -3
- package/src/managers/pluginScopeManager.ts +57 -8
- package/src/managers/reversionManager.ts +152 -0
- package/src/managers/slashCommandManager.ts +30 -7
- package/src/managers/subagentManager.ts +176 -31
- package/src/managers/toolManager.ts +23 -4
- package/src/services/GitService.ts +6 -2
- package/src/services/MarketplaceService.ts +100 -4
- package/src/services/MemoryRuleService.ts +18 -6
- package/src/services/aiService.ts +1 -1
- package/src/services/configurationService.ts +79 -1
- package/src/services/fileWatcher.ts +0 -13
- package/src/services/memory.ts +1 -1
- package/src/services/pluginLoader.ts +7 -1
- package/src/services/reversionService.ts +94 -0
- package/src/services/session.ts +161 -3
- package/src/tools/bashTool.ts +73 -200
- package/src/tools/deleteFileTool.ts +15 -0
- package/src/tools/editTool.ts +20 -10
- package/src/tools/multiEditTool.ts +21 -11
- package/src/tools/taskOutputTool.ts +174 -0
- package/src/tools/taskStopTool.ts +72 -0
- package/src/tools/taskTool.ts +130 -74
- package/src/tools/types.ts +7 -0
- package/src/tools/writeTool.ts +14 -0
- package/src/types/commands.ts +3 -0
- package/src/types/configuration.ts +4 -0
- package/src/types/environment.ts +3 -1
- package/src/types/history.ts +4 -0
- package/src/types/index.ts +1 -0
- package/src/types/marketplace.ts +5 -0
- package/src/types/messaging.ts +9 -1
- package/src/types/processes.ts +33 -4
- package/src/types/reversion.ts +29 -0
- package/src/utils/builtinSubagents.ts +18 -0
- package/src/utils/constants.ts +2 -2
- package/src/utils/editUtils.ts +66 -58
- package/src/utils/messageOperations.ts +10 -0
- package/src/utils/openaiClient.ts +69 -35
- package/src/utils/promptHistory.ts +133 -0
- package/dist/utils/bashHistory.d.ts +0 -50
- package/dist/utils/bashHistory.d.ts.map +0 -1
- package/dist/utils/bashHistory.js +0 -256
- package/src/utils/bashHistory.ts +0 -320
package/src/tools/bashTool.ts
CHANGED
|
@@ -4,8 +4,7 @@ import { stripAnsiColors } from "../utils/stringUtils.js";
|
|
|
4
4
|
import type { ToolPlugin, ToolResult, ToolContext } from "./types.js";
|
|
5
5
|
import {
|
|
6
6
|
BASH_TOOL_NAME,
|
|
7
|
-
|
|
8
|
-
KILL_BASH_TOOL_NAME,
|
|
7
|
+
TASK_OUTPUT_TOOL_NAME,
|
|
9
8
|
GLOB_TOOL_NAME,
|
|
10
9
|
GREP_TOOL_NAME,
|
|
11
10
|
READ_TOOL_NAME,
|
|
@@ -89,7 +88,7 @@ Usage notes:
|
|
|
89
88
|
},
|
|
90
89
|
run_in_background: {
|
|
91
90
|
type: "boolean",
|
|
92
|
-
description: `Set to true to run this command in the background. Use ${
|
|
91
|
+
description: `Set to true to run this command in the background. Use ${TASK_OUTPUT_TOOL_NAME} to read the output later.`,
|
|
93
92
|
},
|
|
94
93
|
},
|
|
95
94
|
required: ["command"],
|
|
@@ -164,20 +163,20 @@ Usage notes:
|
|
|
164
163
|
|
|
165
164
|
if (runInBackground) {
|
|
166
165
|
// Background execution
|
|
167
|
-
const
|
|
168
|
-
if (!
|
|
166
|
+
const backgroundTaskManager = context?.backgroundTaskManager;
|
|
167
|
+
if (!backgroundTaskManager) {
|
|
169
168
|
return {
|
|
170
169
|
success: false,
|
|
171
170
|
content: "",
|
|
172
|
-
error: "Background
|
|
171
|
+
error: "Background task manager not available",
|
|
173
172
|
};
|
|
174
173
|
}
|
|
175
174
|
|
|
176
|
-
const
|
|
175
|
+
const { id: taskId } = backgroundTaskManager.startShell(command, timeout);
|
|
177
176
|
return {
|
|
178
177
|
success: true,
|
|
179
|
-
content: `Command started in background with ID: ${
|
|
180
|
-
shortResult: `Background process ${
|
|
178
|
+
content: `Command started in background with ID: ${taskId}. Use TaskOutput tool with task_id="${taskId}" to monitor output.`,
|
|
179
|
+
shortResult: `Background process ${taskId} started`,
|
|
181
180
|
};
|
|
182
181
|
}
|
|
183
182
|
|
|
@@ -195,6 +194,41 @@ Usage notes:
|
|
|
195
194
|
let outputBuffer = "";
|
|
196
195
|
let errorBuffer = "";
|
|
197
196
|
let isAborted = false;
|
|
197
|
+
let isBackgrounded = false;
|
|
198
|
+
|
|
199
|
+
const foregroundTaskId = `bash_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
200
|
+
|
|
201
|
+
// Register as foreground task
|
|
202
|
+
if (context.foregroundTaskManager && command) {
|
|
203
|
+
context.foregroundTaskManager.registerForegroundTask({
|
|
204
|
+
id: foregroundTaskId,
|
|
205
|
+
backgroundHandler: async () => {
|
|
206
|
+
isBackgrounded = true;
|
|
207
|
+
if (timeoutHandle) {
|
|
208
|
+
clearTimeout(timeoutHandle);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const backgroundTaskManager = context.backgroundTaskManager;
|
|
212
|
+
if (backgroundTaskManager) {
|
|
213
|
+
const taskId = backgroundTaskManager.adoptProcess(
|
|
214
|
+
child,
|
|
215
|
+
command,
|
|
216
|
+
outputBuffer,
|
|
217
|
+
errorBuffer,
|
|
218
|
+
);
|
|
219
|
+
resolve({
|
|
220
|
+
success: true,
|
|
221
|
+
content: `Command moved to background with ID: ${taskId}. Use TaskOutput tool with task_id="${taskId}" to monitor output.`,
|
|
222
|
+
shortResult: `Process ${taskId} backgrounded`,
|
|
223
|
+
});
|
|
224
|
+
} else {
|
|
225
|
+
handleAbort(
|
|
226
|
+
"Failed to background: Background task manager not available",
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
},
|
|
230
|
+
});
|
|
231
|
+
}
|
|
198
232
|
|
|
199
233
|
// Set up timeout
|
|
200
234
|
let timeoutHandle: NodeJS.Timeout | undefined;
|
|
@@ -257,29 +291,45 @@ Usage notes:
|
|
|
257
291
|
// Handle abort signal from context
|
|
258
292
|
if (context?.abortSignal) {
|
|
259
293
|
if (context.abortSignal.aborted) {
|
|
260
|
-
|
|
294
|
+
if (!isBackgrounded) {
|
|
295
|
+
handleAbort();
|
|
296
|
+
}
|
|
261
297
|
return;
|
|
262
298
|
}
|
|
263
299
|
// Use { once: true } to prevent listener accumulation on signal reuse
|
|
264
|
-
context.abortSignal.addEventListener(
|
|
265
|
-
|
|
266
|
-
|
|
300
|
+
context.abortSignal.addEventListener(
|
|
301
|
+
"abort",
|
|
302
|
+
() => {
|
|
303
|
+
if (!isBackgrounded) {
|
|
304
|
+
handleAbort();
|
|
305
|
+
}
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
once: true,
|
|
309
|
+
},
|
|
310
|
+
);
|
|
267
311
|
}
|
|
268
312
|
|
|
269
313
|
child.stdout?.on("data", (data) => {
|
|
270
|
-
if (!isAborted) {
|
|
314
|
+
if (!isAborted && !isBackgrounded) {
|
|
271
315
|
outputBuffer += stripAnsiColors(data.toString());
|
|
272
316
|
}
|
|
273
317
|
});
|
|
274
318
|
|
|
275
319
|
child.stderr?.on("data", (data) => {
|
|
276
|
-
if (!isAborted) {
|
|
320
|
+
if (!isAborted && !isBackgrounded) {
|
|
277
321
|
errorBuffer += stripAnsiColors(data.toString());
|
|
278
322
|
}
|
|
279
323
|
});
|
|
280
324
|
|
|
281
325
|
child.on("exit", (code) => {
|
|
282
|
-
if (
|
|
326
|
+
if (context.foregroundTaskManager) {
|
|
327
|
+
context.foregroundTaskManager.unregisterForegroundTask(
|
|
328
|
+
foregroundTaskId,
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
if (!isAborted && !isBackgrounded) {
|
|
283
333
|
if (timeoutHandle) {
|
|
284
334
|
clearTimeout(timeoutHandle);
|
|
285
335
|
}
|
|
@@ -309,7 +359,13 @@ Usage notes:
|
|
|
309
359
|
});
|
|
310
360
|
|
|
311
361
|
child.on("error", (error) => {
|
|
312
|
-
if (
|
|
362
|
+
if (context.foregroundTaskManager) {
|
|
363
|
+
context.foregroundTaskManager.unregisterForegroundTask(
|
|
364
|
+
foregroundTaskId,
|
|
365
|
+
);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
if (!isAborted && !isBackgrounded) {
|
|
313
369
|
if (timeoutHandle) {
|
|
314
370
|
clearTimeout(timeoutHandle);
|
|
315
371
|
}
|
|
@@ -334,186 +390,3 @@ Usage notes:
|
|
|
334
390
|
return `${command}${runInBackground ? " (background)" : ""}`;
|
|
335
391
|
},
|
|
336
392
|
};
|
|
337
|
-
|
|
338
|
-
/**
|
|
339
|
-
* BashOutput tool - retrieves output from background bash shells
|
|
340
|
-
*/
|
|
341
|
-
export const bashOutputTool: ToolPlugin = {
|
|
342
|
-
name: BASH_OUTPUT_TOOL_NAME,
|
|
343
|
-
config: {
|
|
344
|
-
type: "function",
|
|
345
|
-
function: {
|
|
346
|
-
name: BASH_OUTPUT_TOOL_NAME,
|
|
347
|
-
description:
|
|
348
|
-
"Retrieves output from a running or completed background bash shell",
|
|
349
|
-
parameters: {
|
|
350
|
-
type: "object",
|
|
351
|
-
properties: {
|
|
352
|
-
bash_id: {
|
|
353
|
-
type: "string",
|
|
354
|
-
description:
|
|
355
|
-
"The ID of the background shell to retrieve output from",
|
|
356
|
-
},
|
|
357
|
-
filter: {
|
|
358
|
-
type: "string",
|
|
359
|
-
description:
|
|
360
|
-
"Optional regular expression to filter the output lines. Only lines matching this regex will be included in the result. Any lines that do not match will no longer be available to read.",
|
|
361
|
-
},
|
|
362
|
-
},
|
|
363
|
-
required: ["bash_id"],
|
|
364
|
-
},
|
|
365
|
-
},
|
|
366
|
-
},
|
|
367
|
-
execute: async (
|
|
368
|
-
args: Record<string, unknown>,
|
|
369
|
-
context: ToolContext,
|
|
370
|
-
): Promise<ToolResult> => {
|
|
371
|
-
const bashId = args.bash_id as string;
|
|
372
|
-
const filter = args.filter as string | undefined;
|
|
373
|
-
|
|
374
|
-
if (!bashId || typeof bashId !== "string") {
|
|
375
|
-
return {
|
|
376
|
-
success: false,
|
|
377
|
-
content: "",
|
|
378
|
-
error: "bash_id parameter is required and must be a string",
|
|
379
|
-
};
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
const backgroundBashManager = context?.backgroundBashManager;
|
|
383
|
-
if (!backgroundBashManager) {
|
|
384
|
-
return {
|
|
385
|
-
success: false,
|
|
386
|
-
content: "",
|
|
387
|
-
error: "Background bash manager not available",
|
|
388
|
-
};
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
const output = backgroundBashManager.getOutput(bashId, filter);
|
|
392
|
-
if (!output) {
|
|
393
|
-
return {
|
|
394
|
-
success: false,
|
|
395
|
-
content: "",
|
|
396
|
-
error: `Background shell with ID ${bashId} not found`,
|
|
397
|
-
};
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
const shell = backgroundBashManager.getShell(bashId);
|
|
401
|
-
if (!shell) {
|
|
402
|
-
return {
|
|
403
|
-
success: false,
|
|
404
|
-
content: "",
|
|
405
|
-
error: `Background shell with ID ${bashId} not found`,
|
|
406
|
-
};
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
let content = "";
|
|
410
|
-
if (output.stdout) {
|
|
411
|
-
content += stripAnsiColors(output.stdout);
|
|
412
|
-
}
|
|
413
|
-
if (output.stderr) {
|
|
414
|
-
content += (content ? "\n" : "") + stripAnsiColors(output.stderr);
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
const finalContent = content || "No output available";
|
|
418
|
-
const processedContent =
|
|
419
|
-
finalContent.length > MAX_OUTPUT_LENGTH
|
|
420
|
-
? finalContent.substring(0, MAX_OUTPUT_LENGTH) +
|
|
421
|
-
"\n\n... (output truncated)"
|
|
422
|
-
: finalContent;
|
|
423
|
-
|
|
424
|
-
return {
|
|
425
|
-
success: true,
|
|
426
|
-
content: processedContent,
|
|
427
|
-
shortResult: `${bashId}: ${output.status}${shell.exitCode !== undefined ? ` (${shell.exitCode})` : ""}`,
|
|
428
|
-
error: undefined,
|
|
429
|
-
};
|
|
430
|
-
},
|
|
431
|
-
formatCompactParams: (params: Record<string, unknown>) => {
|
|
432
|
-
const bashId = params.bash_id as string;
|
|
433
|
-
const filter = params.filter as string | undefined;
|
|
434
|
-
return filter ? `${bashId} filtered: ${filter}` : bashId;
|
|
435
|
-
},
|
|
436
|
-
};
|
|
437
|
-
|
|
438
|
-
/**
|
|
439
|
-
* KillBash tool - kills a running background bash shell
|
|
440
|
-
*/
|
|
441
|
-
export const killBashTool: ToolPlugin = {
|
|
442
|
-
name: KILL_BASH_TOOL_NAME,
|
|
443
|
-
config: {
|
|
444
|
-
type: "function",
|
|
445
|
-
function: {
|
|
446
|
-
name: KILL_BASH_TOOL_NAME,
|
|
447
|
-
description: "Kills a running background bash shell by its ID",
|
|
448
|
-
parameters: {
|
|
449
|
-
type: "object",
|
|
450
|
-
properties: {
|
|
451
|
-
shell_id: {
|
|
452
|
-
type: "string",
|
|
453
|
-
description: "The ID of the background shell to kill",
|
|
454
|
-
},
|
|
455
|
-
},
|
|
456
|
-
required: ["shell_id"],
|
|
457
|
-
},
|
|
458
|
-
},
|
|
459
|
-
},
|
|
460
|
-
execute: async (
|
|
461
|
-
args: Record<string, unknown>,
|
|
462
|
-
context: ToolContext,
|
|
463
|
-
): Promise<ToolResult> => {
|
|
464
|
-
const shellId = args.shell_id as string;
|
|
465
|
-
|
|
466
|
-
if (!shellId || typeof shellId !== "string") {
|
|
467
|
-
return {
|
|
468
|
-
success: false,
|
|
469
|
-
content: "",
|
|
470
|
-
error: "shell_id parameter is required and must be a string",
|
|
471
|
-
};
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
const backgroundBashManager = context?.backgroundBashManager;
|
|
475
|
-
if (!backgroundBashManager) {
|
|
476
|
-
return {
|
|
477
|
-
success: false,
|
|
478
|
-
content: "",
|
|
479
|
-
error: "Background bash manager not available",
|
|
480
|
-
};
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
const shell = backgroundBashManager.getShell(shellId);
|
|
484
|
-
if (!shell) {
|
|
485
|
-
return {
|
|
486
|
-
success: false,
|
|
487
|
-
content: "",
|
|
488
|
-
error: `Background shell with ID ${shellId} not found`,
|
|
489
|
-
};
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
if (shell.status !== "running") {
|
|
493
|
-
return {
|
|
494
|
-
success: false,
|
|
495
|
-
content: "",
|
|
496
|
-
error: `Background shell ${shellId} is not running (status: ${shell.status})`,
|
|
497
|
-
};
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
const killed = backgroundBashManager.killShell(shellId);
|
|
501
|
-
if (killed) {
|
|
502
|
-
return {
|
|
503
|
-
success: true,
|
|
504
|
-
content: `Background shell ${shellId} has been killed`,
|
|
505
|
-
shortResult: `Killed ${shellId}`,
|
|
506
|
-
};
|
|
507
|
-
} else {
|
|
508
|
-
return {
|
|
509
|
-
success: false,
|
|
510
|
-
content: "",
|
|
511
|
-
error: `Failed to kill background shell ${shellId}`,
|
|
512
|
-
};
|
|
513
|
-
}
|
|
514
|
-
},
|
|
515
|
-
formatCompactParams: (params: Record<string, unknown>) => {
|
|
516
|
-
const shellId = params.shell_id as string;
|
|
517
|
-
return shellId;
|
|
518
|
-
},
|
|
519
|
-
};
|
|
@@ -76,9 +76,24 @@ export const deleteFileTool: ToolPlugin = {
|
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
+
// Record snapshot for reversion
|
|
80
|
+
let snapshotId: string | undefined;
|
|
81
|
+
if (context.reversionManager && context.messageId) {
|
|
82
|
+
snapshotId = await context.reversionManager.recordSnapshot(
|
|
83
|
+
context.messageId,
|
|
84
|
+
filePath,
|
|
85
|
+
"delete",
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
79
89
|
// Delete file
|
|
80
90
|
await unlink(filePath);
|
|
81
91
|
|
|
92
|
+
// Commit snapshot on success
|
|
93
|
+
if (context.reversionManager && snapshotId) {
|
|
94
|
+
await context.reversionManager.commitSnapshot(snapshotId);
|
|
95
|
+
}
|
|
96
|
+
|
|
82
97
|
logger.debug(`Successfully deleted file: ${filePath}`);
|
|
83
98
|
|
|
84
99
|
return {
|
package/src/tools/editTool.ts
CHANGED
|
@@ -2,10 +2,7 @@ import { readFile, writeFile } from "fs/promises";
|
|
|
2
2
|
import { logger } from "../utils/globalLogger.js";
|
|
3
3
|
import type { ToolPlugin, ToolResult, ToolContext } from "./types.js";
|
|
4
4
|
import { resolvePath, getDisplayPath } from "../utils/path.js";
|
|
5
|
-
import {
|
|
6
|
-
findIndentationInsensitiveMatch,
|
|
7
|
-
escapeRegExp,
|
|
8
|
-
} from "../utils/editUtils.js";
|
|
5
|
+
import { escapeRegExp, analyzeEditMismatch } from "../utils/editUtils.js";
|
|
9
6
|
import { EDIT_TOOL_NAME, READ_TOOL_NAME } from "../constants/tools.js";
|
|
10
7
|
|
|
11
8
|
/**
|
|
@@ -114,17 +111,16 @@ export const editTool: ToolPlugin = {
|
|
|
114
111
|
};
|
|
115
112
|
}
|
|
116
113
|
|
|
117
|
-
// Check if old_string exists
|
|
118
|
-
const matchedOldString =
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
);
|
|
114
|
+
// Check if old_string exists
|
|
115
|
+
const matchedOldString = originalContent.includes(oldString)
|
|
116
|
+
? oldString
|
|
117
|
+
: null;
|
|
122
118
|
|
|
123
119
|
if (!matchedOldString) {
|
|
124
120
|
return {
|
|
125
121
|
success: false,
|
|
126
122
|
content: "",
|
|
127
|
-
error:
|
|
123
|
+
error: analyzeEditMismatch(originalContent, oldString),
|
|
128
124
|
};
|
|
129
125
|
}
|
|
130
126
|
|
|
@@ -184,9 +180,23 @@ export const editTool: ToolPlugin = {
|
|
|
184
180
|
}
|
|
185
181
|
}
|
|
186
182
|
|
|
183
|
+
// Record snapshot for reversion
|
|
184
|
+
let snapshotId: string | undefined;
|
|
185
|
+
if (context.reversionManager && context.messageId) {
|
|
186
|
+
snapshotId = await context.reversionManager.recordSnapshot(
|
|
187
|
+
context.messageId,
|
|
188
|
+
resolvedPath,
|
|
189
|
+
"modify",
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
187
193
|
// Write file
|
|
188
194
|
try {
|
|
189
195
|
await writeFile(resolvedPath, newContent, "utf-8");
|
|
196
|
+
// Commit snapshot on success
|
|
197
|
+
if (context.reversionManager && snapshotId) {
|
|
198
|
+
await context.reversionManager.commitSnapshot(snapshotId);
|
|
199
|
+
}
|
|
190
200
|
} catch (writeError) {
|
|
191
201
|
return {
|
|
192
202
|
success: false,
|
|
@@ -2,10 +2,7 @@ import { readFile, writeFile } from "fs/promises";
|
|
|
2
2
|
import { logger } from "../utils/globalLogger.js";
|
|
3
3
|
import type { ToolPlugin, ToolResult, ToolContext } from "./types.js";
|
|
4
4
|
import { resolvePath, getDisplayPath } from "../utils/path.js";
|
|
5
|
-
import {
|
|
6
|
-
findIndentationInsensitiveMatch,
|
|
7
|
-
escapeRegExp,
|
|
8
|
-
} from "../utils/editUtils.js";
|
|
5
|
+
import { escapeRegExp, analyzeEditMismatch } from "../utils/editUtils.js";
|
|
9
6
|
import {
|
|
10
7
|
MULTI_EDIT_TOOL_NAME,
|
|
11
8
|
EDIT_TOOL_NAME,
|
|
@@ -184,17 +181,16 @@ export const multiEditTool: ToolPlugin = {
|
|
|
184
181
|
continue;
|
|
185
182
|
}
|
|
186
183
|
|
|
187
|
-
// Check if old_string exists
|
|
188
|
-
const matchedOldString =
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
);
|
|
184
|
+
// Check if old_string exists
|
|
185
|
+
const matchedOldString = currentContent.includes(edit.old_string)
|
|
186
|
+
? edit.old_string
|
|
187
|
+
: null;
|
|
192
188
|
|
|
193
189
|
if (!matchedOldString) {
|
|
194
190
|
return {
|
|
195
191
|
success: false,
|
|
196
192
|
content: "",
|
|
197
|
-
error: `Edit operation ${i + 1}: old_string
|
|
193
|
+
error: `Edit operation ${i + 1}: ${analyzeEditMismatch(currentContent, edit.old_string)}`,
|
|
198
194
|
};
|
|
199
195
|
}
|
|
200
196
|
|
|
@@ -202,7 +198,7 @@ export const multiEditTool: ToolPlugin = {
|
|
|
202
198
|
|
|
203
199
|
if (replaceAll) {
|
|
204
200
|
// Replace all matches
|
|
205
|
-
const regex = new RegExp(escapeRegExp(
|
|
201
|
+
const regex = new RegExp(escapeRegExp(edit.old_string), "g");
|
|
206
202
|
currentContent = currentContent.replace(regex, edit.new_string);
|
|
207
203
|
replacementCount = (currentContent.match(regex) || []).length;
|
|
208
204
|
appliedEdits.push(
|
|
@@ -257,9 +253,23 @@ export const multiEditTool: ToolPlugin = {
|
|
|
257
253
|
}
|
|
258
254
|
}
|
|
259
255
|
|
|
256
|
+
// Record snapshot for reversion
|
|
257
|
+
let snapshotId: string | undefined;
|
|
258
|
+
if (context.reversionManager && context.messageId) {
|
|
259
|
+
snapshotId = await context.reversionManager.recordSnapshot(
|
|
260
|
+
context.messageId,
|
|
261
|
+
resolvedPath,
|
|
262
|
+
isNewFile ? "create" : "modify",
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
|
|
260
266
|
// Write file
|
|
261
267
|
try {
|
|
262
268
|
await writeFile(resolvedPath, currentContent, "utf-8");
|
|
269
|
+
// Commit snapshot on success
|
|
270
|
+
if (context.reversionManager && snapshotId) {
|
|
271
|
+
await context.reversionManager.commitSnapshot(snapshotId);
|
|
272
|
+
}
|
|
263
273
|
} catch (writeError) {
|
|
264
274
|
return {
|
|
265
275
|
success: false,
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { TASK_OUTPUT_TOOL_NAME } from "../constants/tools.js";
|
|
2
|
+
import { ToolContext, ToolPlugin, ToolResult } from "./types.js";
|
|
3
|
+
import { stripAnsiColors } from "../utils/stringUtils.js";
|
|
4
|
+
|
|
5
|
+
const MAX_OUTPUT_LENGTH = 30000;
|
|
6
|
+
|
|
7
|
+
export const taskOutputTool: ToolPlugin = {
|
|
8
|
+
name: TASK_OUTPUT_TOOL_NAME,
|
|
9
|
+
config: {
|
|
10
|
+
type: "function",
|
|
11
|
+
function: {
|
|
12
|
+
name: TASK_OUTPUT_TOOL_NAME,
|
|
13
|
+
description:
|
|
14
|
+
"Retrieves output from a running or completed background task",
|
|
15
|
+
parameters: {
|
|
16
|
+
type: "object",
|
|
17
|
+
properties: {
|
|
18
|
+
task_id: {
|
|
19
|
+
type: "string",
|
|
20
|
+
description:
|
|
21
|
+
"The ID of the background task to retrieve output from",
|
|
22
|
+
},
|
|
23
|
+
filter: {
|
|
24
|
+
type: "string",
|
|
25
|
+
description:
|
|
26
|
+
"Optional regular expression to filter the output lines.",
|
|
27
|
+
},
|
|
28
|
+
block: {
|
|
29
|
+
type: "boolean",
|
|
30
|
+
description:
|
|
31
|
+
"If true, wait for the task to complete before returning output. If false, return current output immediately.",
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
required: ["task_id"],
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
execute: async (
|
|
39
|
+
args: Record<string, unknown>,
|
|
40
|
+
context: ToolContext,
|
|
41
|
+
): Promise<ToolResult> => {
|
|
42
|
+
const taskId = args.task_id as string;
|
|
43
|
+
const filter = args.filter as string | undefined;
|
|
44
|
+
const block = args.block as boolean | undefined;
|
|
45
|
+
|
|
46
|
+
if (!taskId || typeof taskId !== "string") {
|
|
47
|
+
return {
|
|
48
|
+
success: false,
|
|
49
|
+
content: "",
|
|
50
|
+
error: "task_id parameter is required and must be a string",
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const backgroundTaskManager = context?.backgroundTaskManager;
|
|
55
|
+
if (!backgroundTaskManager) {
|
|
56
|
+
return {
|
|
57
|
+
success: false,
|
|
58
|
+
content: "",
|
|
59
|
+
error: "Background task manager not available",
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const getResult = () => {
|
|
64
|
+
const output = backgroundTaskManager.getOutput(taskId, filter);
|
|
65
|
+
if (!output) return null;
|
|
66
|
+
|
|
67
|
+
let content = "";
|
|
68
|
+
if (output.stdout) {
|
|
69
|
+
content += stripAnsiColors(output.stdout);
|
|
70
|
+
}
|
|
71
|
+
if (output.stderr) {
|
|
72
|
+
content += (content ? "\n" : "") + stripAnsiColors(output.stderr);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const finalContent = content || "No output available";
|
|
76
|
+
const processedContent =
|
|
77
|
+
finalContent.length > MAX_OUTPUT_LENGTH
|
|
78
|
+
? finalContent.substring(0, MAX_OUTPUT_LENGTH) +
|
|
79
|
+
"\n\n... (output truncated)"
|
|
80
|
+
: finalContent;
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
success: true,
|
|
84
|
+
content: processedContent,
|
|
85
|
+
shortResult: `${taskId}: ${output.status}`,
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
if (block) {
|
|
90
|
+
// Polling for completion
|
|
91
|
+
return new Promise((resolve) => {
|
|
92
|
+
let timeoutHandle: NodeJS.Timeout | null = null;
|
|
93
|
+
let isAborted = false;
|
|
94
|
+
|
|
95
|
+
const cleanup = () => {
|
|
96
|
+
if (timeoutHandle) {
|
|
97
|
+
clearTimeout(timeoutHandle);
|
|
98
|
+
timeoutHandle = null;
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const onAbort = () => {
|
|
103
|
+
isAborted = true;
|
|
104
|
+
cleanup();
|
|
105
|
+
resolve({
|
|
106
|
+
success: false,
|
|
107
|
+
content: "",
|
|
108
|
+
error: "Task output retrieval was aborted",
|
|
109
|
+
});
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
if (context.abortSignal) {
|
|
113
|
+
if (context.abortSignal.aborted) {
|
|
114
|
+
onAbort();
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
context.abortSignal.addEventListener("abort", onAbort, {
|
|
118
|
+
once: true,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const check = () => {
|
|
123
|
+
if (isAborted) return;
|
|
124
|
+
|
|
125
|
+
const task = backgroundTaskManager.getTask(taskId);
|
|
126
|
+
if (!task) {
|
|
127
|
+
if (context.abortSignal) {
|
|
128
|
+
context.abortSignal.removeEventListener("abort", onAbort);
|
|
129
|
+
}
|
|
130
|
+
resolve({
|
|
131
|
+
success: false,
|
|
132
|
+
content: "",
|
|
133
|
+
error: `Task with ID ${taskId} not found`,
|
|
134
|
+
});
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (task.status !== "running") {
|
|
139
|
+
if (context.abortSignal) {
|
|
140
|
+
context.abortSignal.removeEventListener("abort", onAbort);
|
|
141
|
+
}
|
|
142
|
+
const result = getResult();
|
|
143
|
+
resolve(
|
|
144
|
+
result || {
|
|
145
|
+
success: false,
|
|
146
|
+
content: "",
|
|
147
|
+
error: "Task not found",
|
|
148
|
+
},
|
|
149
|
+
);
|
|
150
|
+
} else {
|
|
151
|
+
timeoutHandle = setTimeout(check, 500);
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
check();
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const result = getResult();
|
|
159
|
+
if (!result) {
|
|
160
|
+
return {
|
|
161
|
+
success: false,
|
|
162
|
+
content: "",
|
|
163
|
+
error: `Task with ID ${taskId} not found`,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return result;
|
|
168
|
+
},
|
|
169
|
+
formatCompactParams: (params: Record<string, unknown>) => {
|
|
170
|
+
const taskId = params.task_id as string;
|
|
171
|
+
const block = params.block as boolean;
|
|
172
|
+
return `${taskId}${block ? " (blocking)" : ""}`;
|
|
173
|
+
},
|
|
174
|
+
};
|