wave-agent-sdk 0.0.7 → 0.0.10
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 +105 -24
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +438 -53
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/managers/aiManager.d.ts +18 -7
- package/dist/managers/aiManager.d.ts.map +1 -1
- package/dist/managers/aiManager.js +254 -142
- package/dist/managers/backgroundBashManager.d.ts.map +1 -1
- package/dist/managers/backgroundBashManager.js +11 -9
- package/dist/managers/hookManager.d.ts +6 -6
- package/dist/managers/hookManager.d.ts.map +1 -1
- package/dist/managers/hookManager.js +81 -39
- package/dist/managers/liveConfigManager.d.ts +95 -0
- package/dist/managers/liveConfigManager.d.ts.map +1 -0
- package/dist/managers/liveConfigManager.js +442 -0
- package/dist/managers/lspManager.d.ts +43 -0
- package/dist/managers/lspManager.d.ts.map +1 -0
- package/dist/managers/lspManager.js +326 -0
- package/dist/managers/messageManager.d.ts +41 -24
- package/dist/managers/messageManager.d.ts.map +1 -1
- package/dist/managers/messageManager.js +184 -73
- package/dist/managers/permissionManager.d.ts +66 -0
- package/dist/managers/permissionManager.d.ts.map +1 -0
- package/dist/managers/permissionManager.js +208 -0
- package/dist/managers/skillManager.d.ts +1 -0
- package/dist/managers/skillManager.d.ts.map +1 -1
- package/dist/managers/skillManager.js +2 -1
- package/dist/managers/slashCommandManager.d.ts.map +1 -1
- package/dist/managers/slashCommandManager.js +4 -2
- package/dist/managers/subagentManager.d.ts +42 -6
- package/dist/managers/subagentManager.d.ts.map +1 -1
- package/dist/managers/subagentManager.js +213 -62
- package/dist/managers/toolManager.d.ts +38 -1
- package/dist/managers/toolManager.d.ts.map +1 -1
- package/dist/managers/toolManager.js +66 -2
- package/dist/services/aiService.d.ts +15 -5
- package/dist/services/aiService.d.ts.map +1 -1
- package/dist/services/aiService.js +446 -77
- package/dist/services/configurationService.d.ts +116 -0
- package/dist/services/configurationService.d.ts.map +1 -0
- package/dist/services/configurationService.js +585 -0
- package/dist/services/fileWatcher.d.ts +69 -0
- package/dist/services/fileWatcher.d.ts.map +1 -0
- package/dist/services/fileWatcher.js +212 -0
- package/dist/services/hook.d.ts +5 -40
- package/dist/services/hook.d.ts.map +1 -1
- package/dist/services/hook.js +47 -109
- package/dist/services/jsonlHandler.d.ts +71 -0
- package/dist/services/jsonlHandler.d.ts.map +1 -0
- package/dist/services/jsonlHandler.js +236 -0
- package/dist/services/memory.d.ts.map +1 -1
- package/dist/services/memory.js +33 -11
- package/dist/services/session.d.ts +116 -52
- package/dist/services/session.d.ts.map +1 -1
- package/dist/services/session.js +415 -143
- package/dist/tools/bashTool.d.ts.map +1 -1
- package/dist/tools/bashTool.js +77 -17
- package/dist/tools/deleteFileTool.d.ts.map +1 -1
- package/dist/tools/deleteFileTool.js +27 -1
- package/dist/tools/editTool.d.ts.map +1 -1
- package/dist/tools/editTool.js +33 -8
- package/dist/tools/lspTool.d.ts +6 -0
- package/dist/tools/lspTool.d.ts.map +1 -0
- package/dist/tools/lspTool.js +589 -0
- package/dist/tools/multiEditTool.d.ts.map +1 -1
- package/dist/tools/multiEditTool.js +30 -10
- package/dist/tools/readTool.d.ts.map +1 -1
- package/dist/tools/readTool.js +113 -3
- package/dist/tools/skillTool.js +2 -2
- package/dist/tools/todoWriteTool.d.ts.map +1 -1
- package/dist/tools/todoWriteTool.js +23 -0
- package/dist/tools/types.d.ts +11 -8
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/writeTool.d.ts.map +1 -1
- package/dist/tools/writeTool.js +30 -15
- package/dist/types/commands.d.ts +4 -1
- package/dist/types/commands.d.ts.map +1 -1
- package/dist/types/config.d.ts +4 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/configuration.d.ts +69 -0
- package/dist/types/configuration.d.ts.map +1 -0
- package/dist/types/configuration.js +8 -0
- package/dist/types/core.d.ts +45 -0
- package/dist/types/core.d.ts.map +1 -1
- package/dist/types/environment.d.ts +83 -0
- package/dist/types/environment.d.ts.map +1 -0
- package/dist/types/environment.js +21 -0
- package/dist/types/fileSearch.d.ts +5 -0
- package/dist/types/fileSearch.d.ts.map +1 -0
- package/dist/types/fileSearch.js +1 -0
- package/dist/types/hooks.d.ts +18 -3
- package/dist/types/hooks.d.ts.map +1 -1
- package/dist/types/hooks.js +8 -8
- package/dist/types/index.d.ts +7 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +7 -0
- package/dist/types/lsp.d.ts +90 -0
- package/dist/types/lsp.d.ts.map +1 -0
- package/dist/types/lsp.js +4 -0
- package/dist/types/messaging.d.ts +19 -12
- package/dist/types/messaging.d.ts.map +1 -1
- package/dist/types/permissions.d.ts +35 -0
- package/dist/types/permissions.d.ts.map +1 -0
- package/dist/types/permissions.js +12 -0
- package/dist/types/session.d.ts +15 -0
- package/dist/types/session.d.ts.map +1 -0
- package/dist/types/session.js +7 -0
- package/dist/types/skills.d.ts +1 -0
- package/dist/types/skills.d.ts.map +1 -1
- package/dist/types/tools.d.ts +35 -0
- package/dist/types/tools.d.ts.map +1 -0
- package/dist/types/tools.js +4 -0
- package/dist/utils/abortUtils.d.ts +34 -0
- package/dist/utils/abortUtils.d.ts.map +1 -0
- package/dist/utils/abortUtils.js +92 -0
- package/dist/utils/bashHistory.d.ts +4 -0
- package/dist/utils/bashHistory.d.ts.map +1 -1
- package/dist/utils/bashHistory.js +48 -30
- package/dist/utils/builtinSubagents.d.ts +7 -0
- package/dist/utils/builtinSubagents.d.ts.map +1 -0
- package/dist/utils/builtinSubagents.js +65 -0
- package/dist/utils/cacheControlUtils.d.ts +96 -0
- package/dist/utils/cacheControlUtils.d.ts.map +1 -0
- package/dist/utils/cacheControlUtils.js +324 -0
- package/dist/utils/commandPathResolver.d.ts +52 -0
- package/dist/utils/commandPathResolver.d.ts.map +1 -0
- package/dist/utils/commandPathResolver.js +145 -0
- package/dist/utils/configPaths.d.ts +85 -0
- package/dist/utils/configPaths.d.ts.map +1 -0
- package/dist/utils/configPaths.js +121 -0
- package/dist/utils/constants.d.ts +1 -13
- package/dist/utils/constants.d.ts.map +1 -1
- package/dist/utils/constants.js +2 -14
- package/dist/utils/convertMessagesForAPI.d.ts +2 -1
- package/dist/utils/convertMessagesForAPI.d.ts.map +1 -1
- package/dist/utils/convertMessagesForAPI.js +39 -18
- package/dist/utils/customCommands.d.ts.map +1 -1
- package/dist/utils/customCommands.js +66 -21
- package/dist/utils/fileSearch.d.ts +14 -0
- package/dist/utils/fileSearch.d.ts.map +1 -0
- package/dist/utils/fileSearch.js +88 -0
- package/dist/utils/fileUtils.d.ts +27 -0
- package/dist/utils/fileUtils.d.ts.map +1 -0
- package/dist/utils/fileUtils.js +145 -0
- package/dist/utils/globalLogger.d.ts +88 -0
- package/dist/utils/globalLogger.d.ts.map +1 -0
- package/dist/utils/globalLogger.js +120 -0
- package/dist/utils/largeOutputHandler.d.ts +15 -0
- package/dist/utils/largeOutputHandler.d.ts.map +1 -0
- package/dist/utils/largeOutputHandler.js +40 -0
- package/dist/utils/markdownParser.d.ts.map +1 -1
- package/dist/utils/markdownParser.js +1 -17
- package/dist/utils/mcpUtils.d.ts.map +1 -1
- package/dist/utils/mcpUtils.js +25 -3
- package/dist/utils/messageOperations.d.ts +20 -18
- package/dist/utils/messageOperations.d.ts.map +1 -1
- package/dist/utils/messageOperations.js +30 -38
- package/dist/utils/pathEncoder.d.ts +108 -0
- package/dist/utils/pathEncoder.d.ts.map +1 -0
- package/dist/utils/pathEncoder.js +279 -0
- package/dist/utils/subagentParser.d.ts +2 -2
- package/dist/utils/subagentParser.d.ts.map +1 -1
- package/dist/utils/subagentParser.js +12 -8
- package/dist/utils/tokenCalculation.d.ts +26 -0
- package/dist/utils/tokenCalculation.d.ts.map +1 -0
- package/dist/utils/tokenCalculation.js +36 -0
- package/dist/utils/tokenEstimator.d.ts +39 -0
- package/dist/utils/tokenEstimator.d.ts.map +1 -0
- package/dist/utils/tokenEstimator.js +55 -0
- package/package.json +6 -6
- package/src/agent.ts +586 -78
- package/src/index.ts +4 -0
- package/src/managers/aiManager.ts +341 -192
- package/src/managers/backgroundBashManager.ts +11 -9
- package/src/managers/hookManager.ts +102 -54
- package/src/managers/liveConfigManager.ts +634 -0
- package/src/managers/lspManager.ts +434 -0
- package/src/managers/messageManager.ts +258 -121
- package/src/managers/permissionManager.ts +276 -0
- package/src/managers/skillManager.ts +3 -1
- package/src/managers/slashCommandManager.ts +5 -3
- package/src/managers/subagentManager.ts +295 -76
- package/src/managers/toolManager.ts +95 -3
- package/src/services/aiService.ts +656 -84
- package/src/services/configurationService.ts +762 -0
- package/src/services/fileWatcher.ts +300 -0
- package/src/services/hook.ts +54 -144
- package/src/services/jsonlHandler.ts +303 -0
- package/src/services/memory.ts +34 -11
- package/src/services/session.ts +522 -173
- package/src/tools/bashTool.ts +94 -20
- package/src/tools/deleteFileTool.ts +38 -1
- package/src/tools/editTool.ts +44 -9
- package/src/tools/lspTool.ts +760 -0
- package/src/tools/multiEditTool.ts +41 -11
- package/src/tools/readTool.ts +127 -3
- package/src/tools/skillTool.ts +2 -2
- package/src/tools/todoWriteTool.ts +33 -1
- package/src/tools/types.ts +15 -9
- package/src/tools/writeTool.ts +43 -16
- package/src/types/commands.ts +6 -1
- package/src/types/config.ts +5 -0
- package/src/types/configuration.ts +73 -0
- package/src/types/core.ts +55 -0
- package/src/types/environment.ts +104 -0
- package/src/types/fileSearch.ts +4 -0
- package/src/types/hooks.ts +32 -16
- package/src/types/index.ts +7 -0
- package/src/types/lsp.ts +96 -0
- package/src/types/messaging.ts +21 -14
- package/src/types/permissions.ts +48 -0
- package/src/types/session.ts +20 -0
- package/src/types/skills.ts +1 -0
- package/src/types/tools.ts +38 -0
- package/src/utils/abortUtils.ts +118 -0
- package/src/utils/bashHistory.ts +55 -31
- package/src/utils/builtinSubagents.ts +71 -0
- package/src/utils/cacheControlUtils.ts +475 -0
- package/src/utils/commandPathResolver.ts +189 -0
- package/src/utils/configPaths.ts +163 -0
- package/src/utils/constants.ts +2 -17
- package/src/utils/convertMessagesForAPI.ts +44 -18
- package/src/utils/customCommands.ts +90 -22
- package/src/utils/fileSearch.ts +107 -0
- package/src/utils/fileUtils.ts +160 -0
- package/src/utils/globalLogger.ts +128 -0
- package/src/utils/largeOutputHandler.ts +55 -0
- package/src/utils/markdownParser.ts +1 -19
- package/src/utils/mcpUtils.ts +34 -3
- package/src/utils/messageOperations.ts +47 -53
- package/src/utils/pathEncoder.ts +394 -0
- package/src/utils/subagentParser.ts +13 -9
- package/src/utils/tokenCalculation.ts +43 -0
- package/src/utils/tokenEstimator.ts +68 -0
- package/dist/utils/configResolver.d.ts +0 -38
- package/dist/utils/configResolver.d.ts.map +0 -1
- package/dist/utils/configResolver.js +0 -106
- package/src/utils/configResolver.ts +0 -142
|
@@ -7,12 +7,49 @@ import type {
|
|
|
7
7
|
ModelConfig,
|
|
8
8
|
Usage,
|
|
9
9
|
} from "../types/index.js";
|
|
10
|
+
import type { SessionData } from "../services/session.js";
|
|
10
11
|
import { AIManager } from "./aiManager.js";
|
|
11
|
-
import {
|
|
12
|
-
MessageManager,
|
|
13
|
-
type MessageManagerCallbacks,
|
|
14
|
-
} from "./messageManager.js";
|
|
12
|
+
import { MessageManager } from "./messageManager.js";
|
|
15
13
|
import { ToolManager } from "./toolManager.js";
|
|
14
|
+
import { HookManager } from "./hookManager.js";
|
|
15
|
+
import {
|
|
16
|
+
UserMessageParams,
|
|
17
|
+
type AgentToolBlockUpdateParams,
|
|
18
|
+
} from "../utils/messageOperations.js";
|
|
19
|
+
import {
|
|
20
|
+
addConsolidatedAbortListener,
|
|
21
|
+
createAbortPromise,
|
|
22
|
+
} from "../utils/abortUtils.js";
|
|
23
|
+
|
|
24
|
+
export interface SubagentManagerCallbacks {
|
|
25
|
+
// Granular subagent message callbacks (015-subagent-message-callbacks)
|
|
26
|
+
/** Triggered when subagent adds user message */
|
|
27
|
+
onSubagentUserMessageAdded?: (
|
|
28
|
+
subagentId: string,
|
|
29
|
+
params: UserMessageParams,
|
|
30
|
+
) => void;
|
|
31
|
+
/** Triggered when subagent creates assistant message */
|
|
32
|
+
onSubagentAssistantMessageAdded?: (subagentId: string) => void;
|
|
33
|
+
/** Triggered during subagent content streaming updates */
|
|
34
|
+
onSubagentAssistantContentUpdated?: (
|
|
35
|
+
subagentId: string,
|
|
36
|
+
chunk: string,
|
|
37
|
+
accumulated: string,
|
|
38
|
+
) => void;
|
|
39
|
+
/** Triggered during subagent reasoning streaming updates */
|
|
40
|
+
onSubagentAssistantReasoningUpdated?: (
|
|
41
|
+
subagentId: string,
|
|
42
|
+
chunk: string,
|
|
43
|
+
accumulated: string,
|
|
44
|
+
) => void;
|
|
45
|
+
/** Triggered when subagent tool block is updated */
|
|
46
|
+
onSubagentToolBlockUpdated?: (
|
|
47
|
+
subagentId: string,
|
|
48
|
+
params: AgentToolBlockUpdateParams,
|
|
49
|
+
) => void;
|
|
50
|
+
/** Triggered when subagent messages change */
|
|
51
|
+
onSubagentMessagesChange?: (subagentId: string, messages: Message[]) => void;
|
|
52
|
+
}
|
|
16
53
|
|
|
17
54
|
export interface SubagentInstance {
|
|
18
55
|
subagentId: string;
|
|
@@ -22,16 +59,19 @@ export interface SubagentInstance {
|
|
|
22
59
|
toolManager: ToolManager;
|
|
23
60
|
status: "initializing" | "active" | "completed" | "error" | "aborted";
|
|
24
61
|
messages: Message[];
|
|
62
|
+
subagentType: string; // Store the subagent type for hook context
|
|
25
63
|
}
|
|
26
64
|
|
|
27
65
|
export interface SubagentManagerOptions {
|
|
28
66
|
workdir: string;
|
|
29
67
|
parentToolManager: ToolManager;
|
|
30
68
|
parentMessageManager: MessageManager;
|
|
69
|
+
callbacks?: SubagentManagerCallbacks; // Use SubagentManagerCallbacks instead of parentCallbacks
|
|
31
70
|
logger?: Logger;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
71
|
+
getGatewayConfig: () => GatewayConfig;
|
|
72
|
+
getModelConfig: () => ModelConfig;
|
|
73
|
+
getTokenLimit: () => number;
|
|
74
|
+
hookManager?: HookManager;
|
|
35
75
|
onUsageAdded?: (usage: Usage) => void;
|
|
36
76
|
}
|
|
37
77
|
|
|
@@ -42,20 +82,24 @@ export class SubagentManager {
|
|
|
42
82
|
private workdir: string;
|
|
43
83
|
private parentToolManager: ToolManager;
|
|
44
84
|
private parentMessageManager: MessageManager;
|
|
85
|
+
private callbacks?: SubagentManagerCallbacks; // Use SubagentManagerCallbacks instead of parentCallbacks
|
|
45
86
|
private logger?: Logger;
|
|
46
|
-
private
|
|
47
|
-
private
|
|
48
|
-
private
|
|
87
|
+
private getGatewayConfig: () => GatewayConfig;
|
|
88
|
+
private getModelConfig: () => ModelConfig;
|
|
89
|
+
private getTokenLimit: () => number;
|
|
90
|
+
private hookManager?: HookManager;
|
|
49
91
|
private onUsageAdded?: (usage: Usage) => void;
|
|
50
92
|
|
|
51
93
|
constructor(options: SubagentManagerOptions) {
|
|
52
94
|
this.workdir = options.workdir;
|
|
53
95
|
this.parentToolManager = options.parentToolManager;
|
|
54
96
|
this.parentMessageManager = options.parentMessageManager;
|
|
97
|
+
this.callbacks = options.callbacks; // Store SubagentManagerCallbacks
|
|
55
98
|
this.logger = options.logger;
|
|
56
|
-
this.
|
|
57
|
-
this.
|
|
58
|
-
this.
|
|
99
|
+
this.getGatewayConfig = options.getGatewayConfig;
|
|
100
|
+
this.getModelConfig = options.getModelConfig;
|
|
101
|
+
this.getTokenLimit = options.getTokenLimit;
|
|
102
|
+
this.hookManager = options.hookManager;
|
|
59
103
|
this.onUsageAdded = options.onUsageAdded;
|
|
60
104
|
}
|
|
61
105
|
|
|
@@ -112,12 +156,7 @@ export class SubagentManager {
|
|
|
112
156
|
subagent_type: string;
|
|
113
157
|
},
|
|
114
158
|
): Promise<SubagentInstance> {
|
|
115
|
-
if (
|
|
116
|
-
!this.parentToolManager ||
|
|
117
|
-
!this.gatewayConfig ||
|
|
118
|
-
!this.modelConfig ||
|
|
119
|
-
!this.tokenLimit
|
|
120
|
-
) {
|
|
159
|
+
if (!this.parentToolManager) {
|
|
121
160
|
throw new Error(
|
|
122
161
|
"SubagentManager not properly initialized - call initialize() first",
|
|
123
162
|
);
|
|
@@ -126,35 +165,19 @@ export class SubagentManager {
|
|
|
126
165
|
const subagentId = randomUUID();
|
|
127
166
|
|
|
128
167
|
// Create isolated MessageManager for the subagent
|
|
129
|
-
const subagentCallbacks
|
|
130
|
-
// These callbacks will be handled by the parent agent
|
|
131
|
-
onMessagesChange: (messages: Message[]) => {
|
|
132
|
-
const instance = this.instances.get(subagentId);
|
|
133
|
-
if (instance) {
|
|
134
|
-
instance.messages = messages;
|
|
135
|
-
// Update parent's subagent block with latest messages
|
|
136
|
-
this.parentMessageManager.updateSubagentBlock(subagentId, {
|
|
137
|
-
messages: messages,
|
|
138
|
-
});
|
|
139
|
-
}
|
|
140
|
-
},
|
|
141
|
-
};
|
|
168
|
+
const subagentCallbacks = this.createSubagentCallbacks(subagentId);
|
|
142
169
|
|
|
143
170
|
const messageManager = new MessageManager({
|
|
144
171
|
callbacks: subagentCallbacks,
|
|
145
172
|
workdir: this.workdir,
|
|
146
173
|
logger: this.logger,
|
|
174
|
+
sessionType: "subagent",
|
|
175
|
+
subagentType: parameters.subagent_type,
|
|
147
176
|
});
|
|
148
177
|
|
|
149
178
|
// Use the parent tool manager directly - tool restrictions will be handled by allowedTools parameter
|
|
150
179
|
const toolManager = this.parentToolManager;
|
|
151
180
|
|
|
152
|
-
// Determine model to use
|
|
153
|
-
const modelToUse =
|
|
154
|
-
configuration.model && configuration.model !== "inherit"
|
|
155
|
-
? configuration.model
|
|
156
|
-
: this.modelConfig.agentModel;
|
|
157
|
-
|
|
158
181
|
// Create isolated AIManager for the subagent
|
|
159
182
|
const aiManager = new AIManager({
|
|
160
183
|
messageManager,
|
|
@@ -162,12 +185,31 @@ export class SubagentManager {
|
|
|
162
185
|
logger: this.logger,
|
|
163
186
|
workdir: this.workdir,
|
|
164
187
|
systemPrompt: configuration.systemPrompt,
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
188
|
+
subagentType: parameters.subagent_type, // Pass subagent type for hook context
|
|
189
|
+
hookManager: this.hookManager,
|
|
190
|
+
getGatewayConfig: this.getGatewayConfig,
|
|
191
|
+
getModelConfig: () => {
|
|
192
|
+
// Determine model dynamically each time
|
|
193
|
+
const parentModelConfig = this.getModelConfig();
|
|
194
|
+
let modelToUse: string;
|
|
195
|
+
|
|
196
|
+
if (!configuration.model || configuration.model === "inherit") {
|
|
197
|
+
// Use parent's agentModel for "inherit" or undefined
|
|
198
|
+
modelToUse = parentModelConfig.agentModel;
|
|
199
|
+
} else if (configuration.model === "fastModel") {
|
|
200
|
+
// Use parent's fastModel for special "fastModel" value
|
|
201
|
+
modelToUse = parentModelConfig.fastModel;
|
|
202
|
+
} else {
|
|
203
|
+
// Use specific model name
|
|
204
|
+
modelToUse = configuration.model;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return {
|
|
208
|
+
...parentModelConfig,
|
|
209
|
+
agentModel: modelToUse,
|
|
210
|
+
};
|
|
169
211
|
},
|
|
170
|
-
|
|
212
|
+
getTokenLimit: this.getTokenLimit,
|
|
171
213
|
callbacks: {
|
|
172
214
|
onUsageAdded: this.onUsageAdded,
|
|
173
215
|
},
|
|
@@ -181,6 +223,7 @@ export class SubagentManager {
|
|
|
181
223
|
toolManager,
|
|
182
224
|
status: "initializing",
|
|
183
225
|
messages: [],
|
|
226
|
+
subagentType: parameters.subagent_type, // Store the subagent type
|
|
184
227
|
};
|
|
185
228
|
|
|
186
229
|
this.instances.set(subagentId, instance);
|
|
@@ -189,8 +232,9 @@ export class SubagentManager {
|
|
|
189
232
|
this.parentMessageManager.addSubagentBlock(
|
|
190
233
|
subagentId,
|
|
191
234
|
configuration.name,
|
|
235
|
+
messageManager.getSessionId(),
|
|
236
|
+
configuration,
|
|
192
237
|
"active",
|
|
193
|
-
[],
|
|
194
238
|
parameters,
|
|
195
239
|
);
|
|
196
240
|
|
|
@@ -220,15 +264,22 @@ export class SubagentManager {
|
|
|
220
264
|
status: "active",
|
|
221
265
|
});
|
|
222
266
|
|
|
223
|
-
// Set up abort handler
|
|
267
|
+
// Set up consolidated abort handler to prevent listener accumulation
|
|
268
|
+
let abortCleanup: (() => void) | undefined;
|
|
224
269
|
if (abortSignal) {
|
|
225
|
-
abortSignal
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
270
|
+
abortCleanup = addConsolidatedAbortListener(abortSignal, [
|
|
271
|
+
() => {
|
|
272
|
+
// Update status to aborted
|
|
273
|
+
this.updateInstanceStatus(instance.subagentId, "aborted");
|
|
274
|
+
this.parentMessageManager.updateSubagentBlock(instance.subagentId, {
|
|
275
|
+
status: "aborted",
|
|
276
|
+
});
|
|
277
|
+
},
|
|
278
|
+
() => {
|
|
279
|
+
// Abort the AI execution
|
|
280
|
+
instance.aiManager.abortAIMessage();
|
|
281
|
+
},
|
|
282
|
+
]);
|
|
232
283
|
}
|
|
233
284
|
|
|
234
285
|
// Add the user's prompt as a message
|
|
@@ -248,32 +299,43 @@ export class SubagentManager {
|
|
|
248
299
|
|
|
249
300
|
// Execute the AI request with tool restrictions
|
|
250
301
|
// The AIManager will handle abort signals through its own abort controllers
|
|
251
|
-
//
|
|
302
|
+
// Resolve model name for sendAIMessage
|
|
303
|
+
let resolvedModel: string | undefined;
|
|
304
|
+
if (
|
|
305
|
+
instance.configuration.model &&
|
|
306
|
+
instance.configuration.model !== "inherit"
|
|
307
|
+
) {
|
|
308
|
+
if (instance.configuration.model === "fastModel") {
|
|
309
|
+
// Use parent's fastModel for special "fastModel" value
|
|
310
|
+
const parentModelConfig = this.getModelConfig();
|
|
311
|
+
resolvedModel = parentModelConfig.fastModel;
|
|
312
|
+
} else {
|
|
313
|
+
// Use specific model name
|
|
314
|
+
resolvedModel = instance.configuration.model;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
// For "inherit" or undefined, resolvedModel remains undefined (uses AIManager default)
|
|
318
|
+
|
|
252
319
|
const executeAI = instance.aiManager.sendAIMessage({
|
|
253
320
|
allowedTools,
|
|
254
|
-
model:
|
|
255
|
-
instance.configuration.model !== "inherit"
|
|
256
|
-
? instance.configuration.model
|
|
257
|
-
: undefined,
|
|
321
|
+
model: resolvedModel,
|
|
258
322
|
});
|
|
259
323
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
} else {
|
|
276
|
-
await executeAI;
|
|
324
|
+
try {
|
|
325
|
+
// If we have an abort signal, race against it using utilities to prevent listener accumulation
|
|
326
|
+
if (abortSignal) {
|
|
327
|
+
await Promise.race([
|
|
328
|
+
executeAI,
|
|
329
|
+
createAbortPromise(abortSignal, "Task was aborted"),
|
|
330
|
+
]);
|
|
331
|
+
} else {
|
|
332
|
+
await executeAI;
|
|
333
|
+
}
|
|
334
|
+
} finally {
|
|
335
|
+
// Clean up abort listeners to prevent memory leaks
|
|
336
|
+
if (abortCleanup) {
|
|
337
|
+
abortCleanup();
|
|
338
|
+
}
|
|
277
339
|
}
|
|
278
340
|
|
|
279
341
|
// Get the latest messages to extract the response
|
|
@@ -292,11 +354,10 @@ export class SubagentManager {
|
|
|
292
354
|
);
|
|
293
355
|
const response = textBlocks.map((block) => block.content).join("\n");
|
|
294
356
|
|
|
295
|
-
// Update status to completed and update parent
|
|
357
|
+
// Update status to completed and update parent
|
|
296
358
|
this.updateInstanceStatus(instance.subagentId, "completed");
|
|
297
359
|
this.parentMessageManager.updateSubagentBlock(instance.subagentId, {
|
|
298
360
|
status: "completed",
|
|
299
|
-
messages: messages,
|
|
300
361
|
});
|
|
301
362
|
|
|
302
363
|
return response || "Task completed with no text response";
|
|
@@ -370,4 +431,162 @@ export class SubagentManager {
|
|
|
370
431
|
cleanup(): void {
|
|
371
432
|
this.instances.clear();
|
|
372
433
|
}
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* Restore subagent instances from saved session data
|
|
437
|
+
* This method is called during agent initialization to restore previous subagent states
|
|
438
|
+
*/
|
|
439
|
+
async restoreSubagentSessions(
|
|
440
|
+
subagentSessions: Array<{
|
|
441
|
+
sessionData: SessionData;
|
|
442
|
+
subagentId: string;
|
|
443
|
+
configuration: SubagentConfiguration;
|
|
444
|
+
}>,
|
|
445
|
+
): Promise<void> {
|
|
446
|
+
for (const { sessionData, subagentId, configuration } of subagentSessions) {
|
|
447
|
+
try {
|
|
448
|
+
// Use the configuration from the SubagentBlock
|
|
449
|
+
|
|
450
|
+
// Create the subagent instance without executing - just restore the state
|
|
451
|
+
|
|
452
|
+
// Create MessageManager for the restored subagent
|
|
453
|
+
const subagentCallbacks = this.createSubagentCallbacks(subagentId);
|
|
454
|
+
const messageManager = new MessageManager({
|
|
455
|
+
callbacks: subagentCallbacks,
|
|
456
|
+
workdir: this.workdir,
|
|
457
|
+
logger: this.logger,
|
|
458
|
+
sessionType: "subagent",
|
|
459
|
+
subagentType: configuration.name, // Use configuration name for restored sessions
|
|
460
|
+
});
|
|
461
|
+
|
|
462
|
+
// Use the parent tool manager
|
|
463
|
+
const toolManager = this.parentToolManager;
|
|
464
|
+
|
|
465
|
+
// Determine model to use
|
|
466
|
+
let modelToUse: string;
|
|
467
|
+
const parentModelConfig = this.getModelConfig();
|
|
468
|
+
|
|
469
|
+
if (!configuration.model || configuration.model === "inherit") {
|
|
470
|
+
modelToUse = parentModelConfig.agentModel;
|
|
471
|
+
} else if (configuration.model === "fastModel") {
|
|
472
|
+
modelToUse = parentModelConfig.fastModel;
|
|
473
|
+
} else {
|
|
474
|
+
modelToUse = configuration.model;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
// Create AIManager for the restored subagent
|
|
478
|
+
const aiManager = new AIManager({
|
|
479
|
+
messageManager,
|
|
480
|
+
toolManager,
|
|
481
|
+
logger: this.logger,
|
|
482
|
+
workdir: this.workdir,
|
|
483
|
+
systemPrompt: configuration.systemPrompt,
|
|
484
|
+
subagentType: configuration.name, // Use configuration name as subagent type for restored instances
|
|
485
|
+
hookManager: this.hookManager,
|
|
486
|
+
getGatewayConfig: this.getGatewayConfig,
|
|
487
|
+
getModelConfig: () => ({
|
|
488
|
+
...parentModelConfig,
|
|
489
|
+
agentModel: modelToUse,
|
|
490
|
+
}),
|
|
491
|
+
getTokenLimit: this.getTokenLimit,
|
|
492
|
+
callbacks: {
|
|
493
|
+
onUsageAdded: this.onUsageAdded,
|
|
494
|
+
},
|
|
495
|
+
});
|
|
496
|
+
|
|
497
|
+
// Create restored instance
|
|
498
|
+
const instance: SubagentInstance = {
|
|
499
|
+
subagentId,
|
|
500
|
+
configuration,
|
|
501
|
+
aiManager,
|
|
502
|
+
messageManager,
|
|
503
|
+
toolManager,
|
|
504
|
+
status: "completed", // Restored sessions are considered completed
|
|
505
|
+
messages: sessionData.messages,
|
|
506
|
+
subagentType: configuration.name, // Use configuration name as subagent type for restored instances
|
|
507
|
+
};
|
|
508
|
+
|
|
509
|
+
// IMPORTANT: Store instance in map BEFORE calling setMessages
|
|
510
|
+
// This ensures the callback can find the instance
|
|
511
|
+
this.instances.set(subagentId, instance);
|
|
512
|
+
|
|
513
|
+
messageManager.initializeFromSession(sessionData);
|
|
514
|
+
} catch (error) {
|
|
515
|
+
this.logger?.warn(
|
|
516
|
+
`Failed to restore subagent session ${subagentId}:`,
|
|
517
|
+
error,
|
|
518
|
+
);
|
|
519
|
+
// Continue with other sessions even if one fails
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
/**
|
|
525
|
+
* Create subagent callbacks for a specific subagent ID
|
|
526
|
+
* Extracted to reuse in both create and restore flows
|
|
527
|
+
*/
|
|
528
|
+
private createSubagentCallbacks(subagentId: string) {
|
|
529
|
+
return {
|
|
530
|
+
onUserMessageAdded: (params: UserMessageParams) => {
|
|
531
|
+
// Forward user message events to parent via SubagentManager callbacks
|
|
532
|
+
if (this.callbacks?.onSubagentUserMessageAdded) {
|
|
533
|
+
this.callbacks.onSubagentUserMessageAdded(subagentId, params);
|
|
534
|
+
}
|
|
535
|
+
},
|
|
536
|
+
|
|
537
|
+
onAssistantMessageAdded: () => {
|
|
538
|
+
// Forward assistant message events to parent via SubagentManager callbacks
|
|
539
|
+
if (this.callbacks?.onSubagentAssistantMessageAdded) {
|
|
540
|
+
this.callbacks.onSubagentAssistantMessageAdded(subagentId);
|
|
541
|
+
}
|
|
542
|
+
},
|
|
543
|
+
|
|
544
|
+
onAssistantContentUpdated: (chunk: string, accumulated: string) => {
|
|
545
|
+
// Forward assistant content updates to parent via SubagentManager callbacks
|
|
546
|
+
if (this.callbacks?.onSubagentAssistantContentUpdated) {
|
|
547
|
+
this.callbacks.onSubagentAssistantContentUpdated(
|
|
548
|
+
subagentId,
|
|
549
|
+
chunk,
|
|
550
|
+
accumulated,
|
|
551
|
+
);
|
|
552
|
+
}
|
|
553
|
+
},
|
|
554
|
+
onAssistantReasoningUpdated: (chunk: string, accumulated: string) => {
|
|
555
|
+
// Forward assistant reasoning updates to parent via SubagentManager callbacks
|
|
556
|
+
if (this.callbacks?.onSubagentAssistantReasoningUpdated) {
|
|
557
|
+
this.callbacks.onSubagentAssistantReasoningUpdated(
|
|
558
|
+
subagentId,
|
|
559
|
+
chunk,
|
|
560
|
+
accumulated,
|
|
561
|
+
);
|
|
562
|
+
}
|
|
563
|
+
},
|
|
564
|
+
|
|
565
|
+
onToolBlockUpdated: (params: AgentToolBlockUpdateParams) => {
|
|
566
|
+
// Forward tool block updates to parent via SubagentManager callbacks
|
|
567
|
+
if (this.callbacks?.onSubagentToolBlockUpdated) {
|
|
568
|
+
this.callbacks.onSubagentToolBlockUpdated(subagentId, params);
|
|
569
|
+
}
|
|
570
|
+
},
|
|
571
|
+
|
|
572
|
+
// These callbacks will be handled by the parent agent
|
|
573
|
+
onMessagesChange: (messages: Message[]) => {
|
|
574
|
+
const instance = this.instances.get(subagentId);
|
|
575
|
+
if (instance) {
|
|
576
|
+
instance.messages = messages;
|
|
577
|
+
// Forward subagent message changes to parent via callbacks
|
|
578
|
+
if (this.callbacks?.onSubagentMessagesChange) {
|
|
579
|
+
this.callbacks.onSubagentMessagesChange(subagentId, messages);
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
},
|
|
583
|
+
|
|
584
|
+
onSessionIdChange: (newSessionId: string) => {
|
|
585
|
+
// Update the subagent block with the new session ID
|
|
586
|
+
this.parentMessageManager.updateSubagentBlock(subagentId, {
|
|
587
|
+
sessionId: newSessionId,
|
|
588
|
+
});
|
|
589
|
+
},
|
|
590
|
+
};
|
|
591
|
+
}
|
|
373
592
|
}
|
|
@@ -10,30 +10,56 @@ import { grepTool } from "../tools/grepTool.js";
|
|
|
10
10
|
import { lsTool } from "../tools/lsTool.js";
|
|
11
11
|
import { readTool } from "../tools/readTool.js";
|
|
12
12
|
import { todoWriteTool } from "../tools/todoWriteTool.js";
|
|
13
|
+
import { lspTool } from "../tools/lspTool.js";
|
|
13
14
|
import { createTaskTool } from "../tools/taskTool.js";
|
|
14
15
|
import { createSkillTool } from "../tools/skillTool.js";
|
|
15
16
|
import { McpManager } from "./mcpManager.js";
|
|
17
|
+
import { PermissionManager } from "./permissionManager.js";
|
|
16
18
|
import { ChatCompletionFunctionTool } from "openai/resources.js";
|
|
17
|
-
import type {
|
|
19
|
+
import type {
|
|
20
|
+
Logger,
|
|
21
|
+
PermissionMode,
|
|
22
|
+
PermissionCallback,
|
|
23
|
+
ILspManager,
|
|
24
|
+
} from "../types/index.js";
|
|
18
25
|
import type { SubagentManager } from "./subagentManager.js";
|
|
19
26
|
import type { SkillManager } from "./skillManager.js";
|
|
20
27
|
|
|
21
28
|
export interface ToolManagerOptions {
|
|
22
29
|
mcpManager: McpManager;
|
|
30
|
+
lspManager?: ILspManager;
|
|
23
31
|
logger?: Logger;
|
|
32
|
+
/** Optional permission manager for handling tool permission checks */
|
|
33
|
+
permissionManager?: PermissionManager;
|
|
34
|
+
/** Permission mode for tool execution (defaults to "default") */
|
|
35
|
+
permissionMode?: PermissionMode;
|
|
36
|
+
/** Custom permission callback for tool usage */
|
|
37
|
+
canUseToolCallback?: PermissionCallback;
|
|
24
38
|
}
|
|
25
39
|
|
|
26
40
|
/**
|
|
27
41
|
* Tool Manager
|
|
42
|
+
*
|
|
43
|
+
* Manages tool registration and execution with optional permission system integration.
|
|
44
|
+
* Supports both built-in tools and MCP (Model Context Protocol) tools.
|
|
28
45
|
*/
|
|
29
46
|
class ToolManager {
|
|
30
47
|
private tools = new Map<string, ToolPlugin>();
|
|
31
48
|
private mcpManager: McpManager;
|
|
49
|
+
private lspManager?: ILspManager;
|
|
32
50
|
private logger?: Logger;
|
|
51
|
+
private permissionManager?: PermissionManager;
|
|
52
|
+
private permissionMode?: PermissionMode;
|
|
53
|
+
private canUseToolCallback?: PermissionCallback;
|
|
33
54
|
|
|
34
55
|
constructor(options: ToolManagerOptions) {
|
|
35
56
|
this.mcpManager = options.mcpManager;
|
|
57
|
+
this.lspManager = options.lspManager;
|
|
36
58
|
this.logger = options.logger;
|
|
59
|
+
this.permissionManager = options.permissionManager;
|
|
60
|
+
// Store CLI permission mode, let PermissionManager resolve effective mode
|
|
61
|
+
this.permissionMode = options.permissionMode;
|
|
62
|
+
this.canUseToolCallback = options.canUseToolCallback;
|
|
37
63
|
}
|
|
38
64
|
|
|
39
65
|
/**
|
|
@@ -83,6 +109,7 @@ class ToolManager {
|
|
|
83
109
|
lsTool,
|
|
84
110
|
readTool,
|
|
85
111
|
todoWriteTool,
|
|
112
|
+
lspTool,
|
|
86
113
|
];
|
|
87
114
|
|
|
88
115
|
for (const tool of builtInTools) {
|
|
@@ -101,22 +128,66 @@ class ToolManager {
|
|
|
101
128
|
}
|
|
102
129
|
}
|
|
103
130
|
|
|
131
|
+
/**
|
|
132
|
+
* Execute a tool by name with the provided arguments and context
|
|
133
|
+
*
|
|
134
|
+
* Enhances the context with permission-related fields before execution:
|
|
135
|
+
* - permissionMode: The current permission mode (default or bypassPermissions)
|
|
136
|
+
* - canUseToolCallback: Custom permission callback if provided
|
|
137
|
+
* - permissionManager: The PermissionManager instance for permission checks
|
|
138
|
+
*
|
|
139
|
+
* @param name - Name of the tool to execute
|
|
140
|
+
* @param args - Arguments to pass to the tool
|
|
141
|
+
* @param context - Execution context for the tool
|
|
142
|
+
* @returns Promise resolving to the tool execution result
|
|
143
|
+
*/
|
|
104
144
|
async execute(
|
|
105
145
|
name: string,
|
|
106
146
|
args: Record<string, unknown>,
|
|
107
147
|
context: ToolContext,
|
|
108
148
|
): Promise<ToolResult> {
|
|
149
|
+
// Resolve effective permission mode (CLI override > configuration > default)
|
|
150
|
+
const effectivePermissionMode = this.permissionManager
|
|
151
|
+
? this.permissionManager.getCurrentEffectiveMode(this.permissionMode)
|
|
152
|
+
: this.permissionMode || "default";
|
|
153
|
+
|
|
154
|
+
// Enhance context with permission-related fields
|
|
155
|
+
const enhancedContext: ToolContext = {
|
|
156
|
+
...context,
|
|
157
|
+
permissionMode: effectivePermissionMode,
|
|
158
|
+
canUseToolCallback: this.canUseToolCallback,
|
|
159
|
+
permissionManager: this.permissionManager,
|
|
160
|
+
mcpManager: this.mcpManager,
|
|
161
|
+
lspManager: this.lspManager,
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
this.logger?.debug("Executing tool with enhanced context", {
|
|
165
|
+
toolName: name,
|
|
166
|
+
cliPermissionMode: this.permissionMode,
|
|
167
|
+
effectivePermissionMode,
|
|
168
|
+
hasPermissionManager: !!this.permissionManager,
|
|
169
|
+
hasPermissionCallback: !!this.canUseToolCallback,
|
|
170
|
+
});
|
|
171
|
+
|
|
109
172
|
// Check if it's an MCP tool first
|
|
110
173
|
if (this.mcpManager.isMcpTool(name)) {
|
|
111
|
-
return this.mcpManager.executeMcpToolByRegistry(
|
|
174
|
+
return this.mcpManager.executeMcpToolByRegistry(
|
|
175
|
+
name,
|
|
176
|
+
args,
|
|
177
|
+
enhancedContext,
|
|
178
|
+
);
|
|
112
179
|
}
|
|
113
180
|
|
|
114
181
|
// Check built-in tools
|
|
115
182
|
const plugin = this.tools.get(name);
|
|
116
183
|
if (plugin) {
|
|
117
184
|
try {
|
|
118
|
-
return await plugin.execute(args,
|
|
185
|
+
return await plugin.execute(args, enhancedContext);
|
|
119
186
|
} catch (error) {
|
|
187
|
+
this.logger?.error("Tool execution failed", {
|
|
188
|
+
toolName: name,
|
|
189
|
+
error: error instanceof Error ? error.message : String(error),
|
|
190
|
+
});
|
|
120
191
|
return {
|
|
121
192
|
success: false,
|
|
122
193
|
content: "",
|
|
@@ -125,6 +196,7 @@ class ToolManager {
|
|
|
125
196
|
}
|
|
126
197
|
}
|
|
127
198
|
|
|
199
|
+
this.logger?.warn("Tool not found", { toolName: name });
|
|
128
200
|
return {
|
|
129
201
|
success: false,
|
|
130
202
|
content: "",
|
|
@@ -145,6 +217,26 @@ class ToolManager {
|
|
|
145
217
|
const mcpToolsConfig = this.mcpManager.getMcpToolsConfig();
|
|
146
218
|
return [...builtInToolsConfig, ...mcpToolsConfig];
|
|
147
219
|
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Get the current permission mode
|
|
223
|
+
*/
|
|
224
|
+
public getPermissionMode(): PermissionMode {
|
|
225
|
+
if (this.permissionManager) {
|
|
226
|
+
return this.permissionManager.getCurrentEffectiveMode(
|
|
227
|
+
this.permissionMode,
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
return this.permissionMode || "default";
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Set the permission mode
|
|
235
|
+
* @param mode - The new permission mode
|
|
236
|
+
*/
|
|
237
|
+
public setPermissionMode(mode: PermissionMode): void {
|
|
238
|
+
this.permissionMode = mode;
|
|
239
|
+
}
|
|
148
240
|
}
|
|
149
241
|
|
|
150
242
|
// Export tool registry class and types
|