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
|
@@ -0,0 +1,196 @@
|
|
|
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"],
|
|
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
|
+
const processedContent =
|
|
86
|
+
finalContent.length > MAX_OUTPUT_LENGTH
|
|
87
|
+
? finalContent.substring(0, MAX_OUTPUT_LENGTH) +
|
|
88
|
+
"\n\n... (output truncated)"
|
|
89
|
+
: finalContent;
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
success: true,
|
|
93
|
+
content: processedContent,
|
|
94
|
+
shortResult: `${taskId}: ${output.status}`,
|
|
95
|
+
};
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
if (block) {
|
|
99
|
+
// Polling for completion
|
|
100
|
+
return new Promise((resolve) => {
|
|
101
|
+
let timeoutHandle: NodeJS.Timeout | null = null;
|
|
102
|
+
let isAborted = false;
|
|
103
|
+
const startTime = Date.now();
|
|
104
|
+
|
|
105
|
+
const cleanup = () => {
|
|
106
|
+
if (timeoutHandle) {
|
|
107
|
+
clearTimeout(timeoutHandle);
|
|
108
|
+
timeoutHandle = null;
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const onAbort = () => {
|
|
113
|
+
isAborted = true;
|
|
114
|
+
cleanup();
|
|
115
|
+
resolve({
|
|
116
|
+
success: false,
|
|
117
|
+
content: "",
|
|
118
|
+
error: "Task output retrieval was aborted",
|
|
119
|
+
});
|
|
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
|
+
|
|
132
|
+
const check = () => {
|
|
133
|
+
if (isAborted) return;
|
|
134
|
+
|
|
135
|
+
if (Date.now() - startTime > timeout) {
|
|
136
|
+
if (context.abortSignal) {
|
|
137
|
+
context.abortSignal.removeEventListener("abort", onAbort);
|
|
138
|
+
}
|
|
139
|
+
resolve({
|
|
140
|
+
success: true,
|
|
141
|
+
content: "Retrieval timed out",
|
|
142
|
+
shortResult: `${taskId}: timeout`,
|
|
143
|
+
});
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const task = backgroundTaskManager.getTask(taskId);
|
|
148
|
+
if (!task) {
|
|
149
|
+
if (context.abortSignal) {
|
|
150
|
+
context.abortSignal.removeEventListener("abort", onAbort);
|
|
151
|
+
}
|
|
152
|
+
resolve({
|
|
153
|
+
success: false,
|
|
154
|
+
content: "",
|
|
155
|
+
error: `Task with ID ${taskId} not found`,
|
|
156
|
+
});
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (task.status !== "running") {
|
|
161
|
+
if (context.abortSignal) {
|
|
162
|
+
context.abortSignal.removeEventListener("abort", onAbort);
|
|
163
|
+
}
|
|
164
|
+
const result = getResult();
|
|
165
|
+
resolve(
|
|
166
|
+
result || {
|
|
167
|
+
success: false,
|
|
168
|
+
content: "",
|
|
169
|
+
error: "Task not found",
|
|
170
|
+
},
|
|
171
|
+
);
|
|
172
|
+
} else {
|
|
173
|
+
timeoutHandle = setTimeout(check, 500);
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
check();
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const result = getResult();
|
|
181
|
+
if (!result) {
|
|
182
|
+
return {
|
|
183
|
+
success: false,
|
|
184
|
+
content: "",
|
|
185
|
+
error: `Task with ID ${taskId} not found`,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return result;
|
|
190
|
+
},
|
|
191
|
+
formatCompactParams: (params: Record<string, unknown>) => {
|
|
192
|
+
const taskId = params.task_id as string;
|
|
193
|
+
const block = params.block as boolean;
|
|
194
|
+
return `${taskId}${block ? " (blocking)" : ""}`;
|
|
195
|
+
},
|
|
196
|
+
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { TASK_STOP_TOOL_NAME } from "../constants/tools.js";
|
|
2
|
+
import { ToolContext, ToolPlugin, ToolResult } from "./types.js";
|
|
3
|
+
|
|
4
|
+
export const taskStopTool: ToolPlugin = {
|
|
5
|
+
name: TASK_STOP_TOOL_NAME,
|
|
6
|
+
config: {
|
|
7
|
+
type: "function",
|
|
8
|
+
function: {
|
|
9
|
+
name: TASK_STOP_TOOL_NAME,
|
|
10
|
+
description: "Stop a running background task by ID",
|
|
11
|
+
parameters: {
|
|
12
|
+
type: "object",
|
|
13
|
+
properties: {
|
|
14
|
+
task_id: {
|
|
15
|
+
type: "string",
|
|
16
|
+
description: "The ID of the background task to stop",
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
required: ["task_id"],
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
prompt: () => `
|
|
24
|
+
- Stops a running background task by its ID
|
|
25
|
+
- Takes a task_id parameter identifying the task to stop
|
|
26
|
+
- Returns a success or failure status
|
|
27
|
+
- Use this tool when you need to terminate a long-running task
|
|
28
|
+
`,
|
|
29
|
+
execute: async (
|
|
30
|
+
args: Record<string, unknown>,
|
|
31
|
+
context: ToolContext,
|
|
32
|
+
): Promise<ToolResult> => {
|
|
33
|
+
const taskId = args.task_id as string;
|
|
34
|
+
|
|
35
|
+
if (!taskId || typeof taskId !== "string") {
|
|
36
|
+
return {
|
|
37
|
+
success: false,
|
|
38
|
+
content: "",
|
|
39
|
+
error: "task_id parameter is required and must be a string",
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const backgroundTaskManager = context?.backgroundTaskManager;
|
|
44
|
+
if (!backgroundTaskManager) {
|
|
45
|
+
return {
|
|
46
|
+
success: false,
|
|
47
|
+
content: "",
|
|
48
|
+
error: "Background task manager not available",
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const stopped = backgroundTaskManager.stopTask(taskId);
|
|
53
|
+
if (stopped) {
|
|
54
|
+
return {
|
|
55
|
+
success: true,
|
|
56
|
+
content: `Task ${taskId} has been stopped`,
|
|
57
|
+
shortResult: `Stopped ${taskId}`,
|
|
58
|
+
};
|
|
59
|
+
} else {
|
|
60
|
+
const task = backgroundTaskManager.getTask(taskId);
|
|
61
|
+
if (!task) {
|
|
62
|
+
return {
|
|
63
|
+
success: false,
|
|
64
|
+
content: "",
|
|
65
|
+
error: `Task with ID ${taskId} not found`,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
success: false,
|
|
70
|
+
content: "",
|
|
71
|
+
error: `Failed to stop task ${taskId} (status: ${task.status})`,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
formatCompactParams: (params: Record<string, unknown>) => {
|
|
76
|
+
return params.task_id as string;
|
|
77
|
+
},
|
|
78
|
+
};
|
package/src/tools/taskTool.ts
CHANGED
|
@@ -46,6 +46,11 @@ export function createTaskTool(subagentManager: SubagentManager): ToolPlugin {
|
|
|
46
46
|
type: "string",
|
|
47
47
|
description: `The type or name of subagent to use. Available options: ${availableSubagents.map((c) => c.name).join(", ") || "none"}`,
|
|
48
48
|
},
|
|
49
|
+
run_in_background: {
|
|
50
|
+
type: "boolean",
|
|
51
|
+
description:
|
|
52
|
+
"Set to true to run this command in the background. Use TaskOutput to read the output later.",
|
|
53
|
+
},
|
|
49
54
|
},
|
|
50
55
|
required: ["description", "prompt", "subagent_type"],
|
|
51
56
|
},
|
|
@@ -53,84 +58,141 @@ export function createTaskTool(subagentManager: SubagentManager): ToolPlugin {
|
|
|
53
58
|
};
|
|
54
59
|
},
|
|
55
60
|
|
|
61
|
+
prompt: () => `
|
|
62
|
+
- When doing file search, prefer to use the ${TASK_TOOL_NAME} tool in order to reduce context usage.
|
|
63
|
+
- You should proactively use the ${TASK_TOOL_NAME} tool with specialized agents when the task at hand matches the agent's description.
|
|
64
|
+
- VERY IMPORTANT: When exploring the codebase to gather context or to answer a question that is not a needle query for a specific file/class/function, it is CRITICAL that you use the ${TASK_TOOL_NAME} tool with subagent_type=Explore instead of running search commands directly.`,
|
|
65
|
+
|
|
56
66
|
execute: async (
|
|
57
67
|
args: Record<string, unknown>,
|
|
58
68
|
context: ToolContext,
|
|
59
69
|
): Promise<ToolResult> => {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
70
|
+
return new Promise((resolve) => {
|
|
71
|
+
(async () => {
|
|
72
|
+
// Input validation
|
|
73
|
+
const description = args.description as string;
|
|
74
|
+
const prompt = args.prompt as string;
|
|
75
|
+
const subagent_type = args.subagent_type as string;
|
|
76
|
+
const run_in_background = args.run_in_background as boolean;
|
|
77
|
+
|
|
78
|
+
if (!description || typeof description !== "string") {
|
|
79
|
+
return resolve({
|
|
80
|
+
success: false,
|
|
81
|
+
content: "",
|
|
82
|
+
error: "description parameter is required and must be a string",
|
|
83
|
+
shortResult: "Task delegation failed",
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (!prompt || typeof prompt !== "string") {
|
|
88
|
+
return resolve({
|
|
89
|
+
success: false,
|
|
90
|
+
content: "",
|
|
91
|
+
error: "prompt parameter is required and must be a string",
|
|
92
|
+
shortResult: "Task delegation failed",
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (!subagent_type || typeof subagent_type !== "string") {
|
|
97
|
+
return resolve({
|
|
98
|
+
success: false,
|
|
99
|
+
content: "",
|
|
100
|
+
error: "subagent_type parameter is required and must be a string",
|
|
101
|
+
shortResult: "Task delegation failed",
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
try {
|
|
106
|
+
// Subagent selection logic with explicit name matching only
|
|
107
|
+
const configuration =
|
|
108
|
+
await subagentManager.findSubagent(subagent_type);
|
|
109
|
+
|
|
110
|
+
if (!configuration) {
|
|
111
|
+
// Error handling for nonexistent subagents with available subagents listing
|
|
112
|
+
const allConfigs = subagentManager.getConfigurations();
|
|
113
|
+
const availableNames = allConfigs.map((c) => c.name).join(", ");
|
|
114
|
+
|
|
115
|
+
return resolve({
|
|
116
|
+
success: false,
|
|
117
|
+
content: "",
|
|
118
|
+
error: `No subagent found matching "${subagent_type}". Available subagents: ${availableNames || "none"}`,
|
|
119
|
+
shortResult: "Subagent not found",
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Create subagent instance and execute task
|
|
124
|
+
const instance = await subagentManager.createInstance(
|
|
125
|
+
configuration,
|
|
126
|
+
{
|
|
127
|
+
description,
|
|
128
|
+
prompt,
|
|
129
|
+
subagent_type,
|
|
130
|
+
},
|
|
131
|
+
run_in_background,
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
let isBackgrounded = false;
|
|
135
|
+
|
|
136
|
+
// Register for backgrounding if not already in background
|
|
137
|
+
if (!run_in_background && context.foregroundTaskManager) {
|
|
138
|
+
context.foregroundTaskManager.registerForegroundTask({
|
|
139
|
+
id: instance.subagentId,
|
|
140
|
+
backgroundHandler: async () => {
|
|
141
|
+
isBackgrounded = true;
|
|
142
|
+
const taskId = await subagentManager.backgroundInstance(
|
|
143
|
+
instance.subagentId,
|
|
144
|
+
);
|
|
145
|
+
// Resolve the tool execution early so the main agent can continue
|
|
146
|
+
resolve({
|
|
147
|
+
success: true,
|
|
148
|
+
content: `Task moved to background with ID: ${taskId}.`,
|
|
149
|
+
shortResult: "Task backgrounded",
|
|
150
|
+
isManuallyBackgrounded: true,
|
|
151
|
+
});
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
try {
|
|
157
|
+
const result = await subagentManager.executeTask(
|
|
158
|
+
instance,
|
|
159
|
+
prompt,
|
|
160
|
+
context.abortSignal,
|
|
161
|
+
run_in_background,
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
if (isBackgrounded) return;
|
|
165
|
+
|
|
166
|
+
if (run_in_background) {
|
|
167
|
+
return resolve({
|
|
168
|
+
success: true,
|
|
169
|
+
content: `Task started in background with ID: ${result}`,
|
|
170
|
+
shortResult: `Task started in background: ${result}`,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return resolve({
|
|
175
|
+
success: true,
|
|
176
|
+
content: result,
|
|
177
|
+
shortResult: `Task completed by ${configuration.name}`,
|
|
178
|
+
});
|
|
179
|
+
} finally {
|
|
180
|
+
if (!run_in_background && context.foregroundTaskManager) {
|
|
181
|
+
context.foregroundTaskManager.unregisterForegroundTask(
|
|
182
|
+
instance.subagentId,
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
} catch (error) {
|
|
187
|
+
return resolve({
|
|
188
|
+
success: false,
|
|
189
|
+
content: "",
|
|
190
|
+
error: `Task delegation failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
191
|
+
shortResult: "Delegation error",
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
})();
|
|
195
|
+
});
|
|
134
196
|
},
|
|
135
197
|
|
|
136
198
|
formatCompactParams: (params: Record<string, unknown>) => {
|
package/src/tools/types.ts
CHANGED
|
@@ -19,6 +19,10 @@ export interface ToolPlugin {
|
|
|
19
19
|
params: Record<string, unknown>,
|
|
20
20
|
context: ToolContext,
|
|
21
21
|
) => string;
|
|
22
|
+
/**
|
|
23
|
+
* Optional function to provide a prompt to be added to the system prompt
|
|
24
|
+
*/
|
|
25
|
+
prompt?: () => string;
|
|
22
26
|
}
|
|
23
27
|
|
|
24
28
|
export interface ToolResult {
|
|
@@ -34,11 +38,14 @@ export interface ToolResult {
|
|
|
34
38
|
data: string; // base64 encoded image data
|
|
35
39
|
mediaType?: string; // Image media type, such as "image/png"
|
|
36
40
|
}>;
|
|
41
|
+
// Whether the tool was manually backgrounded by the user (e.g. via Ctrl-B)
|
|
42
|
+
isManuallyBackgrounded?: boolean;
|
|
37
43
|
}
|
|
38
44
|
|
|
39
45
|
export interface ToolContext {
|
|
40
46
|
abortSignal?: AbortSignal;
|
|
41
47
|
backgroundBashManager?: import("../managers/backgroundBashManager.js").BackgroundBashManager;
|
|
48
|
+
backgroundTaskManager?: import("../managers/backgroundTaskManager.js").BackgroundTaskManager;
|
|
42
49
|
workdir: string;
|
|
43
50
|
/** Permission mode for this tool execution */
|
|
44
51
|
permissionMode?: PermissionMode;
|
|
@@ -54,4 +61,10 @@ export interface ToolContext {
|
|
|
54
61
|
reversionManager?: import("../managers/reversionManager.js").ReversionManager;
|
|
55
62
|
/** Current message ID for associating snapshots */
|
|
56
63
|
messageId?: string;
|
|
64
|
+
/** Foreground task manager for backgrounding tasks */
|
|
65
|
+
foregroundTaskManager?: import("../types/processes.js").IForegroundTaskManager;
|
|
66
|
+
/** Task manager instance for task management */
|
|
67
|
+
taskManager: import("../services/taskManager.js").TaskManager;
|
|
68
|
+
/** Current session ID */
|
|
69
|
+
sessionId?: string;
|
|
57
70
|
}
|
package/src/tools/writeTool.ts
CHANGED
|
@@ -13,8 +13,7 @@ export const writeTool: ToolPlugin = {
|
|
|
13
13
|
type: "function",
|
|
14
14
|
function: {
|
|
15
15
|
name: "Write",
|
|
16
|
-
description:
|
|
17
|
-
"Writes a file to the local filesystem.\n\nUsage:\n- This tool will overwrite the existing file if there is one at the provided path.\n- If this is an existing file, you MUST use the Read tool first to read the file's contents. This tool will fail if you did not read the file first.\n- ALWAYS prefer editing existing files in the codebase. NEVER write new files unless explicitly required.\n- NEVER proactively create documentation files (*.md) or README files. Only create documentation files if explicitly requested by the User.\n- Only use emojis if the user explicitly requests it. Avoid writing emojis to files unless asked.\n- IMPORTANT: Always provide file_path parameter before content parameter when calling this tool.",
|
|
16
|
+
description: "Writes a file to the local filesystem.",
|
|
18
17
|
parameters: {
|
|
19
18
|
type: "object",
|
|
20
19
|
properties: {
|
|
@@ -33,6 +32,14 @@ export const writeTool: ToolPlugin = {
|
|
|
33
32
|
},
|
|
34
33
|
},
|
|
35
34
|
},
|
|
35
|
+
prompt: () => `
|
|
36
|
+
Usage:
|
|
37
|
+
- This tool will overwrite the existing file if there is one at the provided path.
|
|
38
|
+
- If this is an existing file, you MUST use the Read tool first to read the file's contents. This tool will fail if you did not read the file first.
|
|
39
|
+
- ALWAYS prefer editing existing files in the codebase. NEVER write new files unless explicitly required.
|
|
40
|
+
- NEVER proactively create documentation files (*.md) or README files. Only create documentation files if explicitly requested by the User.
|
|
41
|
+
- Only use emojis if the user explicitly requests it. Avoid writing emojis to files unless asked.
|
|
42
|
+
- IMPORTANT: Always provide file_path parameter before content parameter when calling this tool.`,
|
|
36
43
|
execute: async (
|
|
37
44
|
args: Record<string, unknown>,
|
|
38
45
|
context: ToolContext,
|
package/src/types/index.ts
CHANGED
package/src/types/marketplace.ts
CHANGED
package/src/types/messaging.ts
CHANGED
|
@@ -26,7 +26,6 @@ export type MessageBlock =
|
|
|
26
26
|
| ImageBlock
|
|
27
27
|
| CommandOutputBlock
|
|
28
28
|
| CompressBlock
|
|
29
|
-
| MemoryBlock
|
|
30
29
|
| SubagentBlock
|
|
31
30
|
| ReasoningBlock
|
|
32
31
|
| FileHistoryBlock;
|
|
@@ -67,6 +66,7 @@ export interface ToolBlock {
|
|
|
67
66
|
error?: string | Error;
|
|
68
67
|
compactParams?: string; // Compact parameter display
|
|
69
68
|
parametersChunk?: string; // Incremental parameter updates for streaming
|
|
69
|
+
isManuallyBackgrounded?: boolean; // Whether the tool was manually backgrounded by the user
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
export interface ImageBlock {
|
|
@@ -88,14 +88,6 @@ export interface CompressBlock {
|
|
|
88
88
|
sessionId: string;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
export interface MemoryBlock {
|
|
92
|
-
type: "memory";
|
|
93
|
-
content: string;
|
|
94
|
-
isSuccess: boolean;
|
|
95
|
-
memoryType?: "project" | "user"; // Memory type
|
|
96
|
-
storagePath?: string; // Storage path text
|
|
97
|
-
}
|
|
98
|
-
|
|
99
91
|
export interface SubagentBlock {
|
|
100
92
|
type: "subagent";
|
|
101
93
|
subagentId: string;
|
|
@@ -103,6 +95,7 @@ export interface SubagentBlock {
|
|
|
103
95
|
status: "active" | "completed" | "error" | "aborted";
|
|
104
96
|
sessionId: string;
|
|
105
97
|
configuration: SubagentConfiguration;
|
|
98
|
+
runInBackground?: boolean;
|
|
106
99
|
}
|
|
107
100
|
|
|
108
101
|
export interface ReasoningBlock {
|
package/src/types/processes.ts
CHANGED
|
@@ -5,14 +5,49 @@
|
|
|
5
5
|
|
|
6
6
|
import type { ChildProcess } from "child_process";
|
|
7
7
|
|
|
8
|
-
export
|
|
8
|
+
export type BackgroundTaskStatus =
|
|
9
|
+
| "running"
|
|
10
|
+
| "completed"
|
|
11
|
+
| "failed"
|
|
12
|
+
| "killed";
|
|
13
|
+
export type BackgroundTaskType = "shell" | "subagent";
|
|
14
|
+
|
|
15
|
+
export interface BackgroundTaskBase {
|
|
9
16
|
id: string;
|
|
10
|
-
|
|
11
|
-
|
|
17
|
+
type: BackgroundTaskType;
|
|
18
|
+
status: BackgroundTaskStatus;
|
|
12
19
|
startTime: number;
|
|
13
|
-
|
|
20
|
+
endTime?: number;
|
|
21
|
+
command?: string; // for shell
|
|
22
|
+
description?: string; // for subagent
|
|
14
23
|
stdout: string;
|
|
15
24
|
stderr: string;
|
|
16
25
|
exitCode?: number;
|
|
17
26
|
runtime?: number;
|
|
27
|
+
/**
|
|
28
|
+
* Optional callback to be executed when the task is stopped.
|
|
29
|
+
* This allows tasks to define their own cleanup/abortion logic.
|
|
30
|
+
*/
|
|
31
|
+
onStop?: () => void | Promise<void>;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface BackgroundShell extends BackgroundTaskBase {
|
|
35
|
+
type: "shell";
|
|
36
|
+
process: ChildProcess;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface BackgroundSubagent extends BackgroundTaskBase {
|
|
40
|
+
type: "subagent";
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export type BackgroundTask = BackgroundShell | BackgroundSubagent;
|
|
44
|
+
|
|
45
|
+
export interface ForegroundTask {
|
|
46
|
+
id: string;
|
|
47
|
+
backgroundHandler: () => Promise<void>;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface IForegroundTaskManager {
|
|
51
|
+
registerForegroundTask(task: ForegroundTask): void;
|
|
52
|
+
unregisterForegroundTask(id: string): void;
|
|
18
53
|
}
|