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
|
@@ -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)
|
|
@@ -60,6 +62,7 @@ export interface SubagentInstance {
|
|
|
60
62
|
status: "initializing" | "active" | "completed" | "error" | "aborted";
|
|
61
63
|
messages: Message[];
|
|
62
64
|
subagentType: string; // Store the subagent type for hook context
|
|
65
|
+
backgroundTaskId?: string; // ID of the background task if transitioned
|
|
63
66
|
}
|
|
64
67
|
|
|
65
68
|
export interface SubagentManagerOptions {
|
|
@@ -71,8 +74,11 @@ export interface SubagentManagerOptions {
|
|
|
71
74
|
getGatewayConfig: () => GatewayConfig;
|
|
72
75
|
getModelConfig: () => ModelConfig;
|
|
73
76
|
getMaxInputTokens: () => number;
|
|
77
|
+
getLanguage: () => string | undefined;
|
|
74
78
|
hookManager?: HookManager;
|
|
75
79
|
onUsageAdded?: (usage: Usage) => void;
|
|
80
|
+
backgroundTaskManager?: BackgroundTaskManager;
|
|
81
|
+
memoryRuleManager?: MemoryRuleManager;
|
|
76
82
|
}
|
|
77
83
|
|
|
78
84
|
export class SubagentManager {
|
|
@@ -87,8 +93,11 @@ export class SubagentManager {
|
|
|
87
93
|
private getGatewayConfig: () => GatewayConfig;
|
|
88
94
|
private getModelConfig: () => ModelConfig;
|
|
89
95
|
private getMaxInputTokens: () => number;
|
|
96
|
+
private getLanguage: () => string | undefined;
|
|
90
97
|
private hookManager?: HookManager;
|
|
91
98
|
private onUsageAdded?: (usage: Usage) => void;
|
|
99
|
+
private backgroundTaskManager?: BackgroundTaskManager;
|
|
100
|
+
private memoryRuleManager?: MemoryRuleManager;
|
|
92
101
|
|
|
93
102
|
constructor(options: SubagentManagerOptions) {
|
|
94
103
|
this.workdir = options.workdir;
|
|
@@ -99,8 +108,11 @@ export class SubagentManager {
|
|
|
99
108
|
this.getGatewayConfig = options.getGatewayConfig;
|
|
100
109
|
this.getModelConfig = options.getModelConfig;
|
|
101
110
|
this.getMaxInputTokens = options.getMaxInputTokens;
|
|
111
|
+
this.getLanguage = options.getLanguage;
|
|
102
112
|
this.hookManager = options.hookManager;
|
|
103
113
|
this.onUsageAdded = options.onUsageAdded;
|
|
114
|
+
this.backgroundTaskManager = options.backgroundTaskManager;
|
|
115
|
+
this.memoryRuleManager = options.memoryRuleManager;
|
|
104
116
|
}
|
|
105
117
|
|
|
106
118
|
/**
|
|
@@ -155,6 +167,7 @@ export class SubagentManager {
|
|
|
155
167
|
prompt: string;
|
|
156
168
|
subagent_type: string;
|
|
157
169
|
},
|
|
170
|
+
runInBackground?: boolean,
|
|
158
171
|
): Promise<SubagentInstance> {
|
|
159
172
|
if (!this.parentToolManager) {
|
|
160
173
|
throw new Error(
|
|
@@ -173,6 +186,7 @@ export class SubagentManager {
|
|
|
173
186
|
logger: this.logger,
|
|
174
187
|
sessionType: "subagent",
|
|
175
188
|
subagentType: parameters.subagent_type,
|
|
189
|
+
memoryRuleManager: this.memoryRuleManager,
|
|
176
190
|
});
|
|
177
191
|
|
|
178
192
|
// Use the parent tool manager directly - tool restrictions will be handled by allowedTools parameter
|
|
@@ -211,6 +225,7 @@ export class SubagentManager {
|
|
|
211
225
|
};
|
|
212
226
|
},
|
|
213
227
|
getMaxInputTokens: this.getMaxInputTokens,
|
|
228
|
+
getLanguage: this.getLanguage,
|
|
214
229
|
callbacks: {
|
|
215
230
|
onUsageAdded: this.onUsageAdded,
|
|
216
231
|
},
|
|
@@ -237,6 +252,7 @@ export class SubagentManager {
|
|
|
237
252
|
configuration,
|
|
238
253
|
"active",
|
|
239
254
|
parameters,
|
|
255
|
+
runInBackground,
|
|
240
256
|
);
|
|
241
257
|
|
|
242
258
|
return instance;
|
|
@@ -252,6 +268,7 @@ export class SubagentManager {
|
|
|
252
268
|
instance: SubagentInstance,
|
|
253
269
|
prompt: string,
|
|
254
270
|
abortSignal?: AbortSignal,
|
|
271
|
+
runInBackground?: boolean,
|
|
255
272
|
): Promise<string> {
|
|
256
273
|
try {
|
|
257
274
|
// Check if already aborted before starting
|
|
@@ -265,24 +282,125 @@ export class SubagentManager {
|
|
|
265
282
|
status: "active",
|
|
266
283
|
});
|
|
267
284
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
285
|
+
if (runInBackground && this.backgroundTaskManager) {
|
|
286
|
+
const taskId = this.backgroundTaskManager.generateId();
|
|
287
|
+
const startTime = Date.now();
|
|
288
|
+
|
|
289
|
+
this.backgroundTaskManager.addTask({
|
|
290
|
+
id: taskId,
|
|
291
|
+
type: "subagent",
|
|
292
|
+
status: "running",
|
|
293
|
+
startTime,
|
|
294
|
+
description: instance.configuration.description,
|
|
295
|
+
stdout: "",
|
|
296
|
+
stderr: "",
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
instance.backgroundTaskId = taskId;
|
|
300
|
+
|
|
301
|
+
// Execute in background
|
|
302
|
+
(async () => {
|
|
303
|
+
try {
|
|
304
|
+
const result = await this.internalExecute(
|
|
305
|
+
instance,
|
|
306
|
+
prompt,
|
|
307
|
+
abortSignal,
|
|
308
|
+
);
|
|
309
|
+
const task = this.backgroundTaskManager?.getTask(taskId);
|
|
310
|
+
if (task) {
|
|
311
|
+
task.status = "completed";
|
|
312
|
+
task.stdout = result;
|
|
313
|
+
task.endTime = Date.now();
|
|
314
|
+
task.runtime = task.endTime - startTime;
|
|
315
|
+
}
|
|
316
|
+
} catch (error) {
|
|
317
|
+
const task = this.backgroundTaskManager?.getTask(taskId);
|
|
318
|
+
if (task) {
|
|
319
|
+
task.status = "failed";
|
|
320
|
+
task.stderr =
|
|
321
|
+
error instanceof Error ? error.message : String(error);
|
|
322
|
+
task.endTime = Date.now();
|
|
323
|
+
task.runtime = task.endTime - startTime;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
})();
|
|
327
|
+
|
|
328
|
+
return taskId;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
return await this.internalExecute(instance, prompt, abortSignal);
|
|
332
|
+
} catch (error) {
|
|
333
|
+
this.updateInstanceStatus(instance.subagentId, "error");
|
|
334
|
+
this.parentMessageManager.updateSubagentBlock(instance.subagentId, {
|
|
335
|
+
status: "error",
|
|
336
|
+
});
|
|
337
|
+
throw error;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
async backgroundInstance(subagentId: string): Promise<string> {
|
|
342
|
+
const instance = this.instances.get(subagentId);
|
|
343
|
+
if (!instance) {
|
|
344
|
+
throw new Error(`Subagent instance ${subagentId} not found`);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
if (!this.backgroundTaskManager) {
|
|
348
|
+
throw new Error("BackgroundTaskManager not available");
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
const taskId = this.backgroundTaskManager.generateId();
|
|
352
|
+
const startTime = Date.now();
|
|
353
|
+
|
|
354
|
+
this.backgroundTaskManager.addTask({
|
|
355
|
+
id: taskId,
|
|
356
|
+
type: "subagent",
|
|
357
|
+
status: "running",
|
|
358
|
+
startTime,
|
|
359
|
+
description: instance.configuration.description,
|
|
360
|
+
stdout: "",
|
|
361
|
+
stderr: "",
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
instance.backgroundTaskId = taskId;
|
|
365
|
+
|
|
366
|
+
// Update parent message manager to reflect background status
|
|
367
|
+
this.parentMessageManager.updateSubagentBlock(subagentId, {
|
|
368
|
+
runInBackground: true,
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
return taskId;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
private async internalExecute(
|
|
375
|
+
instance: SubagentInstance,
|
|
376
|
+
prompt: string,
|
|
377
|
+
abortSignal?: AbortSignal,
|
|
378
|
+
): Promise<string> {
|
|
379
|
+
// Set up consolidated abort handler to prevent listener accumulation
|
|
380
|
+
let abortCleanup: (() => void) | undefined;
|
|
381
|
+
if (abortSignal) {
|
|
382
|
+
abortCleanup = addConsolidatedAbortListener(abortSignal, [
|
|
383
|
+
() => {
|
|
384
|
+
// Update status to aborted
|
|
385
|
+
// Only update status if it's NOT a background task
|
|
386
|
+
if (!instance.backgroundTaskId) {
|
|
274
387
|
this.updateInstanceStatus(instance.subagentId, "aborted");
|
|
275
388
|
this.parentMessageManager.updateSubagentBlock(instance.subagentId, {
|
|
276
389
|
status: "aborted",
|
|
277
390
|
});
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
|
|
391
|
+
}
|
|
392
|
+
},
|
|
393
|
+
() => {
|
|
394
|
+
// Abort the AI execution
|
|
395
|
+
// Only abort if it's NOT a background task
|
|
396
|
+
if (!instance.backgroundTaskId) {
|
|
281
397
|
instance.aiManager.abortAIMessage();
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
|
|
398
|
+
}
|
|
399
|
+
},
|
|
400
|
+
]);
|
|
401
|
+
}
|
|
285
402
|
|
|
403
|
+
try {
|
|
286
404
|
// Add the user's prompt as a message
|
|
287
405
|
instance.messageManager.addUserMessage({ content: prompt });
|
|
288
406
|
|
|
@@ -322,21 +440,16 @@ export class SubagentManager {
|
|
|
322
440
|
model: resolvedModel,
|
|
323
441
|
});
|
|
324
442
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
} finally {
|
|
336
|
-
// Clean up abort listeners to prevent memory leaks
|
|
337
|
-
if (abortCleanup) {
|
|
338
|
-
abortCleanup();
|
|
339
|
-
}
|
|
443
|
+
// If we have an abort signal, race against it using utilities to prevent listener accumulation
|
|
444
|
+
// BUT: If this is a background task, we DON'T want to race against the abort signal
|
|
445
|
+
// because the abort signal (Esc) should only stop the tool watching the task, not the task itself.
|
|
446
|
+
if (abortSignal && !instance.backgroundTaskId) {
|
|
447
|
+
await Promise.race([
|
|
448
|
+
executeAI,
|
|
449
|
+
createAbortPromise(abortSignal, "Task was aborted"),
|
|
450
|
+
]);
|
|
451
|
+
} else {
|
|
452
|
+
await executeAI;
|
|
340
453
|
}
|
|
341
454
|
|
|
342
455
|
// Get the latest messages to extract the response
|
|
@@ -361,13 +474,43 @@ export class SubagentManager {
|
|
|
361
474
|
status: "completed",
|
|
362
475
|
});
|
|
363
476
|
|
|
477
|
+
// If this was transitioned to background, update the background task
|
|
478
|
+
if (instance.backgroundTaskId && this.backgroundTaskManager) {
|
|
479
|
+
const task = this.backgroundTaskManager.getTask(
|
|
480
|
+
instance.backgroundTaskId,
|
|
481
|
+
);
|
|
482
|
+
if (task) {
|
|
483
|
+
task.status = "completed";
|
|
484
|
+
task.stdout = response || "Task completed with no text response";
|
|
485
|
+
task.endTime = Date.now();
|
|
486
|
+
if (task.startTime) {
|
|
487
|
+
task.runtime = task.endTime - task.startTime;
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
|
|
364
492
|
return response || "Task completed with no text response";
|
|
365
493
|
} catch (error) {
|
|
366
|
-
this
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
494
|
+
// If this was transitioned to background, update the background task with error
|
|
495
|
+
if (instance.backgroundTaskId && this.backgroundTaskManager) {
|
|
496
|
+
const task = this.backgroundTaskManager.getTask(
|
|
497
|
+
instance.backgroundTaskId,
|
|
498
|
+
);
|
|
499
|
+
if (task) {
|
|
500
|
+
task.status = "failed";
|
|
501
|
+
task.stderr = error instanceof Error ? error.message : String(error);
|
|
502
|
+
task.endTime = Date.now();
|
|
503
|
+
if (task.startTime) {
|
|
504
|
+
task.runtime = task.endTime - task.startTime;
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
}
|
|
370
508
|
throw error;
|
|
509
|
+
} finally {
|
|
510
|
+
// Clean up abort listeners to prevent memory leaks
|
|
511
|
+
if (abortCleanup) {
|
|
512
|
+
abortCleanup();
|
|
513
|
+
}
|
|
371
514
|
}
|
|
372
515
|
}
|
|
373
516
|
|
|
@@ -458,6 +601,7 @@ export class SubagentManager {
|
|
|
458
601
|
logger: this.logger,
|
|
459
602
|
sessionType: "subagent",
|
|
460
603
|
subagentType: configuration.name, // Use configuration name for restored sessions
|
|
604
|
+
memoryRuleManager: this.memoryRuleManager,
|
|
461
605
|
});
|
|
462
606
|
|
|
463
607
|
// Use the parent tool manager
|
|
@@ -491,6 +635,7 @@ export class SubagentManager {
|
|
|
491
635
|
agentModel: modelToUse,
|
|
492
636
|
}),
|
|
493
637
|
getMaxInputTokens: this.getMaxInputTokens,
|
|
638
|
+
getLanguage: this.getLanguage,
|
|
494
639
|
callbacks: {
|
|
495
640
|
onUsageAdded: this.onUsageAdded,
|
|
496
641
|
},
|
|
@@ -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";
|
|
@@ -27,12 +29,20 @@ import type {
|
|
|
27
29
|
import type { SubagentManager } from "./subagentManager.js";
|
|
28
30
|
import type { SkillManager } from "./skillManager.js";
|
|
29
31
|
|
|
32
|
+
import { ReversionManager } from "./reversionManager.js";
|
|
33
|
+
|
|
30
34
|
export interface ToolManagerOptions {
|
|
31
35
|
mcpManager: McpManager;
|
|
32
36
|
lspManager?: ILspManager;
|
|
33
37
|
logger?: Logger;
|
|
34
|
-
/**
|
|
38
|
+
/** Permission manager for handling tool permission checks */
|
|
35
39
|
permissionManager?: PermissionManager;
|
|
40
|
+
/** Foreground task manager for backgrounding tasks */
|
|
41
|
+
foregroundTaskManager?: import("../types/processes.js").IForegroundTaskManager;
|
|
42
|
+
/** Reversion manager for file snapshots */
|
|
43
|
+
reversionManager?: ReversionManager;
|
|
44
|
+
/** Background task manager for background execution */
|
|
45
|
+
backgroundTaskManager?: import("./backgroundTaskManager.js").BackgroundTaskManager;
|
|
36
46
|
/** Permission mode for tool execution (defaults to "default") */
|
|
37
47
|
permissionMode?: PermissionMode;
|
|
38
48
|
/** Custom permission callback for tool usage */
|
|
@@ -51,6 +61,9 @@ class ToolManager {
|
|
|
51
61
|
private lspManager?: ILspManager;
|
|
52
62
|
private logger?: Logger;
|
|
53
63
|
private permissionManager?: PermissionManager;
|
|
64
|
+
private foregroundTaskManager?: import("../types/processes.js").IForegroundTaskManager;
|
|
65
|
+
private reversionManager?: ReversionManager;
|
|
66
|
+
private backgroundTaskManager?: import("./backgroundTaskManager.js").BackgroundTaskManager;
|
|
54
67
|
private permissionMode?: PermissionMode;
|
|
55
68
|
private canUseToolCallback?: PermissionCallback;
|
|
56
69
|
|
|
@@ -59,6 +72,9 @@ class ToolManager {
|
|
|
59
72
|
this.lspManager = options.lspManager;
|
|
60
73
|
this.logger = options.logger;
|
|
61
74
|
this.permissionManager = options.permissionManager;
|
|
75
|
+
this.foregroundTaskManager = options.foregroundTaskManager;
|
|
76
|
+
this.reversionManager = options.reversionManager;
|
|
77
|
+
this.backgroundTaskManager = options.backgroundTaskManager;
|
|
62
78
|
// Store CLI permission mode, let PermissionManager resolve effective mode
|
|
63
79
|
this.permissionMode = options.permissionMode;
|
|
64
80
|
this.canUseToolCallback = options.canUseToolCallback;
|
|
@@ -100,8 +116,8 @@ class ToolManager {
|
|
|
100
116
|
}): void {
|
|
101
117
|
const builtInTools = [
|
|
102
118
|
bashTool,
|
|
103
|
-
|
|
104
|
-
|
|
119
|
+
taskOutputTool,
|
|
120
|
+
taskStopTool,
|
|
105
121
|
deleteFileTool,
|
|
106
122
|
editTool,
|
|
107
123
|
multiEditTool,
|
|
@@ -161,6 +177,9 @@ class ToolManager {
|
|
|
161
177
|
permissionMode: effectivePermissionMode,
|
|
162
178
|
canUseToolCallback: this.canUseToolCallback,
|
|
163
179
|
permissionManager: this.permissionManager,
|
|
180
|
+
reversionManager: this.reversionManager,
|
|
181
|
+
backgroundTaskManager: this.backgroundTaskManager,
|
|
182
|
+
foregroundTaskManager: this.foregroundTaskManager,
|
|
164
183
|
mcpManager: this.mcpManager,
|
|
165
184
|
lspManager: this.lspManager,
|
|
166
185
|
};
|
|
@@ -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
|
}
|
|
@@ -25,6 +25,13 @@ export class MarketplaceService {
|
|
|
25
25
|
private cacheDir: string;
|
|
26
26
|
private marketplacesDir: string;
|
|
27
27
|
private gitService: GitService;
|
|
28
|
+
private static readonly BUILTIN_MARKETPLACE: KnownMarketplace = {
|
|
29
|
+
name: "wave-plugins-official",
|
|
30
|
+
source: {
|
|
31
|
+
source: "github",
|
|
32
|
+
repo: "netease-lcap/wave-plugins-official",
|
|
33
|
+
},
|
|
34
|
+
};
|
|
28
35
|
|
|
29
36
|
constructor() {
|
|
30
37
|
this.pluginsDir = getPluginsDir();
|
|
@@ -62,7 +69,14 @@ export class MarketplaceService {
|
|
|
62
69
|
*/
|
|
63
70
|
async getKnownMarketplaces(): Promise<KnownMarketplacesRegistry> {
|
|
64
71
|
if (!existsSync(this.knownMarketplacesPath)) {
|
|
65
|
-
return {
|
|
72
|
+
return {
|
|
73
|
+
marketplaces: [
|
|
74
|
+
{
|
|
75
|
+
...MarketplaceService.BUILTIN_MARKETPLACE,
|
|
76
|
+
isBuiltin: true,
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
};
|
|
66
80
|
}
|
|
67
81
|
try {
|
|
68
82
|
const content = await fs.readFile(this.knownMarketplacesPath, "utf-8");
|
|
@@ -245,6 +259,10 @@ export class MarketplaceService {
|
|
|
245
259
|
registry.marketplaces.push(marketplace);
|
|
246
260
|
}
|
|
247
261
|
|
|
262
|
+
// Ensure builtin is included if we are creating the file for the first time
|
|
263
|
+
// and it hasn't been explicitly removed yet.
|
|
264
|
+
// (getKnownMarketplaces already handles the default injection)
|
|
265
|
+
|
|
248
266
|
await this.saveKnownMarketplaces(registry);
|
|
249
267
|
return marketplace;
|
|
250
268
|
}
|
|
@@ -254,7 +272,27 @@ export class MarketplaceService {
|
|
|
254
272
|
*/
|
|
255
273
|
async listMarketplaces(): Promise<KnownMarketplace[]> {
|
|
256
274
|
const registry = await this.getKnownMarketplaces();
|
|
257
|
-
return registry.marketplaces
|
|
275
|
+
return registry.marketplaces.map((m) => ({
|
|
276
|
+
...m,
|
|
277
|
+
isBuiltin: m.name === MarketplaceService.BUILTIN_MARKETPLACE.name,
|
|
278
|
+
}));
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Removes a marketplace by name
|
|
283
|
+
*/
|
|
284
|
+
async removeMarketplace(name: string): Promise<void> {
|
|
285
|
+
const registry = await this.getKnownMarketplaces();
|
|
286
|
+
const initialCount = registry.marketplaces.length;
|
|
287
|
+
registry.marketplaces = registry.marketplaces.filter(
|
|
288
|
+
(m) => m.name !== name,
|
|
289
|
+
);
|
|
290
|
+
|
|
291
|
+
if (registry.marketplaces.length === initialCount) {
|
|
292
|
+
throw new Error(`Marketplace ${name} not found`);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
await this.saveKnownMarketplaces(registry);
|
|
258
296
|
}
|
|
259
297
|
|
|
260
298
|
/**
|
|
@@ -308,7 +346,10 @@ export class MarketplaceService {
|
|
|
308
346
|
/**
|
|
309
347
|
* Installs a plugin from a marketplace
|
|
310
348
|
*/
|
|
311
|
-
async installPlugin(
|
|
349
|
+
async installPlugin(
|
|
350
|
+
pluginAtMarketplace: string,
|
|
351
|
+
projectPath?: string,
|
|
352
|
+
): Promise<InstalledPlugin> {
|
|
312
353
|
const [pluginName, marketplaceName] = pluginAtMarketplace.split("@");
|
|
313
354
|
if (!pluginName || !marketplaceName) {
|
|
314
355
|
throw new Error("Invalid plugin format. Use name@marketplace");
|
|
@@ -394,7 +435,10 @@ export class MarketplaceService {
|
|
|
394
435
|
|
|
395
436
|
const installedRegistry = await this.getInstalledPlugins();
|
|
396
437
|
const existingIndex = installedRegistry.plugins.findIndex(
|
|
397
|
-
(p) =>
|
|
438
|
+
(p) =>
|
|
439
|
+
p.name === pluginName &&
|
|
440
|
+
p.marketplace === marketplaceName &&
|
|
441
|
+
p.projectPath === projectPath,
|
|
398
442
|
);
|
|
399
443
|
|
|
400
444
|
const installedPlugin: InstalledPlugin = {
|
|
@@ -402,6 +446,7 @@ export class MarketplaceService {
|
|
|
402
446
|
marketplace: marketplaceName,
|
|
403
447
|
version,
|
|
404
448
|
cachePath,
|
|
449
|
+
projectPath,
|
|
405
450
|
};
|
|
406
451
|
|
|
407
452
|
if (existingIndex >= 0) {
|
|
@@ -425,4 +470,55 @@ export class MarketplaceService {
|
|
|
425
470
|
);
|
|
426
471
|
}
|
|
427
472
|
}
|
|
473
|
+
|
|
474
|
+
/**
|
|
475
|
+
* Uninstalls a plugin
|
|
476
|
+
*/
|
|
477
|
+
async uninstallPlugin(
|
|
478
|
+
pluginAtMarketplace: string,
|
|
479
|
+
projectPath?: string,
|
|
480
|
+
): Promise<void> {
|
|
481
|
+
const [pluginName, marketplaceName] = pluginAtMarketplace.split("@");
|
|
482
|
+
if (!pluginName || !marketplaceName) {
|
|
483
|
+
throw new Error("Invalid plugin format. Use name@marketplace");
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
const installedRegistry = await this.getInstalledPlugins();
|
|
487
|
+
const pluginIndex = installedRegistry.plugins.findIndex(
|
|
488
|
+
(p) =>
|
|
489
|
+
p.name === pluginName &&
|
|
490
|
+
p.marketplace === marketplaceName &&
|
|
491
|
+
p.projectPath === projectPath,
|
|
492
|
+
);
|
|
493
|
+
|
|
494
|
+
if (pluginIndex === -1) {
|
|
495
|
+
throw new Error(
|
|
496
|
+
`Plugin ${pluginName}@${marketplaceName} is not installed${projectPath ? ` for project ${projectPath}` : ""}`,
|
|
497
|
+
);
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
const pluginToRemove = installedRegistry.plugins[pluginIndex];
|
|
501
|
+
|
|
502
|
+
// Remove from registry first
|
|
503
|
+
installedRegistry.plugins.splice(pluginIndex, 1);
|
|
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
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
/**
|
|
518
|
+
* Updates a plugin (uninstall followed by install)
|
|
519
|
+
*/
|
|
520
|
+
async updatePlugin(pluginAtMarketplace: string): Promise<InstalledPlugin> {
|
|
521
|
+
await this.uninstallPlugin(pluginAtMarketplace);
|
|
522
|
+
return this.installPlugin(pluginAtMarketplace);
|
|
523
|
+
}
|
|
428
524
|
}
|
|
@@ -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
|
}
|