wave-agent-sdk 0.0.4 → 0.0.6
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 +63 -9
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +103 -27
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/managers/aiManager.d.ts +5 -2
- package/dist/managers/aiManager.d.ts.map +1 -1
- package/dist/managers/aiManager.js +121 -53
- package/dist/managers/backgroundBashManager.d.ts +1 -1
- package/dist/managers/backgroundBashManager.d.ts.map +1 -1
- package/dist/{hooks/manager.d.ts → managers/hookManager.d.ts} +26 -7
- package/dist/managers/hookManager.d.ts.map +1 -0
- package/dist/{hooks/manager.js → managers/hookManager.js} +108 -18
- package/dist/managers/mcpManager.d.ts +1 -1
- package/dist/managers/mcpManager.d.ts.map +1 -1
- package/dist/managers/mcpManager.js +5 -5
- package/dist/managers/messageManager.d.ts +29 -5
- package/dist/managers/messageManager.d.ts.map +1 -1
- package/dist/managers/messageManager.js +33 -12
- package/dist/managers/skillManager.d.ts +1 -1
- package/dist/managers/skillManager.d.ts.map +1 -1
- package/dist/managers/skillManager.js +3 -3
- package/dist/managers/slashCommandManager.d.ts +1 -1
- package/dist/managers/slashCommandManager.d.ts.map +1 -1
- package/dist/managers/slashCommandManager.js +1 -1
- package/dist/managers/subagentManager.d.ts +9 -12
- package/dist/managers/subagentManager.d.ts.map +1 -1
- package/dist/managers/subagentManager.js +43 -45
- package/dist/managers/toolManager.d.ts +1 -1
- package/dist/managers/toolManager.d.ts.map +1 -1
- package/dist/services/aiService.d.ts +10 -2
- package/dist/services/aiService.d.ts.map +1 -1
- package/dist/services/aiService.js +25 -4
- package/dist/services/hook.d.ts +56 -0
- package/dist/services/hook.d.ts.map +1 -0
- package/dist/services/hook.js +276 -0
- package/dist/services/memory.js +3 -3
- package/dist/services/session.d.ts +65 -16
- package/dist/services/session.d.ts.map +1 -1
- package/dist/services/session.js +85 -34
- package/dist/tools/bashTool.js +2 -2
- package/dist/tools/deleteFileTool.js +1 -1
- package/dist/tools/editTool.js +1 -1
- package/dist/tools/multiEditTool.js +2 -2
- package/dist/tools/taskTool.d.ts.map +1 -1
- package/dist/tools/taskTool.js +7 -3
- package/dist/tools/writeTool.js +1 -1
- package/dist/types/commands.d.ts +24 -0
- package/dist/types/commands.d.ts.map +1 -0
- package/dist/types/commands.js +5 -0
- package/dist/types/config.d.ts +13 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +5 -0
- package/dist/types/core.d.ts +38 -0
- package/dist/types/core.d.ts.map +1 -0
- package/dist/{types.js → types/core.js} +4 -13
- package/dist/{hooks/types.d.ts → types/hooks.d.ts} +2 -1
- package/dist/types/hooks.d.ts.map +1 -0
- package/dist/types/index.d.ts +20 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +21 -0
- package/dist/types/mcp.d.ts +28 -0
- package/dist/types/mcp.d.ts.map +1 -0
- package/dist/types/mcp.js +5 -0
- package/dist/types/messaging.d.ts +80 -0
- package/dist/types/messaging.d.ts.map +1 -0
- package/dist/types/messaging.js +5 -0
- package/dist/types/processes.d.ts +17 -0
- package/dist/types/processes.d.ts.map +1 -0
- package/dist/types/processes.js +5 -0
- package/dist/types/skills.d.ts +78 -0
- package/dist/types/skills.d.ts.map +1 -0
- package/dist/types/skills.js +17 -0
- package/dist/utils/configResolver.d.ts +1 -1
- package/dist/utils/configResolver.d.ts.map +1 -1
- package/dist/utils/configResolver.js +1 -1
- package/dist/utils/configValidator.d.ts +1 -1
- package/dist/utils/configValidator.d.ts.map +1 -1
- package/dist/utils/configValidator.js +1 -1
- package/dist/utils/convertMessagesForAPI.d.ts +1 -1
- package/dist/utils/convertMessagesForAPI.d.ts.map +1 -1
- package/dist/utils/customCommands.d.ts +1 -1
- package/dist/utils/customCommands.d.ts.map +1 -1
- package/dist/{hooks/matcher.d.ts → utils/hookMatcher.d.ts} +1 -1
- package/dist/utils/hookMatcher.d.ts.map +1 -0
- package/dist/utils/markdownParser.d.ts +1 -1
- package/dist/utils/markdownParser.d.ts.map +1 -1
- package/dist/utils/mcpUtils.d.ts +1 -1
- package/dist/utils/mcpUtils.d.ts.map +1 -1
- package/dist/utils/messageOperations.d.ts +7 -2
- package/dist/utils/messageOperations.d.ts.map +1 -1
- package/dist/utils/messageOperations.js +18 -1
- package/dist/utils/skillParser.d.ts +1 -1
- package/dist/utils/skillParser.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/agent.ts +150 -50
- package/src/index.ts +3 -4
- package/src/managers/aiManager.ts +282 -164
- package/src/managers/backgroundBashManager.ts +1 -1
- package/src/{hooks/manager.ts → managers/hookManager.ts} +163 -28
- package/src/managers/mcpManager.ts +6 -6
- package/src/managers/messageManager.ts +69 -10
- package/src/managers/skillManager.ts +4 -4
- package/src/managers/slashCommandManager.ts +6 -2
- package/src/managers/subagentManager.ts +58 -53
- package/src/managers/toolManager.ts +1 -1
- package/src/services/aiService.ts +37 -7
- package/src/services/hook.ts +360 -0
- package/src/services/memory.ts +3 -3
- package/src/services/session.ts +99 -33
- package/src/tools/bashTool.ts +2 -2
- package/src/tools/deleteFileTool.ts +1 -1
- package/src/tools/editTool.ts +1 -1
- package/src/tools/multiEditTool.ts +2 -2
- package/src/tools/taskTool.ts +13 -5
- package/src/tools/writeTool.ts +1 -1
- package/src/types/commands.ts +26 -0
- package/src/types/config.ts +14 -0
- package/src/types/core.ts +49 -0
- package/src/{hooks/types.ts → types/hooks.ts} +1 -0
- package/src/types/index.ts +23 -0
- package/src/{types.ts → types/index.ts.backup} +13 -0
- package/src/types/mcp.ts +31 -0
- package/src/types/messaging.ts +103 -0
- package/src/types/processes.ts +18 -0
- package/src/types/skills.ts +91 -0
- package/src/utils/configResolver.ts +1 -1
- package/src/utils/configValidator.ts +5 -1
- package/src/utils/convertMessagesForAPI.ts +1 -1
- package/src/utils/customCommands.ts +1 -1
- package/src/utils/markdownParser.ts +1 -1
- package/src/utils/mcpUtils.ts +1 -1
- package/src/utils/messageOperations.ts +22 -1
- package/src/utils/skillParser.ts +1 -1
- package/dist/hooks/executor.d.ts +0 -56
- package/dist/hooks/executor.d.ts.map +0 -1
- package/dist/hooks/executor.js +0 -312
- package/dist/hooks/index.d.ts +0 -17
- package/dist/hooks/index.d.ts.map +0 -1
- package/dist/hooks/index.js +0 -14
- package/dist/hooks/manager.d.ts.map +0 -1
- package/dist/hooks/matcher.d.ts.map +0 -1
- package/dist/hooks/settings.d.ts +0 -46
- package/dist/hooks/settings.d.ts.map +0 -1
- package/dist/hooks/settings.js +0 -100
- package/dist/hooks/types.d.ts.map +0 -1
- package/dist/types.d.ts +0 -276
- package/dist/types.d.ts.map +0 -1
- package/src/hooks/executor.ts +0 -440
- package/src/hooks/index.ts +0 -52
- package/src/hooks/settings.ts +0 -129
- /package/dist/{hooks/types.js → types/hooks.js} +0 -0
- /package/dist/{hooks/matcher.js → utils/hookMatcher.js} +0 -0
- /package/src/{hooks/matcher.ts → utils/hookMatcher.ts} +0 -0
|
@@ -83,7 +83,7 @@ export class AIManager {
|
|
|
83
83
|
this.messageManager.setlatestTotalTokens(usage.total_tokens);
|
|
84
84
|
// Check if token limit exceeded - use injected configuration
|
|
85
85
|
if (usage.total_tokens > this.tokenLimit) {
|
|
86
|
-
this.logger?.
|
|
86
|
+
this.logger?.debug(`Token usage exceeded ${this.tokenLimit}, compressing messages...`);
|
|
87
87
|
// Check if messages need compression
|
|
88
88
|
const { messagesToCompress, insertIndex } = getMessagesToCompress(this.messageManager.getMessages(), 7);
|
|
89
89
|
// If there are messages to compress, perform compression
|
|
@@ -91,15 +91,29 @@ export class AIManager {
|
|
|
91
91
|
const recentChatMessages = convertMessagesForAPI(messagesToCompress);
|
|
92
92
|
this.setIsCompressing(true);
|
|
93
93
|
try {
|
|
94
|
-
const
|
|
94
|
+
const compressionResult = await compressMessages({
|
|
95
95
|
gatewayConfig: this.gatewayConfig,
|
|
96
96
|
modelConfig: this.modelConfig,
|
|
97
97
|
messages: recentChatMessages,
|
|
98
98
|
abortSignal: abortController.signal,
|
|
99
99
|
});
|
|
100
100
|
// Execute message reconstruction and sessionId update after compression
|
|
101
|
-
this.messageManager.compressMessagesAndUpdateSession(insertIndex,
|
|
102
|
-
|
|
101
|
+
this.messageManager.compressMessagesAndUpdateSession(insertIndex, compressionResult.content);
|
|
102
|
+
// Handle usage tracking for compression operations
|
|
103
|
+
if (compressionResult.usage) {
|
|
104
|
+
const usage = {
|
|
105
|
+
prompt_tokens: compressionResult.usage.prompt_tokens,
|
|
106
|
+
completion_tokens: compressionResult.usage.completion_tokens,
|
|
107
|
+
total_tokens: compressionResult.usage.total_tokens,
|
|
108
|
+
model: this.modelConfig.fastModel,
|
|
109
|
+
operation_type: "compress",
|
|
110
|
+
};
|
|
111
|
+
// Notify Agent to add to usage tracking
|
|
112
|
+
if (this.callbacks?.onUsageAdded) {
|
|
113
|
+
this.callbacks.onUsageAdded(usage);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
this.logger?.debug(`Successfully compressed ${messagesToCompress.length} messages and updated session`);
|
|
103
117
|
}
|
|
104
118
|
catch (compressError) {
|
|
105
119
|
this.logger?.error("Failed to compress messages:", compressError);
|
|
@@ -125,12 +139,22 @@ export class AIManager {
|
|
|
125
139
|
if (recursionDepth === 0 && this.isLoading) {
|
|
126
140
|
return;
|
|
127
141
|
}
|
|
128
|
-
//
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
142
|
+
// Only create new AbortControllers for the initial call (recursionDepth === 0)
|
|
143
|
+
// For recursive calls, reuse existing controllers to maintain abort signal
|
|
144
|
+
let abortController;
|
|
145
|
+
let toolAbortController;
|
|
146
|
+
if (recursionDepth === 0) {
|
|
147
|
+
// Create new AbortControllers for initial call
|
|
148
|
+
abortController = new AbortController();
|
|
149
|
+
this.abortController = abortController;
|
|
150
|
+
toolAbortController = new AbortController();
|
|
151
|
+
this.toolAbortController = toolAbortController;
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
// Reuse existing controllers for recursive calls
|
|
155
|
+
abortController = this.abortController;
|
|
156
|
+
toolAbortController = this.toolAbortController;
|
|
157
|
+
}
|
|
134
158
|
// Only set loading state for the initial call
|
|
135
159
|
if (recursionDepth === 0) {
|
|
136
160
|
this.setIsLoading(true);
|
|
@@ -163,12 +187,29 @@ export class AIManager {
|
|
|
163
187
|
}
|
|
164
188
|
}
|
|
165
189
|
}
|
|
166
|
-
//
|
|
167
|
-
|
|
190
|
+
// Handle usage tracking for agent operations
|
|
191
|
+
let usage;
|
|
192
|
+
if (result.usage) {
|
|
193
|
+
usage = {
|
|
194
|
+
prompt_tokens: result.usage.prompt_tokens,
|
|
195
|
+
completion_tokens: result.usage.completion_tokens,
|
|
196
|
+
total_tokens: result.usage.total_tokens,
|
|
197
|
+
model: model || this.modelConfig.agentModel,
|
|
198
|
+
operation_type: "agent",
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
// Add assistant message at once (including content, tool calls, and usage)
|
|
202
|
+
this.messageManager.addAssistantMessage(content, toolCalls, usage);
|
|
203
|
+
// Notify Agent to add to usage tracking
|
|
204
|
+
if (usage) {
|
|
205
|
+
if (this.callbacks?.onUsageAdded) {
|
|
206
|
+
this.callbacks.onUsageAdded(usage);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
168
209
|
if (toolCalls.length > 0) {
|
|
169
|
-
|
|
210
|
+
// Execute all tools in parallel using Promise.all
|
|
211
|
+
const toolExecutionPromises = toolCalls.map(async (functionToolCall) => {
|
|
170
212
|
const toolId = functionToolCall.id || "";
|
|
171
|
-
// Execute tool
|
|
172
213
|
try {
|
|
173
214
|
// Check if already interrupted, skip tool execution if so
|
|
174
215
|
if (abortController.signal.aborted ||
|
|
@@ -205,7 +246,12 @@ export class AIManager {
|
|
|
205
246
|
});
|
|
206
247
|
try {
|
|
207
248
|
// Execute PreToolUse hooks before tool execution
|
|
208
|
-
await this.executePreToolUseHooks(toolName, toolArgs);
|
|
249
|
+
const shouldExecuteTool = await this.executePreToolUseHooks(toolName, toolArgs, toolId);
|
|
250
|
+
// If PreToolUse hooks blocked execution, skip tool execution
|
|
251
|
+
if (!shouldExecuteTool) {
|
|
252
|
+
this.logger?.info(`Tool ${toolName} execution blocked by PreToolUse hooks`);
|
|
253
|
+
return; // Skip this tool and return from this map function
|
|
254
|
+
}
|
|
209
255
|
// Create tool execution context
|
|
210
256
|
const context = {
|
|
211
257
|
abortSignal: toolAbortController.signal,
|
|
@@ -234,7 +280,7 @@ export class AIManager {
|
|
|
234
280
|
this.messageManager.addDiffBlock(toolResult.filePath, toolResult.diffResult);
|
|
235
281
|
}
|
|
236
282
|
// Execute PostToolUse hooks after successful tool completion
|
|
237
|
-
await this.executePostToolUseHooks(toolName, toolArgs, toolResult);
|
|
283
|
+
await this.executePostToolUseHooks(toolId, toolName, toolArgs, toolResult);
|
|
238
284
|
}
|
|
239
285
|
catch (toolError) {
|
|
240
286
|
const errorMessage = toolError instanceof Error
|
|
@@ -253,19 +299,14 @@ export class AIManager {
|
|
|
253
299
|
}
|
|
254
300
|
}
|
|
255
301
|
catch (parseError) {
|
|
256
|
-
// Check if it's a parsing error due to interruption
|
|
257
|
-
const isAborted = abortController.signal.aborted ||
|
|
258
|
-
toolAbortController.signal.aborted;
|
|
259
|
-
if (isAborted) {
|
|
260
|
-
// If interrupted, return directly without showing error
|
|
261
|
-
return;
|
|
262
|
-
}
|
|
263
302
|
const errorMessage = parseError instanceof Error
|
|
264
303
|
? parseError.message
|
|
265
304
|
: String(parseError);
|
|
266
305
|
this.messageManager.addErrorBlock(`Failed to parse tool arguments for ${functionToolCall.function?.name}: ${errorMessage}`);
|
|
267
306
|
}
|
|
268
|
-
}
|
|
307
|
+
});
|
|
308
|
+
// Wait for all tools to complete execution in parallel
|
|
309
|
+
await Promise.all(toolExecutionPromises);
|
|
269
310
|
}
|
|
270
311
|
// Handle token statistics and message compression
|
|
271
312
|
await this.handleTokenUsageAndCompression(result.usage, abortController);
|
|
@@ -273,10 +314,6 @@ export class AIManager {
|
|
|
273
314
|
if (toolCalls.length > 0) {
|
|
274
315
|
// Check interruption status
|
|
275
316
|
const isCurrentlyAborted = abortController.signal.aborted || toolAbortController.signal.aborted;
|
|
276
|
-
// AI service call ends, clear abort controller
|
|
277
|
-
this.abortController = null;
|
|
278
|
-
// Clear tool AbortController after tool execution completes
|
|
279
|
-
this.toolAbortController = null;
|
|
280
317
|
if (!isCurrentlyAborted) {
|
|
281
318
|
// Recursively call AI service, increment recursion depth, and pass same configuration
|
|
282
319
|
await this.sendAIMessage({
|
|
@@ -286,42 +323,47 @@ export class AIManager {
|
|
|
286
323
|
});
|
|
287
324
|
}
|
|
288
325
|
}
|
|
289
|
-
else {
|
|
290
|
-
// Clear abort controller when no tool operations
|
|
291
|
-
this.abortController = null;
|
|
292
|
-
this.toolAbortController = null;
|
|
293
|
-
}
|
|
294
326
|
}
|
|
295
327
|
catch (error) {
|
|
296
|
-
|
|
297
|
-
const isAborted = abortController.signal.aborted ||
|
|
298
|
-
toolAbortController.signal.aborted ||
|
|
299
|
-
(error instanceof Error &&
|
|
300
|
-
(error.name === "AbortError" || error.message.includes("aborted")));
|
|
301
|
-
if (!isAborted) {
|
|
302
|
-
this.messageManager.addErrorBlock(error instanceof Error ? error.message : "Unknown error occurred");
|
|
303
|
-
}
|
|
304
|
-
// Reset abort controller on error
|
|
305
|
-
this.abortController = null;
|
|
306
|
-
this.toolAbortController = null;
|
|
328
|
+
this.messageManager.addErrorBlock(error instanceof Error ? error.message : "Unknown error occurred");
|
|
307
329
|
}
|
|
308
330
|
finally {
|
|
309
|
-
// Only
|
|
331
|
+
// Only execute Stop hooks for the initial call
|
|
310
332
|
if (recursionDepth === 0) {
|
|
311
|
-
|
|
312
|
-
|
|
333
|
+
// Execute Stop hooks only if the operation was not aborted
|
|
334
|
+
const isCurrentlyAborted = abortController.signal.aborted || toolAbortController.signal.aborted;
|
|
335
|
+
if (!isCurrentlyAborted) {
|
|
336
|
+
const shouldContinue = await this.executeStopHooks();
|
|
337
|
+
// If Stop hooks indicate we should continue (due to blocking errors),
|
|
338
|
+
// restart the AI conversation cycle
|
|
339
|
+
if (shouldContinue) {
|
|
340
|
+
this.logger?.info("Stop hooks indicate issues need fixing, continuing conversation...");
|
|
341
|
+
// Restart the conversation to let AI fix the issues
|
|
342
|
+
// Use recursionDepth = 1 to prevent Stop hooks from running again in continuation
|
|
343
|
+
await this.sendAIMessage({
|
|
344
|
+
recursionDepth: 1,
|
|
345
|
+
model,
|
|
346
|
+
allowedTools,
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
// Save session after all operations (including continuation) are complete
|
|
313
351
|
await this.messageManager.saveSession();
|
|
314
|
-
//
|
|
315
|
-
|
|
352
|
+
// Clear abort controllers and loading state after all operations are complete
|
|
353
|
+
this.abortController = null;
|
|
354
|
+
this.toolAbortController = null;
|
|
355
|
+
// Set loading to false at the very end, after all operations including continuation
|
|
356
|
+
this.setIsLoading(false);
|
|
316
357
|
}
|
|
317
358
|
}
|
|
318
359
|
}
|
|
319
360
|
/**
|
|
320
361
|
* Execute Stop hooks when AI response cycle completes
|
|
362
|
+
* @returns Promise<boolean> - true if should continue conversation, false if should stop
|
|
321
363
|
*/
|
|
322
364
|
async executeStopHooks() {
|
|
323
365
|
if (!this.hookManager)
|
|
324
|
-
return;
|
|
366
|
+
return false;
|
|
325
367
|
try {
|
|
326
368
|
const context = {
|
|
327
369
|
event: "Stop",
|
|
@@ -333,6 +375,16 @@ export class AIManager {
|
|
|
333
375
|
// Stop hooks don't need toolName, toolInput, toolResponse, or userPrompt
|
|
334
376
|
};
|
|
335
377
|
const results = await this.hookManager.executeHooks("Stop", context);
|
|
378
|
+
// Process hook results to handle exit codes and appropriate responses
|
|
379
|
+
let shouldContinue = false;
|
|
380
|
+
if (results.length > 0) {
|
|
381
|
+
const processResult = this.hookManager.processHookResults("Stop", results, this.messageManager);
|
|
382
|
+
// If hook processing indicates we should block (exit code 2), continue conversation
|
|
383
|
+
if (processResult.shouldBlock) {
|
|
384
|
+
this.logger?.info("Stop hook blocked stopping with error:", processResult.errorMessage);
|
|
385
|
+
shouldContinue = true;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
336
388
|
// Log hook execution results for debugging
|
|
337
389
|
if (results.length > 0) {
|
|
338
390
|
this.logger?.debug(`Executed ${results.length} Stop hook(s):`, results.map((r) => ({
|
|
@@ -343,18 +395,21 @@ export class AIManager {
|
|
|
343
395
|
stderr: r.stderr,
|
|
344
396
|
})));
|
|
345
397
|
}
|
|
398
|
+
return shouldContinue;
|
|
346
399
|
}
|
|
347
400
|
catch (error) {
|
|
348
401
|
// Hook execution errors should not interrupt the main workflow
|
|
349
402
|
this.logger?.error("Stop hook execution failed:", error);
|
|
403
|
+
return false;
|
|
350
404
|
}
|
|
351
405
|
}
|
|
352
406
|
/**
|
|
353
407
|
* Execute PreToolUse hooks before tool execution
|
|
408
|
+
* Returns true if hooks allow tool execution, false if blocked
|
|
354
409
|
*/
|
|
355
|
-
async executePreToolUseHooks(toolName, toolInput) {
|
|
410
|
+
async executePreToolUseHooks(toolName, toolInput, toolId) {
|
|
356
411
|
if (!this.hookManager)
|
|
357
|
-
return;
|
|
412
|
+
return true;
|
|
358
413
|
try {
|
|
359
414
|
const context = {
|
|
360
415
|
event: "PreToolUse",
|
|
@@ -367,6 +422,12 @@ export class AIManager {
|
|
|
367
422
|
toolInput,
|
|
368
423
|
};
|
|
369
424
|
const results = await this.hookManager.executeHooks("PreToolUse", context);
|
|
425
|
+
// Process hook results to handle exit codes and determine if tool should be blocked
|
|
426
|
+
let shouldContinue = true;
|
|
427
|
+
if (results.length > 0) {
|
|
428
|
+
const processResult = this.hookManager.processHookResults("PreToolUse", results, this.messageManager, toolId);
|
|
429
|
+
shouldContinue = !processResult.shouldBlock;
|
|
430
|
+
}
|
|
370
431
|
// Log hook execution results for debugging
|
|
371
432
|
if (results.length > 0) {
|
|
372
433
|
this.logger?.debug(`Executed ${results.length} PreToolUse hook(s) for ${toolName}:`, results.map((r) => ({
|
|
@@ -377,16 +438,18 @@ export class AIManager {
|
|
|
377
438
|
stderr: r.stderr,
|
|
378
439
|
})));
|
|
379
440
|
}
|
|
441
|
+
return shouldContinue;
|
|
380
442
|
}
|
|
381
443
|
catch (error) {
|
|
382
444
|
// Hook execution errors should not interrupt the main workflow
|
|
383
445
|
this.logger?.error("PreToolUse hook execution failed:", error);
|
|
446
|
+
return true; // Allow tool execution on hook errors
|
|
384
447
|
}
|
|
385
448
|
}
|
|
386
449
|
/**
|
|
387
450
|
* Execute PostToolUse hooks after tool completion
|
|
388
451
|
*/
|
|
389
|
-
async executePostToolUseHooks(toolName, toolInput, toolResponse) {
|
|
452
|
+
async executePostToolUseHooks(toolId, toolName, toolInput, toolResponse) {
|
|
390
453
|
if (!this.hookManager)
|
|
391
454
|
return;
|
|
392
455
|
try {
|
|
@@ -402,6 +465,11 @@ export class AIManager {
|
|
|
402
465
|
toolResponse,
|
|
403
466
|
};
|
|
404
467
|
const results = await this.hookManager.executeHooks("PostToolUse", context);
|
|
468
|
+
// Process hook results to handle exit codes and update tool results
|
|
469
|
+
if (results.length > 0) {
|
|
470
|
+
const originalToolResult = toolResponse?.content || "";
|
|
471
|
+
this.hookManager.processHookResults("PostToolUse", results, this.messageManager, toolId, originalToolResult);
|
|
472
|
+
}
|
|
405
473
|
// Log hook execution results for debugging
|
|
406
474
|
if (results.length > 0) {
|
|
407
475
|
this.logger?.debug(`Executed ${results.length} PostToolUse hook(s) for ${toolName}:`, results.map((r) => ({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"backgroundBashManager.d.ts","sourceRoot":"","sources":["../../src/managers/backgroundBashManager.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"backgroundBashManager.d.ts","sourceRoot":"","sources":["../../src/managers/backgroundBashManager.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEzD,MAAM,WAAW,8BAA8B;IAC7C,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,EAAE,KAAK,IAAI,CAAC;CACtD;AAED,MAAM,WAAW,4BAA4B;IAC3C,SAAS,CAAC,EAAE,8BAA8B,CAAC;IAC3C,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,qBAAqB;IAChC,OAAO,CAAC,MAAM,CAAsC;IACpD,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,SAAS,CAAiC;IAClD,OAAO,CAAC,OAAO,CAAS;gBAEZ,OAAO,EAAE,4BAA4B;IAKjD,OAAO,CAAC,kBAAkB;IAInB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM;IAsErD,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;IAIjD,YAAY,IAAI,eAAe,EAAE;IAIjC,SAAS,CACd,EAAE,EAAE,MAAM,EACV,MAAM,CAAC,EAAE,MAAM,GACd;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAiCrD,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAmD9B,OAAO,IAAI,IAAI;CAUvB"}
|
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
* Central orchestrator for the hooks system. Handles configuration loading,
|
|
5
5
|
* validation, and hook execution across all supported events.
|
|
6
6
|
*/
|
|
7
|
-
import { type HookEvent, type HookConfiguration, type PartialHookConfiguration, type HookExecutionContext, type ExtendedHookExecutionContext, type HookExecutionResult, type ValidationResult } from "
|
|
8
|
-
import { type IHookMatcher } from "
|
|
9
|
-
import {
|
|
10
|
-
import type {
|
|
7
|
+
import { type HookEvent, type HookConfiguration, type PartialHookConfiguration, type HookExecutionContext, type ExtendedHookExecutionContext, type HookExecutionResult, type ValidationResult } from "../types/hooks.js";
|
|
8
|
+
import { type IHookMatcher } from "../utils/hookMatcher.js";
|
|
9
|
+
import type { Logger } from "../types/index.js";
|
|
10
|
+
import type { MessageManager } from "./messageManager.js";
|
|
11
11
|
export interface IHookManager {
|
|
12
12
|
loadConfiguration(userHooks?: PartialHookConfiguration, projectHooks?: PartialHookConfiguration): void;
|
|
13
13
|
loadConfigurationFromSettings(): void;
|
|
@@ -19,10 +19,9 @@ export interface IHookManager {
|
|
|
19
19
|
export declare class HookManager implements IHookManager {
|
|
20
20
|
private configuration;
|
|
21
21
|
private readonly matcher;
|
|
22
|
-
private readonly executor;
|
|
23
22
|
private readonly logger?;
|
|
24
23
|
private readonly workdir;
|
|
25
|
-
constructor(workdir: string, matcher?: IHookMatcher,
|
|
24
|
+
constructor(workdir: string, matcher?: IHookMatcher, logger?: Logger);
|
|
26
25
|
/**
|
|
27
26
|
* Load and merge hook configurations from user and project settings
|
|
28
27
|
* Project settings take precedence over user settings
|
|
@@ -37,6 +36,26 @@ export declare class HookManager implements IHookManager {
|
|
|
37
36
|
* Execute hooks for a specific event
|
|
38
37
|
*/
|
|
39
38
|
executeHooks(event: HookEvent, context: HookExecutionContext | ExtendedHookExecutionContext): Promise<HookExecutionResult[]>;
|
|
39
|
+
/**
|
|
40
|
+
* Process hook execution results and determine appropriate actions
|
|
41
|
+
* based on exit codes and hook event type
|
|
42
|
+
*/
|
|
43
|
+
processHookResults(event: HookEvent, results: HookExecutionResult[], messageManager?: MessageManager, toolId?: string, originalToolResult?: string): {
|
|
44
|
+
shouldBlock: boolean;
|
|
45
|
+
errorMessage?: string;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Handle successful hook execution (exit code 0)
|
|
49
|
+
*/
|
|
50
|
+
private handleHookSuccess;
|
|
51
|
+
/**
|
|
52
|
+
* Handle blocking error (exit code 2) - behavior varies by hook type
|
|
53
|
+
*/
|
|
54
|
+
private handleBlockingError;
|
|
55
|
+
/**
|
|
56
|
+
* Handle non-blocking error (other exit codes)
|
|
57
|
+
*/
|
|
58
|
+
private handleNonBlockingError;
|
|
40
59
|
/**
|
|
41
60
|
* Check if hooks are configured for an event/tool combination
|
|
42
61
|
*/
|
|
@@ -87,4 +106,4 @@ export declare class HookManager implements IHookManager {
|
|
|
87
106
|
eventBreakdown: Record<HookEvent, number>;
|
|
88
107
|
};
|
|
89
108
|
}
|
|
90
|
-
//# sourceMappingURL=
|
|
109
|
+
//# sourceMappingURL=hookManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hookManager.d.ts","sourceRoot":"","sources":["../../src/managers/hookManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,18 +4,13 @@
|
|
|
4
4
|
* Central orchestrator for the hooks system. Handles configuration loading,
|
|
5
5
|
* validation, and hook execution across all supported events.
|
|
6
6
|
*/
|
|
7
|
-
import { HookConfigurationError, isValidHookEvent, isValidHookEventConfig, } from "
|
|
8
|
-
import { HookMatcher } from "
|
|
9
|
-
import {
|
|
10
|
-
import { loadMergedHooksConfig } from "./settings.js";
|
|
7
|
+
import { HookConfigurationError, isValidHookEvent, isValidHookEventConfig, } from "../types/hooks.js";
|
|
8
|
+
import { HookMatcher } from "../utils/hookMatcher.js";
|
|
9
|
+
import { executeCommand, isCommandSafe, loadMergedHooksConfig, } from "../services/hook.js";
|
|
11
10
|
export class HookManager {
|
|
12
|
-
constructor(workdir, matcher = new HookMatcher(),
|
|
11
|
+
constructor(workdir, matcher = new HookMatcher(), logger) {
|
|
13
12
|
this.workdir = workdir;
|
|
14
13
|
this.matcher = matcher;
|
|
15
|
-
// Create executor with logger if provided, or use passed executor, or create default
|
|
16
|
-
this.executor = logger
|
|
17
|
-
? new HookExecutor(logger)
|
|
18
|
-
: executor || new HookExecutor();
|
|
19
14
|
this.logger = logger;
|
|
20
15
|
}
|
|
21
16
|
/**
|
|
@@ -48,13 +43,15 @@ export class HookManager {
|
|
|
48
43
|
this.logger?.debug(`[HookManager] Loading configuration...`);
|
|
49
44
|
const mergedConfig = loadMergedHooksConfig(this.workdir);
|
|
50
45
|
this.logger?.debug(`[HookManager] Merged config result:`, mergedConfig);
|
|
51
|
-
this.configuration = mergedConfig;
|
|
52
|
-
// Validate the loaded configuration
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
46
|
+
this.configuration = mergedConfig || undefined;
|
|
47
|
+
// Validate the loaded configuration if it exists
|
|
48
|
+
if (mergedConfig) {
|
|
49
|
+
const validation = this.validatePartialConfiguration(mergedConfig);
|
|
50
|
+
if (!validation.valid) {
|
|
51
|
+
throw new HookConfigurationError("filesystem settings", validation.errors);
|
|
52
|
+
}
|
|
56
53
|
}
|
|
57
|
-
this.logger?.debug(`[HookManager] Configuration loaded successfully with ${Object.keys(mergedConfig).length} event types`);
|
|
54
|
+
this.logger?.debug(`[HookManager] Configuration loaded successfully with ${Object.keys(mergedConfig || {}).length} event types`);
|
|
58
55
|
}
|
|
59
56
|
catch (error) {
|
|
60
57
|
// If loading fails, start with undefined configuration (no hooks)
|
|
@@ -110,7 +107,7 @@ export class HookManager {
|
|
|
110
107
|
const hookCommand = config.hooks[commandIndex];
|
|
111
108
|
try {
|
|
112
109
|
this.logger?.debug(`[HookManager] Executing command ${commandIndex + 1}/${config.hooks.length} in configuration ${configIndex + 1}`);
|
|
113
|
-
const result = await
|
|
110
|
+
const result = await executeCommand(hookCommand.command, context);
|
|
114
111
|
results.push(result);
|
|
115
112
|
// Report individual command result
|
|
116
113
|
if (result.success) {
|
|
@@ -138,9 +135,102 @@ export class HookManager {
|
|
|
138
135
|
// Generate execution summary
|
|
139
136
|
const totalDuration = Date.now() - startTime;
|
|
140
137
|
const summary = this.generateExecutionSummary(event, results, totalDuration);
|
|
141
|
-
this.logger?.
|
|
138
|
+
this.logger?.debug(`[HookManager] ${event} execution summary: ${summary}`);
|
|
142
139
|
return results;
|
|
143
140
|
}
|
|
141
|
+
/**
|
|
142
|
+
* Process hook execution results and determine appropriate actions
|
|
143
|
+
* based on exit codes and hook event type
|
|
144
|
+
*/
|
|
145
|
+
processHookResults(event, results, messageManager, toolId, originalToolResult) {
|
|
146
|
+
if (!messageManager || results.length === 0) {
|
|
147
|
+
return { shouldBlock: false };
|
|
148
|
+
}
|
|
149
|
+
// First pass: Check for any blocking errors (exit code 2)
|
|
150
|
+
// Blocking errors take precedence and stop all processing
|
|
151
|
+
for (const result of results) {
|
|
152
|
+
if (result.exitCode === 2) {
|
|
153
|
+
// Handle blocking error immediately and return
|
|
154
|
+
return this.handleBlockingError(event, result, messageManager, toolId, originalToolResult);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// Second pass: Process all non-blocking results
|
|
158
|
+
for (const result of results) {
|
|
159
|
+
if (result.exitCode === undefined) {
|
|
160
|
+
continue; // Skip results without exit codes
|
|
161
|
+
}
|
|
162
|
+
// Handle exit code interpretation
|
|
163
|
+
if (result.exitCode === 0) {
|
|
164
|
+
// Success case - handle stdout based on hook type
|
|
165
|
+
this.handleHookSuccess(event, result, messageManager);
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
// Non-blocking error case (any exit code except 0 and 2)
|
|
169
|
+
this.handleNonBlockingError(result, messageManager);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return { shouldBlock: false };
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Handle successful hook execution (exit code 0)
|
|
176
|
+
*/
|
|
177
|
+
handleHookSuccess(event, result, messageManager) {
|
|
178
|
+
if (event === "UserPromptSubmit" && result.stdout?.trim()) {
|
|
179
|
+
// Inject stdout as user message context for UserPromptSubmit
|
|
180
|
+
messageManager.addUserMessage(result.stdout.trim());
|
|
181
|
+
}
|
|
182
|
+
// For other hook types (PreToolUse, PostToolUse, Stop), ignore stdout
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Handle blocking error (exit code 2) - behavior varies by hook type
|
|
186
|
+
*/
|
|
187
|
+
handleBlockingError(event, result, messageManager, toolId, originalToolResult) {
|
|
188
|
+
const errorMessage = result.stderr?.trim() || "Hook execution failed";
|
|
189
|
+
switch (event) {
|
|
190
|
+
case "UserPromptSubmit":
|
|
191
|
+
// Block prompt processing, show error to user, erase prompt
|
|
192
|
+
messageManager.addErrorBlock(errorMessage);
|
|
193
|
+
messageManager.removeLastUserMessage();
|
|
194
|
+
return {
|
|
195
|
+
shouldBlock: true,
|
|
196
|
+
errorMessage,
|
|
197
|
+
};
|
|
198
|
+
case "PreToolUse":
|
|
199
|
+
// Block tool execution and show error to Wave Agent via tool block
|
|
200
|
+
if (toolId) {
|
|
201
|
+
messageManager.updateToolBlock({
|
|
202
|
+
toolId,
|
|
203
|
+
result: errorMessage,
|
|
204
|
+
success: false,
|
|
205
|
+
error: "Hook blocked tool execution",
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
return { shouldBlock: true };
|
|
209
|
+
case "PostToolUse":
|
|
210
|
+
// Show error to Wave Agent via tool block, execution continues
|
|
211
|
+
if (toolId && originalToolResult !== undefined) {
|
|
212
|
+
messageManager.updateToolBlock({
|
|
213
|
+
toolId,
|
|
214
|
+
result: `${originalToolResult}\n\nHook feedback: ${errorMessage}`,
|
|
215
|
+
success: false,
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
return { shouldBlock: false };
|
|
219
|
+
case "Stop":
|
|
220
|
+
// Show error to Wave Agent via user message and block stopping to continue conversation
|
|
221
|
+
messageManager.addUserMessage(errorMessage);
|
|
222
|
+
return { shouldBlock: true, errorMessage };
|
|
223
|
+
default:
|
|
224
|
+
return { shouldBlock: false };
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Handle non-blocking error (other exit codes)
|
|
229
|
+
*/
|
|
230
|
+
handleNonBlockingError(result, messageManager) {
|
|
231
|
+
const errorMessage = result.stderr?.trim() || "Hook execution failed";
|
|
232
|
+
messageManager.addErrorBlock(errorMessage);
|
|
233
|
+
}
|
|
144
234
|
/**
|
|
145
235
|
* Check if hooks are configured for an event/tool combination
|
|
146
236
|
*/
|
|
@@ -347,7 +437,7 @@ export class HookManager {
|
|
|
347
437
|
}
|
|
348
438
|
// Validate commands
|
|
349
439
|
config.hooks.forEach((hookCommand, cmdIndex) => {
|
|
350
|
-
if (!
|
|
440
|
+
if (!isCommandSafe(hookCommand.command)) {
|
|
351
441
|
errors.push(`${prefix}.hooks[${cmdIndex}]: Command may be unsafe: ${hookCommand.command}`);
|
|
352
442
|
}
|
|
353
443
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ChatCompletionFunctionTool } from "openai/resources.js";
|
|
2
2
|
import type { ToolPlugin, ToolResult, ToolContext } from "../tools/types.js";
|
|
3
|
-
import type { Logger, McpServerConfig, McpConfig, McpTool, McpServerStatus } from "../types.js";
|
|
3
|
+
import type { Logger, McpServerConfig, McpConfig, McpTool, McpServerStatus } from "../types/index.js";
|
|
4
4
|
export interface McpManagerCallbacks {
|
|
5
5
|
onServersChange?: (servers: McpServerStatus[]) => void;
|
|
6
6
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcpManager.d.ts","sourceRoot":"","sources":["../../src/managers/mcpManager.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AAEjE,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC7E,OAAO,KAAK,EACV,MAAM,EACN,eAAe,EACf,SAAS,EACT,OAAO,EACP,eAAe,EAChB,MAAM,
|
|
1
|
+
{"version":3,"file":"mcpManager.d.ts","sourceRoot":"","sources":["../../src/managers/mcpManager.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AAEjE,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC7E,OAAO,KAAK,EACV,MAAM,EACN,eAAe,EACf,SAAS,EACT,OAAO,EACP,eAAe,EAChB,MAAM,mBAAmB,CAAC;AAQ3B,MAAM,WAAW,mBAAmB;IAClC,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,EAAE,KAAK,IAAI,CAAC;CACxD;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,OAAO,CAA2C;IAC1D,OAAO,CAAC,WAAW,CAAyC;IAC5D,OAAO,CAAC,UAAU,CAAc;IAChC,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,SAAS,CAAsB;IACvC,OAAO,CAAC,MAAM,CAAC,CAAS;gBAEZ,OAAO,GAAE,iBAAsB;IAK3C;;OAEG;IACG,UAAU,CACd,OAAO,EAAE,MAAM,EACf,WAAW,GAAE,OAAe,GAC3B,OAAO,CAAC,IAAI,CAAC;IA4CV,kBAAkB,IAAI,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAO/C,UAAU,IAAI,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IA0CvC,UAAU,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC;IAWrD,SAAS,IAAI,SAAS,GAAG,IAAI;IAI7B,aAAa,IAAI,eAAe,EAAE;IAIlC,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;IAIpD,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,IAAI;IASzE,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,GAAG,OAAO;IAyBzD,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAgB7B,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IA4F7C,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IA2BtD,oBAAoB,IAAI,OAAO,EAAE;IAW3B,cAAc,CAClB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC;QACT,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,MAAM,CAAC,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,SAAS,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KACtD,CAAC;IAoEI,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAS9B;;OAEG;IACH,iBAAiB,IAAI,UAAU,EAAE;IAuBjC;;OAEG;IACH,iBAAiB,IAAI,0BAA0B,EAAE;IAIjD;;OAEG;IACG,wBAAwB,CAC5B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,CAAC;IActB;;OAEG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;CAIjC"}
|
|
@@ -20,17 +20,17 @@ export class McpManager {
|
|
|
20
20
|
this.configPath = join(workdir, ".mcp.json");
|
|
21
21
|
this.workdir = workdir;
|
|
22
22
|
if (autoConnect) {
|
|
23
|
-
this.logger?.
|
|
23
|
+
this.logger?.debug("Initializing MCP servers...");
|
|
24
24
|
// Ensure MCP configuration is loaded
|
|
25
25
|
const config = await this.ensureConfigLoaded();
|
|
26
26
|
if (config && config.mcpServers) {
|
|
27
27
|
// Connect to all configured servers
|
|
28
28
|
const connectionPromises = Object.keys(config.mcpServers).map(async (serverName) => {
|
|
29
29
|
try {
|
|
30
|
-
this.logger?.
|
|
30
|
+
this.logger?.debug(`Connecting to MCP server: ${serverName}`);
|
|
31
31
|
const success = await this.connectServer(serverName);
|
|
32
32
|
if (success) {
|
|
33
|
-
this.logger?.
|
|
33
|
+
this.logger?.debug(`Successfully connected to MCP server: ${serverName}`);
|
|
34
34
|
}
|
|
35
35
|
else {
|
|
36
36
|
this.logger?.warn(`Failed to connect to MCP server: ${serverName}`);
|
|
@@ -43,7 +43,7 @@ export class McpManager {
|
|
|
43
43
|
// Wait for all connection attempts to complete
|
|
44
44
|
await Promise.all(connectionPromises);
|
|
45
45
|
}
|
|
46
|
-
this.logger?.
|
|
46
|
+
this.logger?.debug("MCP servers initialization completed");
|
|
47
47
|
// Trigger state change callback after initialization
|
|
48
48
|
this.callbacks.onServersChange?.(this.getAllServers());
|
|
49
49
|
}
|
|
@@ -188,7 +188,7 @@ export class McpManager {
|
|
|
188
188
|
});
|
|
189
189
|
};
|
|
190
190
|
transport.onclose = () => {
|
|
191
|
-
this.logger?.
|
|
191
|
+
this.logger?.debug(`MCP Server ${name} transport closed`);
|
|
192
192
|
this.connections.delete(name);
|
|
193
193
|
this.updateServerStatus(name, {
|
|
194
194
|
status: "disconnected",
|