wave-agent-sdk 0.6.4 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent.d.ts +8 -0
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +49 -240
- package/dist/constants/tools.d.ts +0 -2
- package/dist/constants/tools.d.ts.map +1 -1
- package/dist/constants/tools.js +0 -2
- package/dist/core/plugin.d.ts +86 -0
- package/dist/core/plugin.d.ts.map +1 -0
- package/dist/core/plugin.js +164 -0
- package/dist/index.d.ts +1 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -5
- package/dist/managers/MemoryRuleManager.d.ts +3 -1
- package/dist/managers/MemoryRuleManager.d.ts.map +1 -1
- package/dist/managers/MemoryRuleManager.js +2 -1
- package/dist/managers/aiManager.d.ts +13 -23
- package/dist/managers/aiManager.d.ts.map +1 -1
- package/dist/managers/aiManager.js +59 -32
- package/dist/managers/backgroundTaskManager.d.ts +3 -1
- package/dist/managers/backgroundTaskManager.d.ts.map +1 -1
- package/dist/managers/backgroundTaskManager.js +2 -1
- package/dist/managers/bashManager.d.ts +4 -4
- package/dist/managers/bashManager.d.ts.map +1 -1
- package/dist/managers/bashManager.js +5 -2
- package/dist/managers/foregroundTaskManager.d.ts +3 -0
- package/dist/managers/foregroundTaskManager.d.ts.map +1 -1
- package/dist/managers/foregroundTaskManager.js +2 -1
- package/dist/managers/hookManager.d.ts +3 -3
- package/dist/managers/hookManager.d.ts.map +1 -1
- package/dist/managers/hookManager.js +20 -19
- package/dist/managers/liveConfigManager.d.ts +6 -13
- package/dist/managers/liveConfigManager.d.ts.map +1 -1
- package/dist/managers/liveConfigManager.js +50 -45
- package/dist/managers/lspManager.d.ts +4 -5
- package/dist/managers/lspManager.d.ts.map +1 -1
- package/dist/managers/lspManager.js +13 -12
- package/dist/managers/mcpManager.d.ts +3 -2
- package/dist/managers/mcpManager.d.ts.map +1 -1
- package/dist/managers/mcpManager.js +16 -15
- package/dist/managers/messageManager.d.ts +5 -7
- package/dist/managers/messageManager.d.ts.map +1 -1
- package/dist/managers/messageManager.js +12 -7
- package/dist/managers/permissionManager.d.ts +6 -4
- package/dist/managers/permissionManager.d.ts.map +1 -1
- package/dist/managers/permissionManager.js +39 -63
- package/dist/managers/planManager.d.ts +4 -6
- package/dist/managers/planManager.d.ts.map +1 -1
- package/dist/managers/planManager.js +18 -4
- package/dist/managers/pluginManager.d.ts +10 -22
- package/dist/managers/pluginManager.d.ts.map +1 -1
- package/dist/managers/pluginManager.js +27 -14
- package/dist/managers/reversionManager.d.ts +4 -3
- package/dist/managers/reversionManager.d.ts.map +1 -1
- package/dist/managers/reversionManager.js +5 -2
- package/dist/managers/skillManager.d.ts +3 -2
- package/dist/managers/skillManager.d.ts.map +1 -1
- package/dist/managers/skillManager.js +15 -14
- package/dist/managers/slashCommandManager.d.ts +9 -16
- package/dist/managers/slashCommandManager.d.ts.map +1 -1
- package/dist/managers/slashCommandManager.js +21 -10
- package/dist/managers/subagentManager.d.ts +7 -17
- package/dist/managers/subagentManager.d.ts.map +1 -1
- package/dist/managers/subagentManager.js +41 -34
- package/dist/managers/toolManager.d.ts +15 -38
- package/dist/managers/toolManager.d.ts.map +1 -1
- package/dist/managers/toolManager.js +66 -56
- package/dist/prompts/index.d.ts +6 -3
- package/dist/prompts/index.d.ts.map +1 -1
- package/dist/prompts/index.js +8 -16
- package/dist/services/MarketplaceService.d.ts.map +1 -1
- package/dist/services/MarketplaceService.js +13 -0
- package/dist/services/aiService.d.ts +4 -0
- package/dist/services/aiService.d.ts.map +1 -1
- package/dist/services/aiService.js +47 -7
- package/dist/services/configurationService.d.ts.map +1 -1
- package/dist/services/configurationService.js +30 -11
- package/dist/services/taskManager.d.ts +3 -1
- package/dist/services/taskManager.d.ts.map +1 -1
- package/dist/services/taskManager.js +2 -1
- package/dist/tools/bashTool.js +2 -2
- package/dist/tools/editTool.d.ts.map +1 -1
- package/dist/tools/editTool.js +9 -1
- package/dist/tools/readTool.d.ts.map +1 -1
- package/dist/tools/readTool.js +2 -2
- package/dist/tools/skillTool.d.ts +2 -4
- package/dist/tools/skillTool.d.ts.map +1 -1
- package/dist/tools/skillTool.js +61 -61
- package/dist/tools/taskOutputTool.js +1 -1
- package/dist/tools/taskTool.d.ts +2 -4
- package/dist/tools/taskTool.d.ts.map +1 -1
- package/dist/tools/taskTool.js +192 -187
- package/dist/tools/types.d.ts +11 -1
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/writeTool.d.ts.map +1 -1
- package/dist/tools/writeTool.js +4 -2
- package/dist/types/marketplace.d.ts +8 -0
- package/dist/types/marketplace.d.ts.map +1 -1
- package/dist/types/permissions.d.ts +1 -1
- package/dist/types/permissions.d.ts.map +1 -1
- package/dist/types/permissions.js +1 -3
- package/dist/types/skills.d.ts +0 -2
- package/dist/types/skills.d.ts.map +1 -1
- package/dist/types/tools.d.ts +0 -15
- package/dist/types/tools.d.ts.map +1 -1
- package/dist/utils/container.d.ts +31 -0
- package/dist/utils/container.d.ts.map +1 -0
- package/dist/utils/container.js +79 -0
- package/dist/utils/containerSetup.d.ts +26 -0
- package/dist/utils/containerSetup.d.ts.map +1 -0
- package/dist/utils/containerSetup.js +165 -0
- package/dist/utils/editUtils.d.ts +0 -3
- package/dist/utils/editUtils.d.ts.map +1 -1
- package/dist/utils/editUtils.js +4 -3
- package/dist/utils/hookMatcher.d.ts +1 -1
- package/dist/utils/hookMatcher.d.ts.map +1 -1
- package/dist/utils/hookMatcher.js +2 -2
- package/dist/utils/openaiClient.js +2 -2
- package/dist/utils/stringUtils.d.ts +6 -0
- package/dist/utils/stringUtils.d.ts.map +1 -1
- package/dist/utils/stringUtils.js +8 -0
- package/package.json +1 -1
- package/src/agent.ts +60 -282
- package/src/constants/tools.ts +0 -2
- package/src/core/plugin.ts +224 -0
- package/src/index.ts +1 -6
- package/src/managers/MemoryRuleManager.ts +6 -1
- package/src/managers/aiManager.ts +83 -58
- package/src/managers/backgroundTaskManager.ts +5 -1
- package/src/managers/bashManager.ts +9 -4
- package/src/managers/foregroundTaskManager.ts +3 -0
- package/src/managers/hookManager.ts +21 -23
- package/src/managers/liveConfigManager.ts +57 -53
- package/src/managers/lspManager.ts +14 -19
- package/src/managers/mcpManager.ts +20 -20
- package/src/managers/messageManager.ts +19 -12
- package/src/managers/permissionManager.ts +45 -70
- package/src/managers/planManager.ts +26 -7
- package/src/managers/pluginManager.ts +37 -33
- package/src/managers/reversionManager.ts +5 -3
- package/src/managers/skillManager.ts +19 -20
- package/src/managers/slashCommandManager.ts +30 -25
- package/src/managers/subagentManager.ts +53 -53
- package/src/managers/toolManager.ts +91 -90
- package/src/prompts/index.ts +12 -24
- package/src/services/MarketplaceService.ts +13 -0
- package/src/services/aiService.ts +61 -15
- package/src/services/configurationService.ts +34 -13
- package/src/services/taskManager.ts +5 -1
- package/src/tools/bashTool.ts +2 -2
- package/src/tools/editTool.ts +9 -1
- package/src/tools/readTool.ts +2 -2
- package/src/tools/skillTool.ts +75 -71
- package/src/tools/taskOutputTool.ts +1 -1
- package/src/tools/taskTool.ts +224 -225
- package/src/tools/types.ts +12 -1
- package/src/tools/writeTool.ts +4 -2
- package/src/types/marketplace.ts +9 -0
- package/src/types/permissions.ts +0 -4
- package/src/types/skills.ts +0 -3
- package/src/types/tools.ts +0 -17
- package/src/utils/container.ts +92 -0
- package/src/utils/containerSetup.ts +256 -0
- package/src/utils/editUtils.ts +4 -3
- package/src/utils/hookMatcher.ts +2 -2
- package/src/utils/openaiClient.ts +2 -2
- package/src/utils/stringUtils.ts +9 -0
- package/dist/tools/deleteFileTool.d.ts +0 -6
- package/dist/tools/deleteFileTool.d.ts.map +0 -1
- package/dist/tools/deleteFileTool.js +0 -100
- package/dist/tools/multiEditTool.d.ts +0 -6
- package/dist/tools/multiEditTool.d.ts.map +0 -1
- package/dist/tools/multiEditTool.js +0 -246
- package/src/tools/deleteFileTool.ts +0 -127
- package/src/tools/multiEditTool.ts +0 -306
|
@@ -2,9 +2,7 @@ import type { ToolContext, ToolPlugin, ToolResult } from "../tools/types.js";
|
|
|
2
2
|
import { bashTool } from "../tools/bashTool.js";
|
|
3
3
|
import { taskOutputTool } from "../tools/taskOutputTool.js";
|
|
4
4
|
import { taskStopTool } from "../tools/taskStopTool.js";
|
|
5
|
-
import { deleteFileTool } from "../tools/deleteFileTool.js";
|
|
6
5
|
import { editTool } from "../tools/editTool.js";
|
|
7
|
-
import { multiEditTool } from "../tools/multiEditTool.js";
|
|
8
6
|
import { writeTool } from "../tools/writeTool.js";
|
|
9
7
|
import { exitPlanModeTool } from "../tools/exitPlanMode.js";
|
|
10
8
|
import { askUserQuestionTool } from "../tools/askUserQuestion.js";
|
|
@@ -14,8 +12,8 @@ import { grepTool } from "../tools/grepTool.js";
|
|
|
14
12
|
import { lsTool } from "../tools/lsTool.js";
|
|
15
13
|
import { readTool } from "../tools/readTool.js";
|
|
16
14
|
import { lspTool } from "../tools/lspTool.js";
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
15
|
+
import { taskTool } from "../tools/taskTool.js";
|
|
16
|
+
import { skillTool } from "../tools/skillTool.js";
|
|
19
17
|
import {
|
|
20
18
|
taskCreateTool,
|
|
21
19
|
taskGetTool,
|
|
@@ -26,7 +24,6 @@ import { McpManager } from "./mcpManager.js";
|
|
|
26
24
|
import { PermissionManager } from "./permissionManager.js";
|
|
27
25
|
import { ChatCompletionFunctionTool } from "openai/resources.js";
|
|
28
26
|
import type {
|
|
29
|
-
Logger,
|
|
30
27
|
PermissionMode,
|
|
31
28
|
PermissionCallback,
|
|
32
29
|
ILspManager,
|
|
@@ -36,24 +33,14 @@ import type { SkillManager } from "./skillManager.js";
|
|
|
36
33
|
|
|
37
34
|
import { ReversionManager } from "./reversionManager.js";
|
|
38
35
|
|
|
36
|
+
import { Container } from "../utils/container.js";
|
|
37
|
+
|
|
38
|
+
import { logger } from "../utils/globalLogger.js";
|
|
39
|
+
|
|
39
40
|
export interface ToolManagerOptions {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
/** Permission manager for handling tool permission checks */
|
|
44
|
-
permissionManager?: PermissionManager;
|
|
45
|
-
/** Foreground task manager for backgrounding tasks */
|
|
46
|
-
foregroundTaskManager?: import("../types/processes.js").IForegroundTaskManager;
|
|
47
|
-
/** Task manager for task management */
|
|
48
|
-
taskManager?: import("../services/taskManager.js").TaskManager;
|
|
49
|
-
/** Reversion manager for file snapshots */
|
|
50
|
-
reversionManager?: ReversionManager;
|
|
51
|
-
/** Background task manager for background execution */
|
|
52
|
-
backgroundTaskManager?: import("./backgroundTaskManager.js").BackgroundTaskManager;
|
|
53
|
-
/** Permission mode for tool execution (defaults to "default") */
|
|
54
|
-
permissionMode?: PermissionMode;
|
|
55
|
-
/** Custom permission callback for tool usage */
|
|
56
|
-
canUseToolCallback?: PermissionCallback;
|
|
41
|
+
container: Container;
|
|
42
|
+
/** Optional list of tool names to enable */
|
|
43
|
+
tools?: string[];
|
|
57
44
|
}
|
|
58
45
|
|
|
59
46
|
/**
|
|
@@ -63,44 +50,31 @@ export interface ToolManagerOptions {
|
|
|
63
50
|
* Supports both built-in tools and MCP (Model Context Protocol) tools.
|
|
64
51
|
*/
|
|
65
52
|
class ToolManager {
|
|
66
|
-
private
|
|
67
|
-
private
|
|
68
|
-
private
|
|
69
|
-
private logger?: Logger;
|
|
70
|
-
private permissionManager?: PermissionManager;
|
|
71
|
-
private foregroundTaskManager?: import("../types/processes.js").IForegroundTaskManager;
|
|
72
|
-
private reversionManager?: ReversionManager;
|
|
73
|
-
private taskManager?: import("../services/taskManager.js").TaskManager;
|
|
74
|
-
private backgroundTaskManager?: import("./backgroundTaskManager.js").BackgroundTaskManager;
|
|
75
|
-
private permissionMode?: PermissionMode;
|
|
76
|
-
private canUseToolCallback?: PermissionCallback;
|
|
53
|
+
private toolsRegistry = new Map<string, ToolPlugin>();
|
|
54
|
+
private tools?: string[];
|
|
55
|
+
private container: Container;
|
|
77
56
|
|
|
78
57
|
constructor(options: ToolManagerOptions) {
|
|
79
|
-
this.
|
|
80
|
-
this.
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
this.
|
|
85
|
-
this.reversionManager = options.reversionManager;
|
|
86
|
-
this.backgroundTaskManager = options.backgroundTaskManager;
|
|
87
|
-
// Store CLI permission mode, let PermissionManager resolve effective mode
|
|
88
|
-
this.permissionMode = options.permissionMode;
|
|
89
|
-
this.canUseToolCallback = options.canUseToolCallback;
|
|
58
|
+
this.container = options.container;
|
|
59
|
+
this.tools = options.tools;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
private get mcpManager(): McpManager {
|
|
63
|
+
return this.container.get<McpManager>("McpManager")!;
|
|
90
64
|
}
|
|
91
65
|
|
|
92
66
|
/**
|
|
93
67
|
* Register a new tool
|
|
94
68
|
*/
|
|
95
69
|
public register(tool: ToolPlugin): void {
|
|
96
|
-
this.
|
|
70
|
+
this.toolsRegistry.set(tool.name, tool);
|
|
97
71
|
}
|
|
98
72
|
|
|
99
73
|
/**
|
|
100
74
|
* Initialize built-in tools. Can be called with dependencies for tools that require them.
|
|
101
75
|
*
|
|
102
76
|
* This method can be called multiple times safely. When called without dependencies,
|
|
103
|
-
* it registers basic tools (Bash, Read, Write,
|
|
77
|
+
* it registers basic tools (Bash, Read, Write, TaskCreate, etc.). When called with
|
|
104
78
|
* dependencies, it also registers tools that require managers (Task, Skill).
|
|
105
79
|
*
|
|
106
80
|
* @param deps Optional dependencies for advanced tools
|
|
@@ -119,17 +93,12 @@ class ToolManager {
|
|
|
119
93
|
* });
|
|
120
94
|
* ```
|
|
121
95
|
*/
|
|
122
|
-
public initializeBuiltInTools(
|
|
123
|
-
subagentManager?: SubagentManager;
|
|
124
|
-
skillManager?: SkillManager;
|
|
125
|
-
}): void {
|
|
96
|
+
public initializeBuiltInTools(): void {
|
|
126
97
|
const builtInTools = [
|
|
127
98
|
bashTool,
|
|
128
99
|
taskOutputTool,
|
|
129
100
|
taskStopTool,
|
|
130
|
-
deleteFileTool,
|
|
131
101
|
editTool,
|
|
132
|
-
multiEditTool,
|
|
133
102
|
writeTool,
|
|
134
103
|
exitPlanModeTool,
|
|
135
104
|
askUserQuestionTool,
|
|
@@ -138,6 +107,8 @@ class ToolManager {
|
|
|
138
107
|
lsTool,
|
|
139
108
|
readTool,
|
|
140
109
|
lspTool,
|
|
110
|
+
taskTool,
|
|
111
|
+
skillTool,
|
|
141
112
|
taskCreateTool,
|
|
142
113
|
taskGetTool,
|
|
143
114
|
taskUpdateTool,
|
|
@@ -145,19 +116,22 @@ class ToolManager {
|
|
|
145
116
|
];
|
|
146
117
|
|
|
147
118
|
for (const tool of builtInTools) {
|
|
148
|
-
this.
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
// Register tools that require dependencies
|
|
152
|
-
if (deps?.subagentManager) {
|
|
153
|
-
const taskTool = createTaskTool(deps.subagentManager);
|
|
154
|
-
this.tools.set(taskTool.name, taskTool);
|
|
119
|
+
if (this.shouldEnableTool(tool.name)) {
|
|
120
|
+
this.toolsRegistry.set(tool.name, tool);
|
|
121
|
+
}
|
|
155
122
|
}
|
|
123
|
+
}
|
|
156
124
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
125
|
+
/**
|
|
126
|
+
* Check if a tool should be enabled based on tools configuration
|
|
127
|
+
*/
|
|
128
|
+
private shouldEnableTool(name: string): boolean {
|
|
129
|
+
if (!this.tools) {
|
|
130
|
+
return true;
|
|
160
131
|
}
|
|
132
|
+
return this.tools.some(
|
|
133
|
+
(toolName) => toolName.toLowerCase() === name.toLowerCase(),
|
|
134
|
+
);
|
|
161
135
|
}
|
|
162
136
|
|
|
163
137
|
/**
|
|
@@ -178,32 +152,53 @@ class ToolManager {
|
|
|
178
152
|
args: Record<string, unknown>,
|
|
179
153
|
context: ToolContext,
|
|
180
154
|
): Promise<ToolResult> {
|
|
155
|
+
const permissionManager =
|
|
156
|
+
this.container.get<PermissionManager>("PermissionManager");
|
|
157
|
+
const permissionMode = this.container.has("PermissionMode")
|
|
158
|
+
? this.container.get<PermissionMode>("PermissionMode")
|
|
159
|
+
: undefined;
|
|
160
|
+
|
|
181
161
|
// Resolve effective permission mode (CLI override > configuration > default)
|
|
182
|
-
const effectivePermissionMode =
|
|
183
|
-
?
|
|
184
|
-
:
|
|
162
|
+
const effectivePermissionMode = permissionManager
|
|
163
|
+
? permissionManager.getCurrentEffectiveMode(permissionMode)
|
|
164
|
+
: permissionMode || "default";
|
|
185
165
|
|
|
186
166
|
// Enhance context with permission-related fields
|
|
187
167
|
const enhancedContext: ToolContext = {
|
|
188
168
|
...context,
|
|
189
169
|
permissionMode: effectivePermissionMode,
|
|
190
|
-
canUseToolCallback: this.
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
170
|
+
canUseToolCallback: this.container.has("CanUseToolCallback")
|
|
171
|
+
? this.container.get<PermissionCallback>("CanUseToolCallback")
|
|
172
|
+
: undefined,
|
|
173
|
+
permissionManager,
|
|
174
|
+
taskManager:
|
|
175
|
+
this.container.get<import("../services/taskManager.js").TaskManager>(
|
|
176
|
+
"TaskManager",
|
|
177
|
+
)!,
|
|
178
|
+
reversionManager:
|
|
179
|
+
this.container.get<ReversionManager>("ReversionManager")!,
|
|
180
|
+
backgroundTaskManager: this.container.get<
|
|
181
|
+
import("./backgroundTaskManager.js").BackgroundTaskManager
|
|
182
|
+
>("BackgroundTaskManager")!,
|
|
183
|
+
foregroundTaskManager: this.container.get<
|
|
184
|
+
import("../types/processes.js").IForegroundTaskManager
|
|
185
|
+
>("ForegroundTaskManager")!,
|
|
196
186
|
mcpManager: this.mcpManager,
|
|
197
|
-
lspManager: this.
|
|
187
|
+
lspManager: this.container.get<ILspManager>("LspManager")!,
|
|
188
|
+
subagentManager: this.container.has("SubagentManager")
|
|
189
|
+
? this.container.get<SubagentManager>("SubagentManager")
|
|
190
|
+
: undefined,
|
|
191
|
+
skillManager: this.container.has("SkillManager")
|
|
192
|
+
? this.container.get<SkillManager>("SkillManager")
|
|
193
|
+
: undefined,
|
|
198
194
|
sessionId: context.sessionId,
|
|
199
195
|
};
|
|
200
196
|
|
|
201
|
-
|
|
197
|
+
logger?.debug("Executing tool with enhanced context", {
|
|
202
198
|
toolName: name,
|
|
203
|
-
|
|
199
|
+
permissionMode,
|
|
204
200
|
effectivePermissionMode,
|
|
205
|
-
hasPermissionManager: !!
|
|
206
|
-
hasPermissionCallback: !!this.canUseToolCallback,
|
|
201
|
+
hasPermissionManager: !!permissionManager,
|
|
207
202
|
});
|
|
208
203
|
|
|
209
204
|
// Check if it's an MCP tool first
|
|
@@ -216,12 +211,12 @@ class ToolManager {
|
|
|
216
211
|
}
|
|
217
212
|
|
|
218
213
|
// Check built-in tools
|
|
219
|
-
const plugin = this.
|
|
214
|
+
const plugin = this.toolsRegistry.get(name);
|
|
220
215
|
if (plugin) {
|
|
221
216
|
try {
|
|
222
217
|
return await plugin.execute(args, enhancedContext);
|
|
223
218
|
} catch (error) {
|
|
224
|
-
|
|
219
|
+
logger?.error("Tool execution failed", {
|
|
225
220
|
toolName: name,
|
|
226
221
|
error: error instanceof Error ? error.message : String(error),
|
|
227
222
|
});
|
|
@@ -233,7 +228,7 @@ class ToolManager {
|
|
|
233
228
|
}
|
|
234
229
|
}
|
|
235
230
|
|
|
236
|
-
|
|
231
|
+
logger?.warn("Tool not found", { toolName: name });
|
|
237
232
|
return {
|
|
238
233
|
success: false,
|
|
239
234
|
content: "",
|
|
@@ -242,14 +237,14 @@ class ToolManager {
|
|
|
242
237
|
}
|
|
243
238
|
|
|
244
239
|
list(): ToolPlugin[] {
|
|
245
|
-
const builtInTools = Array.from(this.
|
|
240
|
+
const builtInTools = Array.from(this.toolsRegistry.values());
|
|
246
241
|
const mcpTools = this.mcpManager.getMcpToolPlugins();
|
|
247
242
|
return [...builtInTools, ...mcpTools];
|
|
248
243
|
}
|
|
249
244
|
|
|
250
245
|
getToolsConfig(): ChatCompletionFunctionTool[] {
|
|
251
246
|
const effectivePermissionMode = this.getPermissionMode();
|
|
252
|
-
const builtInToolsConfig = Array.from(this.
|
|
247
|
+
const builtInToolsConfig = Array.from(this.toolsRegistry.values())
|
|
253
248
|
.filter((tool) => {
|
|
254
249
|
if (effectivePermissionMode === "bypassPermissions") {
|
|
255
250
|
if (tool.name === "ExitPlanMode" || tool.name === "AskUserQuestion") {
|
|
@@ -270,19 +265,23 @@ class ToolManager {
|
|
|
270
265
|
* Get the list of registered tool plugins
|
|
271
266
|
*/
|
|
272
267
|
public getTools(): ToolPlugin[] {
|
|
273
|
-
return Array.from(this.
|
|
268
|
+
return Array.from(this.toolsRegistry.values());
|
|
274
269
|
}
|
|
275
270
|
|
|
276
271
|
/**
|
|
277
272
|
* Get the current permission mode
|
|
278
273
|
*/
|
|
279
274
|
public getPermissionMode(): PermissionMode {
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
)
|
|
275
|
+
const permissionManager =
|
|
276
|
+
this.container.get<PermissionManager>("PermissionManager");
|
|
277
|
+
const permissionMode = this.container.has("PermissionMode")
|
|
278
|
+
? this.container.get<PermissionMode>("PermissionMode")
|
|
279
|
+
: undefined;
|
|
280
|
+
|
|
281
|
+
if (permissionManager) {
|
|
282
|
+
return permissionManager.getCurrentEffectiveMode(permissionMode);
|
|
284
283
|
}
|
|
285
|
-
return
|
|
284
|
+
return permissionMode || "default";
|
|
286
285
|
}
|
|
287
286
|
|
|
288
287
|
/**
|
|
@@ -290,14 +289,14 @@ class ToolManager {
|
|
|
290
289
|
* @param mode - The new permission mode
|
|
291
290
|
*/
|
|
292
291
|
public setPermissionMode(mode: PermissionMode): void {
|
|
293
|
-
this.
|
|
292
|
+
this.container.register("PermissionMode", mode);
|
|
294
293
|
}
|
|
295
294
|
|
|
296
295
|
/**
|
|
297
296
|
* Get the permission manager
|
|
298
297
|
*/
|
|
299
298
|
public getPermissionManager(): PermissionManager | undefined {
|
|
300
|
-
return this.
|
|
299
|
+
return this.container.get<PermissionManager>("PermissionManager");
|
|
301
300
|
}
|
|
302
301
|
|
|
303
302
|
/**
|
|
@@ -306,7 +305,9 @@ class ToolManager {
|
|
|
306
305
|
public getTaskManager():
|
|
307
306
|
| import("../services/taskManager.js").TaskManager
|
|
308
307
|
| undefined {
|
|
309
|
-
return this.taskManager
|
|
308
|
+
return this.container.get<import("../services/taskManager.js").TaskManager>(
|
|
309
|
+
"TaskManager",
|
|
310
|
+
);
|
|
310
311
|
}
|
|
311
312
|
}
|
|
312
313
|
|
package/src/prompts/index.ts
CHANGED
|
@@ -12,10 +12,6 @@ import {
|
|
|
12
12
|
GLOB_TOOL_NAME,
|
|
13
13
|
GREP_TOOL_NAME,
|
|
14
14
|
READ_TOOL_NAME,
|
|
15
|
-
TASK_CREATE_TOOL_NAME,
|
|
16
|
-
TASK_GET_TOOL_NAME,
|
|
17
|
-
TASK_UPDATE_TOOL_NAME,
|
|
18
|
-
TASK_LIST_TOOL_NAME,
|
|
19
15
|
WRITE_TOOL_NAME,
|
|
20
16
|
EXIT_PLAN_MODE_TOOL_NAME,
|
|
21
17
|
} from "../constants/tools.js";
|
|
@@ -38,12 +34,6 @@ export const TOOL_POLICY = `
|
|
|
38
34
|
- However, if some tool calls depend on previous calls to inform dependent values, do NOT call these tools in parallel and instead call them sequentially. For instance, if one operation must complete before another starts, run these operations sequentially instead. Never use placeholders or guess missing parameters in tool calls.
|
|
39
35
|
- If the user specifies that they want you to run tools "in parallel", you MUST send a single message with multiple tool use content blocks.`;
|
|
40
36
|
|
|
41
|
-
export const TASK_MANAGEMENT_POLICY = `
|
|
42
|
-
# Task Management
|
|
43
|
-
You have access to the ${TASK_CREATE_TOOL_NAME}, ${TASK_GET_TOOL_NAME}, ${TASK_UPDATE_TOOL_NAME}, and ${TASK_LIST_TOOL_NAME} tools to help you manage and plan tasks. Use these tools VERY frequently to ensure that you are tracking your tasks and giving the user visibility into your progress.
|
|
44
|
-
These tools are also EXTREMELY helpful for planning tasks, and for breaking down larger complex tasks into smaller steps. If you do not use this tool when planning, you may forget to do important tasks - and that is unacceptable.
|
|
45
|
-
It is critical that you mark tasks as completed as soon as you are done with a task. Do not batch up multiple tasks before marking them as completed.`;
|
|
46
|
-
|
|
47
37
|
export function buildPlanModePrompt(
|
|
48
38
|
planFilePath: string,
|
|
49
39
|
planExists: boolean,
|
|
@@ -171,7 +161,6 @@ export const EXPLORE_SUBAGENT_SYSTEM_PROMPT = `You are a file search specialist.
|
|
|
171
161
|
This is a READ-ONLY exploration task. You are STRICTLY PROHIBITED from:
|
|
172
162
|
- Creating new files (no Write, touch, or file creation of any kind)
|
|
173
163
|
- Modifying existing files (no Edit operations)
|
|
174
|
-
- Deleting files (no rm or deletion)
|
|
175
164
|
- Moving or copying files (no mv or cp)
|
|
176
165
|
- Creating temporary files anywhere, including /tmp
|
|
177
166
|
- Using redirect operators (>, >>, |) or heredocs to write to files
|
|
@@ -209,7 +198,6 @@ export const PLAN_SUBAGENT_SYSTEM_PROMPT = `You are a software architect and pla
|
|
|
209
198
|
This is a READ-ONLY planning task. You are STRICTLY PROHIBITED from:
|
|
210
199
|
- Creating new files (no Write, touch, or file creation of any kind)
|
|
211
200
|
- Modifying existing files (no Edit operations)
|
|
212
|
-
- Deleting files (no rm or deletion)
|
|
213
201
|
- Moving or copying files (no mv or cp)
|
|
214
202
|
- Creating temporary files anywhere, including /tmp
|
|
215
203
|
- Using redirect operators (>, >>, |) or heredocs to write to files
|
|
@@ -300,6 +288,9 @@ Any promises made to the user
|
|
|
300
288
|
Be concise but complete—err on the side of including information that would prevent duplicate work or repeated mistakes. Write in a way that enables immediate resumption of the task.
|
|
301
289
|
Wrap your summary in <summary></summary> tags.`;
|
|
302
290
|
|
|
291
|
+
import type { SubagentConfiguration } from "../utils/subagentParser.js";
|
|
292
|
+
import type { SkillMetadata } from "../types/skills.js";
|
|
293
|
+
|
|
303
294
|
export function buildSystemPrompt(
|
|
304
295
|
basePrompt: string | undefined,
|
|
305
296
|
tools: ToolPlugin[],
|
|
@@ -312,25 +303,22 @@ export function buildSystemPrompt(
|
|
|
312
303
|
planFilePath: string;
|
|
313
304
|
planExists: boolean;
|
|
314
305
|
};
|
|
306
|
+
availableSubagents?: SubagentConfiguration[];
|
|
307
|
+
availableSkills?: SkillMetadata[];
|
|
315
308
|
} = {},
|
|
316
309
|
): string {
|
|
317
310
|
let prompt = basePrompt || DEFAULT_SYSTEM_PROMPT;
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
if (
|
|
321
|
-
toolNames.has(TASK_CREATE_TOOL_NAME) ||
|
|
322
|
-
toolNames.has(TASK_GET_TOOL_NAME) ||
|
|
323
|
-
toolNames.has(TASK_UPDATE_TOOL_NAME) ||
|
|
324
|
-
toolNames.has(TASK_LIST_TOOL_NAME)
|
|
325
|
-
) {
|
|
326
|
-
prompt += TASK_MANAGEMENT_POLICY;
|
|
311
|
+
if (tools.length > 0) {
|
|
312
|
+
prompt += `\n\n${TOOL_POLICY}`;
|
|
327
313
|
}
|
|
328
314
|
|
|
329
|
-
prompt += `\n\n${TOOL_POLICY}`;
|
|
330
|
-
|
|
331
315
|
for (const tool of tools) {
|
|
332
316
|
if (tool.prompt) {
|
|
333
|
-
prompt += tool.prompt(
|
|
317
|
+
prompt += tool.prompt({
|
|
318
|
+
availableSubagents: options.availableSubagents,
|
|
319
|
+
availableSkills: options.availableSkills,
|
|
320
|
+
workdir: options.workdir,
|
|
321
|
+
});
|
|
334
322
|
}
|
|
335
323
|
}
|
|
336
324
|
|
|
@@ -80,6 +80,16 @@ export class MarketplaceService {
|
|
|
80
80
|
}
|
|
81
81
|
try {
|
|
82
82
|
const content = await fs.readFile(this.knownMarketplacesPath, "utf-8");
|
|
83
|
+
if (!content.trim()) {
|
|
84
|
+
return {
|
|
85
|
+
marketplaces: [
|
|
86
|
+
{
|
|
87
|
+
...MarketplaceService.BUILTIN_MARKETPLACE,
|
|
88
|
+
isBuiltin: true,
|
|
89
|
+
},
|
|
90
|
+
],
|
|
91
|
+
};
|
|
92
|
+
}
|
|
83
93
|
return JSON.parse(content);
|
|
84
94
|
} catch (error) {
|
|
85
95
|
console.error("Failed to load known marketplaces:", error);
|
|
@@ -96,6 +106,9 @@ export class MarketplaceService {
|
|
|
96
106
|
}
|
|
97
107
|
try {
|
|
98
108
|
const content = await fs.readFile(this.installedPluginsPath, "utf-8");
|
|
109
|
+
if (!content.trim()) {
|
|
110
|
+
return { plugins: [] };
|
|
111
|
+
}
|
|
99
112
|
return JSON.parse(content);
|
|
100
113
|
} catch (error) {
|
|
101
114
|
console.error("Failed to load installed plugins:", error);
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
} from "openai/resources.js";
|
|
9
9
|
import { OpenAIClient } from "../utils/openaiClient.js";
|
|
10
10
|
import { logger } from "../utils/globalLogger.js";
|
|
11
|
+
import { addOnceAbortListener } from "../utils/abortUtils.js";
|
|
11
12
|
import type { GatewayConfig, ModelConfig } from "../types/index.js";
|
|
12
13
|
import {
|
|
13
14
|
transformMessagesForClaudeCache,
|
|
@@ -69,13 +70,50 @@ interface ErrorData {
|
|
|
69
70
|
type OpenAIModelConfig = Omit<
|
|
70
71
|
ChatCompletionCreateParamsNonStreaming,
|
|
71
72
|
"messages"
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
73
|
+
>;
|
|
74
|
+
|
|
75
|
+
// Global rate limiter state for 1 QPS
|
|
76
|
+
let nextAllowedTime = 0;
|
|
77
|
+
const MIN_INTERVAL = 1000; // 1 second for 1 QPS
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Resets the rate limiter state. Primarily used for testing.
|
|
81
|
+
*/
|
|
82
|
+
export function resetRateLimiter(): void {
|
|
83
|
+
nextAllowedTime = 0;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Acquires a slot for an AI request, ensuring 1 QPS limit.
|
|
88
|
+
* @param abortSignal Optional abort signal to cancel waiting
|
|
89
|
+
*/
|
|
90
|
+
async function acquireSlot(abortSignal?: AbortSignal): Promise<void> {
|
|
91
|
+
if (abortSignal?.aborted) {
|
|
92
|
+
throw new Error("Request was aborted");
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const now = Date.now();
|
|
96
|
+
const waitTime = Math.max(0, nextAllowedTime - now);
|
|
97
|
+
|
|
98
|
+
// Reserve the slot synchronously to ensure global ordering
|
|
99
|
+
nextAllowedTime = Math.max(now, nextAllowedTime) + MIN_INTERVAL;
|
|
100
|
+
|
|
101
|
+
if (waitTime > 0) {
|
|
102
|
+
await new Promise<void>((resolve, reject) => {
|
|
103
|
+
const timeout = setTimeout(() => {
|
|
104
|
+
cleanup();
|
|
105
|
+
resolve();
|
|
106
|
+
}, waitTime);
|
|
107
|
+
|
|
108
|
+
const cleanup = abortSignal
|
|
109
|
+
? addOnceAbortListener(abortSignal, () => {
|
|
110
|
+
clearTimeout(timeout);
|
|
111
|
+
reject(new Error("Request was aborted"));
|
|
112
|
+
})
|
|
113
|
+
: () => {};
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
}
|
|
79
117
|
|
|
80
118
|
/**
|
|
81
119
|
* Get specific configuration parameters based on model name
|
|
@@ -99,14 +137,6 @@ function getModelConfig(
|
|
|
99
137
|
config.temperature = undefined;
|
|
100
138
|
}
|
|
101
139
|
|
|
102
|
-
if (modelName.startsWith("gemini-3-flash")) {
|
|
103
|
-
config.vertexai = {
|
|
104
|
-
thinking_config: {
|
|
105
|
-
thinking_level: "minimal",
|
|
106
|
-
},
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
|
|
110
140
|
return config;
|
|
111
141
|
}
|
|
112
142
|
|
|
@@ -170,6 +200,14 @@ export async function callAgent(
|
|
|
170
200
|
onReasoningUpdate,
|
|
171
201
|
} = options;
|
|
172
202
|
|
|
203
|
+
// Apply global 1 QPS rate limit
|
|
204
|
+
if (
|
|
205
|
+
process.env.NODE_ENV !== "test" ||
|
|
206
|
+
modelConfig.agentModel === "rate-limit-test"
|
|
207
|
+
) {
|
|
208
|
+
await acquireSlot(abortSignal);
|
|
209
|
+
}
|
|
210
|
+
|
|
173
211
|
// Declare variables outside try block for error handling access
|
|
174
212
|
let openaiMessages: ChatCompletionMessageParam[] | undefined;
|
|
175
213
|
let createParams:
|
|
@@ -719,6 +757,14 @@ export async function compressMessages(
|
|
|
719
757
|
): Promise<CompressMessagesResult> {
|
|
720
758
|
const { gatewayConfig, modelConfig, messages, abortSignal } = options;
|
|
721
759
|
|
|
760
|
+
// Apply global 1 QPS rate limit
|
|
761
|
+
if (
|
|
762
|
+
process.env.NODE_ENV !== "test" ||
|
|
763
|
+
modelConfig.agentModel === "rate-limit-test"
|
|
764
|
+
) {
|
|
765
|
+
await acquireSlot(abortSignal);
|
|
766
|
+
}
|
|
767
|
+
|
|
722
768
|
// Create OpenAI client with injected configuration
|
|
723
769
|
const openai = new OpenAIClient({
|
|
724
770
|
apiKey: gatewayConfig.apiKey,
|
|
@@ -374,7 +374,7 @@ export class ConfigurationService {
|
|
|
374
374
|
if (apiKey !== undefined) {
|
|
375
375
|
resolvedApiKey = apiKey;
|
|
376
376
|
} else {
|
|
377
|
-
resolvedApiKey = this.env.WAVE_API_KEY
|
|
377
|
+
resolvedApiKey = this.env.WAVE_API_KEY;
|
|
378
378
|
}
|
|
379
379
|
|
|
380
380
|
// Resolve base URL: constructor > env (settings.json) > process.env
|
|
@@ -383,8 +383,25 @@ export class ConfigurationService {
|
|
|
383
383
|
if (baseURL !== undefined) {
|
|
384
384
|
resolvedBaseURL = baseURL;
|
|
385
385
|
} else {
|
|
386
|
-
resolvedBaseURL =
|
|
387
|
-
|
|
386
|
+
resolvedBaseURL = this.env.WAVE_BASE_URL || "";
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// If we have a parent configuration, use it as a fallback for API key and base URL
|
|
390
|
+
if (this.currentConfiguration?.env) {
|
|
391
|
+
if (resolvedApiKey === undefined) {
|
|
392
|
+
resolvedApiKey = this.currentConfiguration.env.WAVE_API_KEY;
|
|
393
|
+
}
|
|
394
|
+
if (!resolvedBaseURL) {
|
|
395
|
+
resolvedBaseURL = this.currentConfiguration.env.WAVE_BASE_URL || "";
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// Fallback to process.env if still not resolved (for dynamic updates in tests)
|
|
400
|
+
if (resolvedApiKey === undefined) {
|
|
401
|
+
resolvedApiKey = process.env.WAVE_API_KEY;
|
|
402
|
+
}
|
|
403
|
+
if (!resolvedBaseURL) {
|
|
404
|
+
resolvedBaseURL = process.env.WAVE_BASE_URL || "";
|
|
388
405
|
}
|
|
389
406
|
|
|
390
407
|
if (!resolvedBaseURL && baseURL === undefined) {
|
|
@@ -443,18 +460,22 @@ export class ConfigurationService {
|
|
|
443
460
|
const DEFAULT_FAST_MODEL = "gemini-2.5-flash";
|
|
444
461
|
|
|
445
462
|
// Resolve agent model: constructor > env (settings.json) > process.env > default
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
463
|
+
let resolvedAgentModel = agentModel || this.env.WAVE_MODEL;
|
|
464
|
+
|
|
465
|
+
if (!resolvedAgentModel && this.currentConfiguration?.env?.WAVE_MODEL) {
|
|
466
|
+
resolvedAgentModel = this.currentConfiguration.env.WAVE_MODEL;
|
|
467
|
+
}
|
|
468
|
+
resolvedAgentModel =
|
|
469
|
+
resolvedAgentModel || process.env.WAVE_MODEL || DEFAULT_AGENT_MODEL;
|
|
451
470
|
|
|
452
471
|
// Resolve fast model: constructor > env (settings.json) > process.env > default
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
472
|
+
let resolvedFastModel = fastModel || this.env.WAVE_FAST_MODEL;
|
|
473
|
+
|
|
474
|
+
if (!resolvedFastModel && this.currentConfiguration?.env?.WAVE_FAST_MODEL) {
|
|
475
|
+
resolvedFastModel = this.currentConfiguration.env.WAVE_FAST_MODEL;
|
|
476
|
+
}
|
|
477
|
+
resolvedFastModel =
|
|
478
|
+
resolvedFastModel || process.env.WAVE_FAST_MODEL || DEFAULT_FAST_MODEL;
|
|
458
479
|
|
|
459
480
|
// Resolve max output tokens
|
|
460
481
|
const resolvedMaxTokens = this.resolveMaxOutputTokens(maxTokens);
|
|
@@ -4,12 +4,16 @@ import { homedir } from "os";
|
|
|
4
4
|
import { EventEmitter } from "events";
|
|
5
5
|
import { Task } from "../types/tasks.js";
|
|
6
6
|
import { logger } from "../utils/globalLogger.js";
|
|
7
|
+
import { Container } from "../utils/container.js";
|
|
7
8
|
|
|
8
9
|
export class TaskManager extends EventEmitter {
|
|
9
10
|
private readonly baseDir: string;
|
|
10
11
|
private taskListId: string;
|
|
11
12
|
|
|
12
|
-
constructor(
|
|
13
|
+
constructor(
|
|
14
|
+
private container: Container,
|
|
15
|
+
taskListId: string,
|
|
16
|
+
) {
|
|
13
17
|
super();
|
|
14
18
|
this.taskListId = taskListId;
|
|
15
19
|
this.baseDir = join(homedir(), ".wave", "tasks");
|
package/src/tools/bashTool.ts
CHANGED
|
@@ -306,7 +306,7 @@ Usage notes:
|
|
|
306
306
|
}
|
|
307
307
|
|
|
308
308
|
child.stdout?.on("data", (data) => {
|
|
309
|
-
if (!isAborted && !isBackgrounded) {
|
|
309
|
+
if (!isAborted && !isBackgrounded && !runInBackground) {
|
|
310
310
|
const chunk = stripAnsiColors(data.toString());
|
|
311
311
|
outputBuffer += chunk;
|
|
312
312
|
context.onShortResultUpdate?.(chunk.trim().split("\n").pop() || "");
|
|
@@ -314,7 +314,7 @@ Usage notes:
|
|
|
314
314
|
});
|
|
315
315
|
|
|
316
316
|
child.stderr?.on("data", (data) => {
|
|
317
|
-
if (!isAborted && !isBackgrounded) {
|
|
317
|
+
if (!isAborted && !isBackgrounded && !runInBackground) {
|
|
318
318
|
const chunk = stripAnsiColors(data.toString());
|
|
319
319
|
errorBuffer += chunk;
|
|
320
320
|
context.onShortResultUpdate?.(chunk.trim().split("\n").pop() || "");
|