@vellumai/assistant 0.8.8-dev.202606080320.8b7fbff → 0.8.8-dev.202606081143.f600053
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/package.json +1 -1
- package/src/__tests__/agent-loop-callsite-precedence.test.ts +42 -14
- package/src/__tests__/agent-loop-exit-reason.test.ts +117 -91
- package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +12 -4
- package/src/__tests__/agent-loop-output-hooks.test.ts +48 -16
- package/src/__tests__/agent-loop-override-profile.test.ts +18 -6
- package/src/__tests__/agent-loop-provider-error-recording.test.ts +33 -27
- package/src/__tests__/agent-loop-thinking.test.ts +32 -24
- package/src/__tests__/agent-loop.test.ts +288 -96
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +2 -2
- package/src/__tests__/agent-wake-override-profile.test.ts +4 -8
- package/src/__tests__/approval-cascade.test.ts +4 -4
- package/src/__tests__/compaction-events.test.ts +4 -4
- package/src/__tests__/conversation-abort-tool-results.test.ts +5 -4
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +7 -9
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +41 -14
- package/src/__tests__/conversation-agent-loop.test.ts +33 -195
- package/src/__tests__/conversation-confirmation-signals.test.ts +4 -4
- package/src/__tests__/conversation-process-callsite.test.ts +13 -14
- package/src/__tests__/conversation-provider-retry-repair.test.ts +13 -11
- package/src/__tests__/conversation-queue.test.ts +8 -9
- package/src/__tests__/conversation-slash-queue.test.ts +5 -4
- package/src/__tests__/conversation-slash-unknown.test.ts +5 -4
- package/src/__tests__/conversation-speed-override.test.ts +9 -9
- package/src/__tests__/conversation-workspace-cache-state.test.ts +5 -4
- package/src/__tests__/conversation-workspace-injection.test.ts +5 -4
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -4
- package/src/__tests__/memory-retrieval-hook.test.ts +73 -6
- package/src/__tests__/parallel-tool.benchmark.test.ts +24 -8
- package/src/agent/loop.ts +62 -26
- package/src/daemon/conversation-agent-loop.ts +31 -126
- package/src/daemon/conversation.ts +3 -1
- package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit-temp.ts +167 -56
- package/src/runtime/__tests__/agent-wake.test.ts +7 -14
- package/src/runtime/agent-wake.ts +22 -24
package/package.json
CHANGED
|
@@ -100,12 +100,16 @@ describe("AgentLoop — call-site precedence", () => {
|
|
|
100
100
|
});
|
|
101
101
|
|
|
102
102
|
const { provider, lastConfig } = makePipeline("anthropic");
|
|
103
|
-
const loop = new AgentLoop(
|
|
103
|
+
const loop = new AgentLoop({
|
|
104
|
+
provider: provider,
|
|
105
|
+
systemPrompt: "system",
|
|
104
106
|
conversationId: "test-conversation",
|
|
105
107
|
config: { maxTokens: 64000 },
|
|
106
108
|
});
|
|
107
109
|
|
|
108
|
-
await loop.run(
|
|
110
|
+
await loop.run({
|
|
111
|
+
messages: [userMessage],
|
|
112
|
+
onEvent: () => {},
|
|
109
113
|
trust: { sourceChannel: "vellum", trustClass: "unknown" },
|
|
110
114
|
callSite: "mainAgent",
|
|
111
115
|
});
|
|
@@ -124,7 +128,9 @@ describe("AgentLoop — call-site precedence", () => {
|
|
|
124
128
|
});
|
|
125
129
|
|
|
126
130
|
const { provider, lastConfig } = makePipeline("anthropic");
|
|
127
|
-
const loop = new AgentLoop(
|
|
131
|
+
const loop = new AgentLoop({
|
|
132
|
+
provider: provider,
|
|
133
|
+
systemPrompt: "system",
|
|
128
134
|
conversationId: "test-conversation",
|
|
129
135
|
config: {
|
|
130
136
|
maxTokens: 64000,
|
|
@@ -132,7 +138,9 @@ describe("AgentLoop — call-site precedence", () => {
|
|
|
132
138
|
},
|
|
133
139
|
});
|
|
134
140
|
|
|
135
|
-
await loop.run(
|
|
141
|
+
await loop.run({
|
|
142
|
+
messages: [userMessage],
|
|
143
|
+
onEvent: () => {},
|
|
136
144
|
trust: { sourceChannel: "vellum", trustClass: "unknown" },
|
|
137
145
|
callSite: "mainAgent",
|
|
138
146
|
});
|
|
@@ -151,7 +159,9 @@ describe("AgentLoop — call-site precedence", () => {
|
|
|
151
159
|
});
|
|
152
160
|
|
|
153
161
|
const { provider, lastConfig } = makePipeline("anthropic");
|
|
154
|
-
const loop = new AgentLoop(
|
|
162
|
+
const loop = new AgentLoop({
|
|
163
|
+
provider: provider,
|
|
164
|
+
systemPrompt: "system",
|
|
155
165
|
conversationId: "test-conversation",
|
|
156
166
|
config: {
|
|
157
167
|
maxTokens: 64000,
|
|
@@ -162,7 +172,9 @@ describe("AgentLoop — call-site precedence", () => {
|
|
|
162
172
|
},
|
|
163
173
|
});
|
|
164
174
|
|
|
165
|
-
await loop.run(
|
|
175
|
+
await loop.run({
|
|
176
|
+
messages: [userMessage],
|
|
177
|
+
onEvent: () => {},
|
|
166
178
|
trust: { sourceChannel: "vellum", trustClass: "unknown" },
|
|
167
179
|
callSite: "mainAgent",
|
|
168
180
|
});
|
|
@@ -186,7 +198,9 @@ describe("AgentLoop — call-site precedence", () => {
|
|
|
186
198
|
});
|
|
187
199
|
|
|
188
200
|
const { provider, lastConfig } = makePipeline("anthropic");
|
|
189
|
-
const loop = new AgentLoop(
|
|
201
|
+
const loop = new AgentLoop({
|
|
202
|
+
provider: provider,
|
|
203
|
+
systemPrompt: "system",
|
|
190
204
|
conversationId: "test-conversation",
|
|
191
205
|
config: {
|
|
192
206
|
maxTokens: 64000,
|
|
@@ -197,7 +211,9 @@ describe("AgentLoop — call-site precedence", () => {
|
|
|
197
211
|
},
|
|
198
212
|
});
|
|
199
213
|
|
|
200
|
-
await loop.run(
|
|
214
|
+
await loop.run({
|
|
215
|
+
messages: [userMessage],
|
|
216
|
+
onEvent: () => {},
|
|
201
217
|
trust: { sourceChannel: "vellum", trustClass: "unknown" },
|
|
202
218
|
callSite: "mainAgent",
|
|
203
219
|
});
|
|
@@ -218,12 +234,16 @@ describe("AgentLoop — call-site precedence", () => {
|
|
|
218
234
|
});
|
|
219
235
|
|
|
220
236
|
const { provider, lastConfig } = makePipeline("anthropic");
|
|
221
|
-
const loop = new AgentLoop(
|
|
237
|
+
const loop = new AgentLoop({
|
|
238
|
+
provider: provider,
|
|
239
|
+
systemPrompt: "system",
|
|
222
240
|
conversationId: "test-conversation",
|
|
223
241
|
config: { maxTokens: 64000 },
|
|
224
242
|
});
|
|
225
243
|
|
|
226
|
-
await loop.run(
|
|
244
|
+
await loop.run({
|
|
245
|
+
messages: [userMessage],
|
|
246
|
+
onEvent: () => {},
|
|
227
247
|
trust: { sourceChannel: "vellum", trustClass: "unknown" },
|
|
228
248
|
callSite: "mainAgent",
|
|
229
249
|
});
|
|
@@ -247,7 +267,9 @@ describe("AgentLoop — call-site precedence", () => {
|
|
|
247
267
|
});
|
|
248
268
|
|
|
249
269
|
const { provider, lastConfig } = makePipeline("anthropic");
|
|
250
|
-
const loop = new AgentLoop(
|
|
270
|
+
const loop = new AgentLoop({
|
|
271
|
+
provider: provider,
|
|
272
|
+
systemPrompt: "system",
|
|
251
273
|
conversationId: "test-conversation",
|
|
252
274
|
config: {
|
|
253
275
|
maxTokens: 64000,
|
|
@@ -257,7 +279,9 @@ describe("AgentLoop — call-site precedence", () => {
|
|
|
257
279
|
},
|
|
258
280
|
});
|
|
259
281
|
|
|
260
|
-
await loop.run(
|
|
282
|
+
await loop.run({
|
|
283
|
+
messages: [userMessage],
|
|
284
|
+
onEvent: () => {},
|
|
261
285
|
trust: { sourceChannel: "vellum", trustClass: "unknown" },
|
|
262
286
|
});
|
|
263
287
|
|
|
@@ -285,13 +309,17 @@ describe("AgentLoop — call-site precedence", () => {
|
|
|
285
309
|
maxTokens: 8192,
|
|
286
310
|
});
|
|
287
311
|
|
|
288
|
-
const loop = new AgentLoop(
|
|
312
|
+
const loop = new AgentLoop({
|
|
313
|
+
provider: provider,
|
|
314
|
+
systemPrompt: "system",
|
|
289
315
|
conversationId: "test-conversation",
|
|
290
316
|
config: { maxTokens: 64000 },
|
|
291
317
|
resolveSystemPrompt: resolveSystemPrompt,
|
|
292
318
|
});
|
|
293
319
|
|
|
294
|
-
await loop.run(
|
|
320
|
+
await loop.run({
|
|
321
|
+
messages: [userMessage],
|
|
322
|
+
onEvent: () => {},
|
|
295
323
|
trust: { sourceChannel: "vellum", trustClass: "unknown" },
|
|
296
324
|
callSite: "mainAgent",
|
|
297
325
|
});
|
|
@@ -163,18 +163,20 @@ describe("AgentLoop exit-reason instrumentation", () => {
|
|
|
163
163
|
|
|
164
164
|
test("emits exit event exactly once with 'no_tool_calls' on plain text response", async () => {
|
|
165
165
|
const { provider } = createMockProvider([textResponse("Hi there!")]);
|
|
166
|
-
const loop = new AgentLoop(
|
|
166
|
+
const loop = new AgentLoop({
|
|
167
|
+
provider: provider,
|
|
168
|
+
systemPrompt: "system prompt",
|
|
167
169
|
conversationId: "test-conversation",
|
|
168
170
|
});
|
|
169
171
|
|
|
170
172
|
const events: AgentEvent[] = [];
|
|
171
|
-
await loop.run(
|
|
172
|
-
[userMessage],
|
|
173
|
-
(e) => {
|
|
173
|
+
await loop.run({
|
|
174
|
+
messages: [userMessage],
|
|
175
|
+
onEvent: (e) => {
|
|
174
176
|
events.push(e);
|
|
175
177
|
},
|
|
176
|
-
|
|
177
|
-
);
|
|
178
|
+
trust: { sourceChannel: "vellum", trustClass: "unknown" },
|
|
179
|
+
});
|
|
178
180
|
|
|
179
181
|
expect(countExitEvents(events)).toBe(1);
|
|
180
182
|
const exit = lastExitEvent(events);
|
|
@@ -183,18 +185,20 @@ describe("AgentLoop exit-reason instrumentation", () => {
|
|
|
183
185
|
|
|
184
186
|
test("agent_loop_exit is the last event emitted", async () => {
|
|
185
187
|
const { provider } = createMockProvider([textResponse("Hi there!")]);
|
|
186
|
-
const loop = new AgentLoop(
|
|
188
|
+
const loop = new AgentLoop({
|
|
189
|
+
provider: provider,
|
|
190
|
+
systemPrompt: "system prompt",
|
|
187
191
|
conversationId: "test-conversation",
|
|
188
192
|
});
|
|
189
193
|
|
|
190
194
|
const events: AgentEvent[] = [];
|
|
191
|
-
await loop.run(
|
|
192
|
-
[userMessage],
|
|
193
|
-
(e) => {
|
|
195
|
+
await loop.run({
|
|
196
|
+
messages: [userMessage],
|
|
197
|
+
onEvent: (e) => {
|
|
194
198
|
events.push(e);
|
|
195
199
|
},
|
|
196
|
-
|
|
197
|
-
);
|
|
200
|
+
trust: { sourceChannel: "vellum", trustClass: "unknown" },
|
|
201
|
+
});
|
|
198
202
|
|
|
199
203
|
expect(events.length).toBeGreaterThan(0);
|
|
200
204
|
expect(events[events.length - 1].type).toBe("agent_loop_exit");
|
|
@@ -204,18 +208,20 @@ describe("AgentLoop exit-reason instrumentation", () => {
|
|
|
204
208
|
const { provider } = createMockProvider([
|
|
205
209
|
maxTokensResponse("Partial answer"),
|
|
206
210
|
]);
|
|
207
|
-
const loop = new AgentLoop(
|
|
211
|
+
const loop = new AgentLoop({
|
|
212
|
+
provider: provider,
|
|
213
|
+
systemPrompt: "system prompt",
|
|
208
214
|
conversationId: "test-conversation",
|
|
209
215
|
});
|
|
210
216
|
|
|
211
217
|
const events: AgentEvent[] = [];
|
|
212
|
-
await loop.run(
|
|
213
|
-
[userMessage],
|
|
214
|
-
(e) => {
|
|
218
|
+
await loop.run({
|
|
219
|
+
messages: [userMessage],
|
|
220
|
+
onEvent: (e) => {
|
|
215
221
|
events.push(e);
|
|
216
222
|
},
|
|
217
|
-
|
|
218
|
-
);
|
|
223
|
+
trust: { sourceChannel: "vellum", trustClass: "unknown" },
|
|
224
|
+
});
|
|
219
225
|
|
|
220
226
|
expect(events.map((e) => e.type)).toEqual([
|
|
221
227
|
"llm_call_started",
|
|
@@ -245,19 +251,21 @@ describe("AgentLoop exit-reason instrumentation", () => {
|
|
|
245
251
|
stopReason: "max_tokens",
|
|
246
252
|
},
|
|
247
253
|
]);
|
|
248
|
-
const loop = new AgentLoop(
|
|
254
|
+
const loop = new AgentLoop({
|
|
255
|
+
provider: provider,
|
|
256
|
+
systemPrompt: "system prompt",
|
|
249
257
|
conversationId: "test-conversation",
|
|
250
258
|
tools: dummyTools,
|
|
251
259
|
});
|
|
252
260
|
|
|
253
261
|
const events: AgentEvent[] = [];
|
|
254
|
-
const { history: result } = await loop.run(
|
|
255
|
-
[userMessage],
|
|
256
|
-
(e) => {
|
|
262
|
+
const { history: result } = await loop.run({
|
|
263
|
+
messages: [userMessage],
|
|
264
|
+
onEvent: (e) => {
|
|
257
265
|
events.push(e);
|
|
258
266
|
},
|
|
259
|
-
|
|
260
|
-
);
|
|
267
|
+
trust: { sourceChannel: "vellum", trustClass: "unknown" },
|
|
268
|
+
});
|
|
261
269
|
|
|
262
270
|
expect(events.some((e) => e.type === "tool_use")).toBe(false);
|
|
263
271
|
expect(lastExitEvent(events)?.reason).toBe("max_tokens_reached");
|
|
@@ -268,7 +276,9 @@ describe("AgentLoop exit-reason instrumentation", () => {
|
|
|
268
276
|
|
|
269
277
|
test("emits 'aborted_pre_call' when signal is already aborted at run start", async () => {
|
|
270
278
|
const { provider } = createMockProvider([textResponse("never sent")]);
|
|
271
|
-
const loop = new AgentLoop(
|
|
279
|
+
const loop = new AgentLoop({
|
|
280
|
+
provider: provider,
|
|
281
|
+
systemPrompt: "system prompt",
|
|
272
282
|
conversationId: "test-conversation",
|
|
273
283
|
});
|
|
274
284
|
|
|
@@ -276,16 +286,14 @@ describe("AgentLoop exit-reason instrumentation", () => {
|
|
|
276
286
|
controller.abort();
|
|
277
287
|
|
|
278
288
|
const events: AgentEvent[] = [];
|
|
279
|
-
await loop.run(
|
|
280
|
-
[userMessage],
|
|
281
|
-
(e) => {
|
|
289
|
+
await loop.run({
|
|
290
|
+
messages: [userMessage],
|
|
291
|
+
onEvent: (e) => {
|
|
282
292
|
events.push(e);
|
|
283
293
|
},
|
|
284
|
-
{
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
},
|
|
288
|
-
);
|
|
294
|
+
trust: { sourceChannel: "vellum", trustClass: "unknown" },
|
|
295
|
+
signal: controller.signal,
|
|
296
|
+
});
|
|
289
297
|
|
|
290
298
|
expect(countExitEvents(events)).toBe(1);
|
|
291
299
|
expect(lastExitEvent(events)?.reason).toBe("aborted_pre_call");
|
|
@@ -300,20 +308,22 @@ describe("AgentLoop exit-reason instrumentation", () => {
|
|
|
300
308
|
isError: false,
|
|
301
309
|
yieldToUser: true,
|
|
302
310
|
});
|
|
303
|
-
const loop = new AgentLoop(
|
|
311
|
+
const loop = new AgentLoop({
|
|
312
|
+
provider: provider,
|
|
313
|
+
systemPrompt: "system",
|
|
304
314
|
conversationId: "test-conversation",
|
|
305
315
|
tools: dummyTools,
|
|
306
316
|
toolExecutor: toolExecutor,
|
|
307
317
|
});
|
|
308
318
|
|
|
309
319
|
const events: AgentEvent[] = [];
|
|
310
|
-
await loop.run(
|
|
311
|
-
[userMessage],
|
|
312
|
-
(e) => {
|
|
320
|
+
await loop.run({
|
|
321
|
+
messages: [userMessage],
|
|
322
|
+
onEvent: (e) => {
|
|
313
323
|
events.push(e);
|
|
314
324
|
},
|
|
315
|
-
|
|
316
|
-
);
|
|
325
|
+
trust: { sourceChannel: "vellum", trustClass: "unknown" },
|
|
326
|
+
});
|
|
317
327
|
|
|
318
328
|
expect(countExitEvents(events)).toBe(1);
|
|
319
329
|
expect(lastExitEvent(events)?.reason).toBe("yield_to_user");
|
|
@@ -325,7 +335,9 @@ describe("AgentLoop exit-reason instrumentation", () => {
|
|
|
325
335
|
textResponse("never reached"),
|
|
326
336
|
]);
|
|
327
337
|
const toolExecutor = async () => ({ content: "ok", isError: false });
|
|
328
|
-
const loop = new AgentLoop(
|
|
338
|
+
const loop = new AgentLoop({
|
|
339
|
+
provider: provider,
|
|
340
|
+
systemPrompt: "system",
|
|
329
341
|
conversationId: "test-conversation",
|
|
330
342
|
tools: dummyTools,
|
|
331
343
|
toolExecutor: toolExecutor,
|
|
@@ -335,16 +347,14 @@ describe("AgentLoop exit-reason instrumentation", () => {
|
|
|
335
347
|
"budget";
|
|
336
348
|
|
|
337
349
|
const events: AgentEvent[] = [];
|
|
338
|
-
await loop.run(
|
|
339
|
-
[userMessage],
|
|
340
|
-
(e) => {
|
|
350
|
+
await loop.run({
|
|
351
|
+
messages: [userMessage],
|
|
352
|
+
onEvent: (e) => {
|
|
341
353
|
events.push(e);
|
|
342
354
|
},
|
|
343
|
-
{
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
},
|
|
347
|
-
);
|
|
355
|
+
trust: { sourceChannel: "vellum", trustClass: "unknown" },
|
|
356
|
+
onCheckpoint,
|
|
357
|
+
});
|
|
348
358
|
|
|
349
359
|
expect(countExitEvents(events)).toBe(0);
|
|
350
360
|
});
|
|
@@ -357,7 +367,9 @@ describe("AgentLoop exit-reason instrumentation", () => {
|
|
|
357
367
|
textResponse("never reached"),
|
|
358
368
|
]);
|
|
359
369
|
const toolExecutor = async () => ({ content: "ok", isError: false });
|
|
360
|
-
const loop = new AgentLoop(
|
|
370
|
+
const loop = new AgentLoop({
|
|
371
|
+
provider: provider,
|
|
372
|
+
systemPrompt: "system",
|
|
361
373
|
conversationId: "test-conversation",
|
|
362
374
|
tools: dummyTools,
|
|
363
375
|
toolExecutor: toolExecutor,
|
|
@@ -366,7 +378,9 @@ describe("AgentLoop exit-reason instrumentation", () => {
|
|
|
366
378
|
// AND an effective context window so small that any real token estimate
|
|
367
379
|
// of the running history exceeds the mid-loop threshold.
|
|
368
380
|
// WHEN the loop checkpoints after the tool results land
|
|
369
|
-
const result = await loop.run(
|
|
381
|
+
const result = await loop.run({
|
|
382
|
+
messages: [userMessage],
|
|
383
|
+
onEvent: () => {},
|
|
370
384
|
trust: { sourceChannel: "vellum", trustClass: "unknown" },
|
|
371
385
|
resolveContextWindow: () => ({
|
|
372
386
|
maxInputTokens: 10,
|
|
@@ -386,14 +400,18 @@ describe("AgentLoop exit-reason instrumentation", () => {
|
|
|
386
400
|
textResponse("done"),
|
|
387
401
|
]);
|
|
388
402
|
const toolExecutor = async () => ({ content: "ok", isError: false });
|
|
389
|
-
const loop = new AgentLoop(
|
|
403
|
+
const loop = new AgentLoop({
|
|
404
|
+
provider: provider,
|
|
405
|
+
systemPrompt: "system",
|
|
390
406
|
conversationId: "test-conversation",
|
|
391
407
|
tools: dummyTools,
|
|
392
408
|
toolExecutor: toolExecutor,
|
|
393
409
|
});
|
|
394
410
|
|
|
395
411
|
// WHEN the loop runs to completion
|
|
396
|
-
const result = await loop.run(
|
|
412
|
+
const result = await loop.run({
|
|
413
|
+
messages: [userMessage],
|
|
414
|
+
onEvent: () => {},
|
|
397
415
|
trust: { sourceChannel: "vellum", trustClass: "unknown" },
|
|
398
416
|
resolveContextWindow: () => ({
|
|
399
417
|
maxInputTokens: 10,
|
|
@@ -413,7 +431,9 @@ describe("AgentLoop exit-reason instrumentation", () => {
|
|
|
413
431
|
textResponse("done after compaction"),
|
|
414
432
|
]);
|
|
415
433
|
const toolExecutor = async () => ({ content: "ok", isError: false });
|
|
416
|
-
const loop = new AgentLoop(
|
|
434
|
+
const loop = new AgentLoop({
|
|
435
|
+
provider: provider,
|
|
436
|
+
systemPrompt: "system",
|
|
417
437
|
conversationId: "test-conversation",
|
|
418
438
|
tools: dummyTools,
|
|
419
439
|
toolExecutor: toolExecutor,
|
|
@@ -427,23 +447,21 @@ describe("AgentLoop exit-reason instrumentation", () => {
|
|
|
427
447
|
};
|
|
428
448
|
|
|
429
449
|
// WHEN the in-loop budget gate trips at the checkpoint
|
|
430
|
-
const result = await loop.run(
|
|
431
|
-
[userMessage],
|
|
432
|
-
(event) => {
|
|
450
|
+
const result = await loop.run({
|
|
451
|
+
messages: [userMessage],
|
|
452
|
+
onEvent: (event) => {
|
|
433
453
|
events.push(event);
|
|
434
454
|
},
|
|
435
|
-
{
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
},
|
|
446
|
-
);
|
|
455
|
+
resolveContextWindow: () => ({
|
|
456
|
+
maxInputTokens: 10,
|
|
457
|
+
overflowRecovery: { enabled: true, safetyMarginRatio: 0 },
|
|
458
|
+
}),
|
|
459
|
+
compactInPlace: true,
|
|
460
|
+
...fakeCompaction({
|
|
461
|
+
compacted: true,
|
|
462
|
+
exhausted: false,
|
|
463
|
+
}),
|
|
464
|
+
});
|
|
447
465
|
|
|
448
466
|
// THEN the loop runs the compaction ceremony in place and continues to a
|
|
449
467
|
// clean exit instead of yielding for budget. The durable commit is
|
|
@@ -461,7 +479,9 @@ describe("AgentLoop exit-reason instrumentation", () => {
|
|
|
461
479
|
textResponse("never reached"),
|
|
462
480
|
]);
|
|
463
481
|
const toolExecutor = async () => ({ content: "ok", isError: false });
|
|
464
|
-
const loop = new AgentLoop(
|
|
482
|
+
const loop = new AgentLoop({
|
|
483
|
+
provider: provider,
|
|
484
|
+
systemPrompt: "system",
|
|
465
485
|
conversationId: "test-conversation",
|
|
466
486
|
tools: dummyTools,
|
|
467
487
|
toolExecutor: toolExecutor,
|
|
@@ -474,7 +494,9 @@ describe("AgentLoop exit-reason instrumentation", () => {
|
|
|
474
494
|
};
|
|
475
495
|
|
|
476
496
|
// WHEN compaction exhausts its retry budget
|
|
477
|
-
const result = await loop.run(
|
|
497
|
+
const result = await loop.run({
|
|
498
|
+
messages: [userMessage],
|
|
499
|
+
onEvent: () => {},
|
|
478
500
|
resolveContextWindow: () => ({
|
|
479
501
|
maxInputTokens: 10,
|
|
480
502
|
overflowRecovery: { enabled: true, safetyMarginRatio: 0 },
|
|
@@ -497,18 +519,20 @@ describe("AgentLoop exit-reason instrumentation", () => {
|
|
|
497
519
|
throw new Error("provider exploded");
|
|
498
520
|
},
|
|
499
521
|
};
|
|
500
|
-
const loop = new AgentLoop(
|
|
522
|
+
const loop = new AgentLoop({
|
|
523
|
+
provider: provider,
|
|
524
|
+
systemPrompt: "system prompt",
|
|
501
525
|
conversationId: "test-conversation",
|
|
502
526
|
});
|
|
503
527
|
|
|
504
528
|
const events: AgentEvent[] = [];
|
|
505
|
-
await loop.run(
|
|
506
|
-
[userMessage],
|
|
507
|
-
(e) => {
|
|
529
|
+
await loop.run({
|
|
530
|
+
messages: [userMessage],
|
|
531
|
+
onEvent: (e) => {
|
|
508
532
|
events.push(e);
|
|
509
533
|
},
|
|
510
|
-
|
|
511
|
-
);
|
|
534
|
+
trust: { sourceChannel: "vellum", trustClass: "unknown" },
|
|
535
|
+
});
|
|
512
536
|
|
|
513
537
|
expect(countExitEvents(events)).toBe(1);
|
|
514
538
|
expect(lastExitEvent(events)?.reason).toBe("error");
|
|
@@ -526,20 +550,22 @@ describe("AgentLoop exit-reason instrumentation", () => {
|
|
|
526
550
|
isError: false,
|
|
527
551
|
yieldToUser: true,
|
|
528
552
|
});
|
|
529
|
-
const loop = new AgentLoop(
|
|
553
|
+
const loop = new AgentLoop({
|
|
554
|
+
provider: provider,
|
|
555
|
+
systemPrompt: "system",
|
|
530
556
|
conversationId: "test-conversation",
|
|
531
557
|
tools: dummyTools,
|
|
532
558
|
toolExecutor: toolExecutor,
|
|
533
559
|
});
|
|
534
560
|
|
|
535
561
|
const events: AgentEvent[] = [];
|
|
536
|
-
await loop.run(
|
|
537
|
-
[userMessage],
|
|
538
|
-
(e) => {
|
|
562
|
+
await loop.run({
|
|
563
|
+
messages: [userMessage],
|
|
564
|
+
onEvent: (e) => {
|
|
539
565
|
events.push(e);
|
|
540
566
|
},
|
|
541
|
-
|
|
542
|
-
);
|
|
567
|
+
trust: { sourceChannel: "vellum", trustClass: "unknown" },
|
|
568
|
+
});
|
|
543
569
|
|
|
544
570
|
expect(countExitEvents(events)).toBe(1);
|
|
545
571
|
});
|
|
@@ -555,23 +581,23 @@ describe("AgentLoop exit-reason instrumentation", () => {
|
|
|
555
581
|
controller.abort();
|
|
556
582
|
return { content: "ok", isError: false };
|
|
557
583
|
};
|
|
558
|
-
const loop = new AgentLoop(
|
|
584
|
+
const loop = new AgentLoop({
|
|
585
|
+
provider: provider,
|
|
586
|
+
systemPrompt: "system",
|
|
559
587
|
conversationId: "test-conversation",
|
|
560
588
|
tools: dummyTools,
|
|
561
589
|
toolExecutor: toolExecutor,
|
|
562
590
|
});
|
|
563
591
|
|
|
564
592
|
const events: AgentEvent[] = [];
|
|
565
|
-
await loop.run(
|
|
566
|
-
[userMessage],
|
|
567
|
-
(e) => {
|
|
593
|
+
await loop.run({
|
|
594
|
+
messages: [userMessage],
|
|
595
|
+
onEvent: (e) => {
|
|
568
596
|
events.push(e);
|
|
569
597
|
},
|
|
570
|
-
{
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
},
|
|
574
|
-
);
|
|
598
|
+
trust: { sourceChannel: "vellum", trustClass: "unknown" },
|
|
599
|
+
signal: controller.signal,
|
|
600
|
+
});
|
|
575
601
|
|
|
576
602
|
expect(countExitEvents(events)).toBe(1);
|
|
577
603
|
expect(lastExitEvent(events)?.reason).toBe("aborted_during_tools");
|
|
@@ -104,7 +104,9 @@ describe("AgentLoop.run — mutableLatestUserMessage from memory-v3-live", () =>
|
|
|
104
104
|
},
|
|
105
105
|
},
|
|
106
106
|
];
|
|
107
|
-
const loop = new AgentLoop(
|
|
107
|
+
const loop = new AgentLoop({
|
|
108
|
+
provider: provider,
|
|
109
|
+
systemPrompt: "system",
|
|
108
110
|
conversationId: "test-conversation",
|
|
109
111
|
config: { maxTokens: 1024 },
|
|
110
112
|
tools: dummyTools,
|
|
@@ -112,7 +114,9 @@ describe("AgentLoop.run — mutableLatestUserMessage from memory-v3-live", () =>
|
|
|
112
114
|
});
|
|
113
115
|
|
|
114
116
|
// WHEN the loop runs
|
|
115
|
-
await loop.run(
|
|
117
|
+
await loop.run({
|
|
118
|
+
messages: [userMessage],
|
|
119
|
+
onEvent: () => {},
|
|
116
120
|
trust: { sourceChannel: "vellum", trustClass: "unknown" },
|
|
117
121
|
callSite: "mainAgent",
|
|
118
122
|
});
|
|
@@ -130,13 +134,17 @@ describe("AgentLoop.run — mutableLatestUserMessage from memory-v3-live", () =>
|
|
|
130
134
|
|
|
131
135
|
// AND a provider that records the config of each LLM call
|
|
132
136
|
const { provider, configs } = makeRecordingProvider([textResponse("hi")]);
|
|
133
|
-
const loop = new AgentLoop(
|
|
137
|
+
const loop = new AgentLoop({
|
|
138
|
+
provider: provider,
|
|
139
|
+
systemPrompt: "system",
|
|
134
140
|
conversationId: "test-conversation",
|
|
135
141
|
config: { maxTokens: 1024 },
|
|
136
142
|
});
|
|
137
143
|
|
|
138
144
|
// WHEN the loop runs
|
|
139
|
-
await loop.run(
|
|
145
|
+
await loop.run({
|
|
146
|
+
messages: [userMessage],
|
|
147
|
+
onEvent: () => {},
|
|
140
148
|
trust: { sourceChannel: "vellum", trustClass: "unknown" },
|
|
141
149
|
callSite: "mainAgent",
|
|
142
150
|
});
|