wave-agent-sdk 0.17.8 → 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.
Files changed (76) hide show
  1. package/builtin/skills/settings/ENV.md +1 -1
  2. package/dist/agent.d.ts +5 -0
  3. package/dist/agent.d.ts.map +1 -1
  4. package/dist/agent.js +7 -0
  5. package/dist/managers/aiManager.d.ts +10 -4
  6. package/dist/managers/aiManager.d.ts.map +1 -1
  7. package/dist/managers/aiManager.js +214 -200
  8. package/dist/managers/backgroundTaskManager.js +1 -1
  9. package/dist/managers/bangManager.js +1 -1
  10. package/dist/managers/hookManager.js +2 -4
  11. package/dist/managers/mcpManager.d.ts.map +1 -1
  12. package/dist/managers/mcpManager.js +1 -3
  13. package/dist/managers/messageManager.d.ts.map +1 -1
  14. package/dist/managers/messageManager.js +1 -8
  15. package/dist/managers/toolManager.d.ts +13 -0
  16. package/dist/managers/toolManager.d.ts.map +1 -1
  17. package/dist/managers/toolManager.js +33 -12
  18. package/dist/services/aiService.d.ts.map +1 -1
  19. package/dist/services/aiService.js +20 -12
  20. package/dist/services/configurationService.d.ts.map +1 -1
  21. package/dist/services/configurationService.js +13 -0
  22. package/dist/services/jsonlHandler.d.ts +1 -1
  23. package/dist/services/jsonlHandler.d.ts.map +1 -1
  24. package/dist/services/jsonlHandler.js +7 -22
  25. package/dist/services/session.d.ts +2 -9
  26. package/dist/services/session.d.ts.map +1 -1
  27. package/dist/services/session.js +16 -46
  28. package/dist/tools/bashTool.d.ts.map +1 -1
  29. package/dist/tools/bashTool.js +3 -1
  30. package/dist/tools/editTool.d.ts.map +1 -1
  31. package/dist/tools/editTool.js +28 -1
  32. package/dist/tools/enterPlanMode.d.ts.map +1 -1
  33. package/dist/tools/enterPlanMode.js +14 -4
  34. package/dist/tools/exitPlanMode.d.ts.map +1 -1
  35. package/dist/tools/exitPlanMode.js +8 -0
  36. package/dist/tools/readTool.d.ts.map +1 -1
  37. package/dist/tools/readTool.js +18 -10
  38. package/dist/tools/types.d.ts +8 -2
  39. package/dist/tools/types.d.ts.map +1 -1
  40. package/dist/tools/writeTool.d.ts.map +1 -1
  41. package/dist/tools/writeTool.js +14 -1
  42. package/dist/types/agent.d.ts +0 -2
  43. package/dist/types/agent.d.ts.map +1 -1
  44. package/dist/types/config.d.ts +1 -0
  45. package/dist/types/config.d.ts.map +1 -1
  46. package/dist/utils/cacheControlUtils.d.ts +20 -15
  47. package/dist/utils/cacheControlUtils.d.ts.map +1 -1
  48. package/dist/utils/cacheControlUtils.js +69 -66
  49. package/dist/utils/constants.d.ts +1 -1
  50. package/dist/utils/constants.js +1 -1
  51. package/dist/utils/containerSetup.js +5 -6
  52. package/package.json +1 -1
  53. package/src/agent.ts +8 -0
  54. package/src/managers/aiManager.ts +292 -263
  55. package/src/managers/backgroundTaskManager.ts +1 -1
  56. package/src/managers/bangManager.ts +1 -1
  57. package/src/managers/hookManager.ts +6 -6
  58. package/src/managers/mcpManager.ts +2 -4
  59. package/src/managers/messageManager.ts +1 -9
  60. package/src/managers/toolManager.ts +37 -12
  61. package/src/services/aiService.ts +23 -12
  62. package/src/services/configurationService.ts +21 -0
  63. package/src/services/jsonlHandler.ts +7 -27
  64. package/src/services/session.ts +16 -57
  65. package/src/tools/bashTool.ts +3 -1
  66. package/src/tools/editTool.ts +31 -1
  67. package/src/tools/enterPlanMode.ts +15 -4
  68. package/src/tools/exitPlanMode.ts +10 -0
  69. package/src/tools/readTool.ts +20 -10
  70. package/src/tools/types.ts +15 -3
  71. package/src/tools/writeTool.ts +15 -1
  72. package/src/types/agent.ts +0 -2
  73. package/src/types/config.ts +1 -0
  74. package/src/utils/cacheControlUtils.ts +77 -95
  75. package/src/utils/constants.ts +1 -1
  76. package/src/utils/containerSetup.ts +7 -7
