wave-agent-sdk 0.17.9 → 0.17.11
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 +11 -4
- package/dist/managers/aiManager.d.ts.map +1 -1
- package/dist/managers/aiManager.js +232 -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/authService.d.ts +0 -1
- package/dist/services/authService.d.ts.map +1 -1
- package/dist/services/authService.js +1 -29
- package/dist/services/configurationService.d.ts.map +1 -1
- package/dist/services/configurationService.js +13 -0
- package/dist/services/fileWatcher.d.ts +2 -0
- package/dist/services/fileWatcher.d.ts.map +1 -1
- package/dist/services/fileWatcher.js +12 -1
- 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/dist/utils/taskReminder.d.ts +17 -0
- package/dist/utils/taskReminder.d.ts.map +1 -0
- package/dist/utils/taskReminder.js +76 -0
- package/package.json +1 -1
- package/src/managers/aiManager.ts +326 -262
- 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/authService.ts +1 -31
- package/src/services/configurationService.ts +21 -0
- package/src/services/fileWatcher.ts +15 -1
- 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/utils/taskReminder.ts +108 -0
|
@@ -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
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"containerSetup.d.ts","sourceRoot":"","sources":["../../src/utils/containerSetup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AA0B3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAM3E,OAAO,KAAK,EAAE,YAAY,EAAmB,MAAM,mBAAmB,CAAC;AACvE,OAAO,KAAK,EACV,cAAc,EACd,KAAK,EACL,IAAI,EACJ,cAAc,EAEf,MAAM,mBAAmB,CAAC;AAM3B,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,oBAAoB,EAAE,oBAAoB,CAAC;IAC3C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,OAAO,CAAC;IAGhB,uBAAuB,EAAE,CAAC,KAAK,EAAE,cAAc,EAAE,KAAK,IAAI,CAAC;IAC3D,aAAa,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;IACvC,sBAAsB,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IACvD,wBAAwB,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IACzD,iBAAiB,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IAClD,iBAAiB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAED,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,0BAA0B,GACvC,SAAS,
|
|
1
|
+
{"version":3,"file":"containerSetup.d.ts","sourceRoot":"","sources":["../../src/utils/containerSetup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AA0B3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAM3E,OAAO,KAAK,EAAE,YAAY,EAAmB,MAAM,mBAAmB,CAAC;AACvE,OAAO,KAAK,EACV,cAAc,EACd,KAAK,EACL,IAAI,EACJ,cAAc,EAEf,MAAM,mBAAmB,CAAC;AAM3B,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,oBAAoB,EAAE,oBAAoB,CAAC;IAC3C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,OAAO,CAAC;IAGhB,uBAAuB,EAAE,CAAC,KAAK,EAAE,cAAc,EAAE,KAAK,IAAI,CAAC;IAC3D,aAAa,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;IACvC,sBAAsB,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IACvD,wBAAwB,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IACzD,iBAAiB,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IAClD,iBAAiB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAED,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,0BAA0B,GACvC,SAAS,CAuSX"}
|
|
@@ -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);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Message } from "../types/messaging.js";
|
|
2
|
+
import type { Task } from "../types/tasks.js";
|
|
3
|
+
import type { ChatCompletionMessageParam } from "openai/resources.js";
|
|
4
|
+
export declare const TASK_REMINDER_CONFIG: {
|
|
5
|
+
TURNS_SINCE_WRITE: number;
|
|
6
|
+
TURNS_BETWEEN_REMINDERS: number;
|
|
7
|
+
};
|
|
8
|
+
export declare function getTaskReminderTurnCounts(messages: Message[]): {
|
|
9
|
+
turnsSinceLastTaskManagement: number;
|
|
10
|
+
turnsSinceLastReminder: number;
|
|
11
|
+
};
|
|
12
|
+
export declare function buildTaskReminderText(tasks: Task[]): string;
|
|
13
|
+
export declare function maybeInjectTaskReminder(messages: ChatCompletionMessageParam[], turnCounts: {
|
|
14
|
+
turnsSinceLastTaskManagement: number;
|
|
15
|
+
turnsSinceLastReminder: number;
|
|
16
|
+
}, tasks: Task[]): void;
|
|
17
|
+
//# sourceMappingURL=taskReminder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"taskReminder.d.ts","sourceRoot":"","sources":["../../src/utils/taskReminder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AAEtE,eAAO,MAAM,oBAAoB;;;CAGhC,CAAC;AAgBF,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG;IAC9D,4BAA4B,EAAE,MAAM,CAAC;IACrC,sBAAsB,EAAE,MAAM,CAAC;CAChC,CAqCA;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,MAAM,CAe3D;AAED,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,0BAA0B,EAAE,EACtC,UAAU,EAAE;IACV,4BAA4B,EAAE,MAAM,CAAC;IACrC,sBAAsB,EAAE,MAAM,CAAC;CAChC,EACD,KAAK,EAAE,IAAI,EAAE,GACZ,IAAI,CAkBN"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
export const TASK_REMINDER_CONFIG = {
|
|
2
|
+
TURNS_SINCE_WRITE: 10,
|
|
3
|
+
TURNS_BETWEEN_REMINDERS: 10,
|
|
4
|
+
};
|
|
5
|
+
const TASK_MANAGEMENT_TOOLS = new Set([
|
|
6
|
+
"TaskCreate",
|
|
7
|
+
"TaskUpdate",
|
|
8
|
+
"TaskList",
|
|
9
|
+
"TaskGet",
|
|
10
|
+
]);
|
|
11
|
+
const TASK_REMINDER_MARKER = "<!-- task-reminder -->";
|
|
12
|
+
function isQualifyingAssistantMessage(message) {
|
|
13
|
+
if (message.role !== "assistant")
|
|
14
|
+
return false;
|
|
15
|
+
if (message.isMeta)
|
|
16
|
+
return false;
|
|
17
|
+
return message.blocks.some((block) => block.type !== "reasoning");
|
|
18
|
+
}
|
|
19
|
+
export function getTaskReminderTurnCounts(messages) {
|
|
20
|
+
let assistantTurnCount = 0;
|
|
21
|
+
let turnsSinceLastTaskManagement;
|
|
22
|
+
let turnsSinceLastReminder;
|
|
23
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
24
|
+
const message = messages[i];
|
|
25
|
+
// Check blocks for task management tools and reminder markers
|
|
26
|
+
for (const block of message.blocks) {
|
|
27
|
+
if (turnsSinceLastTaskManagement === undefined &&
|
|
28
|
+
block.type === "tool" &&
|
|
29
|
+
block.name &&
|
|
30
|
+
TASK_MANAGEMENT_TOOLS.has(block.name)) {
|
|
31
|
+
turnsSinceLastTaskManagement = assistantTurnCount;
|
|
32
|
+
}
|
|
33
|
+
if (turnsSinceLastReminder === undefined &&
|
|
34
|
+
block.type === "text" &&
|
|
35
|
+
block.content.includes(TASK_REMINDER_MARKER)) {
|
|
36
|
+
turnsSinceLastReminder = assistantTurnCount;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (isQualifyingAssistantMessage(message)) {
|
|
40
|
+
assistantTurnCount++;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
turnsSinceLastTaskManagement: turnsSinceLastTaskManagement ?? assistantTurnCount,
|
|
45
|
+
turnsSinceLastReminder: turnsSinceLastReminder ?? assistantTurnCount,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
export function buildTaskReminderText(tasks) {
|
|
49
|
+
let text = `${TASK_REMINDER_MARKER}\n`;
|
|
50
|
+
text +=
|
|
51
|
+
"Here is a gentle reminder about the task list. The user may not have explicitly asked for the following to be done, but you should check the task list to see if any tasks need attention.\n";
|
|
52
|
+
if (tasks.length > 0) {
|
|
53
|
+
text += "\n";
|
|
54
|
+
for (const task of tasks) {
|
|
55
|
+
text += `#${task.id} [${task.status}] ${task.subject}\n`;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
text += "The task list is currently empty.\n";
|
|
60
|
+
}
|
|
61
|
+
return text;
|
|
62
|
+
}
|
|
63
|
+
export function maybeInjectTaskReminder(messages, turnCounts, tasks) {
|
|
64
|
+
if (turnCounts.turnsSinceLastTaskManagement <
|
|
65
|
+
TASK_REMINDER_CONFIG.TURNS_SINCE_WRITE) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (turnCounts.turnsSinceLastReminder <
|
|
69
|
+
TASK_REMINDER_CONFIG.TURNS_BETWEEN_REMINDERS) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
messages.push({
|
|
73
|
+
role: "user",
|
|
74
|
+
content: buildTaskReminderText(tasks),
|
|
75
|
+
});
|
|
76
|
+
}
|