wave-agent-sdk 0.18.3 → 0.18.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +0 -2
- package/dist/managers/MemoryRuleManager.d.ts +9 -0
- package/dist/managers/MemoryRuleManager.d.ts.map +1 -1
- package/dist/managers/MemoryRuleManager.js +18 -0
- package/dist/managers/aiManager.d.ts +1 -1
- package/dist/managers/aiManager.d.ts.map +1 -1
- package/dist/managers/aiManager.js +370 -345
- package/dist/managers/messageManager.d.ts +32 -13
- package/dist/managers/messageManager.d.ts.map +1 -1
- package/dist/managers/messageManager.js +82 -76
- package/dist/prompts/index.d.ts +10 -4
- package/dist/prompts/index.d.ts.map +1 -1
- package/dist/prompts/index.js +21 -20
- package/dist/services/aiService.d.ts +2 -1
- package/dist/services/aiService.d.ts.map +1 -1
- package/dist/services/aiService.js +37 -10
- package/dist/services/memory.d.ts +1 -0
- package/dist/services/memory.d.ts.map +1 -1
- package/dist/services/memory.js +35 -17
- package/dist/tools/agentTool.d.ts.map +1 -1
- package/dist/tools/agentTool.js +24 -2
- package/dist/tools/editTool.js +3 -3
- package/dist/tools/readTool.js +2 -2
- package/dist/tools/writeTool.js +2 -2
- package/dist/utils/containerSetup.d.ts.map +1 -1
- package/dist/utils/containerSetup.js +1 -0
- package/dist/utils/openaiClient.d.ts.map +1 -1
- package/dist/utils/openaiClient.js +28 -7
- package/dist/utils/taskReminder.d.ts +2 -3
- package/dist/utils/taskReminder.d.ts.map +1 -1
- package/dist/utils/taskReminder.js +7 -18
- package/package.json +1 -1
- package/scripts/install_ripgrep.js +21 -1
- package/src/agent.ts +0 -5
- package/src/managers/MemoryRuleManager.ts +23 -0
- package/src/managers/aiManager.ts +473 -434
- package/src/managers/messageManager.ts +99 -82
- package/src/prompts/index.ts +33 -24
- package/src/services/aiService.ts +39 -12
- package/src/services/memory.ts +34 -16
- package/src/tools/agentTool.ts +24 -2
- package/src/tools/editTool.ts +3 -3
- package/src/tools/readTool.ts +2 -2
- package/src/tools/writeTool.ts +2 -2
- package/src/utils/containerSetup.ts +1 -0
- package/src/utils/openaiClient.ts +35 -7
- package/src/utils/taskReminder.ts +7 -19
- package/vendor/ripgrep/linux-aarch64/rg +0 -0
- package/vendor/ripgrep/macos-aarch64/rg +0 -0
- package/vendor/ripgrep/macos-x86_64/rg +0 -0
- package/vendor/ripgrep/windows-aarch64/rg.exe +0 -0
- package/vendor/ripgrep/windows-x86_64/rg.exe +0 -0
package/src/tools/editTool.ts
CHANGED
|
@@ -109,13 +109,13 @@ Usage:
|
|
|
109
109
|
};
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
//
|
|
113
|
-
context.messageManager?.
|
|
112
|
+
// Trigger conditional rule loading for this file
|
|
113
|
+
context.messageManager?.triggerFileRead(filePath);
|
|
114
114
|
|
|
115
115
|
// Enforce read-before-edit: the file must have been read first
|
|
116
116
|
if (
|
|
117
117
|
context.messageManager &&
|
|
118
|
-
!context.messageManager.
|
|
118
|
+
!context.messageManager.hasFileBeenRead(filePath)
|
|
119
119
|
) {
|
|
120
120
|
return {
|
|
121
121
|
success: false,
|
package/src/tools/readTool.ts
CHANGED
|
@@ -195,8 +195,8 @@ Usage:
|
|
|
195
195
|
};
|
|
196
196
|
}
|
|
197
197
|
|
|
198
|
-
//
|
|
199
|
-
context.messageManager?.
|
|
198
|
+
// Trigger conditional rule loading for this file
|
|
199
|
+
context.messageManager?.triggerFileRead(filePath);
|
|
200
200
|
|
|
201
201
|
// Check for binary document formats
|
|
202
202
|
if (isBinaryDocument(filePath)) {
|
package/src/tools/writeTool.ts
CHANGED
|
@@ -68,8 +68,8 @@ Usage:
|
|
|
68
68
|
};
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
//
|
|
72
|
-
context.messageManager?.
|
|
71
|
+
// Trigger conditional rule loading for this file
|
|
72
|
+
context.messageManager?.triggerFileRead(filePath);
|
|
73
73
|
|
|
74
74
|
try {
|
|
75
75
|
const resolvedPath = resolvePath(filePath, context.workdir);
|
|
@@ -7,6 +7,28 @@ import {
|
|
|
7
7
|
import { GatewayConfig } from "../types/config.js";
|
|
8
8
|
import { logger } from "./globalLogger.js";
|
|
9
9
|
|
|
10
|
+
const MAX_RETRIES = 10;
|
|
11
|
+
const BASE_DELAY_MS = 500;
|
|
12
|
+
const MAX_DELAY_MS = 32000;
|
|
13
|
+
|
|
14
|
+
function getRetryDelay(
|
|
15
|
+
attempt: number,
|
|
16
|
+
retryAfterHeader: string | null,
|
|
17
|
+
): number {
|
|
18
|
+
if (retryAfterHeader) {
|
|
19
|
+
const seconds = parseInt(retryAfterHeader, 10);
|
|
20
|
+
if (!isNaN(seconds)) {
|
|
21
|
+
return seconds * 1000;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const baseDelay = Math.min(
|
|
25
|
+
BASE_DELAY_MS * Math.pow(2, attempt - 1),
|
|
26
|
+
MAX_DELAY_MS,
|
|
27
|
+
);
|
|
28
|
+
const jitter = Math.random() * 0.25 * baseDelay;
|
|
29
|
+
return baseDelay + jitter;
|
|
30
|
+
}
|
|
31
|
+
|
|
10
32
|
type CreateParams =
|
|
11
33
|
| ChatCompletionCreateParamsNonStreaming
|
|
12
34
|
| ChatCompletionCreateParamsStreaming;
|
|
@@ -88,12 +110,11 @@ export class OpenAIClient {
|
|
|
88
110
|
|
|
89
111
|
const fetchFn = (customFetch as typeof fetch) || fetch;
|
|
90
112
|
let lastError: (Error & { status?: number; body?: unknown }) | undefined;
|
|
91
|
-
|
|
92
|
-
const initialDelay = 2000;
|
|
113
|
+
let lastRetryAfter: string | null = null;
|
|
93
114
|
|
|
94
|
-
for (let attempt = 0; attempt <=
|
|
115
|
+
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
95
116
|
if (attempt > 0) {
|
|
96
|
-
const delay =
|
|
117
|
+
const delay = getRetryDelay(attempt, lastRetryAfter);
|
|
97
118
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
98
119
|
}
|
|
99
120
|
|
|
@@ -110,12 +131,13 @@ export class OpenAIClient {
|
|
|
110
131
|
if (e instanceof Error && e.name === "AbortError") {
|
|
111
132
|
throw e;
|
|
112
133
|
}
|
|
113
|
-
if (attempt <
|
|
134
|
+
if (attempt < MAX_RETRIES) {
|
|
114
135
|
logger.warn("OpenAI API network error, retrying...", {
|
|
115
136
|
attempt: attempt + 1,
|
|
116
137
|
error: e,
|
|
117
138
|
});
|
|
118
139
|
lastError = e as Error;
|
|
140
|
+
lastRetryAfter = null;
|
|
119
141
|
continue;
|
|
120
142
|
}
|
|
121
143
|
throw e;
|
|
@@ -179,10 +201,12 @@ export class OpenAIClient {
|
|
|
179
201
|
const retryableStatus =
|
|
180
202
|
response.status === 429 ||
|
|
181
203
|
(response.status >= 500 && response.status !== 501);
|
|
182
|
-
if (retryableStatus && attempt <
|
|
204
|
+
if (retryableStatus && attempt < MAX_RETRIES) {
|
|
205
|
+
lastRetryAfter = response.headers.get("retry-after");
|
|
183
206
|
logger.warn("OpenAI API error, retrying...", {
|
|
184
207
|
attempt: attempt + 1,
|
|
185
208
|
status: response.status,
|
|
209
|
+
retryAfter: lastRetryAfter,
|
|
186
210
|
});
|
|
187
211
|
lastError = error;
|
|
188
212
|
continue;
|
|
@@ -222,12 +246,16 @@ export class OpenAIClient {
|
|
|
222
246
|
|
|
223
247
|
const data = trimmedLine.slice(5).trim();
|
|
224
248
|
if (data === "[DONE]") return;
|
|
249
|
+
if (!data) continue; // Skip empty data lines (keepalive heartbeats)
|
|
225
250
|
|
|
226
251
|
try {
|
|
227
252
|
const json = JSON.parse(data);
|
|
228
253
|
yield json as ChatCompletionChunk;
|
|
229
254
|
} catch (e) {
|
|
230
|
-
logger.error("Failed to parse stream chunk", {
|
|
255
|
+
logger.error("Failed to parse stream chunk", {
|
|
256
|
+
error: e instanceof Error ? e.message : String(e),
|
|
257
|
+
data,
|
|
258
|
+
});
|
|
231
259
|
}
|
|
232
260
|
}
|
|
233
261
|
}
|
|
@@ -1,18 +1,12 @@
|
|
|
1
1
|
import type { Message } from "../types/messaging.js";
|
|
2
2
|
import type { Task } from "../types/tasks.js";
|
|
3
|
-
import type { ChatCompletionMessageParam } from "openai/resources.js";
|
|
4
3
|
|
|
5
4
|
export const TASK_REMINDER_CONFIG = {
|
|
6
5
|
TURNS_SINCE_WRITE: 10,
|
|
7
6
|
TURNS_BETWEEN_REMINDERS: 10,
|
|
8
7
|
};
|
|
9
8
|
|
|
10
|
-
const TASK_MANAGEMENT_TOOLS = new Set([
|
|
11
|
-
"TaskCreate",
|
|
12
|
-
"TaskUpdate",
|
|
13
|
-
"TaskList",
|
|
14
|
-
"TaskGet",
|
|
15
|
-
]);
|
|
9
|
+
const TASK_MANAGEMENT_TOOLS = new Set(["TaskCreate", "TaskUpdate"]);
|
|
16
10
|
const TASK_REMINDER_MARKER = "<!-- task-reminder -->";
|
|
17
11
|
|
|
18
12
|
function isQualifyingAssistantMessage(message: Message): boolean {
|
|
@@ -66,43 +60,37 @@ export function getTaskReminderTurnCounts(messages: Message[]): {
|
|
|
66
60
|
export function buildTaskReminderText(tasks: Task[]): string {
|
|
67
61
|
let text = `${TASK_REMINDER_MARKER}\n`;
|
|
68
62
|
text +=
|
|
69
|
-
"
|
|
63
|
+
"The task tools haven't been used recently. If you're working on tasks that would benefit from tracking progress, consider using TaskCreate to add new tasks and TaskUpdate to update task status (set to in_progress when starting, completed when done). Also consider cleaning up the task list if it has become stale. Only use these if relevant to the current work. This is just a gentle reminder - ignore if not applicable. Make sure that you never mention this reminder to the user";
|
|
70
64
|
|
|
71
65
|
if (tasks.length > 0) {
|
|
72
|
-
text += "\n";
|
|
66
|
+
text += "\n\nHere are the existing tasks:\n";
|
|
73
67
|
for (const task of tasks) {
|
|
74
68
|
text += `#${task.id} [${task.status}] ${task.subject}\n`;
|
|
75
69
|
}
|
|
76
|
-
} else {
|
|
77
|
-
text += "The task list is currently empty.\n";
|
|
78
70
|
}
|
|
79
71
|
|
|
80
72
|
return text;
|
|
81
73
|
}
|
|
82
74
|
|
|
83
75
|
export function maybeInjectTaskReminder(
|
|
84
|
-
messages: ChatCompletionMessageParam[],
|
|
85
76
|
turnCounts: {
|
|
86
77
|
turnsSinceLastTaskManagement: number;
|
|
87
78
|
turnsSinceLastReminder: number;
|
|
88
79
|
},
|
|
89
80
|
tasks: Task[],
|
|
90
|
-
):
|
|
81
|
+
): string | null {
|
|
91
82
|
if (
|
|
92
83
|
turnCounts.turnsSinceLastTaskManagement <
|
|
93
84
|
TASK_REMINDER_CONFIG.TURNS_SINCE_WRITE
|
|
94
85
|
) {
|
|
95
|
-
return;
|
|
86
|
+
return null;
|
|
96
87
|
}
|
|
97
88
|
if (
|
|
98
89
|
turnCounts.turnsSinceLastReminder <
|
|
99
90
|
TASK_REMINDER_CONFIG.TURNS_BETWEEN_REMINDERS
|
|
100
91
|
) {
|
|
101
|
-
return;
|
|
92
|
+
return null;
|
|
102
93
|
}
|
|
103
94
|
|
|
104
|
-
|
|
105
|
-
role: "user",
|
|
106
|
-
content: buildTaskReminderText(tasks),
|
|
107
|
-
} as ChatCompletionMessageParam);
|
|
95
|
+
return buildTaskReminderText(tasks);
|
|
108
96
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|