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.
- package/builtin/skills/settings/ENV.md +1 -1
- package/dist/agent.d.ts +5 -0
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +7 -0
- 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 +13 -0
- package/dist/managers/toolManager.d.ts.map +1 -1
- package/dist/managers/toolManager.js +33 -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 +14 -4
- 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.js +5 -6
- package/package.json +1 -1
- package/src/agent.ts +8 -0
- 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 +37 -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 +15 -4
- 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 +7 -7
package/dist/tools/editTool.js
CHANGED
|
@@ -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,
|
|
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
|
|
72
|
-
// canUseTool callback is not invoked, so the
|
|
73
|
-
|
|
74
|
-
|
|
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,
|
|
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,
|
|
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"}
|
package/dist/tools/readTool.js
CHANGED
|
@@ -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
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
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
|
package/dist/tools/types.d.ts
CHANGED
|
@@ -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":"AAAA;;GAEG;AAEH,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,KAAK,EACV,cAAc,EACd,kBAAkB,EACnB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,0BAA0B,CAAC;IACnC,OAAO,EAAE,CACP,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,EAAE,WAAW,KACjB,OAAO,CAAC,UAAU,CAAC,CAAC;IACzB,mBAAmB,CAAC,EAAE,CACpB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,OAAO,EAAE,WAAW,KACjB,MAAM,CAAC;IACZ;;OAEG;IACH,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE;QACf,kBAAkB,CAAC,EAAE,qBAAqB,EAAE,CAAC;QAC7C,eAAe,CAAC,EAAE,aAAa,EAAE,CAAC;QAClC,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,UAAU,CAAC,EAAE,OAAO,CAAC;KACtB,KAAK,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/tools/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,KAAK,EACV,cAAc,EACd,kBAAkB,EACnB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,0BAA0B,CAAC;IACnC,OAAO,EAAE,CACP,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,EAAE,WAAW,KACjB,OAAO,CAAC,UAAU,CAAC,CAAC;IACzB,mBAAmB,CAAC,EAAE,CACpB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,OAAO,EAAE,WAAW,KACjB,MAAM,CAAC;IACZ;;OAEG;IACH,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE;QACf,kBAAkB,CAAC,EAAE,qBAAqB,EAAE,CAAC;QAC7C,eAAe,CAAC,EAAE,aAAa,EAAE,CAAC;QAClC,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,UAAU,CAAC,EAAE,OAAO,CAAC;KACtB,KAAK,MAAM,CAAC;IACb;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,MAAM,CAAC,EAAE,KAAK,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC,CAAC;IAEH,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAEjC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,WAAW;IAC1B,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,qBAAqB,CAAC,EAAE,OAAO,sCAAsC,EAAE,qBAAqB,CAAC;IAC7F,OAAO,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,WAAW,CAAC,EAAE,OAAO,4BAA4B,EAAE,WAAW,CAAC;IAC/D,8CAA8C;IAC9C,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,iCAAiC;IACjC,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACxC,wDAAwD;IACxD,iBAAiB,CAAC,EAAE,OAAO,kCAAkC,EAAE,iBAAiB,CAAC;IACjF,iDAAiD;IACjD,UAAU,CAAC,EAAE,OAAO,2BAA2B,EAAE,UAAU,CAAC;IAC5D,iDAAiD;IACjD,UAAU,CAAC,EAAE,OAAO,iBAAiB,EAAE,WAAW,CAAC;IACnD,oDAAoD;IACpD,gBAAgB,CAAC,EAAE,OAAO,iCAAiC,EAAE,gBAAgB,CAAC;IAC9E,mDAAmD;IACnD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sDAAsD;IACtD,qBAAqB,CAAC,EAAE,OAAO,uBAAuB,EAAE,sBAAsB,CAAC;IAC/E,gDAAgD;IAChD,WAAW,EAAE,OAAO,4BAA4B,EAAE,WAAW,CAAC;IAC9D,qDAAqD;IACrD,eAAe,CAAC,EAAE,OAAO,gCAAgC,EAAE,eAAe,CAAC;IAC3E,kDAAkD;IAClD,YAAY,CAAC,EAAE,OAAO,6BAA6B,EAAE,YAAY,CAAC;IAClE,iDAAiD;IACjD,WAAW,CAAC,EAAE,OAAO,4BAA4B,EAAE,WAAW,CAAC;IAC/D,4CAA4C;IAC5C,SAAS,CAAC,EAAE,OAAO,0BAA0B,EAAE,SAAS,CAAC;IACzD,4CAA4C;IAC5C,SAAS,CAAC,EAAE,cAAc,0BAA0B,CAAC,CAAC;IACtD,sDAAsD;IACtD,cAAc,CAAC,EAAE,OAAO,+BAA+B,EAAE,cAAc,CAAC;IACxE,yBAAyB;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sCAAsC;IACtC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oEAAoE;IACpE,mBAAmB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,mEAAmE;IACnE,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,yCAAyC;IACzC,iBAAiB,CAAC,EAAE;QAClB,YAAY,EAAE,MAAM,CAAC;QACrB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,mEAAmE;IACnE,aAAa,CAAC,EAAE,GAAG,CACjB,MAAM,EACN;QACE,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CACF,CAAC;IACF,gDAAgD;IAChD,WAAW,CAAC,EAAE,OAAO,4BAA4B,EAAE,WAAW,CAAC;IAC/D,oEAAoE;IACpE,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,uEAAuE;IACvE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,eAAe,CAAC,EAAE,OAAO,gCAAgC,EAAE,eAAe,CAAC;CAC5E"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"writeTool.d.ts","sourceRoot":"","sources":["../../src/tools/writeTool.ts"],"names":[],"mappings":"
|
|
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"}
|
package/dist/tools/writeTool.js
CHANGED
|
@@ -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;
|
package/dist/types/agent.d.ts
CHANGED
|
@@ -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":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAC5C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,KAAK,EACV,OAAO,EACP,MAAM,EACN,cAAc,EACd,kBAAkB,EAClB,WAAW,EACX,YAAY,EACZ,cAAc,EACd,eAAe,EAChB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AAC7E,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,sCAAsC,CAAC;AAC3F,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAC/E,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAE3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mFAAmF;IACnF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,mFAAmF;IACnF,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACzD,YAAY,CAAC,EAAE,aAAa,CAAC,cAAc,CAAC,CAAC;IAC7C,KAAK,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAGlB,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;IACrB,6DAA6D;IAC7D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iFAAiF;IACjF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,6CAA6C;IAC7C,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,gCAAgC;IAChC,UAAU,CAAC,EAAE,kBAAkB,CAAC;IAChC,uEAAuE;IACvE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,qFAAqF;IACrF,UAAU,CAAC,EAAE,WAAW,CAAC;IACzB,oCAAoC;IACpC,OAAO,CAAC,EAAE,YAAY,EAAE,CAAC;IACzB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,4BAA4B;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,8CAA8C;IAC9C,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,2DAA2D;IAC3D,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC7C,iFAAiF;IACjF,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;IAC3B;;;OAGG;IACH,KAAK,CAAC,EAAE,wBAAwB,CAAC;IACjC,
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/types/agent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAC5C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,KAAK,EACV,OAAO,EACP,MAAM,EACN,cAAc,EACd,kBAAkB,EAClB,WAAW,EACX,YAAY,EACZ,cAAc,EACd,eAAe,EAChB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AAC7E,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,sCAAsC,CAAC;AAC3F,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAC/E,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAE3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mFAAmF;IACnF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,mFAAmF;IACnF,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACzD,YAAY,CAAC,EAAE,aAAa,CAAC,cAAc,CAAC,CAAC;IAC7C,KAAK,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAGlB,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;IACrB,6DAA6D;IAC7D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iFAAiF;IACjF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,6CAA6C;IAC7C,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,gCAAgC;IAChC,UAAU,CAAC,EAAE,kBAAkB,CAAC;IAChC,uEAAuE;IACvE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,qFAAqF;IACrF,UAAU,CAAC,EAAE,WAAW,CAAC;IACzB,oCAAoC;IACpC,OAAO,CAAC,EAAE,YAAY,EAAE,CAAC;IACzB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,4BAA4B;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,8CAA8C;IAC9C,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,2DAA2D;IAC3D,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC7C,iFAAiF;IACjF,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;IAC3B;;;OAGG;IACH,KAAK,CAAC,EAAE,wBAAwB,CAAC;IACjC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,cACf,SAAQ,uBAAuB,EAC7B,8BAA8B,EAC9B,mBAAmB,EACnB,wBAAwB;IAC1B,uBAAuB,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,EAAE,KAAK,IAAI,CAAC;IAC5D,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,YAAY,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;IAC7D,sBAAsB,CAAC,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IACxD,iCAAiC,CAAC,EAAE,CAClC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,KACX,IAAI,CAAC;IACV,uBAAuB,CAAC,EAAE,MAAM,IAAI,CAAC;IACrC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,wBAAwB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACtD,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAC7C,sBAAsB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACpD,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,sBAAsB,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,EAAE,KAAK,IAAI,CAAC;IAC7D,iBAAiB,CAAC,EAAE,CAClB,MAAM,EAAE,OAAO,EACf,SAAS,CAAC,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,MAAM,KACb,IAAI,CAAC;IACV,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,OAAO,KAAK,IAAI,CAAC;CAClD"}
|
package/dist/types/config.d.ts
CHANGED
|
@@ -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,
|
|
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
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
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
|
|
80
|
+
export declare function countContentBlocks(messages: ChatCompletionMessageParam[]): number;
|
|
86
81
|
/**
|
|
87
|
-
* Transforms messages for
|
|
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
|
|
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,
|
|
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
|
-
*
|
|
134
|
-
*
|
|
135
|
-
*
|
|
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
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
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 (
|
|
149
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
//
|
|
192
|
-
|
|
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
|
-
|
|
195
|
-
|
|
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;
|
|
217
|
+
return message;
|
|
204
218
|
}
|
|
205
|
-
|
|
206
|
-
|
|
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
|
-
|
|
223
|
-
if
|
|
224
|
-
|
|
225
|
-
const
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
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
|
-
|
|
232
|
-
return
|
|
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 =
|
|
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
|
package/dist/utils/constants.js
CHANGED
|
@@ -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 =
|
|
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:
|
|
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
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
|