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,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,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
BASH_SUBAGENT_SYSTEM_PROMPT,
|
|
3
|
+
GENERAL_PURPOSE_SYSTEM_PROMPT,
|
|
4
|
+
PLAN_SUBAGENT_SYSTEM_PROMPT,
|
|
5
|
+
} from "../constants/prompts.js";
|
|
6
|
+
import { BASH_TOOL_NAME } from "../constants/tools.js";
|
|
2
7
|
import type { SubagentConfiguration } from "./subagentParser.js";
|
|
3
8
|
|
|
4
9
|
/**
|
|
@@ -7,12 +12,32 @@ import type { SubagentConfiguration } from "./subagentParser.js";
|
|
|
7
12
|
*/
|
|
8
13
|
export function getBuiltinSubagents(): SubagentConfiguration[] {
|
|
9
14
|
return [
|
|
15
|
+
createBashSubagent(),
|
|
10
16
|
createExploreSubagent(),
|
|
11
17
|
createGeneralPurposeSubagent(),
|
|
18
|
+
createPlanSubagent(),
|
|
12
19
|
// Add more built-in subagents here as needed
|
|
13
20
|
];
|
|
14
21
|
}
|
|
15
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Create the Bash built-in subagent configuration
|
|
25
|
+
* Specialized for executing bash commands and git operations
|
|
26
|
+
*/
|
|
27
|
+
function createBashSubagent(): SubagentConfiguration {
|
|
28
|
+
return {
|
|
29
|
+
name: "Bash",
|
|
30
|
+
description:
|
|
31
|
+
"Command execution specialist for running bash commands. Use this for git operations, command execution, and other terminal tasks.",
|
|
32
|
+
systemPrompt: BASH_SUBAGENT_SYSTEM_PROMPT,
|
|
33
|
+
tools: [BASH_TOOL_NAME],
|
|
34
|
+
model: "inherit",
|
|
35
|
+
filePath: "<builtin:Bash>",
|
|
36
|
+
scope: "builtin",
|
|
37
|
+
priority: 3,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
16
41
|
/**
|
|
17
42
|
* Create the General-Purpose built-in subagent configuration
|
|
18
43
|
* Specialized for multi-step research and implementation tasks
|
|
@@ -87,3 +112,24 @@ Complete the user's search request efficiently and report your findings clearly.
|
|
|
87
112
|
priority: 3, // Lowest priority - can be overridden by user configs
|
|
88
113
|
};
|
|
89
114
|
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Create the Plan built-in subagent configuration
|
|
118
|
+
* Specialized for designing implementation plans and exploring codebases in read-only mode
|
|
119
|
+
*/
|
|
120
|
+
function createPlanSubagent(): SubagentConfiguration {
|
|
121
|
+
// Define allowed tools for read-only operations
|
|
122
|
+
const allowedTools = ["Glob", "Grep", "Read", "Bash", "LS", "LSP"];
|
|
123
|
+
|
|
124
|
+
return {
|
|
125
|
+
name: "Plan",
|
|
126
|
+
description:
|
|
127
|
+
"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.",
|
|
128
|
+
systemPrompt: PLAN_SUBAGENT_SYSTEM_PROMPT,
|
|
129
|
+
tools: allowedTools,
|
|
130
|
+
model: "inherit", // Uses parent agent's model
|
|
131
|
+
filePath: "<builtin:Plan>",
|
|
132
|
+
scope: "builtin",
|
|
133
|
+
priority: 3, // Lowest priority - can be overridden by user configs
|
|
134
|
+
};
|
|
135
|
+
}
|
|
@@ -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
|
@@ -1,128 +1,90 @@
|
|
|
1
|
-
import { mkdir, writeFile } from "fs/promises";
|
|
2
|
-
import path from "path";
|
|
3
|
-
import os from "os";
|
|
4
|
-
import { logger } from "./globalLogger.js";
|
|
5
|
-
|
|
6
1
|
/**
|
|
7
2
|
* Utility functions for file editing tools
|
|
8
3
|
*/
|
|
9
4
|
|
|
10
5
|
/**
|
|
11
|
-
*
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
6
|
+
* Escape regular expression special characters
|
|
7
|
+
*/
|
|
8
|
+
export function escapeRegExp(string: string): string {
|
|
9
|
+
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Analyze why an edit failed by finding the best partial match and highlighting mismatches.
|
|
17
14
|
*/
|
|
18
|
-
export function
|
|
15
|
+
export function analyzeEditMismatch(
|
|
19
16
|
content: string,
|
|
20
17
|
searchString: string,
|
|
21
|
-
): string
|
|
22
|
-
|
|
23
|
-
if (content.includes(searchString)) {
|
|
24
|
-
return searchString;
|
|
25
|
-
}
|
|
26
|
-
|
|
18
|
+
): string {
|
|
19
|
+
const contentLines = content.split("\n");
|
|
27
20
|
const searchLines = searchString.split("\n");
|
|
28
|
-
if (searchLines.length === 0) return null;
|
|
29
21
|
|
|
30
|
-
|
|
31
|
-
|
|
22
|
+
if (searchLines.length === 0 || contentLines.length === 0) {
|
|
23
|
+
return "old_string not found in file (empty search or content)";
|
|
24
|
+
}
|
|
32
25
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
let isMatch = true;
|
|
26
|
+
let bestMatchIndex = -1;
|
|
27
|
+
let bestMatchScore = -1;
|
|
36
28
|
|
|
29
|
+
// Sliding window to find the best partial match
|
|
30
|
+
for (let i = 0; i <= contentLines.length - searchLines.length; i++) {
|
|
31
|
+
let currentScore = 0;
|
|
37
32
|
for (let j = 0; j < searchLines.length; j++) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const sTrimmed = sLine.trimStart();
|
|
42
|
-
const cTrimmed = cLine.trimStart();
|
|
43
|
-
|
|
44
|
-
// If trimmed content doesn't match, it's not a match
|
|
45
|
-
if (sTrimmed !== cTrimmed) {
|
|
46
|
-
isMatch = false;
|
|
47
|
-
break;
|
|
33
|
+
if (contentLines[i + j] === searchLines[j]) {
|
|
34
|
+
currentScore++;
|
|
48
35
|
}
|
|
36
|
+
}
|
|
49
37
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
38
|
+
// Heuristic: prioritize matches where first or last lines match
|
|
39
|
+
if (contentLines[i] === searchLines[0]) currentScore += 0.5;
|
|
40
|
+
if (
|
|
41
|
+
contentLines[i + searchLines.length - 1] ===
|
|
42
|
+
searchLines[searchLines.length - 1]
|
|
43
|
+
)
|
|
44
|
+
currentScore += 0.5;
|
|
55
45
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
46
|
+
// Also consider trimmed matches to catch indentation issues
|
|
47
|
+
for (let j = 0; j < searchLines.length; j++) {
|
|
48
|
+
if (
|
|
49
|
+
contentLines[i + j].trim() === searchLines[j].trim() &&
|
|
50
|
+
contentLines[i + j] !== searchLines[j]
|
|
51
|
+
) {
|
|
52
|
+
currentScore += 0.1;
|
|
62
53
|
}
|
|
63
54
|
}
|
|
64
55
|
|
|
65
|
-
if (
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
.join("\n");
|
|
69
|
-
if (foundMatch !== null && foundMatch !== matchCandidate) {
|
|
70
|
-
// Multiple different smart matches found
|
|
71
|
-
return null;
|
|
72
|
-
}
|
|
73
|
-
foundMatch = matchCandidate;
|
|
56
|
+
if (currentScore > bestMatchScore) {
|
|
57
|
+
bestMatchScore = currentScore;
|
|
58
|
+
bestMatchIndex = i;
|
|
74
59
|
}
|
|
75
60
|
}
|
|
76
61
|
|
|
77
|
-
// If
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Escape regular expression special characters
|
|
84
|
-
*/
|
|
85
|
-
export function escapeRegExp(string: string): string {
|
|
86
|
-
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Save a snapshot of the old string and current file content for debugging
|
|
91
|
-
*/
|
|
92
|
-
export async function saveEditErrorSnapshot(
|
|
93
|
-
filePath: string,
|
|
94
|
-
oldString: string,
|
|
95
|
-
currentContent: string,
|
|
96
|
-
toolName: string,
|
|
97
|
-
): Promise<string | null> {
|
|
98
|
-
try {
|
|
99
|
-
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
100
|
-
const fileName = path.basename(filePath);
|
|
101
|
-
const snapshotDirName = `${timestamp}_${toolName}_${fileName}`;
|
|
102
|
-
const snapshotDir = path.join(
|
|
103
|
-
os.tmpdir(),
|
|
104
|
-
"wave-agent-edit-errors",
|
|
105
|
-
snapshotDirName,
|
|
106
|
-
);
|
|
107
|
-
|
|
108
|
-
await mkdir(snapshotDir, { recursive: true });
|
|
109
|
-
|
|
110
|
-
await Promise.all([
|
|
111
|
-
writeFile(path.join(snapshotDir, "old_string.txt"), oldString, "utf-8"),
|
|
112
|
-
writeFile(
|
|
113
|
-
path.join(snapshotDir, "file_content.txt"),
|
|
114
|
-
currentContent,
|
|
115
|
-
"utf-8",
|
|
116
|
-
),
|
|
117
|
-
]);
|
|
118
|
-
|
|
119
|
-
logger.error(
|
|
120
|
-
`Edit error snapshot saved to: ${snapshotDir}\nFile: ${filePath}\nTool: ${toolName}`,
|
|
121
|
-
);
|
|
62
|
+
// If no decent match found (score <= 0), return generic message
|
|
63
|
+
if (bestMatchScore <= 0) {
|
|
64
|
+
return "old_string not found in file (no similar block found)";
|
|
65
|
+
}
|
|
122
66
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
67
|
+
// Generate detailed report
|
|
68
|
+
const reportLines: string[] = [
|
|
69
|
+
`old_string not found in file. Best partial match found at line ${bestMatchIndex + 1}:`,
|
|
70
|
+
];
|
|
71
|
+
|
|
72
|
+
for (let j = 0; j < searchLines.length; j++) {
|
|
73
|
+
const lineNum = bestMatchIndex + j + 1;
|
|
74
|
+
const actualLine = contentLines[bestMatchIndex + j];
|
|
75
|
+
const expectedLine = searchLines[j];
|
|
76
|
+
|
|
77
|
+
if (actualLine === expectedLine) {
|
|
78
|
+
reportLines.push(`${lineNum.toString().padStart(4)} | ${actualLine}`);
|
|
79
|
+
} else {
|
|
80
|
+
reportLines.push(
|
|
81
|
+
`${lineNum.toString().padStart(4)} | - ${expectedLine} (expected)`,
|
|
82
|
+
);
|
|
83
|
+
reportLines.push(
|
|
84
|
+
`${lineNum.toString().padStart(4)} | + ${actualLine} (actual)`,
|
|
85
|
+
);
|
|
86
|
+
}
|
|
127
87
|
}
|
|
88
|
+
|
|
89
|
+
return reportLines.join("\n");
|
|
128
90
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { Message, Usage } from "../types/index.js";
|
|
2
2
|
import { MessageSource } from "../types/index.js";
|
|
3
|
-
import { DEFAULT_KEEP_LAST_MESSAGES_COUNT } from "./constants.js";
|
|
4
3
|
import type { SubagentConfiguration } from "./subagentParser.js";
|
|
5
4
|
import { readFileSync } from "fs";
|
|
6
5
|
import { extname } from "path";
|
|
@@ -40,6 +39,7 @@ export interface UpdateToolBlockParams {
|
|
|
40
39
|
images?: Array<{ data: string; mediaType?: string }>;
|
|
41
40
|
compactParams?: string;
|
|
42
41
|
parametersChunk?: string; // Incremental parameter updates for streaming
|
|
42
|
+
isManuallyBackgrounded?: boolean;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
// Agent specific interfaces (without messages parameter)
|
|
@@ -53,14 +53,6 @@ export interface AddErrorBlockParams {
|
|
|
53
53
|
error: string;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
export interface AddMemoryBlockParams {
|
|
57
|
-
messages: Message[];
|
|
58
|
-
content: string;
|
|
59
|
-
isSuccess: boolean;
|
|
60
|
-
memoryType?: "project" | "user";
|
|
61
|
-
storagePath?: string;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
56
|
export interface AddCommandOutputParams {
|
|
65
57
|
messages: Message[];
|
|
66
58
|
command: string;
|
|
@@ -78,26 +70,6 @@ export interface CompleteCommandParams {
|
|
|
78
70
|
exitCode: number;
|
|
79
71
|
}
|
|
80
72
|
|
|
81
|
-
/**
|
|
82
|
-
* Extract text content from user messages in the messages array
|
|
83
|
-
* Excludes messages with source HOOK to prevent hook-generated content from entering user history
|
|
84
|
-
*/
|
|
85
|
-
export const extractUserInputHistory = (messages: Message[]): string[] => {
|
|
86
|
-
return messages
|
|
87
|
-
.filter((message) => message.role === "user")
|
|
88
|
-
.map((message) => {
|
|
89
|
-
// Extract text block content, excluding HOOK-sourced blocks
|
|
90
|
-
const textBlocks = message.blocks.filter(
|
|
91
|
-
(block) => block.type === "text" && block.source !== MessageSource.HOOK,
|
|
92
|
-
);
|
|
93
|
-
return textBlocks
|
|
94
|
-
.map((block) => (block as { content: string }).content)
|
|
95
|
-
.join(" ")
|
|
96
|
-
.trim();
|
|
97
|
-
})
|
|
98
|
-
.filter((text) => text.length > 0); // Filter out empty text
|
|
99
|
-
};
|
|
100
|
-
|
|
101
73
|
/**
|
|
102
74
|
* Convert image file path to base64 format
|
|
103
75
|
* @param imagePath Image file path
|
|
@@ -230,6 +202,7 @@ export const updateToolBlockInMessage = ({
|
|
|
230
202
|
images,
|
|
231
203
|
compactParams,
|
|
232
204
|
parametersChunk,
|
|
205
|
+
isManuallyBackgrounded,
|
|
233
206
|
}: UpdateToolBlockParams): Message[] => {
|
|
234
207
|
const newMessages = [...messages];
|
|
235
208
|
// Find the last assistant message
|
|
@@ -253,6 +226,8 @@ export const updateToolBlockInMessage = ({
|
|
|
253
226
|
toolBlock.compactParams = compactParams;
|
|
254
227
|
if (parametersChunk !== undefined)
|
|
255
228
|
toolBlock.parametersChunk = parametersChunk;
|
|
229
|
+
if (isManuallyBackgrounded !== undefined)
|
|
230
|
+
toolBlock.isManuallyBackgrounded = isManuallyBackgrounded;
|
|
256
231
|
}
|
|
257
232
|
} else {
|
|
258
233
|
// If existing block not found, create new one
|
|
@@ -270,6 +245,7 @@ export const updateToolBlockInMessage = ({
|
|
|
270
245
|
stage: stage ?? "start",
|
|
271
246
|
compactParams: compactParams,
|
|
272
247
|
parametersChunk: parametersChunk,
|
|
248
|
+
isManuallyBackgrounded: isManuallyBackgrounded,
|
|
273
249
|
});
|
|
274
250
|
}
|
|
275
251
|
break;
|
|
@@ -315,113 +291,6 @@ export const addErrorBlockToMessage = ({
|
|
|
315
291
|
return newMessages;
|
|
316
292
|
};
|
|
317
293
|
|
|
318
|
-
// Add Memory Block as new assistant message
|
|
319
|
-
export const addMemoryBlockToMessage = ({
|
|
320
|
-
messages,
|
|
321
|
-
content,
|
|
322
|
-
isSuccess,
|
|
323
|
-
memoryType,
|
|
324
|
-
storagePath,
|
|
325
|
-
}: AddMemoryBlockParams): Message[] => {
|
|
326
|
-
const newMessages = [...messages];
|
|
327
|
-
|
|
328
|
-
// Create new assistant message containing MemoryBlock
|
|
329
|
-
const memoryMessage: Message = {
|
|
330
|
-
role: "assistant",
|
|
331
|
-
blocks: [
|
|
332
|
-
{
|
|
333
|
-
type: "memory",
|
|
334
|
-
content,
|
|
335
|
-
isSuccess,
|
|
336
|
-
memoryType,
|
|
337
|
-
storagePath,
|
|
338
|
-
},
|
|
339
|
-
],
|
|
340
|
-
};
|
|
341
|
-
|
|
342
|
-
// Add to end of message list
|
|
343
|
-
newMessages.push(memoryMessage);
|
|
344
|
-
return newMessages;
|
|
345
|
-
};
|
|
346
|
-
|
|
347
|
-
/**
|
|
348
|
-
* Count valid blocks from the end
|
|
349
|
-
* Only text, image, and tool type blocks are counted
|
|
350
|
-
* @param messages Message array
|
|
351
|
-
* @param targetCount Number of valid blocks to count
|
|
352
|
-
* @returns { messageIndex: number, blockCount: number } Message index and actual counted block count
|
|
353
|
-
*/
|
|
354
|
-
export const countValidBlocksFromEnd = (
|
|
355
|
-
messages: Message[],
|
|
356
|
-
targetCount: number,
|
|
357
|
-
): { messageIndex: number; blockCount: number } => {
|
|
358
|
-
let validBlockCount = 0;
|
|
359
|
-
|
|
360
|
-
// Iterate messages from end to beginning
|
|
361
|
-
for (let i = messages.length - 1; i >= 0; i--) {
|
|
362
|
-
const message = messages[i];
|
|
363
|
-
|
|
364
|
-
// Iterate through all blocks of current message
|
|
365
|
-
for (const block of message.blocks) {
|
|
366
|
-
// Only count valid block types
|
|
367
|
-
if (
|
|
368
|
-
block.type === "text" ||
|
|
369
|
-
block.type === "image" ||
|
|
370
|
-
block.type === "tool"
|
|
371
|
-
) {
|
|
372
|
-
validBlockCount++;
|
|
373
|
-
|
|
374
|
-
// If target count reached, return current message index
|
|
375
|
-
if (validBlockCount >= targetCount) {
|
|
376
|
-
return { messageIndex: i, blockCount: validBlockCount };
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
// If target count not reached, return index 0
|
|
383
|
-
return { messageIndex: 0, blockCount: validBlockCount };
|
|
384
|
-
};
|
|
385
|
-
|
|
386
|
-
/**
|
|
387
|
-
* Get messages to be compressed and insertion position
|
|
388
|
-
* @param messages Message array
|
|
389
|
-
* @param keepLastCount Keep the last few valid blocks uncompressed
|
|
390
|
-
* @returns { messagesToCompress: Message[], insertIndex: number }
|
|
391
|
-
*/
|
|
392
|
-
export const getMessagesToCompress = (
|
|
393
|
-
messages: Message[],
|
|
394
|
-
keepLastCount: number = DEFAULT_KEEP_LAST_MESSAGES_COUNT,
|
|
395
|
-
): { messagesToCompress: Message[]; insertIndex: number } => {
|
|
396
|
-
// Calculate message position to keep from end to beginning
|
|
397
|
-
const { messageIndex } = countValidBlocksFromEnd(messages, keepLastCount);
|
|
398
|
-
|
|
399
|
-
// Find the last message containing compression block
|
|
400
|
-
let lastCompressIndex = -1;
|
|
401
|
-
for (let i = messages.length - 1; i >= 0; i--) {
|
|
402
|
-
const hasCompressBlock = messages[i].blocks.some(
|
|
403
|
-
(block) => block.type === "compress",
|
|
404
|
-
);
|
|
405
|
-
if (hasCompressBlock) {
|
|
406
|
-
lastCompressIndex = i;
|
|
407
|
-
break;
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
// Determine compression start position
|
|
412
|
-
// If compression block exists, start from compression block position (include compression block)
|
|
413
|
-
// If no compression block, start from beginning
|
|
414
|
-
const startIndex = lastCompressIndex >= 0 ? lastCompressIndex : 0;
|
|
415
|
-
|
|
416
|
-
// Messages to compress are all messages from start position to before calculated position
|
|
417
|
-
const messagesToCompress = messages.slice(startIndex, messageIndex);
|
|
418
|
-
|
|
419
|
-
// Change insertion position to negative number, indicating position from end
|
|
420
|
-
const insertIndex = messageIndex - messages.length;
|
|
421
|
-
|
|
422
|
-
return { messagesToCompress, insertIndex };
|
|
423
|
-
};
|
|
424
|
-
|
|
425
294
|
// Add command output block to message list
|
|
426
295
|
export const addCommandOutputMessage = ({
|
|
427
296
|
messages,
|
|
@@ -504,6 +373,7 @@ export interface AddSubagentBlockParams {
|
|
|
504
373
|
status: "active" | "completed" | "error" | "aborted";
|
|
505
374
|
sessionId: string;
|
|
506
375
|
configuration: SubagentConfiguration;
|
|
376
|
+
runInBackground?: boolean;
|
|
507
377
|
}
|
|
508
378
|
|
|
509
379
|
export interface UpdateSubagentBlockParams {
|
|
@@ -520,6 +390,7 @@ export const addSubagentBlockToMessage = ({
|
|
|
520
390
|
status,
|
|
521
391
|
sessionId,
|
|
522
392
|
configuration,
|
|
393
|
+
runInBackground,
|
|
523
394
|
}: AddSubagentBlockParams): Message[] => {
|
|
524
395
|
const newMessages = [...messages];
|
|
525
396
|
|
|
@@ -544,6 +415,7 @@ export const addSubagentBlockToMessage = ({
|
|
|
544
415
|
status,
|
|
545
416
|
sessionId,
|
|
546
417
|
configuration,
|
|
418
|
+
runInBackground,
|
|
547
419
|
});
|
|
548
420
|
|
|
549
421
|
return newMessages;
|
|
@@ -555,6 +427,7 @@ export const updateSubagentBlockInMessage = (
|
|
|
555
427
|
updates: Partial<{
|
|
556
428
|
status: "active" | "completed" | "error" | "aborted";
|
|
557
429
|
sessionId: string;
|
|
430
|
+
runInBackground: boolean;
|
|
558
431
|
}>,
|
|
559
432
|
): Message[] => {
|
|
560
433
|
const newMessages = [...messages];
|
|
@@ -571,6 +444,9 @@ export const updateSubagentBlockInMessage = (
|
|
|
571
444
|
if (updates.sessionId !== undefined) {
|
|
572
445
|
block.sessionId = updates.sessionId;
|
|
573
446
|
}
|
|
447
|
+
if (updates.runInBackground !== undefined) {
|
|
448
|
+
block.runInBackground = updates.runInBackground;
|
|
449
|
+
}
|
|
574
450
|
return newMessages;
|
|
575
451
|
}
|
|
576
452
|
}
|
|
@@ -71,8 +71,25 @@ const nouns = [
|
|
|
71
71
|
/**
|
|
72
72
|
* Generates a random English name (adjective-noun)
|
|
73
73
|
*/
|
|
74
|
-
export function generateRandomName(): string {
|
|
75
|
-
|
|
76
|
-
|
|
74
|
+
export function generateRandomName(seed?: string): string {
|
|
75
|
+
let adjIndex: number;
|
|
76
|
+
let nounIndex: number;
|
|
77
|
+
|
|
78
|
+
if (seed) {
|
|
79
|
+
// Simple hash function to derive indices from seed
|
|
80
|
+
let hash = 0;
|
|
81
|
+
for (let i = 0; i < seed.length; i++) {
|
|
82
|
+
hash = (hash << 5) - hash + seed.charCodeAt(i);
|
|
83
|
+
hash |= 0; // Convert to 32bit integer
|
|
84
|
+
}
|
|
85
|
+
adjIndex = Math.abs(hash) % adjectives.length;
|
|
86
|
+
nounIndex = Math.abs(hash >> 8) % nouns.length;
|
|
87
|
+
} else {
|
|
88
|
+
adjIndex = Math.floor(Math.random() * adjectives.length);
|
|
89
|
+
nounIndex = Math.floor(Math.random() * nouns.length);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const adj = adjectives[adjIndex];
|
|
93
|
+
const noun = nouns[nounIndex];
|
|
77
94
|
return `${adj}-${noun}`;
|
|
78
95
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"todoWriteTool.d.ts","sourceRoot":"","sources":["../../src/tools/todoWriteTool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAA2B,MAAM,YAAY,CAAC;AAStE;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,UAoP3B,CAAC"}
|