@@ -1,4 +1,5 @@
1
- import { readFile, writeFile } from "fs/promises";
1
+ import { readFile, writeFile, stat } from "fs/promises";
2
+ import { createHash } from "crypto";
2
3
  import { logger } from "../utils/globalLogger.js";
3
4
  import { resolvePath, getDisplayPath } from "../utils/path.js";
4
5
  import { escapeRegExp, analyzeEditMismatch } from "../utils/editUtils.js";
@@ -15,6 +16,7 @@ function formatCompactParams(args, context) {
15
16
  */
16
17
  export const editTool = {
17
18
  name: EDIT_TOOL_NAME,
19
+ isConcurrencySafe: false,
18
20
  formatCompactParams,
19
21
  prompt: () => `Performs exact string replacements in files.
20
22
 
@@ -116,6 +118,20 @@ Usage:
116
118
  error: `Failed to read file: ${readError instanceof Error ? readError.message : String(readError)}`,
117
119
  };
118
120
  }
121
+ // Staleness check: file must not have been modified since last Read
122
+ if (context.readFileState) {
123
+ const state = context.readFileState.get(resolvedPath);
124
+ if (state) {
125
+ const currentStats = await stat(resolvedPath);
126
+ if (currentStats.mtime.getTime() !== state.mtime) {
127
+ return {
128
+ success: false,
129
+ content: "",
130
+ error: "File has been unexpectedly modified since last read. Read it again before editing it.",
131
+ };
132
+ }
133
+ }
134
+ }
119
135
  // Normalize line endings for matching
120
136
  const normalizedContent = originalContent.replace(/\r\n/g, "\n");
121
137
  const normalizedOldString = oldString.replace(/\r\n/g, "\n");
@@ -200,6 +216,17 @@ Usage:
200
216
  error: `Failed to write file: ${writeError instanceof Error ? writeError.message : String(writeError)}`,
201
217
  };
202
218
  }
219
+ // Update readFileState so subsequent serialized edits see fresh state
220
+ if (context.readFileState) {
221
+ const newStats = await stat(resolvedPath);
222
+ const hash = createHash("sha256").update(newContent).digest("hex");
223
+ context.readFileState.set(resolvedPath, {
224
+ mtime: newStats.mtime.getTime(),
225
+ hash,
226
+ offset: undefined,
227
+ limit: undefined,
228
+ });
229
+ }
203
230
  const shortResult = replaceAll
204
231
  ? `Replaced ${replacementCount} instances`
205
232
  : "Text replaced successfully";
@@ -1 +1 @@
1
- {"version":3,"file":"enterPlanMode.d.ts","sourceRoot":"","sources":["../../src/tools/enterPlanMode.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAA2B,MAAM,YAAY,CAAC;AAItE;;GAEG;AACH,eAAO,MAAM,iBAAiB,EAAE,UAwG/B,CAAC"}
1
+ {"version":3,"file":"enterPlanMode.d.ts","sourceRoot":"","sources":["../../src/tools/enterPlanMode.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAA2B,MAAM,YAAY,CAAC;AAItE;;GAEG;AACH,eAAO,MAAM,iBAAiB,EAAE,UAmH/B,CAAC"}
@@ -42,6 +42,14 @@ export const enterPlanModeTool = {
42
42
  `,
43
43
  execute: async (_args, context) => {
44
44
  try {
45
+ // Runtime guard: tool is always visible but only works outside plan mode
46
+ if (context.permissionMode === "plan") {
47
+ return {
48
+ success: false,
49
+ content: "Already in plan mode. Use ExitPlanMode to exit.",
50
+ error: "Already in plan mode",
51
+ };
52
+ }
45
53
  if (!context.permissionManager) {
46
54
  return {
47
55
  success: false,
@@ -68,10 +76,12 @@ export const enterPlanModeTool = {
68
76
  : "Operation declined by user",
69
77
  };
70
78
  }
71
- // Ensure permission mode is switched to plan (in bypass mode the
72
- // canUseTool callback is not invoked, so the mode change doesn't happen)
73
- if (context.toolManager) {
74
- context.toolManager.setPermissionMode("plan");
79
+ // Ensure the full plan mode transition happens (planManager + UI callback).
80
+ // In bypass mode the canUseTool callback is not invoked, so the transition
81
+ // never occurs. In normal mode, the callback already handled it
82
+ // (permissionResult.newPermissionMode will be set).
83
+ if (!permissionResult.newPermissionMode && context.toolManager) {
84
+ context.toolManager.requestPermissionModeChange("plan");
75
85
  }
76
86
  return {
77
87
  success: true,
@@ -1 +1 @@
1
- {"version":3,"file":"exitPlanMode.d.ts","sourceRoot":"","sources":["../../src/tools/exitPlanMode.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAA2B,MAAM,YAAY,CAAC;AAItE;;GAEG;AACH,eAAO,MAAM,gBAAgB,EAAE,UAuH9B,CAAC"}
1
+ {"version":3,"file":"exitPlanMode.d.ts","sourceRoot":"","sources":["../../src/tools/exitPlanMode.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAA2B,MAAM,YAAY,CAAC;AAItE;;GAEG;AACH,eAAO,MAAM,gBAAgB,EAAE,UAiI9B,CAAC"}
@@ -46,6 +46,14 @@ Ensure your plan is complete and unambiguous:
46
46
  `,
47
47
  execute: async (_args, context) => {
48
48
  try {
49
+ // Runtime guard: tool is always visible but only works in plan mode
50
+ if (context.permissionMode !== "plan") {
51
+ return {
52
+ success: false,
53
+ content: "Not in plan mode. ExitPlanMode can only be used when actively in plan mode.",
54
+ error: "Not in plan mode",
55
+ };
56
+ }
49
57
  if (!context.permissionManager) {
50
58
  return {
51
59
  success: false,
@@ -1 +1 @@
1
- {"version":3,"file":"readTool.d.ts","sourceRoot":"","sources":["../../src/tools/readTool.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAA2B,MAAM,YAAY,CAAC;AAkItE;;GAEG;AACH,eAAO,MAAM,QAAQ,EAAE,UA4RtB,CAAC"}
1
+ {"version":3,"file":"readTool.d.ts","sourceRoot":"","sources":["../../src/tools/readTool.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAA2B,MAAM,YAAY,CAAC;AAkItE;;GAEG;AACH,eAAO,MAAM,QAAQ,EAAE,UAsStB,CAAC"}
@@ -206,18 +206,24 @@ Usage:
206
206
  ? filePath
207
207
  : resolvePath(filePath, context.workdir);
208
208
  const stats = await stat(actualFilePath);
209
- // Deduplication
209
+ // Deduplication: only dedup if the exact same range was read before
210
210
  if (context.readFileState) {
211
211
  const state = context.readFileState.get(actualFilePath);
212
- if (state && state.mtime === stats.mtime.getTime()) {
213
- return {
214
- success: true,
215
- content: `File ${filePath} has not changed since last read.`,
216
- shortResult: "File unchanged",
217
- metadata: {
218
- type: "file_unchanged",
219
- },
220
- };
212
+ // Only dedup entries from a prior Read with explicit offset (not Edit/Write entries)
213
+ if (state &&
214
+ state.mtime === stats.mtime.getTime() &&
215
+ state.offset !== undefined) {
216
+ const rangeMatch = state.offset === offset && state.limit === limit;
217
+ if (rangeMatch) {
218
+ return {
219
+ success: true,
220
+ content: `File ${filePath} has not changed since last read. The content from the earlier Read tool_result in this conversation is still current — refer to that instead of re-reading.`,
221
+ shortResult: "File unchanged",
222
+ metadata: {
223
+ type: "file_unchanged",
224
+ },
225
+ };
226
+ }
221
227
  }
222
228
  }
223
229
  // Resource Limits
@@ -243,6 +249,8 @@ Usage:
243
249
  context.readFileState.set(actualFilePath, {
244
250
  mtime: stats.mtime.getTime(),
245
251
  hash,
252
+ offset, // undefined for full reads
253
+ limit, // undefined for full reads
246
254
  });
247
255
  }
248
256
  // Check if file is empty
@@ -19,6 +19,12 @@ export interface ToolPlugin {
19
19
  workdir?: string;
20
20
  isSubagent?: boolean;
21
21
  }) => string;
22
+ /**
23
+ * Whether this tool is safe to run in parallel with other tools.
24
+ * Default (undefined) = true (parallel). Set to false for tools that
25
+ * perform read-modify-write on shared resources (e.g. Edit, Write).
26
+ */
27
+ isConcurrencySafe?: boolean;
22
28
  }
23
29
  export interface ToolResult {
24
30
  success: boolean;
@@ -87,6 +93,8 @@ export interface ToolContext {
87
93
  readFileState?: Map<string, {
88
94
  mtime: number;
89
95
  hash: string;
96
+ offset?: number;
97
+ limit?: number;
90
98
  }>;
91
99
  /** Hook manager instance for executing hooks */
92
100
  hookManager?: import("../managers/hookManager.js").HookManager;
@@ -94,8 +102,6 @@ export interface ToolContext {
94
102
  onCwdChange?: (newCwd: string) => void;
95
103
  /** Original working directory (before any cd changes) for CWD reset */
96
104
  originalWorkdir?: string;
97
- /** Merged environment variables (process.env + agent env) for child processes */
98
- env?: Record<string, string>;
99
105
  /** Workflow manager instance for workflow orchestration */
100
106
  workflowManager?: import("../managers/workflowManager.js").WorkflowManager;
101
107
  }
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/tools/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/tools/types.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"writeTool.d.ts","sourceRoot":"","sources":["../../src/tools/writeTool.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAA2B,MAAM,YAAY,CAAC;AAItE;;GAEG;AACH,eAAO,MAAM,SAAS,EAAE,UAuMvB,CAAC"}
1
+ {"version":3,"file":"writeTool.d.ts","sourceRoot":"","sources":["../../src/tools/writeTool.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAA2B,MAAM,YAAY,CAAC;AAItE;;GAEG;AACH,eAAO,MAAM,SAAS,EAAE,UAoNvB,CAAC"}
@@ -1,4 +1,5 @@
1
- import { readFile, writeFile, mkdir } from "fs/promises";
1
+ import { readFile, writeFile, mkdir, stat } from "fs/promises";
2
+ import { createHash } from "crypto";
2
3
  import { dirname } from "path";
3
4
  import { logger } from "../utils/globalLogger.js";
4
5
  import { resolvePath, getDisplayPath } from "../utils/path.js";
@@ -8,6 +9,7 @@ import { READ_TOOL_NAME } from "../constants/tools.js";
8
9
  */
9
10
  export const writeTool = {
10
11
  name: "Write",
12
+ isConcurrencySafe: false,
11
13
  config: {
12
14
  type: "function",
13
15
  function: {
@@ -134,6 +136,17 @@ Usage:
134
136
  error: `Failed to write file: ${writeError instanceof Error ? writeError.message : String(writeError)}`,
135
137
  };
136
138
  }
139
+ // Update readFileState so subsequent serialized edits pass staleness check
140
+ if (context.readFileState) {
141
+ const newStats = await stat(resolvedPath);
142
+ const hash = createHash("sha256").update(content).digest("hex");
143
+ context.readFileState.set(resolvedPath, {
144
+ mtime: newStats.mtime.getTime(),
145
+ hash,
146
+ offset: undefined,
147
+ limit: undefined,
148
+ });
149
+ }
137
150
  const shortResult = isExistingFile ? "File overwritten" : "File created";
138
151
  const lines = content.split("\n").length;
139
152
  const chars = content.length;
@@ -84,8 +84,6 @@ export interface AgentOptions {
84
84
  * File-based hooks (from config.json/.waverc.json) merge on top of these.
85
85
  */
86
86
  hooks?: PartialHookConfiguration;
87
- /** Per-agent environment variables, merged on top of process.env for bash, MCP, and hooks */
88
- env?: Record<string, string>;
89
87
  [key: string]: unknown;
90
88
  }
91
89
  export interface AgentCallbacks extends MessageManagerCallbacks, BackgroundTaskManagerCallbacks, McpManagerCallbacks, SubagentManagerCallbacks {
@@ -1 +1 @@
1
- {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/types/agent.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/types/agent.ts"],"names":[],"mappings":"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"}
@@ -16,6 +16,7 @@ export interface ModelConfig {
16
16
  fastModel?: string;
17
17
  maxTokens?: number;
18
18
  permissionMode?: PermissionMode;
19
+ fastModelConfig?: Record<string, unknown>;
19
20
  [key: string]: unknown;
20
21
  }
21
22
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,YAAY,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC,CAAC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,YAAY,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC,CAAC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1C,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB"}
@@ -5,7 +5,7 @@
5
5
  * to optimize token usage and reduce costs. Cache control is only applied to Claude
6
6
  * models and preserves backward compatibility with existing message formats.
7
7
  */
8
- import type { ChatCompletionMessageParam, ChatCompletionContentPart, ChatCompletionContentPartText, ChatCompletionFunctionTool, CompletionUsage } from "openai/resources";
8
+ import type { ChatCompletionMessageParam, ChatCompletionContentPart, ChatCompletionContentPartText, CompletionUsage } from "openai/resources";
9
9
  /**
10
10
  * Cache control directive for Claude models
11
11
  */
@@ -20,14 +20,6 @@ export interface ClaudeChatCompletionContentPartText extends ChatCompletionConte
20
20
  text: string;
21
21
  cache_control?: CacheControl;
22
22
  }
23
- /**
24
- * Extended tool definition with cache control support
25
- */
26
- export interface ClaudeChatCompletionFunctionTool extends ChatCompletionFunctionTool {
27
- type: "function";
28
- function: ChatCompletionFunctionTool["function"];
29
- cache_control?: CacheControl;
30
- }
31
23
  /**
32
24
  * Extended prompt_tokens_details with cache_creation_input_tokens
33
25
  * Some models (e.g. Gemini, DeepSeek) return this field inside prompt_tokens_details
@@ -78,18 +70,31 @@ export declare function isValidCacheControl(control: unknown): control is CacheC
78
70
  */
79
71
  export declare function addCacheControlToContent(content: string | ChatCompletionContentPart[], shouldCache: boolean): ClaudeChatCompletionContentPartText[];
80
72
  /**
81
- * Adds cache control to the last tool in tools array
82
- * @param tools - Array of tool definitions
83
- * @returns Tools array with cache control on last tool
73
+ * Counts the total number of content blocks across all messages.
74
+ * Each element in a message's content array counts as one block.
75
+ * String content counts as one block. Null/undefined content counts as zero
76
+ * (e.g. assistant messages with only tool_calls).
77
+ * @param messages - Array of chat messages
78
+ * @returns Total content block count
84
79
  */
85
- export declare function addCacheControlToLastTool(tools: ChatCompletionFunctionTool[]): ClaudeChatCompletionFunctionTool[];
80
+ export declare function countContentBlocks(messages: ChatCompletionMessageParam[]): number;
86
81
  /**
87
- * Transforms messages for Claude cache control with hardcoded strategy
82
+ * Transforms messages for explicit cache control.
83
+ *
84
+ * Cache breakpoints (following Claude Code's "last message marker" strategy):
85
+ * 1. System message — always marked (stable prefix)
86
+ * 2. Last message — the last user/assistant message with content is marked.
87
+ * The API scans backward from this marker within 20 blocks. Since each
88
+ * turn adds ~2 blocks (< 20), the previous request's marker position
89
+ * always falls within the scan window, ensuring cache hits.
90
+ *
91
+ * Tools are marked separately via addCacheControlToLastTool (called by aiService).
92
+ *
88
93
  * @param messages - Original OpenAI message array
89
94
  * @param modelName - Model name for cache detection
90
95
  * @returns Messages with cache control markers applied
91
96
  */
92
- export declare function transformMessagesForClaudeCache(messages: ChatCompletionMessageParam[], modelName: string): ChatCompletionMessageParam[];
97
+ export declare function transformMessagesForExplicitCache(messages: ChatCompletionMessageParam[], modelName: string): ChatCompletionMessageParam[];
93
98
  /**
94
99
  * Extends standard usage with cache metrics
95
100
  * Extracts cache tokens from both Claude-specific top-level fields and
@@ -1 +1 @@
1
- {"version":3,"file":"cacheControlUtils.d.ts","sourceRoot":"","sources":["../../src/utils/cacheControlUtils.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,0BAA0B,EAC1B,yBAAyB,EACzB,6BAA6B,EAC7B,0BAA0B,EAC1B,eAAe,EAChB,MAAM,kBAAkB,CAAC;AAO1B;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,WAAW,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,mCACf,SAAQ,6BAA6B;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,YAAY,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,gCACf,SAAQ,0BAA0B;IAClC,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,0BAA0B,CAAC,UAAU,CAAC,CAAC;IACjD,aAAa,CAAC,EAAE,YAAY,CAAC;CAC9B;AAED;;;GAGG;AACH,MAAM,WAAW,2BACf,SAAQ,eAAe,CAAC,mBAAmB;IAC3C,2BAA2B,CAAC,EAAE,MAAM,CAAC;CACtC;AAED;;;GAGG;AACH,MAAM,WAAW,WAAY,SAAQ,eAAe;IAClD,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IAGrB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,cAAc,CAAC,EAAE;QACf,yBAAyB,EAAE,MAAM,CAAC;QAClC,yBAAyB,EAAE,MAAM,CAAC;KACnC,CAAC;IAGF,qBAAqB,CAAC,EAAE,2BAA2B,CAAC;CACrD;AAUD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAoBhE;AAED;;;;;GAKG;AACH,eAAO,MAAM,aAAa,8BAAwB,CAAC;AAEnD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI,YAAY,CAQ7E;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,MAAM,GAAG,yBAAyB,EAAE,EAC7C,WAAW,EAAE,OAAO,GACnB,mCAAmC,EAAE,CAmFvC;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,0BAA0B,EAAE,GAClC,gCAAgC,EAAE,CAwCpC;AAED;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,0BAA0B,EAAE,EACtC,SAAS,EAAE,MAAM,GAChB,0BAA0B,EAAE,CA8E9B;AAED;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CACzC,aAAa,EAAE,eAAe,EAC9B,YAAY,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GAClC,WAAW,CAiDb;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,WAAW,CAyCvE"}
1
+ {"version":3,"file":"cacheControlUtils.d.ts","sourceRoot":"","sources":["../../src/utils/cacheControlUtils.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,0BAA0B,EAC1B,yBAAyB,EACzB,6BAA6B,EAC7B,eAAe,EAChB,MAAM,kBAAkB,CAAC;AAO1B;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,WAAW,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,mCACf,SAAQ,6BAA6B;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,YAAY,CAAC;CAC9B;AAED;;;GAGG;AACH,MAAM,WAAW,2BACf,SAAQ,eAAe,CAAC,mBAAmB;IAC3C,2BAA2B,CAAC,EAAE,MAAM,CAAC;CACtC;AAED;;;GAGG;AACH,MAAM,WAAW,WAAY,SAAQ,eAAe;IAClD,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IAGrB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,cAAc,CAAC,EAAE;QACf,yBAAyB,EAAE,MAAM,CAAC;QAClC,yBAAyB,EAAE,MAAM,CAAC;KACnC,CAAC;IAGF,qBAAqB,CAAC,EAAE,2BAA2B,CAAC;CACrD;AAUD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAoBhE;AAED;;;;;GAKG;AACH,eAAO,MAAM,aAAa,8BAAwB,CAAC;AAEnD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI,YAAY,CAQ7E;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,MAAM,GAAG,yBAAyB,EAAE,EAC7C,WAAW,EAAE,OAAO,GACnB,mCAAmC,EAAE,CAmFvC;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,0BAA0B,EAAE,GACrC,MAAM,CAYR;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iCAAiC,CAC/C,QAAQ,EAAE,0BAA0B,EAAE,EACtC,SAAS,EAAE,MAAM,GAChB,0BAA0B,EAAE,CAsF9B;AAED;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CACzC,aAAa,EAAE,eAAe,EAC9B,YAAY,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GAClC,WAAW,CAiDb;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,WAAW,CAyCvE"}
@@ -130,53 +130,48 @@ export function addCacheControlToContent(content, shouldCache) {
130
130
  });
131
131
  }
132
132
  /**
133
- * Adds cache control to the last tool in tools array
134
- * @param tools - Array of tool definitions
135
- * @returns Tools array with cache control on last tool
133
+ * Counts the total number of content blocks across all messages.
134
+ * Each element in a message's content array counts as one block.
135
+ * String content counts as one block. Null/undefined content counts as zero
136
+ * (e.g. assistant messages with only tool_calls).
137
+ * @param messages - Array of chat messages
138
+ * @returns Total content block count
136
139
  */
137
- export function addCacheControlToLastTool(tools) {
138
- // Handle null, undefined, or empty arrays
139
- if (!tools || !Array.isArray(tools) || tools.length === 0) {
140
- return [];
141
- }
142
- // Validate tools structure
143
- const validTools = tools.filter((tool) => {
144
- if (!tool || typeof tool !== "object") {
145
- logger.warn("Invalid tool structure detected, skipping:", tool);
146
- return false;
140
+ export function countContentBlocks(messages) {
141
+ let count = 0;
142
+ for (const message of messages) {
143
+ if (!message || typeof message !== "object")
144
+ continue;
145
+ const content = message.content;
146
+ if (typeof content === "string") {
147
+ count += 1;
147
148
  }
148
- if (tool.type !== "function" || !tool.function) {
149
- logger.warn("Tool is not a function type or missing function property:", tool);
150
- return false;
149
+ else if (Array.isArray(content)) {
150
+ count += content.length;
151
151
  }
152
- return true;
153
- });
154
- if (validTools.length === 0) {
155
- logger.warn("No valid tools found for cache control");
156
- return [];
157
152
  }
158
- // Create a copy of the valid tools array
159
- const result = validTools.map((tool) => ({
160
- ...tool,
161
- }));
162
- // Add cache control to the last tool only
163
- const lastIndex = result.length - 1;
164
- result[lastIndex] = {
165
- ...result[lastIndex],
166
- cache_control: { type: "ephemeral" },
167
- };
168
- return result;
153
+ return count;
169
154
  }
170
155
  /**
171
- * Transforms messages for Claude cache control with hardcoded strategy
156
+ * Transforms messages for explicit cache control.
157
+ *
158
+ * Cache breakpoints (following Claude Code's "last message marker" strategy):
159
+ * 1. System message — always marked (stable prefix)
160
+ * 2. Last message — the last user/assistant message with content is marked.
161
+ * The API scans backward from this marker within 20 blocks. Since each
162
+ * turn adds ~2 blocks (< 20), the previous request's marker position
163
+ * always falls within the scan window, ensuring cache hits.
164
+ *
165
+ * Tools are marked separately via addCacheControlToLastTool (called by aiService).
166
+ *
172
167
  * @param messages - Original OpenAI message array
173
168
  * @param modelName - Model name for cache detection
174
169
  * @returns Messages with cache control markers applied
175
170
  */
176
- export function transformMessagesForClaudeCache(messages, modelName) {
171
+ export function transformMessagesForExplicitCache(messages, modelName) {
177
172
  // Validate inputs
178
173
  if (!messages || !Array.isArray(messages)) {
179
- logger.warn("Invalid messages array provided to transformMessagesForClaudeCache");
174
+ logger.warn("Invalid messages array provided to transformMessagesForExplicitCache");
180
175
  return [];
181
176
  }
182
177
  if (messages.length === 0) {
@@ -188,48 +183,56 @@ export function transformMessagesForClaudeCache(messages, modelName) {
188
183
  }
189
184
  // Find first system message index
190
185
  const firstSystemIndex = messages.findIndex((m) => m.role === "system");
191
- // Find last user message index
192
- let lastUserIndex = -1;
186
+ // Determine which message indices should receive cache_control markers
187
+ const cacheIndices = new Set();
188
+ // Marker 1: First system message (always — stable prefix)
189
+ if (firstSystemIndex !== -1) {
190
+ cacheIndices.add(firstSystemIndex);
191
+ }
192
+ // Marker 2: Last message with content (user or assistant).
193
+ // This marker moves each turn (~2 blocks), but since the move is < 20 blocks,
194
+ // the previous marker position is always within the API's 20-block scan window.
195
+ // This ensures the entire conversation prefix is cached.
193
196
  for (let i = messages.length - 1; i >= 0; i--) {
194
- if (messages[i].role === "user") {
195
- lastUserIndex = i;
197
+ const msg = messages[i];
198
+ if (!msg || typeof msg !== "object")
199
+ continue;
200
+ if (i === firstSystemIndex)
201
+ continue;
202
+ if (msg.role !== "user" && msg.role !== "assistant")
203
+ continue;
204
+ const content = msg.content;
205
+ const hasContent = (typeof content === "string" && content.length > 0) ||
206
+ (Array.isArray(content) && content.length > 0);
207
+ if (hasContent) {
208
+ cacheIndices.add(i);
196
209
  break;
197
210
  }
198
211
  }
212
+ // Apply cache_control markers to selected messages
199
213
  const result = messages.map((message, index) => {
200
214
  // Validate message structure
201
215
  if (!message || typeof message !== "object" || !message.role) {
202
216
  logger.warn("Invalid message structure at index", index, ":", message);
203
- return message; // Return as-is to avoid breaking the flow
217
+ return message;
204
218
  }
205
- // First system message: always cached (hardcoded)
206
- if (message.role === "system" && index === firstSystemIndex) {
207
- const content = message.content || "";
208
- // If content is already an array, check if it already has cache control
209
- if (Array.isArray(content)) {
210
- const hasCacheControl = content.some((part) => part.type === "text" &&
211
- part.cache_control);
212
- if (hasCacheControl) {
213
- return message;
214
- }
215
- }
216
- const transformedContent = addCacheControlToContent(content, true);
217
- return {
218
- ...message,
219
- content: transformedContent,
220
- };
219
+ if (!cacheIndices.has(index)) {
220
+ return message;
221
221
  }
222
- // Last user message: cache recent conversation history
223
- if (message.role === "user" && index === lastUserIndex) {
224
- const content = message.content || "";
225
- const transformedContent = addCacheControlToContent(content, true);
226
- return {
227
- ...message,
228
- content: transformedContent,
229
- };
222
+ const content = message.content || "";
223
+ // Idempotency: skip if content already has cache_control (system message)
224
+ if (message.role === "system" && Array.isArray(content)) {
225
+ const hasCacheControl = content.some((part) => part.type === "text" &&
226
+ part.cache_control);
227
+ if (hasCacheControl) {
228
+ return message;
229
+ }
230
230
  }
231
- // Return message unchanged
232
- return message;
231
+ const transformedContent = addCacheControlToContent(content, true);
232
+ return {
233
+ ...message,
234
+ content: transformedContent,
235
+ };
233
236
  });
234
237
  return result;
235
238
  }
@@ -21,6 +21,6 @@ export declare const USER_MEMORY_FILE: string;
21
21
  /**
22
22
  * AI related constants
23
23
  */
24
- export declare const DEFAULT_WAVE_MAX_INPUT_TOKENS = 128000;
24
+ export declare const DEFAULT_WAVE_MAX_INPUT_TOKENS = 200000;
25
25
  export declare const DEFAULT_WAVE_MAX_OUTPUT_TOKENS = 16384;
26
26
  //# sourceMappingURL=constants.d.ts.map
@@ -23,5 +23,5 @@ export const USER_MEMORY_FILE = path.join(DATA_DIRECTORY, "AGENTS.md");
23
23
  /**
24
24
  * AI related constants
25
25
  */
26
- export const DEFAULT_WAVE_MAX_INPUT_TOKENS = 128000; // Default token limit
26
+ export const DEFAULT_WAVE_MAX_INPUT_TOKENS = 200000; // Default token limit
27
27
  export const DEFAULT_WAVE_MAX_OUTPUT_TOKENS = 16384; // Default output token limit
@@ -38,11 +38,6 @@ export function setupAgentContainer(setupOptions) {
38
38
  const container = new Container();
39
39
  container.register("AgentOptions", options);
40
40
  container.register("Workdir", workdir);
41
- const mergedEnv = {
42
- ...process.env,
43
- ...(options.env || {}),
44
- };
45
- container.register("MergedEnv", mergedEnv);
46
41
  if (options.worktreeName) {
47
42
  container.register("WorktreeName", options.worktreeName);
48
43
  container.register("MainRepoRoot", getGitMainRepoRoot(workdir));
@@ -159,7 +154,7 @@ export function setupAgentContainer(setupOptions) {
159
154
  toolName: context.toolName,
160
155
  toolInput: context.toolInput,
161
156
  planFilePath: permissionManager.getPlanFilePath(),
162
- env: mergedEnv,
157
+ env: Object.fromEntries(Object.entries(process.env).filter((e) => e[1] !== undefined)),
163
158
  });
164
159
  if (results.length > 0) {
165
160
  const processResult = hookManager.processHookResults("PermissionRequest", results, messageManager);
@@ -204,6 +199,10 @@ export function setupAgentContainer(setupOptions) {
204
199
  });
205
200
  container.register("ToolManager", toolManager);
206
201
  container.register("PermissionMode", options.permissionMode);
202
+ // Register the full permission mode transition (Agent.setPermissionMode) so
203
+ // tools like EnterPlanMode can trigger planManager.handlePlanModeTransition
204
+ // and onPermissionModeChange even in bypass mode (where canUseTool is skipped).
205
+ container.register("PermissionModeTransition", setPermissionMode);
207
206
  logger.info("Registering CanUseToolCallback", {
208
207
  hasCallback: !!canUseToolWithPermissionRequest,
209
208
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wave-agent-sdk",
3
- "version": "0.17.8",
3
+ "version": "0.17.10",
4
4
  "description": "SDK for building AI-powered development tools and agents",
5
5
  "keywords": [
6
6
  "ai",
package/src/agent.ts CHANGED
@@ -1139,6 +1139,14 @@ export class Agent {
1139
1139
  return this.toolManager.getPermissionMode();
1140
1140
  }
1141
1141
 
1142
+ /**
1143
+ * Get the names of tools currently visible to the AI model (filtered by
1144
+ * permission mode, denied rules, etc.)
1145
+ */
1146
+ public getAvailableToolNames(): string[] {
1147
+ return this.toolManager.getToolsConfig().map((t) => t.function.name);
1148
+ }
1149
+
1142
1150
  /**
1143
1151
  * Set the permission mode
1144
1152
  * @param mode - The new permission mode