wave-agent-sdk 0.4.0 → 0.6.1
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 +42 -11
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +114 -115
- package/dist/constants/prompts.d.ts +18 -14
- package/dist/constants/prompts.d.ts.map +1 -1
- package/dist/constants/prompts.js +130 -54
- package/dist/constants/tools.d.ts +6 -3
- package/dist/constants/tools.d.ts.map +1 -1
- package/dist/constants/tools.js +6 -3
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/managers/MemoryRuleManager.js +1 -1
- package/dist/managers/aiManager.d.ts +5 -3
- package/dist/managers/aiManager.d.ts.map +1 -1
- package/dist/managers/aiManager.js +57 -20
- 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 +255 -0
- package/dist/managers/foregroundTaskManager.d.ts +9 -0
- package/dist/managers/foregroundTaskManager.d.ts.map +1 -0
- package/dist/managers/foregroundTaskManager.js +21 -0
- package/dist/managers/liveConfigManager.d.ts +1 -1
- package/dist/managers/lspManager.d.ts.map +1 -1
- package/dist/managers/lspManager.js +3 -1
- package/dist/managers/mcpManager.d.ts.map +1 -1
- package/dist/managers/messageManager.d.ts +26 -12
- package/dist/managers/messageManager.d.ts.map +1 -1
- package/dist/managers/messageManager.js +138 -64
- package/dist/managers/permissionManager.d.ts.map +1 -1
- package/dist/managers/permissionManager.js +26 -22
- package/dist/managers/planManager.d.ts +1 -1
- package/dist/managers/planManager.d.ts.map +1 -1
- package/dist/managers/planManager.js +2 -2
- package/dist/managers/pluginManager.d.ts.map +1 -1
- package/dist/managers/pluginManager.js +3 -2
- package/dist/managers/slashCommandManager.d.ts +6 -0
- package/dist/managers/slashCommandManager.d.ts.map +1 -1
- package/dist/managers/slashCommandManager.js +8 -2
- package/dist/managers/subagentManager.d.ts +15 -2
- package/dist/managers/subagentManager.d.ts.map +1 -1
- package/dist/managers/subagentManager.js +153 -39
- package/dist/managers/toolManager.d.ts +18 -1
- package/dist/managers/toolManager.d.ts.map +1 -1
- package/dist/managers/toolManager.js +29 -5
- package/dist/services/GitService.d.ts.map +1 -1
- package/dist/services/GitService.js +6 -2
- package/dist/services/MarketplaceService.d.ts +2 -2
- package/dist/services/MarketplaceService.d.ts.map +1 -1
- package/dist/services/MarketplaceService.js +18 -11
- 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.d.ts +0 -1
- package/dist/services/aiService.d.ts.map +1 -1
- package/dist/services/aiService.js +4 -140
- package/dist/services/memory.d.ts +0 -3
- package/dist/services/memory.d.ts.map +1 -1
- package/dist/services/memory.js +1 -60
- package/dist/services/session.d.ts +15 -1
- package/dist/services/session.d.ts.map +1 -1
- package/dist/services/session.js +57 -1
- package/dist/services/taskManager.d.ts +21 -0
- package/dist/services/taskManager.d.ts.map +1 -0
- package/dist/services/taskManager.js +158 -0
- package/dist/tools/askUserQuestion.d.ts.map +1 -1
- package/dist/tools/askUserQuestion.js +39 -25
- package/dist/tools/bashTool.d.ts +0 -8
- package/dist/tools/bashTool.d.ts.map +1 -1
- package/dist/tools/bashTool.js +48 -172
- package/dist/tools/editTool.d.ts.map +1 -1
- package/dist/tools/editTool.js +8 -6
- package/dist/tools/exitPlanMode.d.ts.map +1 -1
- package/dist/tools/exitPlanMode.js +25 -1
- package/dist/tools/globTool.d.ts.map +1 -1
- package/dist/tools/globTool.js +8 -2
- package/dist/tools/grepTool.d.ts.map +1 -1
- package/dist/tools/grepTool.js +17 -6
- package/dist/tools/lsTool.d.ts.map +1 -1
- package/dist/tools/lsTool.js +3 -1
- package/dist/tools/multiEditTool.d.ts.map +1 -1
- package/dist/tools/multiEditTool.js +7 -6
- package/dist/tools/readTool.d.ts.map +1 -1
- package/dist/tools/readTool.js +16 -1
- package/dist/tools/taskManagementTools.d.ts +6 -0
- package/dist/tools/taskManagementTools.d.ts.map +1 -0
- package/dist/tools/taskManagementTools.js +453 -0
- package/dist/tools/taskOutputTool.d.ts +3 -0
- package/dist/tools/taskOutputTool.d.ts.map +1 -0
- package/dist/tools/taskOutputTool.js +173 -0
- package/dist/tools/taskStopTool.d.ts +3 -0
- package/dist/tools/taskStopTool.d.ts.map +1 -0
- package/dist/tools/taskStopTool.js +71 -0
- package/dist/tools/taskTool.d.ts.map +1 -1
- package/dist/tools/taskTool.js +110 -63
- package/dist/tools/types.d.ts +12 -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 -1
- 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 +1 -0
- package/dist/types/marketplace.d.ts.map +1 -1
- package/dist/types/messaging.d.ts +3 -8
- package/dist/types/messaging.d.ts.map +1 -1
- package/dist/types/processes.d.ts +29 -4
- package/dist/types/processes.d.ts.map +1 -1
- package/dist/types/tasks.d.ts +13 -0
- package/dist/types/tasks.d.ts.map +1 -0
- package/dist/types/tasks.js +1 -0
- package/dist/types/tools.d.ts +4 -1
- package/dist/types/tools.d.ts.map +1 -1
- package/dist/utils/builtinSubagents.d.ts.map +1 -1
- package/dist/utils/builtinSubagents.js +38 -1
- package/dist/utils/cacheControlUtils.d.ts.map +1 -1
- package/dist/utils/cacheControlUtils.js +18 -12
- package/dist/utils/constants.d.ts +0 -4
- package/dist/utils/constants.d.ts.map +1 -1
- package/dist/utils/constants.js +0 -4
- package/dist/utils/convertMessagesForAPI.js +2 -2
- package/dist/utils/editUtils.d.ts +2 -11
- package/dist/utils/editUtils.d.ts.map +1 -1
- package/dist/utils/editUtils.js +52 -79
- package/dist/utils/messageOperations.d.ts +5 -36
- package/dist/utils/messageOperations.d.ts.map +1 -1
- package/dist/utils/messageOperations.js +9 -98
- package/dist/utils/nameGenerator.d.ts +1 -1
- package/dist/utils/nameGenerator.d.ts.map +1 -1
- package/dist/utils/nameGenerator.js +19 -3
- package/package.json +5 -5
- package/src/agent.ts +157 -134
- package/src/constants/prompts.ts +156 -65
- package/src/constants/tools.ts +6 -3
- package/src/index.ts +1 -0
- package/src/managers/MemoryRuleManager.ts +1 -1
- package/src/managers/aiManager.ts +77 -35
- package/src/managers/backgroundBashManager.ts +1 -0
- package/src/managers/backgroundTaskManager.ts +305 -0
- package/src/managers/foregroundTaskManager.ts +27 -0
- package/src/managers/lspManager.ts +3 -1
- package/src/managers/mcpManager.ts +6 -3
- package/src/managers/messageManager.ts +185 -75
- package/src/managers/permissionManager.ts +33 -28
- package/src/managers/planManager.ts +2 -2
- package/src/managers/pluginManager.ts +4 -3
- package/src/managers/slashCommandManager.ts +15 -2
- package/src/managers/subagentManager.ts +194 -35
- package/src/managers/toolManager.ts +48 -6
- package/src/services/GitService.ts +6 -2
- package/src/services/MarketplaceService.ts +30 -12
- package/src/services/MemoryRuleService.ts +18 -6
- package/src/services/aiService.ts +3 -145
- package/src/services/memory.ts +1 -73
- package/src/services/session.ts +73 -0
- package/src/services/taskManager.ts +188 -0
- package/src/tools/askUserQuestion.ts +51 -29
- package/src/tools/bashTool.ts +63 -196
- package/src/tools/editTool.ts +9 -18
- package/src/tools/exitPlanMode.ts +26 -2
- package/src/tools/globTool.ts +10 -2
- package/src/tools/grepTool.ts +17 -6
- package/src/tools/lsTool.ts +3 -1
- package/src/tools/multiEditTool.ts +7 -18
- package/src/tools/readTool.ts +17 -1
- package/src/tools/taskManagementTools.ts +498 -0
- package/src/tools/taskOutputTool.ts +196 -0
- package/src/tools/taskStopTool.ts +78 -0
- package/src/tools/taskTool.ts +136 -74
- package/src/tools/types.ts +13 -0
- package/src/tools/writeTool.ts +9 -2
- package/src/types/index.ts +1 -0
- package/src/types/marketplace.ts +1 -0
- package/src/types/messaging.ts +2 -9
- package/src/types/processes.ts +39 -4
- package/src/types/tasks.ts +13 -0
- package/src/types/tools.ts +4 -1
- package/src/utils/builtinSubagents.ts +47 -1
- package/src/utils/cacheControlUtils.ts +26 -18
- package/src/utils/constants.ts +0 -5
- package/src/utils/convertMessagesForAPI.ts +2 -2
- package/src/utils/editUtils.ts +65 -103
- package/src/utils/messageOperations.ts +12 -136
- package/src/utils/nameGenerator.ts +20 -3
- package/dist/tools/todoWriteTool.d.ts +0 -6
- package/dist/tools/todoWriteTool.d.ts.map +0 -1
- package/dist/tools/todoWriteTool.js +0 -220
- package/src/tools/todoWriteTool.ts +0 -257
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { randomUUID } from "crypto";
|
|
2
|
+
import type { MemoryRuleManager } from "./MemoryRuleManager.js";
|
|
2
3
|
import type { SubagentConfiguration } from "../utils/subagentParser.js";
|
|
3
4
|
import type {
|
|
4
5
|
Message,
|
|
@@ -20,6 +21,7 @@ import {
|
|
|
20
21
|
addConsolidatedAbortListener,
|
|
21
22
|
createAbortPromise,
|
|
22
23
|
} from "../utils/abortUtils.js";
|
|
24
|
+
import { BackgroundTaskManager } from "./backgroundTaskManager.js";
|
|
23
25
|
|
|
24
26
|
export interface SubagentManagerCallbacks {
|
|
25
27
|
// Granular subagent message callbacks (015-subagent-message-callbacks)
|
|
@@ -49,6 +51,11 @@ export interface SubagentManagerCallbacks {
|
|
|
49
51
|
) => void;
|
|
50
52
|
/** Triggered when subagent messages change */
|
|
51
53
|
onSubagentMessagesChange?: (subagentId: string, messages: Message[]) => void;
|
|
54
|
+
/** Triggered when subagent latest total tokens change */
|
|
55
|
+
onSubagentLatestTotalTokensChange?: (
|
|
56
|
+
subagentId: string,
|
|
57
|
+
tokens: number,
|
|
58
|
+
) => void;
|
|
52
59
|
}
|
|
53
60
|
|
|
54
61
|
export interface SubagentInstance {
|
|
@@ -60,12 +67,14 @@ export interface SubagentInstance {
|
|
|
60
67
|
status: "initializing" | "active" | "completed" | "error" | "aborted";
|
|
61
68
|
messages: Message[];
|
|
62
69
|
subagentType: string; // Store the subagent type for hook context
|
|
70
|
+
backgroundTaskId?: string; // ID of the background task if transitioned
|
|
63
71
|
}
|
|
64
72
|
|
|
65
73
|
export interface SubagentManagerOptions {
|
|
66
74
|
workdir: string;
|
|
67
75
|
parentToolManager: ToolManager;
|
|
68
76
|
parentMessageManager: MessageManager;
|
|
77
|
+
taskManager: import("../services/taskManager.js").TaskManager;
|
|
69
78
|
callbacks?: SubagentManagerCallbacks; // Use SubagentManagerCallbacks instead of parentCallbacks
|
|
70
79
|
logger?: Logger;
|
|
71
80
|
getGatewayConfig: () => GatewayConfig;
|
|
@@ -74,6 +83,8 @@ export interface SubagentManagerOptions {
|
|
|
74
83
|
getLanguage: () => string | undefined;
|
|
75
84
|
hookManager?: HookManager;
|
|
76
85
|
onUsageAdded?: (usage: Usage) => void;
|
|
86
|
+
backgroundTaskManager?: BackgroundTaskManager;
|
|
87
|
+
memoryRuleManager?: MemoryRuleManager;
|
|
77
88
|
}
|
|
78
89
|
|
|
79
90
|
export class SubagentManager {
|
|
@@ -83,6 +94,7 @@ export class SubagentManager {
|
|
|
83
94
|
private workdir: string;
|
|
84
95
|
private parentToolManager: ToolManager;
|
|
85
96
|
private parentMessageManager: MessageManager;
|
|
97
|
+
private taskManager: import("../services/taskManager.js").TaskManager;
|
|
86
98
|
private callbacks?: SubagentManagerCallbacks; // Use SubagentManagerCallbacks instead of parentCallbacks
|
|
87
99
|
private logger?: Logger;
|
|
88
100
|
private getGatewayConfig: () => GatewayConfig;
|
|
@@ -91,11 +103,14 @@ export class SubagentManager {
|
|
|
91
103
|
private getLanguage: () => string | undefined;
|
|
92
104
|
private hookManager?: HookManager;
|
|
93
105
|
private onUsageAdded?: (usage: Usage) => void;
|
|
106
|
+
private backgroundTaskManager?: BackgroundTaskManager;
|
|
107
|
+
private memoryRuleManager?: MemoryRuleManager;
|
|
94
108
|
|
|
95
109
|
constructor(options: SubagentManagerOptions) {
|
|
96
110
|
this.workdir = options.workdir;
|
|
97
111
|
this.parentToolManager = options.parentToolManager;
|
|
98
112
|
this.parentMessageManager = options.parentMessageManager;
|
|
113
|
+
this.taskManager = options.taskManager;
|
|
99
114
|
this.callbacks = options.callbacks; // Store SubagentManagerCallbacks
|
|
100
115
|
this.logger = options.logger;
|
|
101
116
|
this.getGatewayConfig = options.getGatewayConfig;
|
|
@@ -104,6 +119,8 @@ export class SubagentManager {
|
|
|
104
119
|
this.getLanguage = options.getLanguage;
|
|
105
120
|
this.hookManager = options.hookManager;
|
|
106
121
|
this.onUsageAdded = options.onUsageAdded;
|
|
122
|
+
this.backgroundTaskManager = options.backgroundTaskManager;
|
|
123
|
+
this.memoryRuleManager = options.memoryRuleManager;
|
|
107
124
|
}
|
|
108
125
|
|
|
109
126
|
/**
|
|
@@ -158,6 +175,7 @@ export class SubagentManager {
|
|
|
158
175
|
prompt: string;
|
|
159
176
|
subagent_type: string;
|
|
160
177
|
},
|
|
178
|
+
runInBackground?: boolean,
|
|
161
179
|
): Promise<SubagentInstance> {
|
|
162
180
|
if (!this.parentToolManager) {
|
|
163
181
|
throw new Error(
|
|
@@ -176,6 +194,7 @@ export class SubagentManager {
|
|
|
176
194
|
logger: this.logger,
|
|
177
195
|
sessionType: "subagent",
|
|
178
196
|
subagentType: parameters.subagent_type,
|
|
197
|
+
memoryRuleManager: this.memoryRuleManager,
|
|
179
198
|
});
|
|
180
199
|
|
|
181
200
|
// Use the parent tool manager directly - tool restrictions will be handled by allowedTools parameter
|
|
@@ -185,6 +204,7 @@ export class SubagentManager {
|
|
|
185
204
|
const aiManager = new AIManager({
|
|
186
205
|
messageManager,
|
|
187
206
|
toolManager,
|
|
207
|
+
taskManager: this.taskManager,
|
|
188
208
|
logger: this.logger,
|
|
189
209
|
workdir: this.workdir,
|
|
190
210
|
systemPrompt: configuration.systemPrompt,
|
|
@@ -241,6 +261,7 @@ export class SubagentManager {
|
|
|
241
261
|
configuration,
|
|
242
262
|
"active",
|
|
243
263
|
parameters,
|
|
264
|
+
runInBackground,
|
|
244
265
|
);
|
|
245
266
|
|
|
246
267
|
return instance;
|
|
@@ -256,6 +277,7 @@ export class SubagentManager {
|
|
|
256
277
|
instance: SubagentInstance,
|
|
257
278
|
prompt: string,
|
|
258
279
|
abortSignal?: AbortSignal,
|
|
280
|
+
runInBackground?: boolean,
|
|
259
281
|
): Promise<string> {
|
|
260
282
|
try {
|
|
261
283
|
// Check if already aborted before starting
|
|
@@ -269,24 +291,122 @@ export class SubagentManager {
|
|
|
269
291
|
status: "active",
|
|
270
292
|
});
|
|
271
293
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
294
|
+
if (runInBackground && this.backgroundTaskManager) {
|
|
295
|
+
const taskId = this.backgroundTaskManager.generateId();
|
|
296
|
+
const startTime = Date.now();
|
|
297
|
+
|
|
298
|
+
this.backgroundTaskManager.addTask({
|
|
299
|
+
id: taskId,
|
|
300
|
+
type: "subagent",
|
|
301
|
+
status: "running",
|
|
302
|
+
startTime,
|
|
303
|
+
description: instance.configuration.description,
|
|
304
|
+
stdout: "",
|
|
305
|
+
stderr: "",
|
|
306
|
+
onStop: () => instance.aiManager.abortAIMessage(),
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
instance.backgroundTaskId = taskId;
|
|
310
|
+
|
|
311
|
+
// Execute in background
|
|
312
|
+
(async () => {
|
|
313
|
+
try {
|
|
314
|
+
const result = await this.internalExecute(
|
|
315
|
+
instance,
|
|
316
|
+
prompt,
|
|
317
|
+
abortSignal,
|
|
318
|
+
);
|
|
319
|
+
const task = this.backgroundTaskManager?.getTask(taskId);
|
|
320
|
+
if (task) {
|
|
321
|
+
task.status = "completed";
|
|
322
|
+
task.stdout = result;
|
|
323
|
+
task.endTime = Date.now();
|
|
324
|
+
task.runtime = task.endTime - startTime;
|
|
325
|
+
}
|
|
326
|
+
} catch (error) {
|
|
327
|
+
const task = this.backgroundTaskManager?.getTask(taskId);
|
|
328
|
+
if (task) {
|
|
329
|
+
task.status = "failed";
|
|
330
|
+
task.stderr =
|
|
331
|
+
error instanceof Error ? error.message : String(error);
|
|
332
|
+
task.endTime = Date.now();
|
|
333
|
+
task.runtime = task.endTime - startTime;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
})();
|
|
337
|
+
|
|
338
|
+
return taskId;
|
|
288
339
|
}
|
|
289
340
|
|
|
341
|
+
return await this.internalExecute(instance, prompt, abortSignal);
|
|
342
|
+
} catch (error) {
|
|
343
|
+
this.updateInstanceStatus(instance.subagentId, "error");
|
|
344
|
+
this.parentMessageManager.updateSubagentBlock(instance.subagentId, {
|
|
345
|
+
status: "error",
|
|
346
|
+
});
|
|
347
|
+
throw error;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
async backgroundInstance(subagentId: string): Promise<string> {
|
|
352
|
+
const instance = this.instances.get(subagentId);
|
|
353
|
+
if (!instance) {
|
|
354
|
+
throw new Error(`Subagent instance ${subagentId} not found`);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
if (!this.backgroundTaskManager) {
|
|
358
|
+
throw new Error("BackgroundTaskManager not available");
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
const taskId = this.backgroundTaskManager.generateId();
|
|
362
|
+
const startTime = Date.now();
|
|
363
|
+
|
|
364
|
+
this.backgroundTaskManager.addTask({
|
|
365
|
+
id: taskId,
|
|
366
|
+
type: "subagent",
|
|
367
|
+
status: "running",
|
|
368
|
+
startTime,
|
|
369
|
+
description: instance.configuration.description,
|
|
370
|
+
stdout: "",
|
|
371
|
+
stderr: "",
|
|
372
|
+
onStop: () => instance.aiManager.abortAIMessage(),
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
instance.backgroundTaskId = taskId;
|
|
376
|
+
|
|
377
|
+
// Update parent message manager to reflect background status
|
|
378
|
+
this.parentMessageManager.updateSubagentBlock(subagentId, {
|
|
379
|
+
runInBackground: true,
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
return taskId;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
private async internalExecute(
|
|
386
|
+
instance: SubagentInstance,
|
|
387
|
+
prompt: string,
|
|
388
|
+
abortSignal?: AbortSignal,
|
|
389
|
+
): Promise<string> {
|
|
390
|
+
// Set up consolidated abort handler to prevent listener accumulation
|
|
391
|
+
let abortCleanup: (() => void) | undefined;
|
|
392
|
+
// Only link to parent abort signal if NOT running in background
|
|
393
|
+
if (abortSignal && !instance.backgroundTaskId) {
|
|
394
|
+
abortCleanup = addConsolidatedAbortListener(abortSignal, [
|
|
395
|
+
() => {
|
|
396
|
+
// Update status to aborted
|
|
397
|
+
this.updateInstanceStatus(instance.subagentId, "aborted");
|
|
398
|
+
this.parentMessageManager.updateSubagentBlock(instance.subagentId, {
|
|
399
|
+
status: "aborted",
|
|
400
|
+
});
|
|
401
|
+
},
|
|
402
|
+
() => {
|
|
403
|
+
// Abort the AI execution
|
|
404
|
+
instance.aiManager.abortAIMessage();
|
|
405
|
+
},
|
|
406
|
+
]);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
try {
|
|
290
410
|
// Add the user's prompt as a message
|
|
291
411
|
instance.messageManager.addUserMessage({ content: prompt });
|
|
292
412
|
|
|
@@ -326,21 +446,14 @@ export class SubagentManager {
|
|
|
326
446
|
model: resolvedModel,
|
|
327
447
|
});
|
|
328
448
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
await executeAI;
|
|
338
|
-
}
|
|
339
|
-
} finally {
|
|
340
|
-
// Clean up abort listeners to prevent memory leaks
|
|
341
|
-
if (abortCleanup) {
|
|
342
|
-
abortCleanup();
|
|
343
|
-
}
|
|
449
|
+
// If we have an abort signal, race against it using utilities to prevent listener accumulation
|
|
450
|
+
if (abortSignal && !instance.backgroundTaskId) {
|
|
451
|
+
await Promise.race([
|
|
452
|
+
executeAI,
|
|
453
|
+
createAbortPromise(abortSignal, "Task was aborted"),
|
|
454
|
+
]);
|
|
455
|
+
} else {
|
|
456
|
+
await executeAI;
|
|
344
457
|
}
|
|
345
458
|
|
|
346
459
|
// Get the latest messages to extract the response
|
|
@@ -365,13 +478,43 @@ export class SubagentManager {
|
|
|
365
478
|
status: "completed",
|
|
366
479
|
});
|
|
367
480
|
|
|
481
|
+
// If this was transitioned to background, update the background task
|
|
482
|
+
if (instance.backgroundTaskId && this.backgroundTaskManager) {
|
|
483
|
+
const task = this.backgroundTaskManager.getTask(
|
|
484
|
+
instance.backgroundTaskId,
|
|
485
|
+
);
|
|
486
|
+
if (task) {
|
|
487
|
+
task.status = "completed";
|
|
488
|
+
task.stdout = response || "Task completed with no text response";
|
|
489
|
+
task.endTime = Date.now();
|
|
490
|
+
if (task.startTime) {
|
|
491
|
+
task.runtime = task.endTime - task.startTime;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
368
496
|
return response || "Task completed with no text response";
|
|
369
497
|
} catch (error) {
|
|
370
|
-
this
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
498
|
+
// If this was transitioned to background, update the background task with error
|
|
499
|
+
if (instance.backgroundTaskId && this.backgroundTaskManager) {
|
|
500
|
+
const task = this.backgroundTaskManager.getTask(
|
|
501
|
+
instance.backgroundTaskId,
|
|
502
|
+
);
|
|
503
|
+
if (task) {
|
|
504
|
+
task.status = "failed";
|
|
505
|
+
task.stderr = error instanceof Error ? error.message : String(error);
|
|
506
|
+
task.endTime = Date.now();
|
|
507
|
+
if (task.startTime) {
|
|
508
|
+
task.runtime = task.endTime - task.startTime;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
374
512
|
throw error;
|
|
513
|
+
} finally {
|
|
514
|
+
// Clean up abort listeners to prevent memory leaks
|
|
515
|
+
if (abortCleanup) {
|
|
516
|
+
abortCleanup();
|
|
517
|
+
}
|
|
375
518
|
}
|
|
376
519
|
}
|
|
377
520
|
|
|
@@ -462,6 +605,7 @@ export class SubagentManager {
|
|
|
462
605
|
logger: this.logger,
|
|
463
606
|
sessionType: "subagent",
|
|
464
607
|
subagentType: configuration.name, // Use configuration name for restored sessions
|
|
608
|
+
memoryRuleManager: this.memoryRuleManager,
|
|
465
609
|
});
|
|
466
610
|
|
|
467
611
|
// Use the parent tool manager
|
|
@@ -483,6 +627,7 @@ export class SubagentManager {
|
|
|
483
627
|
const aiManager = new AIManager({
|
|
484
628
|
messageManager,
|
|
485
629
|
toolManager,
|
|
630
|
+
taskManager: this.taskManager,
|
|
486
631
|
logger: this.logger,
|
|
487
632
|
workdir: this.workdir,
|
|
488
633
|
systemPrompt: configuration.systemPrompt,
|
|
@@ -594,6 +739,20 @@ export class SubagentManager {
|
|
|
594
739
|
sessionId: newSessionId,
|
|
595
740
|
});
|
|
596
741
|
},
|
|
742
|
+
|
|
743
|
+
onLatestTotalTokensChange: (tokens: number) => {
|
|
744
|
+
// Forward latest total tokens to parent via SubagentManager callbacks
|
|
745
|
+
if (this.callbacks?.onSubagentLatestTotalTokensChange) {
|
|
746
|
+
this.callbacks.onSubagentLatestTotalTokensChange(subagentId, tokens);
|
|
747
|
+
}
|
|
748
|
+
},
|
|
749
|
+
|
|
750
|
+
onFileHistoryBlockAdded: (
|
|
751
|
+
snapshots: import("../types/reversion.js").FileSnapshot[],
|
|
752
|
+
) => {
|
|
753
|
+
// Forward file history blocks to parent MessageManager
|
|
754
|
+
this.parentMessageManager.addFileHistoryBlock(snapshots);
|
|
755
|
+
},
|
|
597
756
|
};
|
|
598
757
|
}
|
|
599
758
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { ToolContext, ToolPlugin, ToolResult } from "../tools/types.js";
|
|
2
|
-
import { bashTool
|
|
2
|
+
import { bashTool } from "../tools/bashTool.js";
|
|
3
|
+
import { taskOutputTool } from "../tools/taskOutputTool.js";
|
|
4
|
+
import { taskStopTool } from "../tools/taskStopTool.js";
|
|
3
5
|
import { deleteFileTool } from "../tools/deleteFileTool.js";
|
|
4
6
|
import { editTool } from "../tools/editTool.js";
|
|
5
7
|
import { multiEditTool } from "../tools/multiEditTool.js";
|
|
@@ -11,10 +13,15 @@ import { globTool } from "../tools/globTool.js";
|
|
|
11
13
|
import { grepTool } from "../tools/grepTool.js";
|
|
12
14
|
import { lsTool } from "../tools/lsTool.js";
|
|
13
15
|
import { readTool } from "../tools/readTool.js";
|
|
14
|
-
import { todoWriteTool } from "../tools/todoWriteTool.js";
|
|
15
16
|
import { lspTool } from "../tools/lspTool.js";
|
|
16
17
|
import { createTaskTool } from "../tools/taskTool.js";
|
|
17
18
|
import { createSkillTool } from "../tools/skillTool.js";
|
|
19
|
+
import {
|
|
20
|
+
taskCreateTool,
|
|
21
|
+
taskGetTool,
|
|
22
|
+
taskUpdateTool,
|
|
23
|
+
taskListTool,
|
|
24
|
+
} from "../tools/taskManagementTools.js";
|
|
18
25
|
import { McpManager } from "./mcpManager.js";
|
|
19
26
|
import { PermissionManager } from "./permissionManager.js";
|
|
20
27
|
import { ChatCompletionFunctionTool } from "openai/resources.js";
|
|
@@ -33,10 +40,16 @@ export interface ToolManagerOptions {
|
|
|
33
40
|
mcpManager: McpManager;
|
|
34
41
|
lspManager?: ILspManager;
|
|
35
42
|
logger?: Logger;
|
|
36
|
-
/**
|
|
43
|
+
/** Permission manager for handling tool permission checks */
|
|
37
44
|
permissionManager?: PermissionManager;
|
|
45
|
+
/** Foreground task manager for backgrounding tasks */
|
|
46
|
+
foregroundTaskManager?: import("../types/processes.js").IForegroundTaskManager;
|
|
47
|
+
/** Task manager for task management */
|
|
48
|
+
taskManager?: import("../services/taskManager.js").TaskManager;
|
|
38
49
|
/** Reversion manager for file snapshots */
|
|
39
50
|
reversionManager?: ReversionManager;
|
|
51
|
+
/** Background task manager for background execution */
|
|
52
|
+
backgroundTaskManager?: import("./backgroundTaskManager.js").BackgroundTaskManager;
|
|
40
53
|
/** Permission mode for tool execution (defaults to "default") */
|
|
41
54
|
permissionMode?: PermissionMode;
|
|
42
55
|
/** Custom permission callback for tool usage */
|
|
@@ -55,7 +68,10 @@ class ToolManager {
|
|
|
55
68
|
private lspManager?: ILspManager;
|
|
56
69
|
private logger?: Logger;
|
|
57
70
|
private permissionManager?: PermissionManager;
|
|
71
|
+
private foregroundTaskManager?: import("../types/processes.js").IForegroundTaskManager;
|
|
58
72
|
private reversionManager?: ReversionManager;
|
|
73
|
+
private taskManager?: import("../services/taskManager.js").TaskManager;
|
|
74
|
+
private backgroundTaskManager?: import("./backgroundTaskManager.js").BackgroundTaskManager;
|
|
59
75
|
private permissionMode?: PermissionMode;
|
|
60
76
|
private canUseToolCallback?: PermissionCallback;
|
|
61
77
|
|
|
@@ -64,7 +80,10 @@ class ToolManager {
|
|
|
64
80
|
this.lspManager = options.lspManager;
|
|
65
81
|
this.logger = options.logger;
|
|
66
82
|
this.permissionManager = options.permissionManager;
|
|
83
|
+
this.taskManager = options.taskManager;
|
|
84
|
+
this.foregroundTaskManager = options.foregroundTaskManager;
|
|
67
85
|
this.reversionManager = options.reversionManager;
|
|
86
|
+
this.backgroundTaskManager = options.backgroundTaskManager;
|
|
68
87
|
// Store CLI permission mode, let PermissionManager resolve effective mode
|
|
69
88
|
this.permissionMode = options.permissionMode;
|
|
70
89
|
this.canUseToolCallback = options.canUseToolCallback;
|
|
@@ -106,8 +125,8 @@ class ToolManager {
|
|
|
106
125
|
}): void {
|
|
107
126
|
const builtInTools = [
|
|
108
127
|
bashTool,
|
|
109
|
-
|
|
110
|
-
|
|
128
|
+
taskOutputTool,
|
|
129
|
+
taskStopTool,
|
|
111
130
|
deleteFileTool,
|
|
112
131
|
editTool,
|
|
113
132
|
multiEditTool,
|
|
@@ -118,8 +137,11 @@ class ToolManager {
|
|
|
118
137
|
grepTool,
|
|
119
138
|
lsTool,
|
|
120
139
|
readTool,
|
|
121
|
-
todoWriteTool,
|
|
122
140
|
lspTool,
|
|
141
|
+
taskCreateTool,
|
|
142
|
+
taskGetTool,
|
|
143
|
+
taskUpdateTool,
|
|
144
|
+
taskListTool,
|
|
123
145
|
];
|
|
124
146
|
|
|
125
147
|
for (const tool of builtInTools) {
|
|
@@ -167,9 +189,13 @@ class ToolManager {
|
|
|
167
189
|
permissionMode: effectivePermissionMode,
|
|
168
190
|
canUseToolCallback: this.canUseToolCallback,
|
|
169
191
|
permissionManager: this.permissionManager,
|
|
192
|
+
taskManager: this.taskManager!,
|
|
170
193
|
reversionManager: this.reversionManager,
|
|
194
|
+
backgroundTaskManager: this.backgroundTaskManager,
|
|
195
|
+
foregroundTaskManager: this.foregroundTaskManager,
|
|
171
196
|
mcpManager: this.mcpManager,
|
|
172
197
|
lspManager: this.lspManager,
|
|
198
|
+
sessionId: context.sessionId,
|
|
173
199
|
};
|
|
174
200
|
|
|
175
201
|
this.logger?.debug("Executing tool with enhanced context", {
|
|
@@ -240,6 +266,13 @@ class ToolManager {
|
|
|
240
266
|
return [...builtInToolsConfig, ...mcpToolsConfig];
|
|
241
267
|
}
|
|
242
268
|
|
|
269
|
+
/**
|
|
270
|
+
* Get the list of registered tool plugins
|
|
271
|
+
*/
|
|
272
|
+
public getTools(): ToolPlugin[] {
|
|
273
|
+
return Array.from(this.tools.values());
|
|
274
|
+
}
|
|
275
|
+
|
|
243
276
|
/**
|
|
244
277
|
* Get the current permission mode
|
|
245
278
|
*/
|
|
@@ -266,6 +299,15 @@ class ToolManager {
|
|
|
266
299
|
public getPermissionManager(): PermissionManager | undefined {
|
|
267
300
|
return this.permissionManager;
|
|
268
301
|
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Get the task manager
|
|
305
|
+
*/
|
|
306
|
+
public getTaskManager():
|
|
307
|
+
| import("../services/taskManager.js").TaskManager
|
|
308
|
+
| undefined {
|
|
309
|
+
return this.taskManager;
|
|
310
|
+
}
|
|
269
311
|
}
|
|
270
312
|
|
|
271
313
|
// Export tool registry class and types
|
|
@@ -43,7 +43,9 @@ export class GitService {
|
|
|
43
43
|
|
|
44
44
|
try {
|
|
45
45
|
const refArgs = ref ? `-b "${ref}"` : "--depth 1";
|
|
46
|
-
await execAsync(`
|
|
46
|
+
await execAsync(`git clone ${refArgs} "${url}" "${targetPath}"`, {
|
|
47
|
+
env: { ...process.env, LC_ALL: "C" },
|
|
48
|
+
});
|
|
47
49
|
} catch (error) {
|
|
48
50
|
throw this.handleGitError(urlOrRepo, error);
|
|
49
51
|
}
|
|
@@ -59,7 +61,9 @@ export class GitService {
|
|
|
59
61
|
);
|
|
60
62
|
}
|
|
61
63
|
try {
|
|
62
|
-
await execAsync(`
|
|
64
|
+
await execAsync(`git -C "${targetPath}" pull`, {
|
|
65
|
+
env: { ...process.env, LC_ALL: "C" },
|
|
66
|
+
});
|
|
63
67
|
} catch (error) {
|
|
64
68
|
throw this.handleGitError(targetPath, error);
|
|
65
69
|
}
|
|
@@ -346,7 +346,10 @@ export class MarketplaceService {
|
|
|
346
346
|
/**
|
|
347
347
|
* Installs a plugin from a marketplace
|
|
348
348
|
*/
|
|
349
|
-
async installPlugin(
|
|
349
|
+
async installPlugin(
|
|
350
|
+
pluginAtMarketplace: string,
|
|
351
|
+
projectPath?: string,
|
|
352
|
+
): Promise<InstalledPlugin> {
|
|
350
353
|
const [pluginName, marketplaceName] = pluginAtMarketplace.split("@");
|
|
351
354
|
if (!pluginName || !marketplaceName) {
|
|
352
355
|
throw new Error("Invalid plugin format. Use name@marketplace");
|
|
@@ -432,7 +435,10 @@ export class MarketplaceService {
|
|
|
432
435
|
|
|
433
436
|
const installedRegistry = await this.getInstalledPlugins();
|
|
434
437
|
const existingIndex = installedRegistry.plugins.findIndex(
|
|
435
|
-
(p) =>
|
|
438
|
+
(p) =>
|
|
439
|
+
p.name === pluginName &&
|
|
440
|
+
p.marketplace === marketplaceName &&
|
|
441
|
+
p.projectPath === projectPath,
|
|
436
442
|
);
|
|
437
443
|
|
|
438
444
|
const installedPlugin: InstalledPlugin = {
|
|
@@ -440,6 +446,7 @@ export class MarketplaceService {
|
|
|
440
446
|
marketplace: marketplaceName,
|
|
441
447
|
version,
|
|
442
448
|
cachePath,
|
|
449
|
+
projectPath,
|
|
443
450
|
};
|
|
444
451
|
|
|
445
452
|
if (existingIndex >= 0) {
|
|
@@ -467,7 +474,10 @@ export class MarketplaceService {
|
|
|
467
474
|
/**
|
|
468
475
|
* Uninstalls a plugin
|
|
469
476
|
*/
|
|
470
|
-
async uninstallPlugin(
|
|
477
|
+
async uninstallPlugin(
|
|
478
|
+
pluginAtMarketplace: string,
|
|
479
|
+
projectPath?: string,
|
|
480
|
+
): Promise<void> {
|
|
471
481
|
const [pluginName, marketplaceName] = pluginAtMarketplace.split("@");
|
|
472
482
|
if (!pluginName || !marketplaceName) {
|
|
473
483
|
throw new Error("Invalid plugin format. Use name@marketplace");
|
|
@@ -475,25 +485,33 @@ export class MarketplaceService {
|
|
|
475
485
|
|
|
476
486
|
const installedRegistry = await this.getInstalledPlugins();
|
|
477
487
|
const pluginIndex = installedRegistry.plugins.findIndex(
|
|
478
|
-
(p) =>
|
|
488
|
+
(p) =>
|
|
489
|
+
p.name === pluginName &&
|
|
490
|
+
p.marketplace === marketplaceName &&
|
|
491
|
+
p.projectPath === projectPath,
|
|
479
492
|
);
|
|
480
493
|
|
|
481
494
|
if (pluginIndex === -1) {
|
|
482
495
|
throw new Error(
|
|
483
|
-
`Plugin ${pluginName}@${marketplaceName} is not installed`,
|
|
496
|
+
`Plugin ${pluginName}@${marketplaceName} is not installed${projectPath ? ` for project ${projectPath}` : ""}`,
|
|
484
497
|
);
|
|
485
498
|
}
|
|
486
499
|
|
|
487
|
-
const
|
|
488
|
-
|
|
489
|
-
// Remove cached files
|
|
490
|
-
if (existsSync(plugin.cachePath)) {
|
|
491
|
-
await fs.rm(plugin.cachePath, { recursive: true, force: true });
|
|
492
|
-
}
|
|
500
|
+
const pluginToRemove = installedRegistry.plugins[pluginIndex];
|
|
493
501
|
|
|
494
|
-
// Remove from registry
|
|
502
|
+
// Remove from registry first
|
|
495
503
|
installedRegistry.plugins.splice(pluginIndex, 1);
|
|
496
504
|
await this.saveInstalledPlugins(installedRegistry);
|
|
505
|
+
|
|
506
|
+
// Check if any other project is still using this same cache path
|
|
507
|
+
const isStillReferenced = installedRegistry.plugins.some(
|
|
508
|
+
(p) => p.cachePath === pluginToRemove.cachePath,
|
|
509
|
+
);
|
|
510
|
+
|
|
511
|
+
// Only remove cached files if no other references exist
|
|
512
|
+
if (!isStillReferenced && existsSync(pluginToRemove.cachePath)) {
|
|
513
|
+
await fs.rm(pluginToRemove.cachePath, { recursive: true, force: true });
|
|
514
|
+
}
|
|
497
515
|
}
|
|
498
516
|
|
|
499
517
|
/**
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { minimatch } from "minimatch";
|
|
2
|
+
import * as path from "node:path";
|
|
2
3
|
import { parseFrontmatter } from "../utils/markdownParser.js";
|
|
3
4
|
import type { MemoryRule, MemoryRuleMetadata } from "../types/memoryRule.js";
|
|
4
5
|
|
|
@@ -45,15 +46,26 @@ export class MemoryRuleService {
|
|
|
45
46
|
/**
|
|
46
47
|
* Determines if a rule matches any of the given file paths using minimatch.
|
|
47
48
|
*/
|
|
48
|
-
isRuleActive(
|
|
49
|
+
isRuleActive(
|
|
50
|
+
rule: MemoryRule,
|
|
51
|
+
filesInContext: string[],
|
|
52
|
+
workdir?: string,
|
|
53
|
+
): boolean {
|
|
49
54
|
if (!rule.metadata.paths || rule.metadata.paths.length === 0) {
|
|
50
55
|
return true;
|
|
51
56
|
}
|
|
52
57
|
|
|
53
|
-
return filesInContext.some((filePath) =>
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
)
|
|
57
|
-
|
|
58
|
+
return filesInContext.some((filePath) => {
|
|
59
|
+
// Normalize path relative to workdir if it's an absolute path
|
|
60
|
+
let normalizedPath = filePath;
|
|
61
|
+
if (workdir && path.isAbsolute(filePath)) {
|
|
62
|
+
normalizedPath = path.relative(workdir, filePath);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return rule.metadata.paths!.some((pattern) => {
|
|
66
|
+
const isMatch = minimatch(normalizedPath, pattern, { dot: true });
|
|
67
|
+
return isMatch;
|
|
68
|
+
});
|
|
69
|
+
});
|
|
58
70
|
}
|
|
59
71
|
}
|