wave-agent-sdk 0.17.9 → 0.17.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/builtin/skills/settings/ENV.md +1 -1
- package/dist/managers/aiManager.d.ts +10 -4
- package/dist/managers/aiManager.d.ts.map +1 -1
- package/dist/managers/aiManager.js +214 -200
- package/dist/managers/backgroundTaskManager.js +1 -1
- package/dist/managers/bangManager.js +1 -1
- package/dist/managers/hookManager.js +2 -4
- package/dist/managers/mcpManager.d.ts.map +1 -1
- package/dist/managers/mcpManager.js +1 -3
- package/dist/managers/messageManager.d.ts.map +1 -1
- package/dist/managers/messageManager.js +1 -8
- package/dist/managers/toolManager.d.ts +6 -0
- package/dist/managers/toolManager.d.ts.map +1 -1
- package/dist/managers/toolManager.js +17 -12
- package/dist/services/aiService.d.ts.map +1 -1
- package/dist/services/aiService.js +20 -12
- package/dist/services/configurationService.d.ts.map +1 -1
- package/dist/services/configurationService.js +13 -0
- package/dist/services/jsonlHandler.d.ts +1 -1
- package/dist/services/jsonlHandler.d.ts.map +1 -1
- package/dist/services/jsonlHandler.js +7 -22
- package/dist/services/session.d.ts +2 -9
- package/dist/services/session.d.ts.map +1 -1
- package/dist/services/session.js +16 -46
- package/dist/tools/bashTool.d.ts.map +1 -1
- package/dist/tools/bashTool.js +3 -1
- package/dist/tools/editTool.d.ts.map +1 -1
- package/dist/tools/editTool.js +28 -1
- package/dist/tools/enterPlanMode.d.ts.map +1 -1
- package/dist/tools/enterPlanMode.js +8 -0
- package/dist/tools/exitPlanMode.d.ts.map +1 -1
- package/dist/tools/exitPlanMode.js +8 -0
- package/dist/tools/readTool.d.ts.map +1 -1
- package/dist/tools/readTool.js +18 -10
- package/dist/tools/types.d.ts +8 -2
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/writeTool.d.ts.map +1 -1
- package/dist/tools/writeTool.js +14 -1
- package/dist/types/agent.d.ts +0 -2
- package/dist/types/agent.d.ts.map +1 -1
- package/dist/types/config.d.ts +1 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/utils/cacheControlUtils.d.ts +20 -15
- package/dist/utils/cacheControlUtils.d.ts.map +1 -1
- package/dist/utils/cacheControlUtils.js +69 -66
- package/dist/utils/constants.d.ts +1 -1
- package/dist/utils/constants.js +1 -1
- package/dist/utils/containerSetup.d.ts.map +1 -1
- package/dist/utils/containerSetup.js +1 -6
- package/package.json +1 -1
- package/src/managers/aiManager.ts +292 -263
- package/src/managers/backgroundTaskManager.ts +1 -1
- package/src/managers/bangManager.ts +1 -1
- package/src/managers/hookManager.ts +6 -6
- package/src/managers/mcpManager.ts +2 -4
- package/src/managers/messageManager.ts +1 -9
- package/src/managers/toolManager.ts +18 -12
- package/src/services/aiService.ts +23 -12
- package/src/services/configurationService.ts +21 -0
- package/src/services/jsonlHandler.ts +7 -27
- package/src/services/session.ts +16 -57
- package/src/tools/bashTool.ts +3 -1
- package/src/tools/editTool.ts +31 -1
- package/src/tools/enterPlanMode.ts +9 -0
- package/src/tools/exitPlanMode.ts +10 -0
- package/src/tools/readTool.ts +20 -10
- package/src/tools/types.ts +15 -3
- package/src/tools/writeTool.ts +15 -1
- package/src/types/agent.ts +0 -2
- package/src/types/config.ts +1 -0
- package/src/utils/cacheControlUtils.ts +77 -95
- package/src/utils/constants.ts +1 -1
- package/src/utils/containerSetup.ts +3 -7
package/src/types/config.ts
CHANGED
|
@@ -10,7 +10,6 @@ import type {
|
|
|
10
10
|
ChatCompletionMessageParam,
|
|
11
11
|
ChatCompletionContentPart,
|
|
12
12
|
ChatCompletionContentPartText,
|
|
13
|
-
ChatCompletionFunctionTool,
|
|
14
13
|
CompletionUsage,
|
|
15
14
|
} from "openai/resources";
|
|
16
15
|
import { logger } from "./globalLogger.js";
|
|
@@ -36,16 +35,6 @@ export interface ClaudeChatCompletionContentPartText
|
|
|
36
35
|
cache_control?: CacheControl;
|
|
37
36
|
}
|
|
38
37
|
|
|
39
|
-
/**
|
|
40
|
-
* Extended tool definition with cache control support
|
|
41
|
-
*/
|
|
42
|
-
export interface ClaudeChatCompletionFunctionTool
|
|
43
|
-
extends ChatCompletionFunctionTool {
|
|
44
|
-
type: "function";
|
|
45
|
-
function: ChatCompletionFunctionTool["function"];
|
|
46
|
-
cache_control?: CacheControl;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
38
|
/**
|
|
50
39
|
* Extended prompt_tokens_details with cache_creation_input_tokens
|
|
51
40
|
* Some models (e.g. Gemini, DeepSeek) return this field inside prompt_tokens_details
|
|
@@ -229,68 +218,53 @@ export function addCacheControlToContent(
|
|
|
229
218
|
}
|
|
230
219
|
|
|
231
220
|
/**
|
|
232
|
-
*
|
|
233
|
-
*
|
|
234
|
-
*
|
|
221
|
+
* Counts the total number of content blocks across all messages.
|
|
222
|
+
* Each element in a message's content array counts as one block.
|
|
223
|
+
* String content counts as one block. Null/undefined content counts as zero
|
|
224
|
+
* (e.g. assistant messages with only tool_calls).
|
|
225
|
+
* @param messages - Array of chat messages
|
|
226
|
+
* @returns Total content block count
|
|
235
227
|
*/
|
|
236
|
-
export function
|
|
237
|
-
|
|
238
|
-
):
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
logger.warn("Invalid tool structure detected, skipping:", tool);
|
|
248
|
-
return false;
|
|
249
|
-
}
|
|
250
|
-
if (tool.type !== "function" || !tool.function) {
|
|
251
|
-
logger.warn(
|
|
252
|
-
"Tool is not a function type or missing function property:",
|
|
253
|
-
tool,
|
|
254
|
-
);
|
|
255
|
-
return false;
|
|
228
|
+
export function countContentBlocks(
|
|
229
|
+
messages: ChatCompletionMessageParam[],
|
|
230
|
+
): number {
|
|
231
|
+
let count = 0;
|
|
232
|
+
for (const message of messages) {
|
|
233
|
+
if (!message || typeof message !== "object") continue;
|
|
234
|
+
const content = message.content;
|
|
235
|
+
if (typeof content === "string") {
|
|
236
|
+
count += 1;
|
|
237
|
+
} else if (Array.isArray(content)) {
|
|
238
|
+
count += content.length;
|
|
256
239
|
}
|
|
257
|
-
return true;
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
if (validTools.length === 0) {
|
|
261
|
-
logger.warn("No valid tools found for cache control");
|
|
262
|
-
return [];
|
|
263
240
|
}
|
|
264
|
-
|
|
265
|
-
// Create a copy of the valid tools array
|
|
266
|
-
const result = validTools.map((tool) => ({
|
|
267
|
-
...tool,
|
|
268
|
-
})) as ClaudeChatCompletionFunctionTool[];
|
|
269
|
-
|
|
270
|
-
// Add cache control to the last tool only
|
|
271
|
-
const lastIndex = result.length - 1;
|
|
272
|
-
result[lastIndex] = {
|
|
273
|
-
...result[lastIndex],
|
|
274
|
-
cache_control: { type: "ephemeral" },
|
|
275
|
-
};
|
|
276
|
-
|
|
277
|
-
return result;
|
|
241
|
+
return count;
|
|
278
242
|
}
|
|
279
243
|
|
|
280
244
|
/**
|
|
281
|
-
* Transforms messages for
|
|
245
|
+
* Transforms messages for explicit cache control.
|
|
246
|
+
*
|
|
247
|
+
* Cache breakpoints (following Claude Code's "last message marker" strategy):
|
|
248
|
+
* 1. System message — always marked (stable prefix)
|
|
249
|
+
* 2. Last message — the last user/assistant message with content is marked.
|
|
250
|
+
* The API scans backward from this marker within 20 blocks. Since each
|
|
251
|
+
* turn adds ~2 blocks (< 20), the previous request's marker position
|
|
252
|
+
* always falls within the scan window, ensuring cache hits.
|
|
253
|
+
*
|
|
254
|
+
* Tools are marked separately via addCacheControlToLastTool (called by aiService).
|
|
255
|
+
*
|
|
282
256
|
* @param messages - Original OpenAI message array
|
|
283
257
|
* @param modelName - Model name for cache detection
|
|
284
258
|
* @returns Messages with cache control markers applied
|
|
285
259
|
*/
|
|
286
|
-
export function
|
|
260
|
+
export function transformMessagesForExplicitCache(
|
|
287
261
|
messages: ChatCompletionMessageParam[],
|
|
288
262
|
modelName: string,
|
|
289
263
|
): ChatCompletionMessageParam[] {
|
|
290
264
|
// Validate inputs
|
|
291
265
|
if (!messages || !Array.isArray(messages)) {
|
|
292
266
|
logger.warn(
|
|
293
|
-
"Invalid messages array provided to
|
|
267
|
+
"Invalid messages array provided to transformMessagesForExplicitCache",
|
|
294
268
|
);
|
|
295
269
|
return [];
|
|
296
270
|
}
|
|
@@ -307,60 +281,68 @@ export function transformMessagesForClaudeCache(
|
|
|
307
281
|
// Find first system message index
|
|
308
282
|
const firstSystemIndex = messages.findIndex((m) => m.role === "system");
|
|
309
283
|
|
|
310
|
-
//
|
|
311
|
-
|
|
284
|
+
// Determine which message indices should receive cache_control markers
|
|
285
|
+
const cacheIndices = new Set<number>();
|
|
286
|
+
|
|
287
|
+
// Marker 1: First system message (always — stable prefix)
|
|
288
|
+
if (firstSystemIndex !== -1) {
|
|
289
|
+
cacheIndices.add(firstSystemIndex);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// Marker 2: Last message with content (user or assistant).
|
|
293
|
+
// This marker moves each turn (~2 blocks), but since the move is < 20 blocks,
|
|
294
|
+
// the previous marker position is always within the API's 20-block scan window.
|
|
295
|
+
// This ensures the entire conversation prefix is cached.
|
|
312
296
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
313
|
-
|
|
314
|
-
|
|
297
|
+
const msg = messages[i];
|
|
298
|
+
if (!msg || typeof msg !== "object") continue;
|
|
299
|
+
if (i === firstSystemIndex) continue;
|
|
300
|
+
if (msg.role !== "user" && msg.role !== "assistant") continue;
|
|
301
|
+
|
|
302
|
+
const content = msg.content;
|
|
303
|
+
const hasContent =
|
|
304
|
+
(typeof content === "string" && content.length > 0) ||
|
|
305
|
+
(Array.isArray(content) && content.length > 0);
|
|
306
|
+
|
|
307
|
+
if (hasContent) {
|
|
308
|
+
cacheIndices.add(i);
|
|
315
309
|
break;
|
|
316
310
|
}
|
|
317
311
|
}
|
|
318
312
|
|
|
313
|
+
// Apply cache_control markers to selected messages
|
|
319
314
|
const result = messages.map((message, index) => {
|
|
320
315
|
// Validate message structure
|
|
321
316
|
if (!message || typeof message !== "object" || !message.role) {
|
|
322
317
|
logger.warn("Invalid message structure at index", index, ":", message);
|
|
323
|
-
return message;
|
|
318
|
+
return message;
|
|
324
319
|
}
|
|
325
320
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
const content =
|
|
329
|
-
(message.content as string | ChatCompletionContentPart[]) || "";
|
|
330
|
-
// If content is already an array, check if it already has cache control
|
|
331
|
-
if (Array.isArray(content)) {
|
|
332
|
-
const hasCacheControl = content.some(
|
|
333
|
-
(part) =>
|
|
334
|
-
part.type === "text" &&
|
|
335
|
-
(part as ClaudeChatCompletionContentPartText).cache_control,
|
|
336
|
-
);
|
|
337
|
-
if (hasCacheControl) {
|
|
338
|
-
return message;
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
const transformedContent = addCacheControlToContent(content, true);
|
|
343
|
-
|
|
344
|
-
return {
|
|
345
|
-
...message,
|
|
346
|
-
content: transformedContent,
|
|
347
|
-
} as ChatCompletionMessageParam;
|
|
321
|
+
if (!cacheIndices.has(index)) {
|
|
322
|
+
return message;
|
|
348
323
|
}
|
|
349
324
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
const content =
|
|
353
|
-
(message.content as string | ChatCompletionContentPart[]) || "";
|
|
354
|
-
const transformedContent = addCacheControlToContent(content, true);
|
|
325
|
+
const content =
|
|
326
|
+
(message.content as string | ChatCompletionContentPart[]) || "";
|
|
355
327
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
328
|
+
// Idempotency: skip if content already has cache_control (system message)
|
|
329
|
+
if (message.role === "system" && Array.isArray(content)) {
|
|
330
|
+
const hasCacheControl = content.some(
|
|
331
|
+
(part) =>
|
|
332
|
+
part.type === "text" &&
|
|
333
|
+
(part as ClaudeChatCompletionContentPartText).cache_control,
|
|
334
|
+
);
|
|
335
|
+
if (hasCacheControl) {
|
|
336
|
+
return message;
|
|
337
|
+
}
|
|
360
338
|
}
|
|
361
339
|
|
|
362
|
-
|
|
363
|
-
|
|
340
|
+
const transformedContent = addCacheControlToContent(content, true);
|
|
341
|
+
|
|
342
|
+
return {
|
|
343
|
+
...message,
|
|
344
|
+
content: transformedContent,
|
|
345
|
+
} as ChatCompletionMessageParam;
|
|
364
346
|
});
|
|
365
347
|
|
|
366
348
|
return result;
|
package/src/utils/constants.ts
CHANGED
|
@@ -29,5 +29,5 @@ export const USER_MEMORY_FILE = path.join(DATA_DIRECTORY, "AGENTS.md");
|
|
|
29
29
|
/**
|
|
30
30
|
* AI related constants
|
|
31
31
|
*/
|
|
32
|
-
export const DEFAULT_WAVE_MAX_INPUT_TOKENS =
|
|
32
|
+
export const DEFAULT_WAVE_MAX_INPUT_TOKENS = 200000; // Default token limit
|
|
33
33
|
export const DEFAULT_WAVE_MAX_OUTPUT_TOKENS = 16384; // Default output token limit
|
|
@@ -83,12 +83,6 @@ export function setupAgentContainer(
|
|
|
83
83
|
container.register("AgentOptions", options);
|
|
84
84
|
container.register("Workdir", workdir);
|
|
85
85
|
|
|
86
|
-
const mergedEnv: Record<string, string> = {
|
|
87
|
-
...(process.env as Record<string, string>),
|
|
88
|
-
...(options.env || {}),
|
|
89
|
-
};
|
|
90
|
-
container.register("MergedEnv", mergedEnv);
|
|
91
|
-
|
|
92
86
|
if (options.worktreeName) {
|
|
93
87
|
container.register("WorktreeName", options.worktreeName);
|
|
94
88
|
container.register("MainRepoRoot", getGitMainRepoRoot(workdir));
|
|
@@ -227,7 +221,9 @@ export function setupAgentContainer(
|
|
|
227
221
|
toolName: context.toolName,
|
|
228
222
|
toolInput: context.toolInput,
|
|
229
223
|
planFilePath: permissionManager.getPlanFilePath(),
|
|
230
|
-
env:
|
|
224
|
+
env: Object.fromEntries(
|
|
225
|
+
Object.entries(process.env).filter((e) => e[1] !== undefined),
|
|
226
|
+
) as Record<string, string>,
|
|
231
227
|
});
|
|
232
228
|
|
|
233
229
|
if (results.length > 0) {
|