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
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
callAgent,
|
|
3
|
+
compressMessages,
|
|
4
|
+
type CallAgentOptions,
|
|
5
|
+
} from "../services/aiService.js";
|
|
2
6
|
import { getMessagesToCompress } from "../utils/messageOperations.js";
|
|
3
7
|
import { convertMessagesForAPI } from "../utils/convertMessagesForAPI.js";
|
|
8
|
+
import { calculateComprehensiveTotalTokens } from "../utils/tokenCalculation.js";
|
|
4
9
|
import * as memory from "../services/memory.js";
|
|
5
10
|
import type {
|
|
6
11
|
Logger,
|
|
@@ -30,10 +35,14 @@ export interface AIManagerOptions {
|
|
|
30
35
|
callbacks?: AIManagerCallbacks;
|
|
31
36
|
workdir: string;
|
|
32
37
|
systemPrompt?: string;
|
|
33
|
-
//
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
38
|
+
subagentType?: string; // Optional subagent type for hook context
|
|
39
|
+
/**Whether to use streaming mode for AI responses - defaults to true */
|
|
40
|
+
stream?: boolean;
|
|
41
|
+
// Dynamic configuration getters
|
|
42
|
+
getGatewayConfig: () => GatewayConfig;
|
|
43
|
+
getModelConfig: () => ModelConfig;
|
|
44
|
+
getTokenLimit: () => number;
|
|
45
|
+
getEnvironmentVars?: () => Record<string, string>; // Get configuration environment variables for hooks
|
|
37
46
|
}
|
|
38
47
|
|
|
39
48
|
export class AIManager {
|
|
@@ -47,11 +56,14 @@ export class AIManager {
|
|
|
47
56
|
private hookManager?: HookManager;
|
|
48
57
|
private workdir: string;
|
|
49
58
|
private systemPrompt?: string;
|
|
59
|
+
private subagentType?: string; // Store subagent type for hook context
|
|
60
|
+
private stream: boolean; // Streaming mode flag
|
|
50
61
|
|
|
51
|
-
// Configuration properties
|
|
52
|
-
private
|
|
53
|
-
private
|
|
54
|
-
private
|
|
62
|
+
// Configuration properties (replaced with getter function storage)
|
|
63
|
+
private getGatewayConfigFn: () => GatewayConfig;
|
|
64
|
+
private getModelConfigFn: () => ModelConfig;
|
|
65
|
+
private getTokenLimitFn: () => number;
|
|
66
|
+
private getEnvironmentVarsFn?: () => Record<string, string>;
|
|
55
67
|
|
|
56
68
|
constructor(options: AIManagerOptions) {
|
|
57
69
|
this.messageManager = options.messageManager;
|
|
@@ -61,12 +73,28 @@ export class AIManager {
|
|
|
61
73
|
this.logger = options.logger;
|
|
62
74
|
this.workdir = options.workdir;
|
|
63
75
|
this.systemPrompt = options.systemPrompt;
|
|
76
|
+
this.subagentType = options.subagentType; // Store subagent type
|
|
77
|
+
this.stream = options.stream ?? true; // Default to true if not specified
|
|
64
78
|
this.callbacks = options.callbacks ?? {};
|
|
65
79
|
|
|
66
|
-
// Store
|
|
67
|
-
this.
|
|
68
|
-
this.
|
|
69
|
-
this.
|
|
80
|
+
// Store configuration getter functions for dynamic resolution
|
|
81
|
+
this.getGatewayConfigFn = options.getGatewayConfig;
|
|
82
|
+
this.getModelConfigFn = options.getModelConfig;
|
|
83
|
+
this.getTokenLimitFn = options.getTokenLimit;
|
|
84
|
+
this.getEnvironmentVarsFn = options.getEnvironmentVars;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Getter methods for accessing dynamic configuration
|
|
88
|
+
public getGatewayConfig(): GatewayConfig {
|
|
89
|
+
return this.getGatewayConfigFn();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
public getModelConfig(): ModelConfig {
|
|
93
|
+
return this.getModelConfigFn();
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
public getTokenLimit(): number {
|
|
97
|
+
return this.getTokenLimitFn();
|
|
70
98
|
}
|
|
71
99
|
|
|
72
100
|
private isCompressing: boolean = false;
|
|
@@ -117,7 +145,7 @@ export class AIManager {
|
|
|
117
145
|
private generateCompactParams(
|
|
118
146
|
toolName: string,
|
|
119
147
|
toolArgs: Record<string, unknown>,
|
|
120
|
-
): string
|
|
148
|
+
): string {
|
|
121
149
|
try {
|
|
122
150
|
const toolPlugin = this.toolManager
|
|
123
151
|
.list()
|
|
@@ -131,23 +159,29 @@ export class AIManager {
|
|
|
131
159
|
} catch (error) {
|
|
132
160
|
this.logger?.warn("Failed to generate compactParams", error);
|
|
133
161
|
}
|
|
134
|
-
return
|
|
162
|
+
return "";
|
|
135
163
|
}
|
|
136
164
|
|
|
137
165
|
// Private method to handle token statistics and message compression
|
|
138
166
|
private async handleTokenUsageAndCompression(
|
|
139
|
-
usage:
|
|
167
|
+
usage: Usage | undefined,
|
|
140
168
|
abortController: AbortController,
|
|
141
169
|
): Promise<void> {
|
|
142
170
|
if (!usage) return;
|
|
143
171
|
|
|
144
|
-
// Update token statistics - display
|
|
145
|
-
|
|
172
|
+
// Update token statistics - display comprehensive token usage including cache tokens
|
|
173
|
+
const comprehensiveTotalTokens = calculateComprehensiveTotalTokens(usage);
|
|
174
|
+
this.messageManager.setlatestTotalTokens(comprehensiveTotalTokens);
|
|
146
175
|
|
|
147
176
|
// Check if token limit exceeded - use injected configuration
|
|
148
|
-
if (
|
|
177
|
+
if (
|
|
178
|
+
usage.total_tokens +
|
|
179
|
+
(usage.cache_read_input_tokens || 0) +
|
|
180
|
+
(usage.cache_creation_input_tokens || 0) >
|
|
181
|
+
this.getTokenLimit()
|
|
182
|
+
) {
|
|
149
183
|
this.logger?.debug(
|
|
150
|
-
`Token usage exceeded ${this.
|
|
184
|
+
`Token usage exceeded ${this.getTokenLimit()}, compressing messages...`,
|
|
151
185
|
);
|
|
152
186
|
|
|
153
187
|
// Check if messages need compression
|
|
@@ -160,35 +194,40 @@ export class AIManager {
|
|
|
160
194
|
if (messagesToCompress.length > 0) {
|
|
161
195
|
const recentChatMessages = convertMessagesForAPI(messagesToCompress);
|
|
162
196
|
|
|
197
|
+
// Save session before compression to preserve original messages
|
|
198
|
+
await this.messageManager.saveSession();
|
|
199
|
+
|
|
163
200
|
this.setIsCompressing(true);
|
|
164
201
|
try {
|
|
165
202
|
const compressionResult = await compressMessages({
|
|
166
|
-
gatewayConfig: this.
|
|
167
|
-
modelConfig: this.
|
|
203
|
+
gatewayConfig: this.getGatewayConfig(),
|
|
204
|
+
modelConfig: this.getModelConfig(),
|
|
168
205
|
messages: recentChatMessages,
|
|
169
206
|
abortSignal: abortController.signal,
|
|
170
207
|
});
|
|
171
208
|
|
|
172
|
-
// Execute message reconstruction and sessionId update after compression
|
|
173
|
-
this.messageManager.compressMessagesAndUpdateSession(
|
|
174
|
-
insertIndex,
|
|
175
|
-
compressionResult.content,
|
|
176
|
-
);
|
|
177
|
-
|
|
178
209
|
// Handle usage tracking for compression operations
|
|
210
|
+
let compressionUsage: Usage | undefined;
|
|
179
211
|
if (compressionResult.usage) {
|
|
180
|
-
|
|
212
|
+
compressionUsage = {
|
|
181
213
|
prompt_tokens: compressionResult.usage.prompt_tokens,
|
|
182
214
|
completion_tokens: compressionResult.usage.completion_tokens,
|
|
183
215
|
total_tokens: compressionResult.usage.total_tokens,
|
|
184
|
-
model: this.
|
|
216
|
+
model: this.getModelConfig().fastModel,
|
|
185
217
|
operation_type: "compress",
|
|
186
218
|
};
|
|
219
|
+
}
|
|
187
220
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
221
|
+
// Execute message reconstruction and sessionId update after compression
|
|
222
|
+
this.messageManager.compressMessagesAndUpdateSession(
|
|
223
|
+
insertIndex,
|
|
224
|
+
compressionResult.content,
|
|
225
|
+
compressionUsage,
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
// Notify Agent to add to usage tracking
|
|
229
|
+
if (compressionUsage && this.callbacks?.onUsageAdded) {
|
|
230
|
+
this.callbacks.onUsageAdded(compressionUsage);
|
|
192
231
|
}
|
|
193
232
|
|
|
194
233
|
this.logger?.debug(
|
|
@@ -228,6 +267,9 @@ export class AIManager {
|
|
|
228
267
|
return;
|
|
229
268
|
}
|
|
230
269
|
|
|
270
|
+
// Save session in each recursion to ensure message persistence
|
|
271
|
+
await this.messageManager.saveSession();
|
|
272
|
+
|
|
231
273
|
// Only create new AbortControllers for the initial call (recursionDepth === 0)
|
|
232
274
|
// For recursive calls, reuse existing controllers to maintain abort signal
|
|
233
275
|
let abortController: AbortController;
|
|
@@ -262,10 +304,15 @@ export class AIManager {
|
|
|
262
304
|
this.workdir,
|
|
263
305
|
);
|
|
264
306
|
|
|
265
|
-
//
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
307
|
+
// Track if assistant message has been created
|
|
308
|
+
let assistantMessageCreated = false;
|
|
309
|
+
|
|
310
|
+
this.logger?.debug("modelConfig in sendAIMessage", this.getModelConfig());
|
|
311
|
+
|
|
312
|
+
// Call AI service with streaming callbacks if enabled
|
|
313
|
+
const callAgentOptions: CallAgentOptions = {
|
|
314
|
+
gatewayConfig: this.getGatewayConfig(),
|
|
315
|
+
modelConfig: this.getModelConfig(),
|
|
269
316
|
messages: recentMessages,
|
|
270
317
|
sessionId: this.messageManager.getSessionId(),
|
|
271
318
|
abortSignal: abortController.signal,
|
|
@@ -274,19 +321,94 @@ export class AIManager {
|
|
|
274
321
|
tools: this.getFilteredToolsConfig(allowedTools), // Pass filtered tool configuration
|
|
275
322
|
model: model, // Use passed model
|
|
276
323
|
systemPrompt: this.systemPrompt, // Pass custom system prompt
|
|
277
|
-
}
|
|
324
|
+
};
|
|
278
325
|
|
|
279
|
-
//
|
|
280
|
-
|
|
281
|
-
|
|
326
|
+
// Add streaming callbacks only if streaming is enabled
|
|
327
|
+
if (this.stream) {
|
|
328
|
+
callAgentOptions.onContentUpdate = (content: string) => {
|
|
329
|
+
// Create assistant message on first chunk if not already created
|
|
330
|
+
if (!assistantMessageCreated) {
|
|
331
|
+
this.messageManager.addAssistantMessage();
|
|
332
|
+
assistantMessageCreated = true;
|
|
333
|
+
}
|
|
334
|
+
this.messageManager.updateCurrentMessageContent(content);
|
|
335
|
+
};
|
|
336
|
+
callAgentOptions.onToolUpdate = (toolCall) => {
|
|
337
|
+
// Create assistant message on first tool update if not already created
|
|
338
|
+
if (!assistantMessageCreated) {
|
|
339
|
+
this.messageManager.addAssistantMessage();
|
|
340
|
+
assistantMessageCreated = true;
|
|
341
|
+
}
|
|
282
342
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
343
|
+
// Use parametersChunk as compact param for better performance
|
|
344
|
+
// No need to extract params or generate compact params during streaming
|
|
345
|
+
|
|
346
|
+
// Update tool block with streaming parameters using parametersChunk as compact param
|
|
347
|
+
this.messageManager.updateToolBlock({
|
|
348
|
+
id: toolCall.id,
|
|
349
|
+
name: toolCall.name,
|
|
350
|
+
parameters: toolCall.parameters,
|
|
351
|
+
parametersChunk: toolCall.parametersChunk,
|
|
352
|
+
compactParams: toolCall.parameters?.split("\n").pop()?.slice(-30),
|
|
353
|
+
stage: toolCall.stage || "streaming", // Default to streaming if stage not provided
|
|
354
|
+
});
|
|
355
|
+
};
|
|
356
|
+
callAgentOptions.onReasoningUpdate = (reasoning: string) => {
|
|
357
|
+
// Create assistant message on first reasoning update if not already created
|
|
358
|
+
if (!assistantMessageCreated) {
|
|
359
|
+
this.messageManager.addAssistantMessage();
|
|
360
|
+
assistantMessageCreated = true;
|
|
288
361
|
}
|
|
289
|
-
|
|
362
|
+
this.messageManager.updateCurrentMessageReasoning(reasoning);
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
const result = await callAgent(callAgentOptions);
|
|
367
|
+
const createdByStreaming = assistantMessageCreated;
|
|
368
|
+
|
|
369
|
+
// For non-streaming mode, create assistant message after callAgent returns
|
|
370
|
+
// Also create if streaming mode but no streaming callbacks were called (e.g., when content comes directly in result)
|
|
371
|
+
if (
|
|
372
|
+
!this.stream ||
|
|
373
|
+
(!assistantMessageCreated &&
|
|
374
|
+
(result.content || result.tool_calls || result.reasoning_content))
|
|
375
|
+
) {
|
|
376
|
+
this.messageManager.addAssistantMessage();
|
|
377
|
+
assistantMessageCreated = true;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// Log finish reason and response headers if available
|
|
381
|
+
if (result.finish_reason) {
|
|
382
|
+
this.logger?.debug(
|
|
383
|
+
`AI response finished with reason: ${result.finish_reason}`,
|
|
384
|
+
);
|
|
385
|
+
}
|
|
386
|
+
if (
|
|
387
|
+
result.response_headers &&
|
|
388
|
+
Object.keys(result.response_headers).length > 0
|
|
389
|
+
) {
|
|
390
|
+
this.logger?.debug("AI response headers:", result.response_headers);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
if (
|
|
394
|
+
result.additionalFields &&
|
|
395
|
+
Object.keys(result.additionalFields).length > 0
|
|
396
|
+
) {
|
|
397
|
+
this.messageManager.mergeAssistantAdditionalFields(
|
|
398
|
+
result.additionalFields,
|
|
399
|
+
);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// Handle result reasoning content from non-streaming mode
|
|
403
|
+
if (result.reasoning_content && !createdByStreaming) {
|
|
404
|
+
this.messageManager.updateCurrentMessageReasoning(
|
|
405
|
+
result.reasoning_content,
|
|
406
|
+
);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// Handle result content from non-streaming mode
|
|
410
|
+
if (result.content && !createdByStreaming) {
|
|
411
|
+
this.messageManager.updateCurrentMessageContent(result.content);
|
|
290
412
|
}
|
|
291
413
|
|
|
292
414
|
// Handle usage tracking for agent operations
|
|
@@ -296,158 +418,173 @@ export class AIManager {
|
|
|
296
418
|
prompt_tokens: result.usage.prompt_tokens,
|
|
297
419
|
completion_tokens: result.usage.completion_tokens,
|
|
298
420
|
total_tokens: result.usage.total_tokens,
|
|
299
|
-
model: model || this.
|
|
421
|
+
model: model || this.getModelConfig().agentModel,
|
|
300
422
|
operation_type: "agent",
|
|
423
|
+
// Preserve cache fields if present
|
|
424
|
+
...(result.usage.cache_read_input_tokens !== undefined && {
|
|
425
|
+
cache_read_input_tokens: result.usage.cache_read_input_tokens,
|
|
426
|
+
}),
|
|
427
|
+
...(result.usage.cache_creation_input_tokens !== undefined && {
|
|
428
|
+
cache_creation_input_tokens:
|
|
429
|
+
result.usage.cache_creation_input_tokens,
|
|
430
|
+
}),
|
|
431
|
+
...(result.usage.cache_creation && {
|
|
432
|
+
cache_creation: result.usage.cache_creation,
|
|
433
|
+
}),
|
|
301
434
|
};
|
|
302
435
|
}
|
|
303
436
|
|
|
304
|
-
//
|
|
305
|
-
this.messageManager.addAssistantMessage(content, toolCalls, usage);
|
|
306
|
-
|
|
307
|
-
// Notify Agent to add to usage tracking
|
|
437
|
+
// Set usage on the assistant message if available
|
|
308
438
|
if (usage) {
|
|
439
|
+
const messages = this.messageManager.getMessages();
|
|
440
|
+
const lastMessage = messages[messages.length - 1];
|
|
441
|
+
if (lastMessage && lastMessage.role === "assistant") {
|
|
442
|
+
lastMessage.usage = usage;
|
|
443
|
+
this.messageManager.setMessages(messages);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
// Notify Agent to add to usage tracking
|
|
309
447
|
if (this.callbacks?.onUsageAdded) {
|
|
310
448
|
this.callbacks.onUsageAdded(usage);
|
|
311
449
|
}
|
|
312
450
|
}
|
|
313
451
|
|
|
452
|
+
// Collect tool calls for processing
|
|
453
|
+
const toolCalls: ChatCompletionMessageFunctionToolCall[] = [];
|
|
454
|
+
if (result.tool_calls) {
|
|
455
|
+
for (const toolCall of result.tool_calls) {
|
|
456
|
+
if (toolCall.type === "function") {
|
|
457
|
+
toolCalls.push(toolCall);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
|
|
314
462
|
if (toolCalls.length > 0) {
|
|
315
463
|
// Execute all tools in parallel using Promise.all
|
|
316
464
|
const toolExecutionPromises = toolCalls.map(
|
|
317
465
|
async (functionToolCall) => {
|
|
318
466
|
const toolId = functionToolCall.id || "";
|
|
319
467
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
468
|
+
// Check if already interrupted, skip tool execution if so
|
|
469
|
+
if (
|
|
470
|
+
abortController.signal.aborted ||
|
|
471
|
+
toolAbortController.signal.aborted
|
|
472
|
+
) {
|
|
473
|
+
return;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
const toolName = functionToolCall.function?.name || "";
|
|
477
|
+
// Safely parse tool parameters, handle tools without parameters
|
|
478
|
+
let toolArgs: Record<string, unknown> = {};
|
|
479
|
+
const argsString = functionToolCall.function?.arguments?.trim();
|
|
480
|
+
|
|
481
|
+
if (!argsString || argsString === "") {
|
|
482
|
+
// Tool without parameters, use empty object
|
|
483
|
+
toolArgs = {};
|
|
484
|
+
} else {
|
|
485
|
+
try {
|
|
486
|
+
toolArgs = JSON.parse(argsString);
|
|
487
|
+
} catch (parseError) {
|
|
488
|
+
// For non-empty but malformed JSON, still throw exception
|
|
489
|
+
const errorMessage = `Failed to parse tool arguments, finish_reason: ${result.finish_reason}`;
|
|
490
|
+
const fullErrorMessage = `${errorMessage}\nAI response headers:, ${JSON.stringify(result.response_headers)}`;
|
|
491
|
+
this.logger?.error(fullErrorMessage, parseError);
|
|
492
|
+
this.messageManager.updateToolBlock({
|
|
493
|
+
id: toolId,
|
|
494
|
+
parameters: argsString,
|
|
495
|
+
result: errorMessage,
|
|
496
|
+
success: false,
|
|
497
|
+
error: fullErrorMessage,
|
|
498
|
+
stage: "end",
|
|
499
|
+
name: toolName,
|
|
500
|
+
compactParams: "",
|
|
501
|
+
});
|
|
326
502
|
return;
|
|
327
503
|
}
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
const compactParams = this.generateCompactParams(
|
|
507
|
+
toolName,
|
|
508
|
+
toolArgs,
|
|
509
|
+
);
|
|
510
|
+
|
|
511
|
+
// Emit running stage for non-streaming tool calls (tool execution about to start)
|
|
512
|
+
this.messageManager.updateToolBlock({
|
|
513
|
+
id: toolId,
|
|
514
|
+
stage: "running",
|
|
515
|
+
name: toolName,
|
|
516
|
+
compactParams,
|
|
517
|
+
parameters: argsString,
|
|
518
|
+
parametersChunk: "",
|
|
519
|
+
});
|
|
328
520
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
const
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
throw new Error(errorMessage);
|
|
344
|
-
}
|
|
521
|
+
try {
|
|
522
|
+
// Execute PreToolUse hooks before tool execution
|
|
523
|
+
const shouldExecuteTool = await this.executePreToolUseHooks(
|
|
524
|
+
toolName,
|
|
525
|
+
toolArgs,
|
|
526
|
+
toolId,
|
|
527
|
+
);
|
|
528
|
+
|
|
529
|
+
// If PreToolUse hooks blocked execution, skip tool execution
|
|
530
|
+
if (!shouldExecuteTool) {
|
|
531
|
+
this.logger?.info(
|
|
532
|
+
`Tool ${toolName} execution blocked by PreToolUse hooks`,
|
|
533
|
+
);
|
|
534
|
+
return; // Skip this tool and return from this map function
|
|
345
535
|
}
|
|
346
536
|
|
|
347
|
-
//
|
|
348
|
-
const
|
|
349
|
-
|
|
537
|
+
// Create tool execution context
|
|
538
|
+
const context: ToolContext = {
|
|
539
|
+
abortSignal: toolAbortController.signal,
|
|
540
|
+
backgroundBashManager: this.backgroundBashManager,
|
|
541
|
+
workdir: this.workdir,
|
|
542
|
+
};
|
|
543
|
+
|
|
544
|
+
// Execute tool
|
|
545
|
+
const toolResult = await this.toolManager.execute(
|
|
546
|
+
functionToolCall.function?.name || "",
|
|
547
|
+
toolArgs,
|
|
548
|
+
context,
|
|
549
|
+
);
|
|
550
|
+
|
|
551
|
+
// Update message state - tool execution completed
|
|
552
|
+
this.messageManager.updateToolBlock({
|
|
553
|
+
id: toolId,
|
|
554
|
+
parameters: argsString,
|
|
555
|
+
result:
|
|
556
|
+
toolResult.content ||
|
|
557
|
+
(toolResult.error ? `Error: ${toolResult.error}` : ""),
|
|
558
|
+
success: toolResult.success,
|
|
559
|
+
error: toolResult.error,
|
|
560
|
+
stage: "end",
|
|
561
|
+
name: toolName,
|
|
562
|
+
shortResult: toolResult.shortResult,
|
|
563
|
+
});
|
|
564
|
+
|
|
565
|
+
// Execute PostToolUse hooks after successful tool completion
|
|
566
|
+
await this.executePostToolUseHooks(
|
|
567
|
+
toolId,
|
|
350
568
|
toolName,
|
|
351
569
|
toolArgs,
|
|
570
|
+
toolResult,
|
|
352
571
|
);
|
|
572
|
+
} catch (toolError) {
|
|
573
|
+
const errorMessage =
|
|
574
|
+
toolError instanceof Error
|
|
575
|
+
? toolError.message
|
|
576
|
+
: String(toolError);
|
|
353
577
|
|
|
354
578
|
this.messageManager.updateToolBlock({
|
|
355
579
|
id: toolId,
|
|
356
580
|
parameters: JSON.stringify(toolArgs, null, 2),
|
|
357
|
-
|
|
581
|
+
result: `Tool execution failed: ${errorMessage}`,
|
|
582
|
+
success: false,
|
|
583
|
+
error: errorMessage,
|
|
584
|
+
stage: "end",
|
|
358
585
|
name: toolName,
|
|
359
586
|
compactParams,
|
|
360
587
|
});
|
|
361
|
-
|
|
362
|
-
try {
|
|
363
|
-
// Execute PreToolUse hooks before tool execution
|
|
364
|
-
const shouldExecuteTool = await this.executePreToolUseHooks(
|
|
365
|
-
toolName,
|
|
366
|
-
toolArgs,
|
|
367
|
-
toolId,
|
|
368
|
-
);
|
|
369
|
-
|
|
370
|
-
// If PreToolUse hooks blocked execution, skip tool execution
|
|
371
|
-
if (!shouldExecuteTool) {
|
|
372
|
-
this.logger?.info(
|
|
373
|
-
`Tool ${toolName} execution blocked by PreToolUse hooks`,
|
|
374
|
-
);
|
|
375
|
-
return; // Skip this tool and return from this map function
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
// Create tool execution context
|
|
379
|
-
const context: ToolContext = {
|
|
380
|
-
abortSignal: toolAbortController.signal,
|
|
381
|
-
backgroundBashManager: this.backgroundBashManager,
|
|
382
|
-
workdir: this.workdir,
|
|
383
|
-
};
|
|
384
|
-
|
|
385
|
-
// Execute tool
|
|
386
|
-
const toolResult = await this.toolManager.execute(
|
|
387
|
-
functionToolCall.function?.name || "",
|
|
388
|
-
toolArgs,
|
|
389
|
-
context,
|
|
390
|
-
);
|
|
391
|
-
|
|
392
|
-
// Update message state - tool execution completed
|
|
393
|
-
this.messageManager.updateToolBlock({
|
|
394
|
-
id: toolId,
|
|
395
|
-
parameters: JSON.stringify(toolArgs, null, 2),
|
|
396
|
-
result:
|
|
397
|
-
toolResult.content ||
|
|
398
|
-
(toolResult.error ? `Error: ${toolResult.error}` : ""),
|
|
399
|
-
success: toolResult.success,
|
|
400
|
-
error: toolResult.error,
|
|
401
|
-
isRunning: false, // isRunning: false
|
|
402
|
-
name: toolName,
|
|
403
|
-
shortResult: toolResult.shortResult,
|
|
404
|
-
compactParams,
|
|
405
|
-
});
|
|
406
|
-
|
|
407
|
-
// If tool returns diff information, add diff block
|
|
408
|
-
if (
|
|
409
|
-
toolResult.success &&
|
|
410
|
-
toolResult.diffResult &&
|
|
411
|
-
toolResult.filePath
|
|
412
|
-
) {
|
|
413
|
-
this.messageManager.addDiffBlock(
|
|
414
|
-
toolResult.filePath,
|
|
415
|
-
toolResult.diffResult,
|
|
416
|
-
);
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
// Execute PostToolUse hooks after successful tool completion
|
|
420
|
-
await this.executePostToolUseHooks(
|
|
421
|
-
toolId,
|
|
422
|
-
toolName,
|
|
423
|
-
toolArgs,
|
|
424
|
-
toolResult,
|
|
425
|
-
);
|
|
426
|
-
} catch (toolError) {
|
|
427
|
-
const errorMessage =
|
|
428
|
-
toolError instanceof Error
|
|
429
|
-
? toolError.message
|
|
430
|
-
: String(toolError);
|
|
431
|
-
|
|
432
|
-
this.messageManager.updateToolBlock({
|
|
433
|
-
id: toolId,
|
|
434
|
-
parameters: JSON.stringify(toolArgs, null, 2),
|
|
435
|
-
result: `Tool execution failed: ${errorMessage}`,
|
|
436
|
-
success: false,
|
|
437
|
-
error: errorMessage,
|
|
438
|
-
isRunning: false,
|
|
439
|
-
name: toolName,
|
|
440
|
-
compactParams,
|
|
441
|
-
});
|
|
442
|
-
}
|
|
443
|
-
} catch (parseError) {
|
|
444
|
-
const errorMessage =
|
|
445
|
-
parseError instanceof Error
|
|
446
|
-
? parseError.message
|
|
447
|
-
: String(parseError);
|
|
448
|
-
this.messageManager.addErrorBlock(
|
|
449
|
-
`Failed to parse tool arguments for ${functionToolCall.function?.name}: ${errorMessage}`,
|
|
450
|
-
);
|
|
451
588
|
}
|
|
452
589
|
},
|
|
453
590
|
);
|
|
@@ -479,70 +616,75 @@ export class AIManager {
|
|
|
479
616
|
error instanceof Error ? error.message : "Unknown error occurred",
|
|
480
617
|
);
|
|
481
618
|
} finally {
|
|
482
|
-
// Only execute
|
|
619
|
+
// Only execute cleanup and hooks for the initial call
|
|
483
620
|
if (recursionDepth === 0) {
|
|
484
|
-
//
|
|
621
|
+
// Save session in each recursion to ensure message persistence
|
|
622
|
+
await this.messageManager.saveSession();
|
|
623
|
+
// Set loading to false first
|
|
624
|
+
this.setIsLoading(false);
|
|
625
|
+
|
|
626
|
+
// Clear abort controllers
|
|
627
|
+
this.abortController = null;
|
|
628
|
+
this.toolAbortController = null;
|
|
629
|
+
|
|
630
|
+
// Execute Stop/SubagentStop hooks only if the operation was not aborted
|
|
485
631
|
const isCurrentlyAborted =
|
|
486
632
|
abortController.signal.aborted || toolAbortController.signal.aborted;
|
|
487
633
|
|
|
488
634
|
if (!isCurrentlyAborted) {
|
|
489
635
|
const shouldContinue = await this.executeStopHooks();
|
|
490
636
|
|
|
491
|
-
// If Stop hooks indicate we should continue (due to blocking errors),
|
|
637
|
+
// If Stop/SubagentStop hooks indicate we should continue (due to blocking errors),
|
|
492
638
|
// restart the AI conversation cycle
|
|
493
639
|
if (shouldContinue) {
|
|
494
640
|
this.logger?.info(
|
|
495
|
-
"Stop hooks indicate issues need fixing, continuing conversation
|
|
641
|
+
`${this.subagentType ? "SubagentStop" : "Stop"} hooks indicate issues need fixing, continuing conversation...`,
|
|
496
642
|
);
|
|
497
643
|
|
|
498
644
|
// Restart the conversation to let AI fix the issues
|
|
499
|
-
// Use recursionDepth =
|
|
645
|
+
// Use recursionDepth = 0 to set loading false again for continuation
|
|
500
646
|
await this.sendAIMessage({
|
|
501
|
-
recursionDepth:
|
|
647
|
+
recursionDepth: 0,
|
|
502
648
|
model,
|
|
503
649
|
allowedTools,
|
|
504
650
|
});
|
|
505
651
|
}
|
|
506
652
|
}
|
|
507
|
-
|
|
508
|
-
// Save session after all operations (including continuation) are complete
|
|
509
|
-
await this.messageManager.saveSession();
|
|
510
|
-
|
|
511
|
-
// Clear abort controllers and loading state after all operations are complete
|
|
512
|
-
this.abortController = null;
|
|
513
|
-
this.toolAbortController = null;
|
|
514
|
-
|
|
515
|
-
// Set loading to false at the very end, after all operations including continuation
|
|
516
|
-
this.setIsLoading(false);
|
|
517
653
|
}
|
|
518
654
|
}
|
|
519
655
|
}
|
|
520
656
|
|
|
521
657
|
/**
|
|
522
|
-
* Execute Stop hooks when AI response cycle completes
|
|
658
|
+
* Execute Stop or SubagentStop hooks when AI response cycle completes
|
|
659
|
+
* Uses "SubagentStop" hook name when triggered by a subagent, otherwise uses "Stop"
|
|
523
660
|
* @returns Promise<boolean> - true if should continue conversation, false if should stop
|
|
524
661
|
*/
|
|
525
662
|
private async executeStopHooks(): Promise<boolean> {
|
|
526
663
|
if (!this.hookManager) return false;
|
|
527
664
|
|
|
528
665
|
try {
|
|
666
|
+
// Use "SubagentStop" hook name when triggered by a subagent, otherwise use "Stop"
|
|
667
|
+
const hookName = this.subagentType ? "SubagentStop" : "Stop";
|
|
668
|
+
|
|
529
669
|
const context: ExtendedHookExecutionContext = {
|
|
530
|
-
event:
|
|
670
|
+
event: hookName,
|
|
531
671
|
projectDir: this.workdir,
|
|
532
672
|
timestamp: new Date(),
|
|
533
673
|
sessionId: this.messageManager.getSessionId(),
|
|
534
674
|
transcriptPath: this.messageManager.getTranscriptPath(),
|
|
535
675
|
cwd: this.workdir,
|
|
676
|
+
subagentType: this.subagentType, // Include subagent type in hook context
|
|
536
677
|
// Stop hooks don't need toolName, toolInput, toolResponse, or userPrompt
|
|
678
|
+
env: this.getEnvironmentVarsFn?.() || {}, // Include configuration environment variables
|
|
537
679
|
};
|
|
538
680
|
|
|
539
|
-
const results = await this.hookManager.executeHooks(
|
|
681
|
+
const results = await this.hookManager.executeHooks(hookName, context);
|
|
540
682
|
|
|
541
683
|
// Process hook results to handle exit codes and appropriate responses
|
|
542
684
|
let shouldContinue = false;
|
|
543
685
|
if (results.length > 0) {
|
|
544
686
|
const processResult = this.hookManager.processHookResults(
|
|
545
|
-
|
|
687
|
+
hookName,
|
|
546
688
|
results,
|
|
547
689
|
this.messageManager,
|
|
548
690
|
);
|
|
@@ -550,7 +692,7 @@ export class AIManager {
|
|
|
550
692
|
// If hook processing indicates we should block (exit code 2), continue conversation
|
|
551
693
|
if (processResult.shouldBlock) {
|
|
552
694
|
this.logger?.info(
|
|
553
|
-
|
|
695
|
+
`${hookName} hook blocked stopping with error:`,
|
|
554
696
|
processResult.errorMessage,
|
|
555
697
|
);
|
|
556
698
|
shouldContinue = true;
|
|
@@ -560,7 +702,7 @@ export class AIManager {
|
|
|
560
702
|
// Log hook execution results for debugging
|
|
561
703
|
if (results.length > 0) {
|
|
562
704
|
this.logger?.debug(
|
|
563
|
-
`Executed ${results.length}
|
|
705
|
+
`Executed ${results.length} ${hookName} hook(s):`,
|
|
564
706
|
results.map((r) => ({
|
|
565
707
|
success: r.success,
|
|
566
708
|
duration: r.duration,
|
|
@@ -574,7 +716,10 @@ export class AIManager {
|
|
|
574
716
|
return shouldContinue;
|
|
575
717
|
} catch (error) {
|
|
576
718
|
// Hook execution errors should not interrupt the main workflow
|
|
577
|
-
this.logger?.error(
|
|
719
|
+
this.logger?.error(
|
|
720
|
+
`${this.subagentType ? "SubagentStop" : "Stop"} hook execution failed:`,
|
|
721
|
+
error,
|
|
722
|
+
);
|
|
578
723
|
return false;
|
|
579
724
|
}
|
|
580
725
|
}
|
|
@@ -600,6 +745,8 @@ export class AIManager {
|
|
|
600
745
|
transcriptPath: this.messageManager.getTranscriptPath(),
|
|
601
746
|
cwd: this.workdir,
|
|
602
747
|
toolInput,
|
|
748
|
+
subagentType: this.subagentType, // Include subagent type in hook context
|
|
749
|
+
env: this.getEnvironmentVarsFn?.() || {}, // Include configuration environment variables
|
|
603
750
|
};
|
|
604
751
|
|
|
605
752
|
const results = await this.hookManager.executeHooks(
|
|
@@ -664,6 +811,8 @@ export class AIManager {
|
|
|
664
811
|
cwd: this.workdir,
|
|
665
812
|
toolInput,
|
|
666
813
|
toolResponse,
|
|
814
|
+
subagentType: this.subagentType, // Include subagent type in hook context
|
|
815
|
+
env: this.getEnvironmentVarsFn?.() || {}, // Include configuration environment variables
|
|
667
816
|
};
|
|
668
817
|
|
|
669
818
|
const results = await this.hookManager.executeHooks(
|