wave-agent-sdk 1.0.0 → 1.0.1
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 +9 -20
- package/dist/agent.js +23 -97
- package/dist/managers/aiManager.d.ts +63 -8
- package/dist/managers/aiManager.js +270 -80
- package/dist/managers/messageManager.d.ts +9 -5
- package/dist/managers/messageManager.js +36 -12
- package/dist/managers/subagentManager.d.ts +6 -0
- package/dist/managers/subagentManager.js +33 -22
- package/dist/prompts/index.d.ts +0 -1
- package/dist/prompts/index.js +0 -4
- package/dist/services/aiService.d.ts +1 -34
- package/dist/services/aiService.js +18 -130
- package/dist/services/autoMemoryService.d.ts +27 -2
- package/dist/services/autoMemoryService.js +124 -36
- package/dist/services/configurationService.js +14 -1
- package/dist/services/session.d.ts +13 -0
- package/dist/services/session.js +64 -0
- package/dist/types/agent.d.ts +0 -2
- package/dist/types/config.d.ts +7 -0
- package/dist/types/core.d.ts +1 -1
- package/dist/utils/containerSetup.js +12 -3
- package/package.json +1 -1
- package/src/agent.ts +36 -110
- package/src/managers/aiManager.ts +366 -105
- package/src/managers/messageManager.ts +51 -23
- package/src/managers/subagentManager.ts +36 -25
- package/src/prompts/index.ts +0 -4
- package/src/services/aiService.ts +25 -203
- package/src/services/autoMemoryService.ts +145 -39
- package/src/services/configurationService.ts +16 -1
- package/src/services/session.ts +68 -0
- package/src/types/agent.ts +0 -6
- package/src/types/config.ts +7 -0
- package/src/types/core.ts +1 -1
- package/src/utils/containerSetup.ts +12 -4
- package/dist/constants/goalPrompts.d.ts +0 -1
- package/dist/constants/goalPrompts.js +0 -10
- package/dist/managers/goalManager.d.ts +0 -42
- package/dist/managers/goalManager.js +0 -177
- package/src/constants/goalPrompts.ts +0 -10
- package/src/managers/goalManager.ts +0 -232
|
@@ -1,232 +0,0 @@
|
|
|
1
|
-
import { Container } from "../utils/container.js";
|
|
2
|
-
import type { MessageManager } from "./messageManager.js";
|
|
3
|
-
import type { AIManager } from "./aiManager.js";
|
|
4
|
-
import type { Usage } from "../types/index.js";
|
|
5
|
-
import { evaluateGoal as aiEvaluateGoal } from "../services/aiService.js";
|
|
6
|
-
import { convertMessagesForAPI } from "../utils/convertMessagesForAPI.js";
|
|
7
|
-
import { logger } from "../utils/globalLogger.js";
|
|
8
|
-
|
|
9
|
-
export interface GoalState {
|
|
10
|
-
condition: string;
|
|
11
|
-
startedAt: number;
|
|
12
|
-
turnCount: number;
|
|
13
|
-
tokenBaseline: number;
|
|
14
|
-
lastReason?: string;
|
|
15
|
-
consecutiveEvalFailures: number;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const MAX_GOAL_TURNS = 50;
|
|
19
|
-
const MAX_GOAL_DURATION_MS = 30 * 60 * 1000; // 30 minutes
|
|
20
|
-
const MAX_CONSECUTIVE_EVAL_FAILURES = 3;
|
|
21
|
-
const MAX_CONDITION_LENGTH = 4000;
|
|
22
|
-
|
|
23
|
-
export class GoalManager {
|
|
24
|
-
private state: GoalState | null = null;
|
|
25
|
-
private onGoalStateChange?: (
|
|
26
|
-
active: boolean,
|
|
27
|
-
condition?: string,
|
|
28
|
-
elapsed?: string,
|
|
29
|
-
) => void;
|
|
30
|
-
private onGoalEvaluating?: (evaluating: boolean) => void;
|
|
31
|
-
|
|
32
|
-
constructor(private container: Container) {}
|
|
33
|
-
|
|
34
|
-
private get messageManager(): MessageManager {
|
|
35
|
-
return this.container.get<MessageManager>("MessageManager")!;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
private get aiManager(): AIManager {
|
|
39
|
-
return this.container.get<AIManager>("AIManager")!;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
public setOnGoalStateChange(
|
|
43
|
-
callback: (active: boolean, condition?: string, elapsed?: string) => void,
|
|
44
|
-
): void {
|
|
45
|
-
this.onGoalStateChange = callback;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
public setOnGoalEvaluating(callback: (evaluating: boolean) => void): void {
|
|
49
|
-
this.onGoalEvaluating = callback;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
public setGoal(condition: string): void {
|
|
53
|
-
if (condition.length > MAX_CONDITION_LENGTH) {
|
|
54
|
-
throw new Error(
|
|
55
|
-
`Goal condition exceeds maximum length of ${MAX_CONDITION_LENGTH} characters`,
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const totalTokens = this.messageManager.getLatestTotalTokens?.() ?? 0;
|
|
60
|
-
|
|
61
|
-
this.state = {
|
|
62
|
-
condition,
|
|
63
|
-
startedAt: Date.now(),
|
|
64
|
-
turnCount: 0,
|
|
65
|
-
tokenBaseline: totalTokens,
|
|
66
|
-
consecutiveEvalFailures: 0,
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
this.onGoalStateChange?.(true, condition, "0m");
|
|
70
|
-
logger?.info(`[Goal] Set goal: ${condition}`);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
public clearGoal(): void {
|
|
74
|
-
if (this.state) {
|
|
75
|
-
logger?.info(`[Goal] Cleared goal: ${this.state.condition}`);
|
|
76
|
-
this.state = null;
|
|
77
|
-
this.onGoalStateChange?.(false);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
public getGoal(): GoalState | null {
|
|
82
|
-
return this.state;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
public isGoalActive(): boolean {
|
|
86
|
-
return this.state !== null;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
public incrementTurnCount(): void {
|
|
90
|
-
if (this.state) {
|
|
91
|
-
this.state.turnCount++;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
public getStatusString(): string {
|
|
96
|
-
if (!this.state) return "No active goal";
|
|
97
|
-
const elapsed = this.formatElapsed(Date.now() - this.state.startedAt);
|
|
98
|
-
let status = `Goal: ${this.state.condition}\nElapsed: ${elapsed}\nTurns: ${this.state.turnCount}`;
|
|
99
|
-
if (this.state.lastReason) {
|
|
100
|
-
status += `\nLast evaluation: ${this.state.lastReason}`;
|
|
101
|
-
}
|
|
102
|
-
return status;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Check circuit breakers. Returns a clear reason if goal should be force-cleared, null otherwise.
|
|
107
|
-
*/
|
|
108
|
-
public checkCircuitBreakers(): string | null {
|
|
109
|
-
if (!this.state) return null;
|
|
110
|
-
|
|
111
|
-
if (this.state.turnCount >= MAX_GOAL_TURNS) {
|
|
112
|
-
return `Goal cancelled: maximum turns (${MAX_GOAL_TURNS}) exceeded`;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
if (Date.now() - this.state.startedAt >= MAX_GOAL_DURATION_MS) {
|
|
116
|
-
return `Goal cancelled: time limit (${MAX_GOAL_DURATION_MS / 60000} minutes) exceeded`;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
if (this.state.consecutiveEvalFailures >= MAX_CONSECUTIVE_EVAL_FAILURES) {
|
|
120
|
-
return `Goal cancelled: ${MAX_CONSECUTIVE_EVAL_FAILURES} consecutive evaluation failures`;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
return null;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Evaluate whether the goal has been met using the fast model.
|
|
128
|
-
*/
|
|
129
|
-
public async evaluateGoal(abortSignal?: AbortSignal): Promise<{
|
|
130
|
-
isMet: boolean;
|
|
131
|
-
reason: string;
|
|
132
|
-
}> {
|
|
133
|
-
if (!this.state) {
|
|
134
|
-
return { isMet: false, reason: "No active goal" };
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
try {
|
|
138
|
-
const messages = this.messageManager.getMessages();
|
|
139
|
-
const apiMessages = convertMessagesForAPI(messages);
|
|
140
|
-
const gatewayConfig = this.aiManager.getGatewayConfig();
|
|
141
|
-
const modelConfig = this.aiManager.getModelConfig();
|
|
142
|
-
const fastModel = modelConfig.fastModel || modelConfig.model;
|
|
143
|
-
if (!fastModel) {
|
|
144
|
-
return {
|
|
145
|
-
isMet: false,
|
|
146
|
-
reason: "No model configured for goal evaluation",
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
this.onGoalEvaluating?.(true);
|
|
151
|
-
const result = await aiEvaluateGoal({
|
|
152
|
-
gatewayConfig,
|
|
153
|
-
modelConfig,
|
|
154
|
-
model: fastModel,
|
|
155
|
-
goalCondition: this.state.condition,
|
|
156
|
-
messages: apiMessages,
|
|
157
|
-
abortSignal,
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
// Track evaluation tokens separately
|
|
161
|
-
if (result.usage) {
|
|
162
|
-
const usage: Usage = {
|
|
163
|
-
...result.usage,
|
|
164
|
-
operation_type: "goal_evaluation",
|
|
165
|
-
model: fastModel,
|
|
166
|
-
};
|
|
167
|
-
this.messageManager.addUsage(usage);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
// Reset failure counter on success
|
|
171
|
-
this.state.consecutiveEvalFailures = 0;
|
|
172
|
-
|
|
173
|
-
this.onGoalEvaluating?.(false);
|
|
174
|
-
|
|
175
|
-
// Parse the response
|
|
176
|
-
return this.parseEvaluationResponse(result.content);
|
|
177
|
-
} catch (error) {
|
|
178
|
-
this.onGoalEvaluating?.(false);
|
|
179
|
-
this.state.consecutiveEvalFailures++;
|
|
180
|
-
logger?.warn(
|
|
181
|
-
`[Goal] Evaluation failed (${this.state.consecutiveEvalFailures}/${MAX_CONSECUTIVE_EVAL_FAILURES}): ${(error as Error).message}`,
|
|
182
|
-
);
|
|
183
|
-
return {
|
|
184
|
-
isMet: false,
|
|
185
|
-
reason: `Evaluation failed: ${(error as Error).message}`,
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* Parse the evaluation response from the fast model.
|
|
192
|
-
*/
|
|
193
|
-
private parseEvaluationResponse(content: string): {
|
|
194
|
-
isMet: boolean;
|
|
195
|
-
reason: string;
|
|
196
|
-
} {
|
|
197
|
-
// Try direct JSON parse
|
|
198
|
-
try {
|
|
199
|
-
const parsed = JSON.parse(content);
|
|
200
|
-
if (typeof parsed.met === "boolean") {
|
|
201
|
-
return {
|
|
202
|
-
isMet: parsed.met,
|
|
203
|
-
reason: parsed.reason || "No reason provided",
|
|
204
|
-
};
|
|
205
|
-
}
|
|
206
|
-
} catch {
|
|
207
|
-
// Fall through to regex
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
// Try regex extraction
|
|
211
|
-
const metMatch = content.match(/"met"\s*:\s*(true|false)/);
|
|
212
|
-
const reasonMatch = content.match(/"reason"\s*:\s*"([^"]*)"/);
|
|
213
|
-
if (metMatch) {
|
|
214
|
-
return {
|
|
215
|
-
isMet: metMatch[1] === "true",
|
|
216
|
-
reason: reasonMatch?.[1] || "No reason provided",
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
// Default: not met
|
|
221
|
-
return { isMet: false, reason: "Could not parse evaluation response" };
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
private formatElapsed(ms: number): string {
|
|
225
|
-
const minutes = Math.floor(ms / 60000);
|
|
226
|
-
if (minutes < 1) return "<1m";
|
|
227
|
-
if (minutes < 60) return `${minutes}m`;
|
|
228
|
-
const hours = Math.floor(minutes / 60);
|
|
229
|
-
const remainingMin = minutes % 60;
|
|
230
|
-
return `${hours}h${remainingMin}m`;
|
|
231
|
-
}
|
|
232
|
-
}
|