wave-agent-sdk 0.0.8 → 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 +92 -23
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +340 -137
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/managers/aiManager.d.ts +14 -36
- package/dist/managers/aiManager.d.ts.map +1 -1
- package/dist/managers/aiManager.js +74 -77
- package/dist/managers/backgroundBashManager.d.ts.map +1 -1
- package/dist/managers/backgroundBashManager.js +4 -3
- package/dist/managers/hookManager.d.ts +3 -8
- package/dist/managers/hookManager.d.ts.map +1 -1
- package/dist/managers/hookManager.js +39 -29
- package/dist/managers/liveConfigManager.d.ts +55 -18
- package/dist/managers/liveConfigManager.d.ts.map +1 -1
- package/dist/managers/liveConfigManager.js +372 -90
- 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 +8 -16
- package/dist/managers/messageManager.d.ts.map +1 -1
- package/dist/managers/messageManager.js +52 -74
- 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 +0 -1
- package/dist/managers/subagentManager.d.ts +8 -23
- package/dist/managers/subagentManager.d.ts.map +1 -1
- package/dist/managers/subagentManager.js +97 -117
- 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 +3 -1
- package/dist/services/aiService.d.ts.map +1 -1
- package/dist/services/aiService.js +123 -30
- 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.map +1 -1
- package/dist/services/fileWatcher.js +5 -6
- package/dist/services/hook.d.ts +7 -124
- package/dist/services/hook.d.ts.map +1 -1
- package/dist/services/hook.js +46 -458
- package/dist/services/jsonlHandler.d.ts +24 -15
- package/dist/services/jsonlHandler.d.ts.map +1 -1
- package/dist/services/jsonlHandler.js +67 -88
- package/dist/services/memory.d.ts +0 -9
- package/dist/services/memory.d.ts.map +1 -1
- package/dist/services/memory.js +2 -49
- package/dist/services/session.d.ts +82 -33
- package/dist/services/session.d.ts.map +1 -1
- package/dist/services/session.js +275 -181
- package/dist/tools/bashTool.d.ts.map +1 -1
- package/dist/tools/bashTool.js +72 -13
- package/dist/tools/deleteFileTool.d.ts.map +1 -1
- package/dist/tools/deleteFileTool.js +25 -0
- package/dist/tools/editTool.d.ts.map +1 -1
- package/dist/tools/editTool.js +30 -6
- 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 +26 -7
- package/dist/tools/readTool.d.ts.map +1 -1
- package/dist/tools/readTool.js +111 -2
- 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 +25 -9
- package/dist/types/commands.d.ts +0 -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 +10 -0
- package/dist/types/core.d.ts.map +1 -1
- package/dist/types/environment.d.ts +41 -0
- package/dist/types/environment.d.ts.map +1 -1
- 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 +11 -2
- package/dist/types/hooks.d.ts.map +1 -1
- package/dist/types/hooks.js +1 -7
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +5 -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 +6 -11
- 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 +1 -6
- package/dist/types/session.d.ts.map +1 -1
- 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 +21 -4
- 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 +8 -33
- package/dist/utils/cacheControlUtils.d.ts.map +1 -1
- package/dist/utils/cacheControlUtils.js +83 -126
- package/dist/utils/constants.d.ts +0 -12
- package/dist/utils/constants.d.ts.map +1 -1
- package/dist/utils/constants.js +1 -13
- package/dist/utils/convertMessagesForAPI.d.ts +2 -1
- package/dist/utils/convertMessagesForAPI.d.ts.map +1 -1
- package/dist/utils/convertMessagesForAPI.js +33 -14
- 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 +14 -2
- package/dist/utils/fileUtils.d.ts.map +1 -1
- package/dist/utils/fileUtils.js +101 -17
- package/dist/utils/globalLogger.d.ts +0 -14
- package/dist/utils/globalLogger.d.ts.map +1 -1
- package/dist/utils/globalLogger.js +0 -16
- 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/messageOperations.d.ts +1 -11
- package/dist/utils/messageOperations.d.ts.map +1 -1
- package/dist/utils/messageOperations.js +7 -24
- package/dist/utils/pathEncoder.d.ts +4 -0
- package/dist/utils/pathEncoder.d.ts.map +1 -1
- package/dist/utils/pathEncoder.js +16 -9
- package/dist/utils/subagentParser.d.ts +2 -2
- package/dist/utils/subagentParser.d.ts.map +1 -1
- package/dist/utils/subagentParser.js +10 -7
- 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 +5 -8
- package/src/agent.ts +460 -216
- package/src/index.ts +2 -0
- package/src/managers/aiManager.ts +107 -111
- package/src/managers/backgroundBashManager.ts +4 -3
- package/src/managers/hookManager.ts +44 -39
- package/src/managers/liveConfigManager.ts +524 -138
- package/src/managers/lspManager.ts +434 -0
- package/src/managers/messageManager.ts +73 -103
- package/src/managers/permissionManager.ts +276 -0
- package/src/managers/skillManager.ts +3 -1
- package/src/managers/slashCommandManager.ts +1 -2
- package/src/managers/subagentManager.ts +116 -159
- package/src/managers/toolManager.ts +95 -3
- package/src/services/aiService.ts +207 -26
- package/src/services/configurationService.ts +762 -0
- package/src/services/fileWatcher.ts +5 -6
- package/src/services/hook.ts +50 -631
- package/src/services/jsonlHandler.ts +84 -100
- package/src/services/memory.ts +2 -59
- package/src/services/session.ts +338 -213
- package/src/tools/bashTool.ts +89 -16
- package/src/tools/deleteFileTool.ts +36 -0
- package/src/tools/editTool.ts +41 -7
- package/src/tools/lspTool.ts +760 -0
- package/src/tools/multiEditTool.ts +37 -8
- package/src/tools/readTool.ts +125 -2
- 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 +36 -10
- package/src/types/commands.ts +0 -1
- package/src/types/config.ts +5 -0
- package/src/types/configuration.ts +73 -0
- package/src/types/core.ts +11 -0
- package/src/types/environment.ts +44 -0
- package/src/types/fileSearch.ts +4 -0
- package/src/types/hooks.ts +14 -11
- package/src/types/index.ts +5 -0
- package/src/types/lsp.ts +96 -0
- package/src/types/messaging.ts +8 -13
- package/src/types/permissions.ts +48 -0
- package/src/types/session.ts +3 -8
- 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 +28 -4
- package/src/utils/builtinSubagents.ts +71 -0
- package/src/utils/cacheControlUtils.ts +106 -171
- package/src/utils/constants.ts +1 -16
- package/src/utils/convertMessagesForAPI.ts +38 -14
- package/src/utils/fileSearch.ts +107 -0
- package/src/utils/fileUtils.ts +114 -19
- package/src/utils/globalLogger.ts +0 -17
- package/src/utils/largeOutputHandler.ts +55 -0
- package/src/utils/markdownParser.ts +1 -19
- package/src/utils/messageOperations.ts +7 -35
- package/src/utils/pathEncoder.ts +24 -9
- package/src/utils/subagentParser.ts +11 -8
- package/src/utils/tokenEstimator.ts +68 -0
- package/dist/constants/events.d.ts +0 -28
- package/dist/constants/events.d.ts.map +0 -1
- package/dist/constants/events.js +0 -27
- package/dist/services/configurationWatcher.d.ts +0 -120
- package/dist/services/configurationWatcher.d.ts.map +0 -1
- package/dist/services/configurationWatcher.js +0 -439
- package/dist/services/memoryStore.d.ts +0 -81
- package/dist/services/memoryStore.d.ts.map +0 -1
- package/dist/services/memoryStore.js +0 -200
- package/dist/types/memoryStore.d.ts +0 -82
- package/dist/types/memoryStore.d.ts.map +0 -1
- package/dist/types/memoryStore.js +0 -7
- package/dist/utils/configResolver.d.ts +0 -65
- package/dist/utils/configResolver.d.ts.map +0 -1
- package/dist/utils/configResolver.js +0 -210
- package/src/constants/events.ts +0 -38
- package/src/services/configurationWatcher.ts +0 -622
- package/src/services/memoryStore.ts +0 -279
- package/src/types/memoryStore.ts +0 -94
- package/src/utils/configResolver.ts +0 -302
|
@@ -11,8 +11,10 @@ import type {
|
|
|
11
11
|
ChatCompletionContentPart,
|
|
12
12
|
ChatCompletionContentPartText,
|
|
13
13
|
ChatCompletionFunctionTool,
|
|
14
|
+
ChatCompletionMessageToolCall,
|
|
14
15
|
CompletionUsage,
|
|
15
16
|
} from "openai/resources";
|
|
17
|
+
import { logger } from "./globalLogger.js";
|
|
16
18
|
|
|
17
19
|
// ============================================================================
|
|
18
20
|
// Core Types
|
|
@@ -62,28 +64,10 @@ export interface ClaudeUsage extends CompletionUsage {
|
|
|
62
64
|
};
|
|
63
65
|
}
|
|
64
66
|
|
|
65
|
-
/**
|
|
66
|
-
* Configuration for cache control application
|
|
67
|
-
*/
|
|
68
|
-
export interface CacheControlConfig {
|
|
69
|
-
cacheSystemMessage: boolean;
|
|
70
|
-
cacheUserMessageCount: number;
|
|
71
|
-
cacheLastTool: boolean;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
67
|
// ============================================================================
|
|
75
68
|
// Default Configuration
|
|
76
69
|
// ============================================================================
|
|
77
70
|
|
|
78
|
-
/**
|
|
79
|
-
* Default cache control configuration
|
|
80
|
-
*/
|
|
81
|
-
export const DEFAULT_CACHE_CONTROL_CONFIG: CacheControlConfig = {
|
|
82
|
-
cacheSystemMessage: true,
|
|
83
|
-
cacheUserMessageCount: 2,
|
|
84
|
-
cacheLastTool: true,
|
|
85
|
-
} as const;
|
|
86
|
-
|
|
87
71
|
// ============================================================================
|
|
88
72
|
// Utility Functions (Basic Structure - to be implemented)
|
|
89
73
|
// ============================================================================
|
|
@@ -123,6 +107,30 @@ export function isValidCacheControl(control: unknown): control is CacheControl {
|
|
|
123
107
|
);
|
|
124
108
|
}
|
|
125
109
|
|
|
110
|
+
/**
|
|
111
|
+
* Adds cache control to the last tool call in an array
|
|
112
|
+
* @param toolCalls - Array of tool calls
|
|
113
|
+
* @returns Tool calls array with cache control on the last tool call
|
|
114
|
+
*/
|
|
115
|
+
function addCacheControlToLastToolCall(
|
|
116
|
+
toolCalls: ChatCompletionMessageToolCall[],
|
|
117
|
+
): ChatCompletionMessageToolCall[] {
|
|
118
|
+
if (!toolCalls || toolCalls.length === 0) {
|
|
119
|
+
return toolCalls;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const result = [...toolCalls];
|
|
123
|
+
const lastIndex = result.length - 1;
|
|
124
|
+
|
|
125
|
+
// Add cache control to the last tool call
|
|
126
|
+
result[lastIndex] = {
|
|
127
|
+
...result[lastIndex],
|
|
128
|
+
cache_control: { type: "ephemeral" },
|
|
129
|
+
} as ChatCompletionMessageToolCall & { cache_control: CacheControl };
|
|
130
|
+
|
|
131
|
+
return result;
|
|
132
|
+
}
|
|
133
|
+
|
|
126
134
|
/**
|
|
127
135
|
* Adds cache control markers to message content
|
|
128
136
|
* @param content - Original content (string or structured)
|
|
@@ -146,7 +154,7 @@ export function addCacheControlToContent(
|
|
|
146
154
|
|
|
147
155
|
// Validate array input
|
|
148
156
|
if (!Array.isArray(content)) {
|
|
149
|
-
|
|
157
|
+
logger.warn(
|
|
150
158
|
"Invalid content type for cache control transformation:",
|
|
151
159
|
typeof content,
|
|
152
160
|
);
|
|
@@ -178,7 +186,7 @@ export function addCacheControlToContent(
|
|
|
178
186
|
|
|
179
187
|
// Validate array input
|
|
180
188
|
if (!Array.isArray(content)) {
|
|
181
|
-
|
|
189
|
+
logger.warn(
|
|
182
190
|
"Invalid content type for cache control transformation:",
|
|
183
191
|
typeof content,
|
|
184
192
|
);
|
|
@@ -216,11 +224,11 @@ export function addCacheControlToLastTool(
|
|
|
216
224
|
// Validate tools structure
|
|
217
225
|
const validTools = tools.filter((tool) => {
|
|
218
226
|
if (!tool || typeof tool !== "object") {
|
|
219
|
-
|
|
227
|
+
logger.warn("Invalid tool structure detected, skipping:", tool);
|
|
220
228
|
return false;
|
|
221
229
|
}
|
|
222
230
|
if (tool.type !== "function" || !tool.function) {
|
|
223
|
-
|
|
231
|
+
logger.warn(
|
|
224
232
|
"Tool is not a function type or missing function property:",
|
|
225
233
|
tool,
|
|
226
234
|
);
|
|
@@ -230,7 +238,7 @@ export function addCacheControlToLastTool(
|
|
|
230
238
|
});
|
|
231
239
|
|
|
232
240
|
if (validTools.length === 0) {
|
|
233
|
-
|
|
241
|
+
logger.warn("No valid tools found for cache control");
|
|
234
242
|
return [];
|
|
235
243
|
}
|
|
236
244
|
|
|
@@ -250,20 +258,47 @@ export function addCacheControlToLastTool(
|
|
|
250
258
|
}
|
|
251
259
|
|
|
252
260
|
/**
|
|
253
|
-
*
|
|
261
|
+
* Finds the latest message index at 20-message intervals (sliding window approach)
|
|
262
|
+
* @param messages - Array of chat completion messages
|
|
263
|
+
* @returns Index of the latest interval message (20th, 40th, 60th, etc.) or -1 if none
|
|
264
|
+
*/
|
|
265
|
+
export function findIntervalMessageIndex(
|
|
266
|
+
messages: ChatCompletionMessageParam[],
|
|
267
|
+
): number {
|
|
268
|
+
if (!Array.isArray(messages) || messages.length === 0) {
|
|
269
|
+
return -1;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
const interval = 20; // Hardcoded interval
|
|
273
|
+
const messageCount = messages.length;
|
|
274
|
+
|
|
275
|
+
// Find the largest interval that fits within the message count
|
|
276
|
+
// Math.floor(messageCount / interval) gives us how many complete intervals we have
|
|
277
|
+
// Multiply by interval to get the position of the latest interval message
|
|
278
|
+
const latestIntervalPosition = Math.floor(messageCount / interval) * interval;
|
|
279
|
+
|
|
280
|
+
// If no complete intervals exist, return -1
|
|
281
|
+
if (latestIntervalPosition === 0) {
|
|
282
|
+
return -1;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Convert from 1-based position to 0-based index
|
|
286
|
+
return latestIntervalPosition - 1;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Transforms messages for Claude cache control with hardcoded strategy
|
|
254
291
|
* @param messages - Original OpenAI message array
|
|
255
292
|
* @param modelName - Model name for cache detection
|
|
256
|
-
* @param config - Cache control configuration
|
|
257
293
|
* @returns Messages with cache control markers applied
|
|
258
294
|
*/
|
|
259
295
|
export function transformMessagesForClaudeCache(
|
|
260
296
|
messages: ChatCompletionMessageParam[],
|
|
261
297
|
modelName: string,
|
|
262
|
-
config: CacheControlConfig = DEFAULT_CACHE_CONTROL_CONFIG,
|
|
263
298
|
): ChatCompletionMessageParam[] {
|
|
264
299
|
// Validate inputs
|
|
265
300
|
if (!messages || !Array.isArray(messages)) {
|
|
266
|
-
|
|
301
|
+
logger.warn(
|
|
267
302
|
"Invalid messages array provided to transformMessagesForClaudeCache",
|
|
268
303
|
);
|
|
269
304
|
return [];
|
|
@@ -278,46 +313,64 @@ export function transformMessagesForClaudeCache(
|
|
|
278
313
|
return messages;
|
|
279
314
|
}
|
|
280
315
|
|
|
281
|
-
//
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
316
|
+
// Find the latest interval message index (20th, 40th, 60th, etc.)
|
|
317
|
+
const intervalMessageIndex = findIntervalMessageIndex(messages);
|
|
318
|
+
|
|
319
|
+
// Find last system message index
|
|
320
|
+
let lastSystemIndex = -1;
|
|
321
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
322
|
+
if (messages[i].role === "system") {
|
|
323
|
+
lastSystemIndex = i;
|
|
324
|
+
break;
|
|
325
|
+
}
|
|
285
326
|
}
|
|
286
327
|
|
|
287
328
|
const result = messages.map((message, index) => {
|
|
288
329
|
// Validate message structure
|
|
289
330
|
if (!message || typeof message !== "object" || !message.role) {
|
|
290
|
-
|
|
331
|
+
logger.warn("Invalid message structure at index", index, ":", message);
|
|
291
332
|
return message; // Return as-is to avoid breaking the flow
|
|
292
333
|
}
|
|
293
334
|
|
|
294
|
-
//
|
|
295
|
-
if (message.role === "system" &&
|
|
335
|
+
// Last system message: always cached (hardcoded)
|
|
336
|
+
if (message.role === "system" && index === lastSystemIndex) {
|
|
296
337
|
return {
|
|
297
338
|
...message,
|
|
298
|
-
content: addCacheControlToContent(
|
|
299
|
-
|
|
339
|
+
content: addCacheControlToContent(
|
|
340
|
+
(message.content as string | ChatCompletionContentPart[]) || "",
|
|
341
|
+
true,
|
|
342
|
+
),
|
|
343
|
+
} as ChatCompletionMessageParam;
|
|
300
344
|
}
|
|
301
345
|
|
|
302
|
-
//
|
|
303
|
-
if (
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
//
|
|
312
|
-
|
|
313
|
-
.
|
|
314
|
-
.
|
|
315
|
-
|
|
316
|
-
|
|
346
|
+
// Interval-based message caching: cache message at latest interval position (sliding window)
|
|
347
|
+
if (index === intervalMessageIndex) {
|
|
348
|
+
// If the message is a tool role, add cache control directly to the message
|
|
349
|
+
if (message.role === "tool") {
|
|
350
|
+
return {
|
|
351
|
+
...message,
|
|
352
|
+
cache_control: { type: "ephemeral" },
|
|
353
|
+
} as ChatCompletionMessageParam;
|
|
354
|
+
}
|
|
355
|
+
// If the message has tool calls, cache the last tool call instead of content
|
|
356
|
+
else if (
|
|
357
|
+
message.role === "assistant" &&
|
|
358
|
+
message.tool_calls &&
|
|
359
|
+
message.tool_calls.length > 0
|
|
360
|
+
) {
|
|
361
|
+
return {
|
|
362
|
+
...message,
|
|
363
|
+
tool_calls: addCacheControlToLastToolCall(message.tool_calls),
|
|
364
|
+
} as ChatCompletionMessageParam;
|
|
365
|
+
} else {
|
|
366
|
+
// For other message types without tool calls, cache the content
|
|
317
367
|
return {
|
|
318
368
|
...message,
|
|
319
|
-
content: addCacheControlToContent(
|
|
320
|
-
|
|
369
|
+
content: addCacheControlToContent(
|
|
370
|
+
(message.content as string | ChatCompletionContentPart[]) || "",
|
|
371
|
+
true,
|
|
372
|
+
),
|
|
373
|
+
} as ChatCompletionMessageParam;
|
|
321
374
|
}
|
|
322
375
|
}
|
|
323
376
|
|
|
@@ -420,121 +473,3 @@ export function isValidClaudeUsage(usage: unknown): usage is ClaudeUsage {
|
|
|
420
473
|
|
|
421
474
|
return true;
|
|
422
475
|
}
|
|
423
|
-
|
|
424
|
-
/**
|
|
425
|
-
* Adds cache control to the last N user messages in a conversation
|
|
426
|
-
* This optimizes multi-turn conversations by caching recent user context
|
|
427
|
-
*
|
|
428
|
-
* @param messages - Array of chat completion messages
|
|
429
|
-
* @param maxUserMessagesToCache - Maximum number of recent user messages to cache (default: 2)
|
|
430
|
-
* @returns Modified messages array with cache control on recent user messages
|
|
431
|
-
*/
|
|
432
|
-
export function addCacheControlToRecentUserMessages(
|
|
433
|
-
messages: ChatCompletionMessageParam[],
|
|
434
|
-
maxUserMessagesToCache: number = 2,
|
|
435
|
-
): ChatCompletionMessageParam[] {
|
|
436
|
-
// Validate inputs
|
|
437
|
-
if (!messages || !Array.isArray(messages)) {
|
|
438
|
-
console.warn(
|
|
439
|
-
"Invalid messages array provided to addCacheControlToRecentUserMessages",
|
|
440
|
-
);
|
|
441
|
-
return [];
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
if (messages.length === 0 || maxUserMessagesToCache <= 0) {
|
|
445
|
-
return messages;
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
// Validate maxUserMessagesToCache is a reasonable number
|
|
449
|
-
if (maxUserMessagesToCache > 100) {
|
|
450
|
-
console.warn(
|
|
451
|
-
"maxUserMessagesToCache is unusually high:",
|
|
452
|
-
maxUserMessagesToCache,
|
|
453
|
-
"limiting to 100",
|
|
454
|
-
);
|
|
455
|
-
maxUserMessagesToCache = 100;
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
// Find all user message indices in reverse order (most recent first)
|
|
459
|
-
const userMessageIndices: number[] = [];
|
|
460
|
-
for (let i = messages.length - 1; i >= 0; i--) {
|
|
461
|
-
const message = messages[i];
|
|
462
|
-
|
|
463
|
-
// Validate message structure
|
|
464
|
-
if (!message || typeof message !== "object" || !message.role) {
|
|
465
|
-
console.warn("Invalid message at index", i, ", skipping");
|
|
466
|
-
continue;
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
if (message.role === "user") {
|
|
470
|
-
userMessageIndices.push(i);
|
|
471
|
-
if (userMessageIndices.length >= maxUserMessagesToCache) {
|
|
472
|
-
break;
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
// If no user messages found, return unchanged
|
|
478
|
-
if (userMessageIndices.length === 0) {
|
|
479
|
-
return messages;
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
// Create a copy of messages and modify the identified user messages
|
|
483
|
-
const modifiedMessages = [...messages];
|
|
484
|
-
|
|
485
|
-
for (const index of userMessageIndices) {
|
|
486
|
-
const message = modifiedMessages[index];
|
|
487
|
-
if (message.role === "user" && message.content != null) {
|
|
488
|
-
try {
|
|
489
|
-
modifiedMessages[index] = {
|
|
490
|
-
...message,
|
|
491
|
-
content: addCacheControlToContent(message.content, true),
|
|
492
|
-
};
|
|
493
|
-
} catch (error) {
|
|
494
|
-
console.warn(
|
|
495
|
-
"Failed to add cache control to user message at index",
|
|
496
|
-
index,
|
|
497
|
-
":",
|
|
498
|
-
error,
|
|
499
|
-
);
|
|
500
|
-
// Continue with original message if transformation fails
|
|
501
|
-
}
|
|
502
|
-
}
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
return modifiedMessages;
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
/**
|
|
509
|
-
* Helper function to identify user message indices that should be cached
|
|
510
|
-
* Used for testing and validation purposes
|
|
511
|
-
*
|
|
512
|
-
* @param messages - Array of chat completion messages
|
|
513
|
-
* @param maxUserMessagesToCache - Maximum number of recent user messages to identify
|
|
514
|
-
* @returns Array of indices for user messages that should be cached
|
|
515
|
-
*/
|
|
516
|
-
export function findRecentUserMessageIndices(
|
|
517
|
-
messages: ChatCompletionMessageParam[],
|
|
518
|
-
maxUserMessagesToCache: number = 2,
|
|
519
|
-
): number[] {
|
|
520
|
-
if (
|
|
521
|
-
!Array.isArray(messages) ||
|
|
522
|
-
messages.length === 0 ||
|
|
523
|
-
maxUserMessagesToCache <= 0
|
|
524
|
-
) {
|
|
525
|
-
return [];
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
const userMessageIndices: number[] = [];
|
|
529
|
-
for (let i = messages.length - 1; i >= 0; i--) {
|
|
530
|
-
if (messages[i].role === "user") {
|
|
531
|
-
userMessageIndices.push(i);
|
|
532
|
-
if (userMessageIndices.length >= maxUserMessagesToCache) {
|
|
533
|
-
break;
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
// Return indices in original order (not reversed)
|
|
539
|
-
return userMessageIndices.reverse();
|
|
540
|
-
}
|
package/src/utils/constants.ts
CHANGED
|
@@ -24,24 +24,9 @@ export const ERROR_LOG_DIRECTORY = path.join(DATA_DIRECTORY, "error-logs");
|
|
|
24
24
|
/**
|
|
25
25
|
* User-level memory file path
|
|
26
26
|
*/
|
|
27
|
-
export const USER_MEMORY_FILE = path.join(DATA_DIRECTORY, "
|
|
27
|
+
export const USER_MEMORY_FILE = path.join(DATA_DIRECTORY, "AGENTS.md");
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
30
|
* AI related constants
|
|
31
31
|
*/
|
|
32
32
|
export const DEFAULT_TOKEN_LIMIT = 96000; // Default token limit
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* @deprecated These constants are now legacy. Use ModelConfig through Agent constructor instead.
|
|
36
|
-
* They are maintained for backward compatibility with existing code that might still reference them,
|
|
37
|
-
* but the actual AI services now use configuration injection.
|
|
38
|
-
*/
|
|
39
|
-
export const FAST_MODEL_ID = process.env.AIGW_FAST_MODEL || "gemini-2.5-flash";
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* @deprecated These constants are now legacy. Use ModelConfig through Agent constructor instead.
|
|
43
|
-
* They are maintained for backward compatibility with existing code that might still reference them,
|
|
44
|
-
* but the actual AI services now use configuration injection.
|
|
45
|
-
*/
|
|
46
|
-
export const AGENT_MODEL_ID =
|
|
47
|
-
process.env.AIGW_MODEL || "claude-sonnet-4-20250514";
|
|
@@ -30,7 +30,8 @@ function safeToolArguments(args: string): string {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
|
-
* Convert message format to API call format, stopping when a compressed message is encountered
|
|
33
|
+
* Convert message format to API call format, stopping when a compressed message is encountered.
|
|
34
|
+
* Messages with no meaningful content or tool calls are filtered out.
|
|
34
35
|
* @param messages Message list
|
|
35
36
|
* @returns Converted API message format list
|
|
36
37
|
*/
|
|
@@ -61,7 +62,7 @@ export function convertMessagesForAPI(
|
|
|
61
62
|
break;
|
|
62
63
|
}
|
|
63
64
|
|
|
64
|
-
// Skip empty assistant messages
|
|
65
|
+
// Skip empty assistant messages (no blocks or all blocks are empty)
|
|
65
66
|
if (message.role === "assistant" && message.blocks.length === 0) {
|
|
66
67
|
continue;
|
|
67
68
|
}
|
|
@@ -128,12 +129,17 @@ export function convertMessagesForAPI(
|
|
|
128
129
|
let content = "";
|
|
129
130
|
let tool_calls: ChatCompletionMessageToolCall[] | undefined = undefined;
|
|
130
131
|
|
|
131
|
-
// Construct content from text blocks
|
|
132
|
+
// Construct content from text blocks - filter out empty content
|
|
132
133
|
const textBlocks = message.blocks.filter(
|
|
133
|
-
(block) =>
|
|
134
|
+
(block) =>
|
|
135
|
+
block.type === "text" &&
|
|
136
|
+
block.content &&
|
|
137
|
+
block.content.trim().length > 0,
|
|
134
138
|
);
|
|
135
139
|
if (textBlocks.length > 0) {
|
|
136
|
-
content = textBlocks
|
|
140
|
+
content = textBlocks
|
|
141
|
+
.map((block) => (block.type === "text" ? block.content : ""))
|
|
142
|
+
.join("\n");
|
|
137
143
|
}
|
|
138
144
|
|
|
139
145
|
// Construct tool calls from tool blocks
|
|
@@ -158,13 +164,16 @@ export function convertMessagesForAPI(
|
|
|
158
164
|
}
|
|
159
165
|
}
|
|
160
166
|
|
|
161
|
-
// Construct assistant message - only add if there is content or tool calls
|
|
162
|
-
|
|
167
|
+
// Construct assistant message - only add if there is meaningful content or tool calls
|
|
168
|
+
const hasContent = content && content.trim().length > 0;
|
|
169
|
+
const hasToolCalls = tool_calls && tool_calls.length > 0;
|
|
170
|
+
|
|
171
|
+
if (hasContent || hasToolCalls) {
|
|
163
172
|
const assistantMessage: ChatCompletionMessageParam = {
|
|
164
173
|
role: "assistant",
|
|
165
|
-
content,
|
|
174
|
+
content: hasContent ? content : undefined,
|
|
166
175
|
tool_calls,
|
|
167
|
-
...(message.
|
|
176
|
+
...(message.additionalFields ? { ...message.additionalFields } : {}),
|
|
168
177
|
};
|
|
169
178
|
|
|
170
179
|
recentMessages.unshift(assistantMessage);
|
|
@@ -174,8 +183,12 @@ export function convertMessagesForAPI(
|
|
|
174
183
|
const contentParts: ChatCompletionContentPart[] = [];
|
|
175
184
|
|
|
176
185
|
message.blocks.forEach((block) => {
|
|
177
|
-
// Add text content
|
|
178
|
-
if (
|
|
186
|
+
// Add text content - only if it has meaningful content
|
|
187
|
+
if (
|
|
188
|
+
block.type === "text" &&
|
|
189
|
+
block.content &&
|
|
190
|
+
block.content.trim().length > 0
|
|
191
|
+
) {
|
|
179
192
|
contentParts.push({
|
|
180
193
|
type: "text",
|
|
181
194
|
text: block.customCommandContent || block.content,
|
|
@@ -217,11 +230,22 @@ export function convertMessagesForAPI(
|
|
|
217
230
|
}
|
|
218
231
|
});
|
|
219
232
|
|
|
233
|
+
// Only add user message if there is meaningful content
|
|
220
234
|
if (contentParts.length > 0) {
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
235
|
+
// Filter out empty text parts
|
|
236
|
+
const meaningfulParts = contentParts.filter((part) => {
|
|
237
|
+
if (part.type === "text") {
|
|
238
|
+
return part.text && part.text.trim().length > 0;
|
|
239
|
+
}
|
|
240
|
+
return true; // Keep image parts
|
|
224
241
|
});
|
|
242
|
+
|
|
243
|
+
if (meaningfulParts.length > 0) {
|
|
244
|
+
recentMessages.unshift({
|
|
245
|
+
role: "user",
|
|
246
|
+
content: meaningfulParts,
|
|
247
|
+
});
|
|
248
|
+
}
|
|
225
249
|
}
|
|
226
250
|
}
|
|
227
251
|
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { globIterate, type Path } from "glob";
|
|
2
|
+
import { getGlobIgnorePatterns } from "./fileFilter.js";
|
|
3
|
+
import type { FileItem } from "../types/fileSearch.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Convert Path objects to FileItem objects
|
|
7
|
+
*/
|
|
8
|
+
export const convertPathsToFileItems = (paths: Path[]): FileItem[] => {
|
|
9
|
+
return paths.map((pathObj) => ({
|
|
10
|
+
path: pathObj.relative(),
|
|
11
|
+
type: pathObj.isDirectory() ? "directory" : "file",
|
|
12
|
+
}));
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Search files and directories using glob patterns
|
|
17
|
+
*/
|
|
18
|
+
export const searchFiles = async (
|
|
19
|
+
query: string,
|
|
20
|
+
options?: {
|
|
21
|
+
maxResults?: number;
|
|
22
|
+
workingDirectory?: string;
|
|
23
|
+
},
|
|
24
|
+
): Promise<FileItem[]> => {
|
|
25
|
+
const { maxResults = 10, workingDirectory = process.cwd() } = options || {};
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
const globOptions: import("glob").GlobOptionsWithFileTypesTrue = {
|
|
29
|
+
ignore: getGlobIgnorePatterns(workingDirectory),
|
|
30
|
+
maxDepth: 10,
|
|
31
|
+
nocase: true, // Case insensitive
|
|
32
|
+
dot: true, // Include hidden files and directories
|
|
33
|
+
cwd: workingDirectory, // Specify search root directory
|
|
34
|
+
withFileTypes: true, // Get Path objects instead of strings
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// Build glob patterns based on query
|
|
38
|
+
let patterns: string[] = [];
|
|
39
|
+
|
|
40
|
+
if (!query.trim()) {
|
|
41
|
+
// When query is empty, show some common file types and directories
|
|
42
|
+
patterns = [
|
|
43
|
+
"**/*.{ts,tsx,js,jsx,json,py,java}", // Combine common file extensions
|
|
44
|
+
"*/", // First level directories
|
|
45
|
+
];
|
|
46
|
+
} else {
|
|
47
|
+
// Build multiple glob patterns to support more flexible search
|
|
48
|
+
patterns = [
|
|
49
|
+
// Match files with filenames containing query
|
|
50
|
+
`**/*${query}*`,
|
|
51
|
+
// Match files with query in path (match directory names)
|
|
52
|
+
`**/${query}*/**/*`,
|
|
53
|
+
// Match directory names containing query
|
|
54
|
+
`**/*${query}*/`,
|
|
55
|
+
// Match directories containing query in path
|
|
56
|
+
`**/${query}*/`,
|
|
57
|
+
];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Collect results until we reach maxResults
|
|
61
|
+
const collectedPaths: Path[] = [];
|
|
62
|
+
const seenPaths = new Set<string>();
|
|
63
|
+
|
|
64
|
+
// Process each pattern sequentially
|
|
65
|
+
for (const pattern of patterns) {
|
|
66
|
+
if (collectedPaths.length >= maxResults) {
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Use globIterate to get results one by one
|
|
71
|
+
const iterator = globIterate(pattern, globOptions) as AsyncGenerator<
|
|
72
|
+
Path,
|
|
73
|
+
void,
|
|
74
|
+
void
|
|
75
|
+
>;
|
|
76
|
+
|
|
77
|
+
for await (const pathObj of iterator) {
|
|
78
|
+
if (collectedPaths.length >= maxResults) {
|
|
79
|
+
// Stop the iterator when we have enough results
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const relativePath = pathObj.relative();
|
|
84
|
+
if (!seenPaths.has(relativePath)) {
|
|
85
|
+
seenPaths.add(relativePath);
|
|
86
|
+
collectedPaths.push(pathObj);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Sort collected paths: directories first, then files
|
|
92
|
+
collectedPaths.sort((a, b) => {
|
|
93
|
+
const aIsDir = a.isDirectory();
|
|
94
|
+
const bIsDir = b.isDirectory();
|
|
95
|
+
if (aIsDir && !bIsDir) return -1;
|
|
96
|
+
if (!aIsDir && bIsDir) return 1;
|
|
97
|
+
return a.relative().localeCompare(b.relative());
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// Convert to FileItems
|
|
101
|
+
const fileItems = convertPathsToFileItems(collectedPaths);
|
|
102
|
+
return fileItems;
|
|
103
|
+
} catch (error) {
|
|
104
|
+
console.error("Glob search error:", error);
|
|
105
|
+
return [];
|
|
106
|
+
}
|
|
107
|
+
};
|