wave-agent-sdk 0.11.6 → 0.11.7
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/builtin/skills/init/SKILL.md +2 -0
- package/builtin/skills/settings/SKILLS.md +3 -2
- package/builtin/skills/settings/SUBAGENTS.md +1 -3
- package/dist/agent.d.ts +6 -0
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +18 -1
- package/dist/constants/tools.d.ts +1 -1
- package/dist/constants/tools.d.ts.map +1 -1
- package/dist/constants/tools.js +1 -1
- package/dist/managers/MemoryRuleManager.d.ts.map +1 -1
- package/dist/managers/MemoryRuleManager.js +1 -9
- package/dist/managers/aiManager.d.ts.map +1 -1
- package/dist/managers/aiManager.js +22 -3
- package/dist/managers/messageManager.d.ts +13 -5
- package/dist/managers/messageManager.d.ts.map +1 -1
- package/dist/managers/messageManager.js +62 -34
- package/dist/managers/pluginManager.d.ts.map +1 -1
- package/dist/managers/pluginManager.js +4 -2
- package/dist/managers/slashCommandManager.d.ts +2 -0
- package/dist/managers/slashCommandManager.d.ts.map +1 -1
- package/dist/managers/slashCommandManager.js +98 -4
- package/dist/managers/toolManager.d.ts.map +1 -1
- package/dist/managers/toolManager.js +8 -2
- package/dist/prompts/index.d.ts +2 -0
- package/dist/prompts/index.d.ts.map +1 -1
- package/dist/prompts/index.js +5 -0
- package/dist/services/GitService.d.ts +1 -0
- package/dist/services/GitService.d.ts.map +1 -1
- package/dist/services/GitService.js +16 -0
- package/dist/services/MarketplaceService.d.ts +7 -0
- package/dist/services/MarketplaceService.d.ts.map +1 -1
- package/dist/services/MarketplaceService.js +321 -252
- package/dist/services/aiService.d.ts +34 -0
- package/dist/services/aiService.d.ts.map +1 -1
- package/dist/services/aiService.js +124 -1
- package/dist/services/initializationService.d.ts.map +1 -1
- package/dist/services/initializationService.js +18 -0
- package/dist/tools/agentTool.js +3 -3
- package/dist/tools/bashTool.d.ts.map +1 -1
- package/dist/tools/bashTool.js +4 -4
- package/dist/tools/editTool.d.ts.map +1 -1
- package/dist/tools/editTool.js +2 -0
- package/dist/tools/globTool.d.ts.map +1 -1
- package/dist/tools/globTool.js +15 -3
- package/dist/tools/grepTool.d.ts.map +1 -1
- package/dist/tools/grepTool.js +38 -12
- package/dist/tools/readTool.d.ts.map +1 -1
- package/dist/tools/readTool.js +61 -0
- package/dist/tools/skillTool.js +2 -2
- package/dist/tools/types.d.ts +16 -0
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/webFetchTool.d.ts +3 -0
- package/dist/tools/webFetchTool.d.ts.map +1 -0
- package/dist/tools/webFetchTool.js +171 -0
- package/dist/tools/writeTool.d.ts.map +1 -1
- package/dist/tools/writeTool.js +2 -0
- package/dist/types/commands.d.ts +1 -1
- package/dist/types/commands.d.ts.map +1 -1
- package/dist/types/messaging.d.ts +1 -0
- package/dist/types/messaging.d.ts.map +1 -1
- package/dist/utils/bashParser.d.ts +14 -0
- package/dist/utils/bashParser.d.ts.map +1 -1
- package/dist/utils/bashParser.js +243 -142
- package/dist/utils/convertMessagesForAPI.d.ts.map +1 -1
- package/dist/utils/convertMessagesForAPI.js +7 -0
- package/dist/utils/fileUtils.d.ts +8 -0
- package/dist/utils/fileUtils.d.ts.map +1 -1
- package/dist/utils/fileUtils.js +52 -0
- package/dist/utils/messageOperations.d.ts +12 -3
- package/dist/utils/messageOperations.d.ts.map +1 -1
- package/dist/utils/messageOperations.js +77 -9
- package/package.json +4 -2
- package/src/agent.ts +19 -1
- package/src/constants/tools.ts +1 -1
- package/src/managers/MemoryRuleManager.ts +1 -10
- package/src/managers/aiManager.ts +23 -3
- package/src/managers/messageManager.ts +76 -38
- package/src/managers/pluginManager.ts +4 -2
- package/src/managers/slashCommandManager.ts +130 -4
- package/src/managers/toolManager.ts +11 -2
- package/src/prompts/index.ts +6 -0
- package/src/services/GitService.ts +20 -0
- package/src/services/MarketplaceService.ts +397 -324
- package/src/services/aiService.ts +197 -1
- package/src/services/initializationService.ts +38 -0
- package/src/tools/agentTool.ts +3 -3
- package/src/tools/bashTool.ts +3 -4
- package/src/tools/editTool.ts +3 -0
- package/src/tools/globTool.ts +16 -3
- package/src/tools/grepTool.ts +41 -13
- package/src/tools/readTool.ts +69 -0
- package/src/tools/skillTool.ts +2 -2
- package/src/tools/types.ts +13 -0
- package/src/tools/webFetchTool.ts +194 -0
- package/src/tools/writeTool.ts +3 -0
- package/src/types/commands.ts +1 -1
- package/src/types/messaging.ts +1 -0
- package/src/utils/bashParser.ts +268 -157
- package/src/utils/convertMessagesForAPI.ts +8 -0
- package/src/utils/fileUtils.ts +69 -0
- package/src/utils/messageOperations.ts +84 -9
- package/dist/tools/taskOutputTool.d.ts +0 -3
- package/dist/tools/taskOutputTool.d.ts.map +0 -1
- package/dist/tools/taskOutputTool.js +0 -198
- package/src/tools/taskOutputTool.ts +0 -222
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { randomUUID } from "crypto";
|
|
2
|
-
import type { Message, Usage } from "../types/index.js";
|
|
2
|
+
import type { Message, Usage, ToolBlock } from "../types/index.js";
|
|
3
3
|
import { MessageSource } from "../types/index.js";
|
|
4
4
|
import { readFileSync } from "fs";
|
|
5
5
|
import { extname } from "path";
|
|
@@ -12,6 +12,7 @@ export interface UserMessageParams {
|
|
|
12
12
|
images?: Array<{ path: string; mimeType: string }>;
|
|
13
13
|
customCommandContent?: string;
|
|
14
14
|
source?: MessageSource;
|
|
15
|
+
isMeta?: boolean;
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
// Parameter interfaces for message operations
|
|
@@ -23,6 +24,7 @@ export interface AddUserMessageParams extends UserMessageParams {
|
|
|
23
24
|
export interface UpdateToolBlockParams {
|
|
24
25
|
messages: Message[];
|
|
25
26
|
id: string;
|
|
27
|
+
messageId?: string; // Optional message ID to target a specific message
|
|
26
28
|
parameters?: string;
|
|
27
29
|
result?: string;
|
|
28
30
|
success?: boolean;
|
|
@@ -34,7 +36,7 @@ export interface UpdateToolBlockParams {
|
|
|
34
36
|
* - 'running': Tool execution in progress
|
|
35
37
|
* - 'end': Tool execution completed with final result
|
|
36
38
|
*/
|
|
37
|
-
stage
|
|
39
|
+
stage?: "start" | "streaming" | "running" | "end";
|
|
38
40
|
name?: string;
|
|
39
41
|
shortResult?: string;
|
|
40
42
|
startLineNumber?: number;
|
|
@@ -125,6 +127,7 @@ export const addUserMessageToMessages = ({
|
|
|
125
127
|
customCommandContent,
|
|
126
128
|
source,
|
|
127
129
|
id,
|
|
130
|
+
isMeta,
|
|
128
131
|
}: AddUserMessageParams): Message[] => {
|
|
129
132
|
const blocks: Message["blocks"] = [];
|
|
130
133
|
|
|
@@ -150,6 +153,7 @@ export const addUserMessageToMessages = ({
|
|
|
150
153
|
id: id || generateMessageId(),
|
|
151
154
|
role: "user",
|
|
152
155
|
blocks,
|
|
156
|
+
...(isMeta !== undefined && { isMeta }),
|
|
153
157
|
};
|
|
154
158
|
return [...messages, userMessage];
|
|
155
159
|
};
|
|
@@ -177,7 +181,11 @@ export const updateUserMessageInMessages = (
|
|
|
177
181
|
}
|
|
178
182
|
return block;
|
|
179
183
|
});
|
|
180
|
-
return {
|
|
184
|
+
return {
|
|
185
|
+
...msg,
|
|
186
|
+
blocks: newBlocks,
|
|
187
|
+
...(params.isMeta !== undefined && { isMeta: params.isMeta }),
|
|
188
|
+
};
|
|
181
189
|
}
|
|
182
190
|
return msg;
|
|
183
191
|
});
|
|
@@ -223,10 +231,43 @@ export const addAssistantMessageToMessages = (
|
|
|
223
231
|
return [...messages, initialAssistantMessage];
|
|
224
232
|
};
|
|
225
233
|
|
|
226
|
-
|
|
234
|
+
/**
|
|
235
|
+
* Add a tool block to a specific message by ID.
|
|
236
|
+
*/
|
|
237
|
+
export const addToolBlockToMessageInMessages = (
|
|
238
|
+
messages: Message[],
|
|
239
|
+
messageId: string,
|
|
240
|
+
params: Omit<AgentToolBlockUpdateParams, "id">,
|
|
241
|
+
): { messages: Message[]; toolBlockId: string } => {
|
|
242
|
+
const toolBlockId = randomUUID();
|
|
243
|
+
const newMessages = messages.map((msg) => {
|
|
244
|
+
if (msg.id === messageId) {
|
|
245
|
+
return {
|
|
246
|
+
...msg,
|
|
247
|
+
blocks: [
|
|
248
|
+
...msg.blocks,
|
|
249
|
+
{
|
|
250
|
+
type: "tool" as const,
|
|
251
|
+
id: toolBlockId,
|
|
252
|
+
name: params.name || "unknown",
|
|
253
|
+
parameters: params.parameters || "",
|
|
254
|
+
result: params.result || "",
|
|
255
|
+
stage: "start",
|
|
256
|
+
...params,
|
|
257
|
+
} as ToolBlock,
|
|
258
|
+
],
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
return msg;
|
|
262
|
+
});
|
|
263
|
+
return { messages: newMessages, toolBlockId };
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
// Update Tool Block of the last assistant or user message
|
|
227
267
|
export const updateToolBlockInMessage = ({
|
|
228
268
|
messages,
|
|
229
269
|
id,
|
|
270
|
+
messageId,
|
|
230
271
|
parameters,
|
|
231
272
|
result,
|
|
232
273
|
success,
|
|
@@ -241,9 +282,42 @@ export const updateToolBlockInMessage = ({
|
|
|
241
282
|
isManuallyBackgrounded,
|
|
242
283
|
}: UpdateToolBlockParams): Message[] => {
|
|
243
284
|
const newMessages = [...messages];
|
|
244
|
-
|
|
285
|
+
|
|
286
|
+
// If messageId is provided, target that specific message
|
|
287
|
+
if (messageId) {
|
|
288
|
+
const messageIndex = newMessages.findIndex((msg) => msg.id === messageId);
|
|
289
|
+
if (messageIndex !== -1) {
|
|
290
|
+
const toolBlockIndex = newMessages[messageIndex].blocks.findIndex(
|
|
291
|
+
(block) => block.type === "tool" && block.id === id,
|
|
292
|
+
);
|
|
293
|
+
|
|
294
|
+
if (toolBlockIndex !== -1) {
|
|
295
|
+
const toolBlock = newMessages[messageIndex].blocks[toolBlockIndex];
|
|
296
|
+
if (toolBlock.type === "tool") {
|
|
297
|
+
if (parameters !== undefined) toolBlock.parameters = parameters;
|
|
298
|
+
if (result !== undefined) toolBlock.result = result;
|
|
299
|
+
if (shortResult !== undefined) toolBlock.shortResult = shortResult;
|
|
300
|
+
if (startLineNumber !== undefined)
|
|
301
|
+
toolBlock.startLineNumber = startLineNumber;
|
|
302
|
+
if (images !== undefined) toolBlock.images = images;
|
|
303
|
+
if (success !== undefined) toolBlock.success = success;
|
|
304
|
+
if (error !== undefined) toolBlock.error = error;
|
|
305
|
+
if (stage !== undefined) toolBlock.stage = stage;
|
|
306
|
+
if (compactParams !== undefined)
|
|
307
|
+
toolBlock.compactParams = compactParams;
|
|
308
|
+
if (parametersChunk !== undefined)
|
|
309
|
+
toolBlock.parametersChunk = parametersChunk;
|
|
310
|
+
if (isManuallyBackgrounded !== undefined)
|
|
311
|
+
toolBlock.isManuallyBackgrounded = isManuallyBackgrounded;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
return newMessages;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// Find the last assistant or user message
|
|
245
319
|
for (let i = newMessages.length - 1; i >= 0; i--) {
|
|
246
|
-
if (newMessages[i].role === "assistant") {
|
|
320
|
+
if (newMessages[i].role === "assistant" || newMessages[i].role === "user") {
|
|
247
321
|
const toolBlockIndex = newMessages[i].blocks.findIndex(
|
|
248
322
|
(block) => block.type === "tool" && block.id === id,
|
|
249
323
|
);
|
|
@@ -267,8 +341,9 @@ export const updateToolBlockInMessage = ({
|
|
|
267
341
|
if (isManuallyBackgrounded !== undefined)
|
|
268
342
|
toolBlock.isManuallyBackgrounded = isManuallyBackgrounded;
|
|
269
343
|
}
|
|
270
|
-
|
|
271
|
-
|
|
344
|
+
break; // Found and updated, stop searching
|
|
345
|
+
} else if (newMessages[i].role === "assistant") {
|
|
346
|
+
// If existing block not found in assistant message, create new one
|
|
272
347
|
// This handles cases where we're streaming tool parameters before execution
|
|
273
348
|
newMessages[i].blocks.push({
|
|
274
349
|
type: "tool",
|
|
@@ -286,8 +361,8 @@ export const updateToolBlockInMessage = ({
|
|
|
286
361
|
parametersChunk: parametersChunk,
|
|
287
362
|
isManuallyBackgrounded: isManuallyBackgrounded,
|
|
288
363
|
});
|
|
364
|
+
break; // Created and added, stop searching
|
|
289
365
|
}
|
|
290
|
-
break;
|
|
291
366
|
}
|
|
292
367
|
}
|
|
293
368
|
return newMessages;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"taskOutputTool.d.ts","sourceRoot":"","sources":["../../src/tools/taskOutputTool.ts"],"names":[],"mappings":"AACA,OAAO,EAAe,UAAU,EAAc,MAAM,YAAY,CAAC;AAKjE,eAAO,MAAM,cAAc,EAAE,UAuN5B,CAAC"}
|
|
@@ -1,198 +0,0 @@
|
|
|
1
|
-
import { TASK_OUTPUT_TOOL_NAME } from "../constants/tools.js";
|
|
2
|
-
import { stripAnsiColors } from "../utils/stringUtils.js";
|
|
3
|
-
const MAX_OUTPUT_LENGTH = 30000;
|
|
4
|
-
export const taskOutputTool = {
|
|
5
|
-
name: TASK_OUTPUT_TOOL_NAME,
|
|
6
|
-
config: {
|
|
7
|
-
type: "function",
|
|
8
|
-
function: {
|
|
9
|
-
name: TASK_OUTPUT_TOOL_NAME,
|
|
10
|
-
description: "Retrieves output from a running or completed task",
|
|
11
|
-
parameters: {
|
|
12
|
-
type: "object",
|
|
13
|
-
properties: {
|
|
14
|
-
task_id: {
|
|
15
|
-
type: "string",
|
|
16
|
-
description: "The task ID to get output from",
|
|
17
|
-
},
|
|
18
|
-
block: {
|
|
19
|
-
type: "boolean",
|
|
20
|
-
default: true,
|
|
21
|
-
description: "Whether to wait for completion",
|
|
22
|
-
},
|
|
23
|
-
timeout: {
|
|
24
|
-
type: "number",
|
|
25
|
-
minimum: 0,
|
|
26
|
-
maximum: 600000,
|
|
27
|
-
default: 30000,
|
|
28
|
-
description: "Max wait time in ms",
|
|
29
|
-
},
|
|
30
|
-
},
|
|
31
|
-
required: ["task_id", "block", "timeout"],
|
|
32
|
-
},
|
|
33
|
-
},
|
|
34
|
-
},
|
|
35
|
-
prompt: () => `- Retrieves output from a running or completed task (background shell, agent, or remote session)
|
|
36
|
-
- Takes a task_id parameter identifying the task
|
|
37
|
-
- Returns the task output along with status information
|
|
38
|
-
- Use block=true (default) to wait for task completion
|
|
39
|
-
- Use block=false for non-blocking check of current status
|
|
40
|
-
- Task IDs can be found using the /tasks command
|
|
41
|
-
- Works with all task types: background shells, async agents, and remote sessions`,
|
|
42
|
-
execute: async (args, context) => {
|
|
43
|
-
const taskId = args.task_id;
|
|
44
|
-
const filter = args.filter;
|
|
45
|
-
const block = args.block ?? true;
|
|
46
|
-
const timeout = args.timeout ?? 30000;
|
|
47
|
-
if (!taskId || typeof taskId !== "string") {
|
|
48
|
-
return {
|
|
49
|
-
success: false,
|
|
50
|
-
content: "",
|
|
51
|
-
error: "task_id parameter is required and must be a string",
|
|
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
|
-
const getResult = () => {
|
|
63
|
-
const output = backgroundTaskManager.getOutput(taskId, filter);
|
|
64
|
-
if (!output)
|
|
65
|
-
return null;
|
|
66
|
-
let content = "";
|
|
67
|
-
if (output.stdout) {
|
|
68
|
-
content += stripAnsiColors(output.stdout);
|
|
69
|
-
}
|
|
70
|
-
if (output.stderr) {
|
|
71
|
-
content += (content ? "\n" : "") + stripAnsiColors(output.stderr);
|
|
72
|
-
}
|
|
73
|
-
const finalContent = content || "No output available";
|
|
74
|
-
let processedContent = finalContent;
|
|
75
|
-
let isTruncated = false;
|
|
76
|
-
if (finalContent.length > MAX_OUTPUT_LENGTH) {
|
|
77
|
-
processedContent =
|
|
78
|
-
"\n\n... (output truncated)\n" +
|
|
79
|
-
finalContent.substring(finalContent.length - MAX_OUTPUT_LENGTH);
|
|
80
|
-
isTruncated = true;
|
|
81
|
-
}
|
|
82
|
-
if (isTruncated && output.outputPath) {
|
|
83
|
-
processedContent += `\n\nFull output available at: ${output.outputPath}`;
|
|
84
|
-
}
|
|
85
|
-
let shortResult = `${taskId}: ${output.status}`;
|
|
86
|
-
if (output.status === "failed" && output.exitCode !== undefined) {
|
|
87
|
-
shortResult += ` (exit code: ${output.exitCode})`;
|
|
88
|
-
}
|
|
89
|
-
return {
|
|
90
|
-
success: true,
|
|
91
|
-
content: processedContent,
|
|
92
|
-
shortResult,
|
|
93
|
-
metadata: {
|
|
94
|
-
outputPath: output.outputPath,
|
|
95
|
-
status: output.status,
|
|
96
|
-
type: output.type,
|
|
97
|
-
exitCode: output.exitCode,
|
|
98
|
-
},
|
|
99
|
-
};
|
|
100
|
-
};
|
|
101
|
-
if (block) {
|
|
102
|
-
// Polling for completion
|
|
103
|
-
return new Promise((resolve) => {
|
|
104
|
-
let timeoutHandle = null;
|
|
105
|
-
let isAborted = false;
|
|
106
|
-
const startTime = Date.now();
|
|
107
|
-
const cleanup = () => {
|
|
108
|
-
if (timeoutHandle) {
|
|
109
|
-
clearTimeout(timeoutHandle);
|
|
110
|
-
timeoutHandle = null;
|
|
111
|
-
}
|
|
112
|
-
};
|
|
113
|
-
const onAbort = () => {
|
|
114
|
-
isAborted = true;
|
|
115
|
-
cleanup();
|
|
116
|
-
resolve({
|
|
117
|
-
success: false,
|
|
118
|
-
content: "",
|
|
119
|
-
error: "Task output retrieval was aborted",
|
|
120
|
-
});
|
|
121
|
-
};
|
|
122
|
-
if (context.abortSignal) {
|
|
123
|
-
if (context.abortSignal.aborted) {
|
|
124
|
-
onAbort();
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
context.abortSignal.addEventListener("abort", onAbort, {
|
|
128
|
-
once: true,
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
const check = () => {
|
|
132
|
-
if (isAborted)
|
|
133
|
-
return;
|
|
134
|
-
if (Date.now() - startTime > timeout) {
|
|
135
|
-
if (context.abortSignal) {
|
|
136
|
-
context.abortSignal.removeEventListener("abort", onAbort);
|
|
137
|
-
}
|
|
138
|
-
const result = getResult();
|
|
139
|
-
if (result) {
|
|
140
|
-
result.shortResult = `${taskId}: timeout`;
|
|
141
|
-
resolve(result);
|
|
142
|
-
}
|
|
143
|
-
else {
|
|
144
|
-
resolve({
|
|
145
|
-
success: true,
|
|
146
|
-
content: "Retrieval timed out",
|
|
147
|
-
shortResult: `${taskId}: timeout`,
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
const task = backgroundTaskManager.getTask(taskId);
|
|
153
|
-
if (!task) {
|
|
154
|
-
if (context.abortSignal) {
|
|
155
|
-
context.abortSignal.removeEventListener("abort", onAbort);
|
|
156
|
-
}
|
|
157
|
-
resolve({
|
|
158
|
-
success: false,
|
|
159
|
-
content: "",
|
|
160
|
-
error: `Task with ID ${taskId} not found`,
|
|
161
|
-
});
|
|
162
|
-
return;
|
|
163
|
-
}
|
|
164
|
-
if (task.status !== "running") {
|
|
165
|
-
if (context.abortSignal) {
|
|
166
|
-
context.abortSignal.removeEventListener("abort", onAbort);
|
|
167
|
-
}
|
|
168
|
-
const result = getResult();
|
|
169
|
-
resolve(result || {
|
|
170
|
-
success: false,
|
|
171
|
-
content: "",
|
|
172
|
-
error: "Task not found",
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
else {
|
|
176
|
-
const pollingInterval = process.env.NODE_ENV === "test" ? 10 : 500;
|
|
177
|
-
timeoutHandle = setTimeout(check, pollingInterval);
|
|
178
|
-
}
|
|
179
|
-
};
|
|
180
|
-
check();
|
|
181
|
-
});
|
|
182
|
-
}
|
|
183
|
-
const result = getResult();
|
|
184
|
-
if (!result) {
|
|
185
|
-
return {
|
|
186
|
-
success: false,
|
|
187
|
-
content: "",
|
|
188
|
-
error: `Task with ID ${taskId} not found`,
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
return result;
|
|
192
|
-
},
|
|
193
|
-
formatCompactParams: (params) => {
|
|
194
|
-
const taskId = params.task_id;
|
|
195
|
-
const block = params.block ?? true;
|
|
196
|
-
return `${taskId}${block ? " (blocking)" : ""}`;
|
|
197
|
-
},
|
|
198
|
-
};
|
|
@@ -1,222 +0,0 @@
|
|
|
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: "Retrieves output from a running or completed task",
|
|
14
|
-
parameters: {
|
|
15
|
-
type: "object",
|
|
16
|
-
properties: {
|
|
17
|
-
task_id: {
|
|
18
|
-
type: "string",
|
|
19
|
-
description: "The task ID to get output from",
|
|
20
|
-
},
|
|
21
|
-
block: {
|
|
22
|
-
type: "boolean",
|
|
23
|
-
default: true,
|
|
24
|
-
description: "Whether to wait for completion",
|
|
25
|
-
},
|
|
26
|
-
timeout: {
|
|
27
|
-
type: "number",
|
|
28
|
-
minimum: 0,
|
|
29
|
-
maximum: 600000,
|
|
30
|
-
default: 30000,
|
|
31
|
-
description: "Max wait time in ms",
|
|
32
|
-
},
|
|
33
|
-
},
|
|
34
|
-
required: ["task_id", "block", "timeout"],
|
|
35
|
-
},
|
|
36
|
-
},
|
|
37
|
-
},
|
|
38
|
-
prompt:
|
|
39
|
-
() => `- Retrieves output from a running or completed task (background shell, agent, or remote session)
|
|
40
|
-
- Takes a task_id parameter identifying the task
|
|
41
|
-
- Returns the task output along with status information
|
|
42
|
-
- Use block=true (default) to wait for task completion
|
|
43
|
-
- Use block=false for non-blocking check of current status
|
|
44
|
-
- Task IDs can be found using the /tasks command
|
|
45
|
-
- Works with all task types: background shells, async agents, and remote sessions`,
|
|
46
|
-
execute: async (
|
|
47
|
-
args: Record<string, unknown>,
|
|
48
|
-
context: ToolContext,
|
|
49
|
-
): Promise<ToolResult> => {
|
|
50
|
-
const taskId = args.task_id as string;
|
|
51
|
-
const filter = args.filter as string | undefined;
|
|
52
|
-
const block = (args.block as boolean | undefined) ?? true;
|
|
53
|
-
const timeout = (args.timeout as number | undefined) ?? 30000;
|
|
54
|
-
|
|
55
|
-
if (!taskId || typeof taskId !== "string") {
|
|
56
|
-
return {
|
|
57
|
-
success: false,
|
|
58
|
-
content: "",
|
|
59
|
-
error: "task_id parameter is required and must be a string",
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const backgroundTaskManager = context?.backgroundTaskManager;
|
|
64
|
-
if (!backgroundTaskManager) {
|
|
65
|
-
return {
|
|
66
|
-
success: false,
|
|
67
|
-
content: "",
|
|
68
|
-
error: "Background task manager not available",
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const getResult = () => {
|
|
73
|
-
const output = backgroundTaskManager.getOutput(taskId, filter);
|
|
74
|
-
if (!output) return null;
|
|
75
|
-
|
|
76
|
-
let content = "";
|
|
77
|
-
if (output.stdout) {
|
|
78
|
-
content += stripAnsiColors(output.stdout);
|
|
79
|
-
}
|
|
80
|
-
if (output.stderr) {
|
|
81
|
-
content += (content ? "\n" : "") + stripAnsiColors(output.stderr);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const finalContent = content || "No output available";
|
|
85
|
-
let processedContent = finalContent;
|
|
86
|
-
let isTruncated = false;
|
|
87
|
-
|
|
88
|
-
if (finalContent.length > MAX_OUTPUT_LENGTH) {
|
|
89
|
-
processedContent =
|
|
90
|
-
"\n\n... (output truncated)\n" +
|
|
91
|
-
finalContent.substring(finalContent.length - MAX_OUTPUT_LENGTH);
|
|
92
|
-
isTruncated = true;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
if (isTruncated && output.outputPath) {
|
|
96
|
-
processedContent += `\n\nFull output available at: ${output.outputPath}`;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
let shortResult = `${taskId}: ${output.status}`;
|
|
100
|
-
if (output.status === "failed" && output.exitCode !== undefined) {
|
|
101
|
-
shortResult += ` (exit code: ${output.exitCode})`;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
return {
|
|
105
|
-
success: true,
|
|
106
|
-
content: processedContent,
|
|
107
|
-
shortResult,
|
|
108
|
-
metadata: {
|
|
109
|
-
outputPath: output.outputPath,
|
|
110
|
-
status: output.status,
|
|
111
|
-
type: output.type,
|
|
112
|
-
exitCode: output.exitCode,
|
|
113
|
-
},
|
|
114
|
-
};
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
if (block) {
|
|
118
|
-
// Polling for completion
|
|
119
|
-
return new Promise((resolve) => {
|
|
120
|
-
let timeoutHandle: NodeJS.Timeout | null = null;
|
|
121
|
-
let isAborted = false;
|
|
122
|
-
const startTime = Date.now();
|
|
123
|
-
|
|
124
|
-
const cleanup = () => {
|
|
125
|
-
if (timeoutHandle) {
|
|
126
|
-
clearTimeout(timeoutHandle);
|
|
127
|
-
timeoutHandle = null;
|
|
128
|
-
}
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
const onAbort = () => {
|
|
132
|
-
isAborted = true;
|
|
133
|
-
cleanup();
|
|
134
|
-
resolve({
|
|
135
|
-
success: false,
|
|
136
|
-
content: "",
|
|
137
|
-
error: "Task output retrieval was aborted",
|
|
138
|
-
});
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
if (context.abortSignal) {
|
|
142
|
-
if (context.abortSignal.aborted) {
|
|
143
|
-
onAbort();
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
context.abortSignal.addEventListener("abort", onAbort, {
|
|
147
|
-
once: true,
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
const check = () => {
|
|
152
|
-
if (isAborted) return;
|
|
153
|
-
|
|
154
|
-
if (Date.now() - startTime > timeout) {
|
|
155
|
-
if (context.abortSignal) {
|
|
156
|
-
context.abortSignal.removeEventListener("abort", onAbort);
|
|
157
|
-
}
|
|
158
|
-
const result = getResult();
|
|
159
|
-
if (result) {
|
|
160
|
-
result.shortResult = `${taskId}: timeout`;
|
|
161
|
-
resolve(result);
|
|
162
|
-
} else {
|
|
163
|
-
resolve({
|
|
164
|
-
success: true,
|
|
165
|
-
content: "Retrieval timed out",
|
|
166
|
-
shortResult: `${taskId}: timeout`,
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
return;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
const task = backgroundTaskManager.getTask(taskId);
|
|
173
|
-
if (!task) {
|
|
174
|
-
if (context.abortSignal) {
|
|
175
|
-
context.abortSignal.removeEventListener("abort", onAbort);
|
|
176
|
-
}
|
|
177
|
-
resolve({
|
|
178
|
-
success: false,
|
|
179
|
-
content: "",
|
|
180
|
-
error: `Task with ID ${taskId} not found`,
|
|
181
|
-
});
|
|
182
|
-
return;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
if (task.status !== "running") {
|
|
186
|
-
if (context.abortSignal) {
|
|
187
|
-
context.abortSignal.removeEventListener("abort", onAbort);
|
|
188
|
-
}
|
|
189
|
-
const result = getResult();
|
|
190
|
-
resolve(
|
|
191
|
-
result || {
|
|
192
|
-
success: false,
|
|
193
|
-
content: "",
|
|
194
|
-
error: "Task not found",
|
|
195
|
-
},
|
|
196
|
-
);
|
|
197
|
-
} else {
|
|
198
|
-
const pollingInterval = process.env.NODE_ENV === "test" ? 10 : 500;
|
|
199
|
-
timeoutHandle = setTimeout(check, pollingInterval);
|
|
200
|
-
}
|
|
201
|
-
};
|
|
202
|
-
check();
|
|
203
|
-
});
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
const result = getResult();
|
|
207
|
-
if (!result) {
|
|
208
|
-
return {
|
|
209
|
-
success: false,
|
|
210
|
-
content: "",
|
|
211
|
-
error: `Task with ID ${taskId} not found`,
|
|
212
|
-
};
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
return result;
|
|
216
|
-
},
|
|
217
|
-
formatCompactParams: (params: Record<string, unknown>) => {
|
|
218
|
-
const taskId = params.task_id as string;
|
|
219
|
-
const block = (params.block as boolean | undefined) ?? true;
|
|
220
|
-
return `${taskId}${block ? " (blocking)" : ""}`;
|
|
221
|
-
},
|
|
222
|
-
};
|