wave-agent-sdk 0.5.0 → 0.6.2
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 +14 -11
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +64 -151
- package/dist/constants/subagents.d.ts +5 -0
- package/dist/constants/subagents.d.ts.map +1 -0
- package/dist/constants/subagents.js +4 -0
- package/dist/constants/tools.d.ts +4 -1
- package/dist/constants/tools.d.ts.map +1 -1
- package/dist/constants/tools.js +4 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/managers/aiManager.d.ts +2 -5
- package/dist/managers/aiManager.d.ts.map +1 -1
- package/dist/managers/aiManager.js +43 -48
- package/dist/managers/backgroundTaskManager.d.ts.map +1 -1
- package/dist/managers/backgroundTaskManager.js +63 -53
- package/dist/managers/foregroundTaskManager.d.ts.map +1 -1
- package/dist/managers/foregroundTaskManager.js +3 -2
- package/dist/managers/mcpManager.d.ts.map +1 -1
- package/dist/managers/messageManager.d.ts +13 -27
- package/dist/managers/messageManager.d.ts.map +1 -1
- package/dist/managers/messageManager.js +94 -89
- package/dist/managers/permissionManager.d.ts.map +1 -1
- package/dist/managers/permissionManager.js +25 -15
- 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/reversionManager.d.ts.map +1 -1
- package/dist/managers/reversionManager.js +23 -2
- package/dist/managers/slashCommandManager.d.ts +3 -0
- package/dist/managers/slashCommandManager.d.ts.map +1 -1
- package/dist/managers/slashCommandManager.js +8 -3
- package/dist/managers/subagentManager.d.ts +8 -14
- package/dist/managers/subagentManager.d.ts.map +1 -1
- package/dist/managers/subagentManager.js +46 -112
- package/dist/managers/toolManager.d.ts +11 -0
- package/dist/managers/toolManager.d.ts.map +1 -1
- package/dist/managers/toolManager.js +20 -2
- package/dist/{constants/prompts.d.ts → prompts/index.d.ts} +17 -15
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +309 -0
- 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 +0 -59
- 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 +25 -0
- package/dist/services/taskManager.d.ts.map +1 -0
- package/dist/services/taskManager.js +164 -0
- package/dist/tools/askUserQuestion.d.ts.map +1 -1
- package/dist/tools/askUserQuestion.js +39 -25
- package/dist/tools/bashTool.d.ts.map +1 -1
- package/dist/tools/bashTool.js +13 -11
- package/dist/tools/editTool.d.ts.map +1 -1
- package/dist/tools/editTool.js +2 -1
- package/dist/tools/exitPlanMode.d.ts.map +1 -1
- package/dist/tools/exitPlanMode.js +26 -2
- 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/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 +461 -0
- package/dist/tools/taskOutputTool.d.ts.map +1 -1
- package/dist/tools/taskOutputTool.js +32 -8
- package/dist/tools/taskStopTool.d.ts.map +1 -1
- package/dist/tools/taskStopTool.js +7 -1
- package/dist/tools/taskTool.d.ts.map +1 -1
- package/dist/tools/taskTool.js +37 -2
- package/dist/tools/types.d.ts +11 -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/messaging.d.ts +2 -18
- package/dist/types/messaging.d.ts.map +1 -1
- package/dist/types/processes.d.ts +16 -6
- 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 +59 -44
- 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.map +1 -1
- package/dist/utils/editUtils.js +2 -2
- package/dist/utils/gitUtils.d.ts +7 -0
- package/dist/utils/gitUtils.d.ts.map +1 -0
- package/dist/utils/gitUtils.js +24 -0
- package/dist/utils/messageOperations.d.ts +3 -58
- package/dist/utils/messageOperations.d.ts.map +1 -1
- package/dist/utils/messageOperations.js +4 -146
- 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 +1 -1
- package/src/agent.ts +86 -183
- package/src/constants/subagents.ts +4 -0
- package/src/constants/tools.ts +4 -1
- package/src/index.ts +1 -0
- package/src/managers/aiManager.ts +63 -70
- package/src/managers/backgroundTaskManager.ts +58 -54
- package/src/managers/foregroundTaskManager.ts +3 -2
- package/src/managers/mcpManager.ts +6 -3
- package/src/managers/messageManager.ts +126 -142
- package/src/managers/permissionManager.ts +32 -21
- package/src/managers/planManager.ts +2 -2
- package/src/managers/reversionManager.ts +26 -2
- package/src/managers/slashCommandManager.ts +12 -3
- package/src/managers/subagentManager.ts +60 -144
- package/src/managers/toolManager.ts +32 -2
- package/src/prompts/index.ts +366 -0
- package/src/services/aiService.ts +3 -145
- package/src/services/memory.ts +0 -72
- package/src/services/session.ts +73 -0
- package/src/services/taskManager.ts +195 -0
- package/src/tools/askUserQuestion.ts +51 -29
- package/src/tools/bashTool.ts +15 -17
- package/src/tools/editTool.ts +3 -1
- package/src/tools/exitPlanMode.ts +27 -3
- package/src/tools/globTool.ts +10 -2
- package/src/tools/grepTool.ts +17 -6
- package/src/tools/lsTool.ts +3 -1
- package/src/tools/readTool.ts +17 -1
- package/src/tools/taskManagementTools.ts +516 -0
- package/src/tools/taskOutputTool.ts +34 -12
- package/src/tools/taskStopTool.ts +7 -1
- package/src/tools/taskTool.ts +45 -1
- package/src/tools/types.ts +12 -0
- package/src/tools/writeTool.ts +9 -2
- package/src/types/index.ts +1 -0
- package/src/types/messaging.ts +1 -21
- package/src/types/processes.ts +18 -7
- package/src/types/tasks.ts +13 -0
- package/src/types/tools.ts +4 -1
- package/src/utils/builtinSubagents.ts +81 -45
- 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 +2 -6
- package/src/utils/gitUtils.ts +24 -0
- package/src/utils/messageOperations.ts +6 -229
- package/src/utils/nameGenerator.ts +20 -3
- package/dist/constants/prompts.d.ts.map +0 -1
- package/dist/constants/prompts.js +0 -118
- 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/constants/prompts.ts +0 -155
- package/src/tools/todoWriteTool.ts +0 -257
|
@@ -10,38 +10,47 @@ export const taskOutputTool: ToolPlugin = {
|
|
|
10
10
|
type: "function",
|
|
11
11
|
function: {
|
|
12
12
|
name: TASK_OUTPUT_TOOL_NAME,
|
|
13
|
-
description:
|
|
14
|
-
"Retrieves output from a running or completed background task",
|
|
13
|
+
description: "Retrieves output from a running or completed task",
|
|
15
14
|
parameters: {
|
|
16
15
|
type: "object",
|
|
17
16
|
properties: {
|
|
18
17
|
task_id: {
|
|
19
18
|
type: "string",
|
|
20
|
-
description:
|
|
21
|
-
"The ID of the background task to retrieve output from",
|
|
22
|
-
},
|
|
23
|
-
filter: {
|
|
24
|
-
type: "string",
|
|
25
|
-
description:
|
|
26
|
-
"Optional regular expression to filter the output lines.",
|
|
19
|
+
description: "The task ID to get output from",
|
|
27
20
|
},
|
|
28
21
|
block: {
|
|
29
22
|
type: "boolean",
|
|
30
|
-
|
|
31
|
-
|
|
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
32
|
},
|
|
33
33
|
},
|
|
34
34
|
required: ["task_id"],
|
|
35
35
|
},
|
|
36
36
|
},
|
|
37
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`,
|
|
38
46
|
execute: async (
|
|
39
47
|
args: Record<string, unknown>,
|
|
40
48
|
context: ToolContext,
|
|
41
49
|
): Promise<ToolResult> => {
|
|
42
50
|
const taskId = args.task_id as string;
|
|
43
51
|
const filter = args.filter as string | undefined;
|
|
44
|
-
const block = args.block as boolean | undefined;
|
|
52
|
+
const block = (args.block as boolean | undefined) ?? true;
|
|
53
|
+
const timeout = (args.timeout as number | undefined) ?? 30000;
|
|
45
54
|
|
|
46
55
|
if (!taskId || typeof taskId !== "string") {
|
|
47
56
|
return {
|
|
@@ -91,6 +100,7 @@ export const taskOutputTool: ToolPlugin = {
|
|
|
91
100
|
return new Promise((resolve) => {
|
|
92
101
|
let timeoutHandle: NodeJS.Timeout | null = null;
|
|
93
102
|
let isAborted = false;
|
|
103
|
+
const startTime = Date.now();
|
|
94
104
|
|
|
95
105
|
const cleanup = () => {
|
|
96
106
|
if (timeoutHandle) {
|
|
@@ -122,6 +132,18 @@ export const taskOutputTool: ToolPlugin = {
|
|
|
122
132
|
const check = () => {
|
|
123
133
|
if (isAborted) return;
|
|
124
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
|
+
|
|
125
147
|
const task = backgroundTaskManager.getTask(taskId);
|
|
126
148
|
if (!task) {
|
|
127
149
|
if (context.abortSignal) {
|
|
@@ -7,7 +7,7 @@ export const taskStopTool: ToolPlugin = {
|
|
|
7
7
|
type: "function",
|
|
8
8
|
function: {
|
|
9
9
|
name: TASK_STOP_TOOL_NAME,
|
|
10
|
-
description: "
|
|
10
|
+
description: "Stop a running background task by ID",
|
|
11
11
|
parameters: {
|
|
12
12
|
type: "object",
|
|
13
13
|
properties: {
|
|
@@ -20,6 +20,12 @@ export const taskStopTool: ToolPlugin = {
|
|
|
20
20
|
},
|
|
21
21
|
},
|
|
22
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
|
+
`,
|
|
23
29
|
execute: async (
|
|
24
30
|
args: Record<string, unknown>,
|
|
25
31
|
context: ToolContext,
|
package/src/tools/taskTool.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ToolPlugin, ToolResult, ToolContext } from "./types.js";
|
|
2
2
|
import type { SubagentManager } from "../managers/subagentManager.js";
|
|
3
|
+
import { EXPLORE_SUBAGENT_TYPE } from "../constants/subagents.js";
|
|
3
4
|
import { TASK_TOOL_NAME } from "../constants/tools.js";
|
|
4
5
|
|
|
5
6
|
/**
|
|
@@ -58,6 +59,11 @@ export function createTaskTool(subagentManager: SubagentManager): ToolPlugin {
|
|
|
58
59
|
};
|
|
59
60
|
},
|
|
60
61
|
|
|
62
|
+
prompt: () => `
|
|
63
|
+
- When doing file search, prefer to use the ${TASK_TOOL_NAME} tool in order to reduce context usage.
|
|
64
|
+
- You should proactively use the ${TASK_TOOL_NAME} tool with specialized agents when the task at hand matches the agent's description.
|
|
65
|
+
- 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_SUBAGENT_TYPE} instead of running search commands directly.`,
|
|
66
|
+
|
|
61
67
|
execute: async (
|
|
62
68
|
args: Record<string, unknown>,
|
|
63
69
|
context: ToolContext,
|
|
@@ -115,6 +121,36 @@ export function createTaskTool(subagentManager: SubagentManager): ToolPlugin {
|
|
|
115
121
|
});
|
|
116
122
|
}
|
|
117
123
|
|
|
124
|
+
// Set up callback to update shortResult with tool names, tool count and tokens
|
|
125
|
+
const updateShortResult = () => {
|
|
126
|
+
const messages = instance.messageManager.getMessages();
|
|
127
|
+
const tokens = instance.messageManager.getlatestTotalTokens();
|
|
128
|
+
const lastTools = instance.lastTools;
|
|
129
|
+
|
|
130
|
+
// Count tool blocks in messages
|
|
131
|
+
let toolCount = 0;
|
|
132
|
+
messages.forEach((msg) => {
|
|
133
|
+
msg.blocks.forEach((block) => {
|
|
134
|
+
if (block.type === "tool") {
|
|
135
|
+
toolCount++;
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
let shortResult = "";
|
|
141
|
+
if (lastTools.length > 0) {
|
|
142
|
+
shortResult += `${lastTools.join(", ")} `;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
shortResult += `(${toolCount} tools`;
|
|
146
|
+
if (tokens > 0) {
|
|
147
|
+
shortResult += ` | ${tokens.toLocaleString()} tokens`;
|
|
148
|
+
}
|
|
149
|
+
shortResult += ")";
|
|
150
|
+
|
|
151
|
+
context.onShortResultUpdate?.(shortResult);
|
|
152
|
+
};
|
|
153
|
+
|
|
118
154
|
// Create subagent instance and execute task
|
|
119
155
|
const instance = await subagentManager.createInstance(
|
|
120
156
|
configuration,
|
|
@@ -124,8 +160,12 @@ export function createTaskTool(subagentManager: SubagentManager): ToolPlugin {
|
|
|
124
160
|
subagent_type,
|
|
125
161
|
},
|
|
126
162
|
run_in_background,
|
|
163
|
+
updateShortResult,
|
|
127
164
|
);
|
|
128
165
|
|
|
166
|
+
// Initial update
|
|
167
|
+
updateShortResult();
|
|
168
|
+
|
|
129
169
|
let isBackgrounded = false;
|
|
130
170
|
|
|
131
171
|
// Register for backgrounding if not already in background
|
|
@@ -140,8 +180,9 @@ export function createTaskTool(subagentManager: SubagentManager): ToolPlugin {
|
|
|
140
180
|
// Resolve the tool execution early so the main agent can continue
|
|
141
181
|
resolve({
|
|
142
182
|
success: true,
|
|
143
|
-
content: `Task moved to background with ID: ${taskId}
|
|
183
|
+
content: `Task moved to background with ID: ${taskId}.`,
|
|
144
184
|
shortResult: "Task backgrounded",
|
|
185
|
+
isManuallyBackgrounded: true,
|
|
145
186
|
});
|
|
146
187
|
},
|
|
147
188
|
});
|
|
@@ -165,6 +206,9 @@ export function createTaskTool(subagentManager: SubagentManager): ToolPlugin {
|
|
|
165
206
|
});
|
|
166
207
|
}
|
|
167
208
|
|
|
209
|
+
// Cleanup subagent instance after task completion
|
|
210
|
+
subagentManager.cleanupInstance(instance.subagentId);
|
|
211
|
+
|
|
168
212
|
return resolve({
|
|
169
213
|
success: true,
|
|
170
214
|
content: result,
|
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,6 +38,8 @@ 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 {
|
|
@@ -57,4 +63,10 @@ export interface ToolContext {
|
|
|
57
63
|
messageId?: string;
|
|
58
64
|
/** Foreground task manager for backgrounding tasks */
|
|
59
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;
|
|
70
|
+
/** Callback to update the short result of the current tool block */
|
|
71
|
+
onShortResultUpdate?: (shortResult: string) => void;
|
|
60
72
|
}
|
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/messaging.ts
CHANGED
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import type { Usage } from "./core.js";
|
|
7
|
-
import type { SubagentConfiguration } from "../utils/subagentParser.js";
|
|
8
7
|
|
|
9
8
|
export enum MessageSource {
|
|
10
9
|
USER = "user",
|
|
@@ -26,8 +25,6 @@ export type MessageBlock =
|
|
|
26
25
|
| ImageBlock
|
|
27
26
|
| CommandOutputBlock
|
|
28
27
|
| CompressBlock
|
|
29
|
-
| MemoryBlock
|
|
30
|
-
| SubagentBlock
|
|
31
28
|
| ReasoningBlock
|
|
32
29
|
| FileHistoryBlock;
|
|
33
30
|
|
|
@@ -67,6 +64,7 @@ export interface ToolBlock {
|
|
|
67
64
|
error?: string | Error;
|
|
68
65
|
compactParams?: string; // Compact parameter display
|
|
69
66
|
parametersChunk?: string; // Incremental parameter updates for streaming
|
|
67
|
+
isManuallyBackgrounded?: boolean; // Whether the tool was manually backgrounded by the user
|
|
70
68
|
}
|
|
71
69
|
|
|
72
70
|
export interface ImageBlock {
|
|
@@ -88,24 +86,6 @@ export interface CompressBlock {
|
|
|
88
86
|
sessionId: string;
|
|
89
87
|
}
|
|
90
88
|
|
|
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
|
-
export interface SubagentBlock {
|
|
100
|
-
type: "subagent";
|
|
101
|
-
subagentId: string;
|
|
102
|
-
subagentName: string;
|
|
103
|
-
status: "active" | "completed" | "error" | "aborted";
|
|
104
|
-
sessionId: string;
|
|
105
|
-
configuration: SubagentConfiguration;
|
|
106
|
-
runInBackground?: boolean;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
89
|
export interface ReasoningBlock {
|
|
110
90
|
type: "reasoning";
|
|
111
91
|
content: string;
|
package/src/types/processes.ts
CHANGED
|
@@ -12,7 +12,7 @@ export type BackgroundTaskStatus =
|
|
|
12
12
|
| "killed";
|
|
13
13
|
export type BackgroundTaskType = "shell" | "subagent";
|
|
14
14
|
|
|
15
|
-
export interface
|
|
15
|
+
export interface BackgroundTaskBase {
|
|
16
16
|
id: string;
|
|
17
17
|
type: BackgroundTaskType;
|
|
18
18
|
status: BackgroundTaskStatus;
|
|
@@ -24,13 +24,29 @@ export interface BackgroundTask {
|
|
|
24
24
|
stderr: string;
|
|
25
25
|
exitCode?: number;
|
|
26
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
|
+
* Optional subagent ID associated with this task.
|
|
34
|
+
* Used for cleanup when the task is stopped.
|
|
35
|
+
*/
|
|
36
|
+
subagentId?: string;
|
|
27
37
|
}
|
|
28
38
|
|
|
29
|
-
export interface BackgroundShell extends
|
|
39
|
+
export interface BackgroundShell extends BackgroundTaskBase {
|
|
30
40
|
type: "shell";
|
|
31
41
|
process: ChildProcess;
|
|
32
42
|
}
|
|
33
43
|
|
|
44
|
+
export interface BackgroundSubagent extends BackgroundTaskBase {
|
|
45
|
+
type: "subagent";
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export type BackgroundTask = BackgroundShell | BackgroundSubagent;
|
|
49
|
+
|
|
34
50
|
export interface ForegroundTask {
|
|
35
51
|
id: string;
|
|
36
52
|
backgroundHandler: () => Promise<void>;
|
|
@@ -40,8 +56,3 @@ export interface IForegroundTaskManager {
|
|
|
40
56
|
registerForegroundTask(task: ForegroundTask): void;
|
|
41
57
|
unregisterForegroundTask(id: string): void;
|
|
42
58
|
}
|
|
43
|
-
|
|
44
|
-
export interface IForegroundTaskManager {
|
|
45
|
-
registerForegroundTask(task: ForegroundTask): void;
|
|
46
|
-
unregisterForegroundTask(id: string): void;
|
|
47
|
-
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type TaskStatus = "pending" | "in_progress" | "completed" | "deleted";
|
|
2
|
+
|
|
3
|
+
export interface Task {
|
|
4
|
+
id: string;
|
|
5
|
+
subject: string;
|
|
6
|
+
description: string;
|
|
7
|
+
status: TaskStatus;
|
|
8
|
+
activeForm?: string;
|
|
9
|
+
owner?: string;
|
|
10
|
+
blocks: string[];
|
|
11
|
+
blockedBy: string[];
|
|
12
|
+
metadata: Record<string, unknown>;
|
|
13
|
+
}
|
package/src/types/tools.ts
CHANGED
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
export interface AskUserQuestionOption {
|
|
9
9
|
label: string;
|
|
10
10
|
description?: string;
|
|
11
|
-
isRecommended?: boolean;
|
|
12
11
|
}
|
|
13
12
|
|
|
14
13
|
export interface AskUserQuestion {
|
|
@@ -20,6 +19,10 @@ export interface AskUserQuestion {
|
|
|
20
19
|
|
|
21
20
|
export interface AskUserQuestionInput {
|
|
22
21
|
questions: AskUserQuestion[];
|
|
22
|
+
answers?: Record<string, string>;
|
|
23
|
+
metadata?: {
|
|
24
|
+
source?: string;
|
|
25
|
+
};
|
|
23
26
|
}
|
|
24
27
|
|
|
25
28
|
/**
|
|
@@ -1,4 +1,23 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
BASH_SUBAGENT_TYPE,
|
|
3
|
+
EXPLORE_SUBAGENT_TYPE,
|
|
4
|
+
PLAN_SUBAGENT_TYPE,
|
|
5
|
+
GENERAL_PURPOSE_SUBAGENT_TYPE,
|
|
6
|
+
} from "../constants/subagents.js";
|
|
7
|
+
import {
|
|
8
|
+
BASH_SUBAGENT_SYSTEM_PROMPT,
|
|
9
|
+
GENERAL_PURPOSE_SYSTEM_PROMPT,
|
|
10
|
+
PLAN_SUBAGENT_SYSTEM_PROMPT,
|
|
11
|
+
EXPLORE_SUBAGENT_SYSTEM_PROMPT,
|
|
12
|
+
} from "../prompts/index.js";
|
|
13
|
+
import {
|
|
14
|
+
BASH_TOOL_NAME,
|
|
15
|
+
GLOB_TOOL_NAME,
|
|
16
|
+
GREP_TOOL_NAME,
|
|
17
|
+
READ_TOOL_NAME,
|
|
18
|
+
LS_TOOL_NAME,
|
|
19
|
+
LSP_TOOL_NAME,
|
|
20
|
+
} from "../constants/tools.js";
|
|
2
21
|
import type { SubagentConfiguration } from "./subagentParser.js";
|
|
3
22
|
|
|
4
23
|
/**
|
|
@@ -7,23 +26,43 @@ import type { SubagentConfiguration } from "./subagentParser.js";
|
|
|
7
26
|
*/
|
|
8
27
|
export function getBuiltinSubagents(): SubagentConfiguration[] {
|
|
9
28
|
return [
|
|
29
|
+
createBashSubagent(),
|
|
10
30
|
createExploreSubagent(),
|
|
11
31
|
createGeneralPurposeSubagent(),
|
|
32
|
+
createPlanSubagent(),
|
|
12
33
|
// Add more built-in subagents here as needed
|
|
13
34
|
];
|
|
14
35
|
}
|
|
15
36
|
|
|
37
|
+
/**
|
|
38
|
+
* Create the Bash built-in subagent configuration
|
|
39
|
+
* Specialized for executing bash commands and git operations
|
|
40
|
+
*/
|
|
41
|
+
function createBashSubagent(): SubagentConfiguration {
|
|
42
|
+
return {
|
|
43
|
+
name: BASH_SUBAGENT_TYPE,
|
|
44
|
+
description:
|
|
45
|
+
"Command execution specialist for running bash commands. Use this for git operations, command execution, and other terminal tasks.",
|
|
46
|
+
systemPrompt: BASH_SUBAGENT_SYSTEM_PROMPT,
|
|
47
|
+
tools: [BASH_TOOL_NAME],
|
|
48
|
+
model: "inherit",
|
|
49
|
+
filePath: `<builtin:${BASH_SUBAGENT_TYPE}>`,
|
|
50
|
+
scope: "builtin",
|
|
51
|
+
priority: 3,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
16
55
|
/**
|
|
17
56
|
* Create the General-Purpose built-in subagent configuration
|
|
18
57
|
* Specialized for multi-step research and implementation tasks
|
|
19
58
|
*/
|
|
20
59
|
function createGeneralPurposeSubagent(): SubagentConfiguration {
|
|
21
60
|
return {
|
|
22
|
-
name:
|
|
61
|
+
name: GENERAL_PURPOSE_SUBAGENT_TYPE,
|
|
23
62
|
description:
|
|
24
63
|
"General-purpose agent for researching complex questions, searching for code, and executing multi-step tasks. When you are searching for a keyword or file and are not confident that you will find the right match in the first few tries use this agent to perform the search for you.",
|
|
25
64
|
systemPrompt: GENERAL_PURPOSE_SYSTEM_PROMPT,
|
|
26
|
-
filePath:
|
|
65
|
+
filePath: `<builtin:${GENERAL_PURPOSE_SUBAGENT_TYPE}>`,
|
|
27
66
|
scope: "builtin",
|
|
28
67
|
priority: 3,
|
|
29
68
|
};
|
|
@@ -34,55 +73,52 @@ function createGeneralPurposeSubagent(): SubagentConfiguration {
|
|
|
34
73
|
* Specialized for codebase exploration and file search tasks
|
|
35
74
|
*/
|
|
36
75
|
function createExploreSubagent(): SubagentConfiguration {
|
|
37
|
-
const systemPrompt = `You are a file search specialist. You excel at thoroughly navigating and exploring codebases.
|
|
38
|
-
|
|
39
|
-
=== CRITICAL: READ-ONLY MODE - NO FILE MODIFICATIONS ===
|
|
40
|
-
This is a READ-ONLY exploration task. You are STRICTLY PROHIBITED from:
|
|
41
|
-
- Creating new files (no Write, touch, or file creation of any kind)
|
|
42
|
-
- Modifying existing files (no Edit operations)
|
|
43
|
-
- Deleting files (no rm or deletion)
|
|
44
|
-
- Moving or copying files (no mv or cp)
|
|
45
|
-
- Creating temporary files anywhere, including /tmp
|
|
46
|
-
- Using redirect operators (>, >>, |) or heredocs to write to files
|
|
47
|
-
- Running ANY commands that change system state
|
|
48
|
-
|
|
49
|
-
Your role is EXCLUSIVELY to search and analyze existing code. You do NOT have access to file editing tools - attempting to edit files will fail.
|
|
50
|
-
|
|
51
|
-
Your strengths:
|
|
52
|
-
- Rapidly finding files using glob patterns
|
|
53
|
-
- Searching code and text with powerful regex patterns
|
|
54
|
-
- Reading and analyzing file contents
|
|
55
|
-
- Using Language Server Protocol (LSP) for deep code intelligence (definitions, references, etc.)
|
|
56
|
-
|
|
57
|
-
Guidelines:
|
|
58
|
-
- Use Glob for broad file pattern matching
|
|
59
|
-
- Use Grep for searching file contents with regex
|
|
60
|
-
- Use Read when you know the specific file path you need to read
|
|
61
|
-
- Use LSP for code intelligence features like finding definitions, references, implementations, and symbols. This is especially useful for understanding complex code relationships.
|
|
62
|
-
- Use Bash ONLY for read-only operations (ls, git status, git log, git diff, find, cat, head, tail)
|
|
63
|
-
- NEVER use Bash for: mkdir, touch, rm, cp, mv, git add, git commit, npm install, pip install, or any file creation/modification
|
|
64
|
-
- Adapt your search approach based on the thoroughness level specified by the caller
|
|
65
|
-
- Return file paths as absolute paths in your final response
|
|
66
|
-
- For clear communication, avoid using emojis
|
|
67
|
-
- Communicate your final report directly as a regular message - do NOT attempt to create files
|
|
68
|
-
|
|
69
|
-
NOTE: You are meant to be a fast agent that returns output as quickly as possible. In order to achieve this you must:
|
|
70
|
-
- Make efficient use of the tools that you have at your disposal: be smart about how you search for files and implementations
|
|
71
|
-
- Wherever possible you should try to spawn multiple parallel tool calls for grepping and reading files
|
|
72
|
-
|
|
73
|
-
Complete the user's search request efficiently and report your findings clearly.`;
|
|
74
|
-
|
|
75
76
|
// Define allowed tools for read-only operations
|
|
76
|
-
const allowedTools = [
|
|
77
|
+
const allowedTools = [
|
|
78
|
+
GLOB_TOOL_NAME,
|
|
79
|
+
GREP_TOOL_NAME,
|
|
80
|
+
READ_TOOL_NAME,
|
|
81
|
+
BASH_TOOL_NAME,
|
|
82
|
+
LS_TOOL_NAME,
|
|
83
|
+
LSP_TOOL_NAME,
|
|
84
|
+
];
|
|
77
85
|
|
|
78
86
|
return {
|
|
79
|
-
name:
|
|
87
|
+
name: EXPLORE_SUBAGENT_TYPE,
|
|
80
88
|
description:
|
|
81
89
|
'Fast agent specialized for exploring codebases. Use this when you need to quickly find files by patterns (eg. "src/components/**/*.tsx"), search code for keywords (eg. "API endpoints"), or answer questions about the codebase (eg. "how do API endpoints work?"). When calling this agent, specify the desired thoroughness level: "quick" for basic searches, "medium" for moderate exploration, or "very thorough" for comprehensive analysis across multiple locations and naming conventions.',
|
|
82
|
-
systemPrompt,
|
|
90
|
+
systemPrompt: EXPLORE_SUBAGENT_SYSTEM_PROMPT,
|
|
83
91
|
tools: allowedTools,
|
|
84
92
|
model: "fastModel", // Special value that will use parent's fastModel
|
|
85
|
-
filePath:
|
|
93
|
+
filePath: `<builtin:${EXPLORE_SUBAGENT_TYPE}>`,
|
|
94
|
+
scope: "builtin",
|
|
95
|
+
priority: 3, // Lowest priority - can be overridden by user configs
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Create the Plan built-in subagent configuration
|
|
101
|
+
* Specialized for designing implementation plans and exploring codebases in read-only mode
|
|
102
|
+
*/
|
|
103
|
+
function createPlanSubagent(): SubagentConfiguration {
|
|
104
|
+
// Define allowed tools for read-only operations
|
|
105
|
+
const allowedTools = [
|
|
106
|
+
GLOB_TOOL_NAME,
|
|
107
|
+
GREP_TOOL_NAME,
|
|
108
|
+
READ_TOOL_NAME,
|
|
109
|
+
BASH_TOOL_NAME,
|
|
110
|
+
LS_TOOL_NAME,
|
|
111
|
+
LSP_TOOL_NAME,
|
|
112
|
+
];
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
name: PLAN_SUBAGENT_TYPE,
|
|
116
|
+
description:
|
|
117
|
+
"Software architect agent for designing implementation plans. Use this when you need to plan the implementation strategy for a task. Returns step-by-step plans, identifies critical files, and considers architectural trade-offs.",
|
|
118
|
+
systemPrompt: PLAN_SUBAGENT_SYSTEM_PROMPT,
|
|
119
|
+
tools: allowedTools,
|
|
120
|
+
model: "inherit", // Uses parent agent's model
|
|
121
|
+
filePath: `<builtin:${PLAN_SUBAGENT_TYPE}>`,
|
|
86
122
|
scope: "builtin",
|
|
87
123
|
priority: 3, // Lowest priority - can be overridden by user configs
|
|
88
124
|
};
|
|
@@ -316,14 +316,8 @@ export function transformMessagesForClaudeCache(
|
|
|
316
316
|
// Find the latest interval message index (20th, 40th, 60th, etc.)
|
|
317
317
|
const intervalMessageIndex = findIntervalMessageIndex(messages);
|
|
318
318
|
|
|
319
|
-
// Find
|
|
320
|
-
|
|
321
|
-
for (let i = messages.length - 1; i >= 0; i--) {
|
|
322
|
-
if (messages[i].role === "system") {
|
|
323
|
-
lastSystemIndex = i;
|
|
324
|
-
break;
|
|
325
|
-
}
|
|
326
|
-
}
|
|
319
|
+
// Find first system message index
|
|
320
|
+
const firstSystemIndex = messages.findIndex((m) => m.role === "system");
|
|
327
321
|
|
|
328
322
|
const result = messages.map((message, index) => {
|
|
329
323
|
// Validate message structure
|
|
@@ -332,14 +326,27 @@ export function transformMessagesForClaudeCache(
|
|
|
332
326
|
return message; // Return as-is to avoid breaking the flow
|
|
333
327
|
}
|
|
334
328
|
|
|
335
|
-
//
|
|
336
|
-
if (message.role === "system" && index ===
|
|
329
|
+
// First system message: always cached (hardcoded)
|
|
330
|
+
if (message.role === "system" && index === firstSystemIndex) {
|
|
331
|
+
const content =
|
|
332
|
+
(message.content as string | ChatCompletionContentPart[]) || "";
|
|
333
|
+
// If content is already an array, check if it already has cache control
|
|
334
|
+
if (Array.isArray(content)) {
|
|
335
|
+
const hasCacheControl = content.some(
|
|
336
|
+
(part) =>
|
|
337
|
+
part.type === "text" &&
|
|
338
|
+
(part as ClaudeChatCompletionContentPartText).cache_control,
|
|
339
|
+
);
|
|
340
|
+
if (hasCacheControl) {
|
|
341
|
+
return message;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
const transformedContent = addCacheControlToContent(content, true);
|
|
346
|
+
|
|
337
347
|
return {
|
|
338
348
|
...message,
|
|
339
|
-
content:
|
|
340
|
-
(message.content as string | ChatCompletionContentPart[]) || "",
|
|
341
|
-
true,
|
|
342
|
-
),
|
|
349
|
+
content: transformedContent,
|
|
343
350
|
} as ChatCompletionMessageParam;
|
|
344
351
|
}
|
|
345
352
|
|
|
@@ -364,12 +371,13 @@ export function transformMessagesForClaudeCache(
|
|
|
364
371
|
} as ChatCompletionMessageParam;
|
|
365
372
|
} else {
|
|
366
373
|
// For other message types without tool calls, cache the content
|
|
374
|
+
const content =
|
|
375
|
+
(message.content as string | ChatCompletionContentPart[]) || "";
|
|
376
|
+
const transformedContent = addCacheControlToContent(content, true);
|
|
377
|
+
|
|
367
378
|
return {
|
|
368
379
|
...message,
|
|
369
|
-
content:
|
|
370
|
-
(message.content as string | ChatCompletionContentPart[]) || "",
|
|
371
|
-
true,
|
|
372
|
-
),
|
|
380
|
+
content: transformedContent,
|
|
373
381
|
} as ChatCompletionMessageParam;
|
|
374
382
|
}
|
|
375
383
|
}
|
package/src/utils/constants.ts
CHANGED
|
@@ -31,8 +31,3 @@ export const USER_MEMORY_FILE = path.join(DATA_DIRECTORY, "AGENTS.md");
|
|
|
31
31
|
*/
|
|
32
32
|
export const DEFAULT_WAVE_MAX_INPUT_TOKENS = 96000; // Default token limit
|
|
33
33
|
export const DEFAULT_WAVE_MAX_OUTPUT_TOKENS = 8192; // Default output token limit
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Default number of messages to keep uncompressed
|
|
37
|
-
*/
|
|
38
|
-
export const DEFAULT_KEEP_LAST_MESSAGES_COUNT = 7;
|
|
@@ -57,8 +57,8 @@ export function convertMessagesForAPI(
|
|
|
57
57
|
);
|
|
58
58
|
if (compressBlock && compressBlock.type === "compress") {
|
|
59
59
|
recentMessages.unshift({
|
|
60
|
-
role: "
|
|
61
|
-
content:
|
|
60
|
+
role: "assistant",
|
|
61
|
+
content: compressBlock.content,
|
|
62
62
|
});
|
|
63
63
|
}
|
|
64
64
|
break;
|
package/src/utils/editUtils.ts
CHANGED
|
@@ -77,12 +77,8 @@ export function analyzeEditMismatch(
|
|
|
77
77
|
if (actualLine === expectedLine) {
|
|
78
78
|
reportLines.push(`${lineNum.toString().padStart(4)} | ${actualLine}`);
|
|
79
79
|
} else {
|
|
80
|
-
reportLines.push(
|
|
81
|
-
|
|
82
|
-
);
|
|
83
|
-
reportLines.push(
|
|
84
|
-
`${lineNum.toString().padStart(4)} | + ${actualLine} (actual)`,
|
|
85
|
-
);
|
|
80
|
+
reportLines.push(`${lineNum.toString().padStart(4)} | - ${expectedLine}`);
|
|
81
|
+
reportLines.push(`${lineNum.toString().padStart(4)} | + ${actualLine}`);
|
|
86
82
|
}
|
|
87
83
|
}
|
|
88
84
|
|