@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.
Files changed (35) hide show
  1. package/package.json +1 -1
  2. package/src/__tests__/agent-loop-callsite-precedence.test.ts +42 -14
  3. package/src/__tests__/agent-loop-exit-reason.test.ts +117 -91
  4. package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +12 -4
  5. package/src/__tests__/agent-loop-output-hooks.test.ts +48 -16
  6. package/src/__tests__/agent-loop-override-profile.test.ts +18 -6
  7. package/src/__tests__/agent-loop-provider-error-recording.test.ts +33 -27
  8. package/src/__tests__/agent-loop-thinking.test.ts +32 -24
  9. package/src/__tests__/agent-loop.test.ts +288 -96
  10. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +2 -2
  11. package/src/__tests__/agent-wake-override-profile.test.ts +4 -8
  12. package/src/__tests__/approval-cascade.test.ts +4 -4
  13. package/src/__tests__/compaction-events.test.ts +4 -4
  14. package/src/__tests__/conversation-abort-tool-results.test.ts +5 -4
  15. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +7 -9
  16. package/src/__tests__/conversation-agent-loop-overflow.test.ts +41 -14
  17. package/src/__tests__/conversation-agent-loop.test.ts +33 -195
  18. package/src/__tests__/conversation-confirmation-signals.test.ts +4 -4
  19. package/src/__tests__/conversation-process-callsite.test.ts +13 -14
  20. package/src/__tests__/conversation-provider-retry-repair.test.ts +13 -11
  21. package/src/__tests__/conversation-queue.test.ts +8 -9
  22. package/src/__tests__/conversation-slash-queue.test.ts +5 -4
  23. package/src/__tests__/conversation-slash-unknown.test.ts +5 -4
  24. package/src/__tests__/conversation-speed-override.test.ts +9 -9
  25. package/src/__tests__/conversation-workspace-cache-state.test.ts +5 -4
  26. package/src/__tests__/conversation-workspace-injection.test.ts +5 -4
  27. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -4
  28. package/src/__tests__/memory-retrieval-hook.test.ts +73 -6
  29. package/src/__tests__/parallel-tool.benchmark.test.ts +24 -8
  30. package/src/agent/loop.ts +62 -26
  31. package/src/daemon/conversation-agent-loop.ts +31 -126
  32. package/src/daemon/conversation.ts +3 -1
  33. package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit-temp.ts +167 -56
  34. package/src/runtime/__tests__/agent-wake.test.ts +7 -14
  35. package/src/runtime/agent-wake.ts +22 -24
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vellumai/assistant",
3
- "version": "0.8.8-dev.202606080320.8b7fbff",
3
+ "version": "0.8.8-dev.202606081143.f600053",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "exports": {
@@ -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(provider, "system", {
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([userMessage], () => {}, {
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(provider, "system", {
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([userMessage], () => {}, {
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(provider, "system", {
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([userMessage], () => {}, {
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(provider, "system", {
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([userMessage], () => {}, {
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(provider, "system", {
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([userMessage], () => {}, {
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(provider, "system", {
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([userMessage], () => {}, {
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(provider, "system", {
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([userMessage], () => {}, {
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(provider, "system prompt", {
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
- { trust: { sourceChannel: "vellum", trustClass: "unknown" } },
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(provider, "system prompt", {
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
- { trust: { sourceChannel: "vellum", trustClass: "unknown" } },
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(provider, "system prompt", {
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
- { trust: { sourceChannel: "vellum", trustClass: "unknown" } },
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(provider, "system prompt", {
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
- { trust: { sourceChannel: "vellum", trustClass: "unknown" } },
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(provider, "system prompt", {
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
- trust: { sourceChannel: "vellum", trustClass: "unknown" },
286
- signal: controller.signal,
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(provider, "system", {
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
- { trust: { sourceChannel: "vellum", trustClass: "unknown" } },
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(provider, "system", {
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
- trust: { sourceChannel: "vellum", trustClass: "unknown" },
345
- onCheckpoint,
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(provider, "system", {
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([userMessage], () => {}, {
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(provider, "system", {
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([userMessage], () => {}, {
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(provider, "system", {
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
- resolveContextWindow: () => ({
437
- maxInputTokens: 10,
438
- overflowRecovery: { enabled: true, safetyMarginRatio: 0 },
439
- }),
440
- compactInPlace: true,
441
- ...fakeCompaction({
442
- compacted: true,
443
- exhausted: false,
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(provider, "system", {
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([userMessage], () => {}, {
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(provider, "system prompt", {
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
- { trust: { sourceChannel: "vellum", trustClass: "unknown" } },
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(provider, "system", {
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
- { trust: { sourceChannel: "vellum", trustClass: "unknown" } },
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(provider, "system", {
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
- trust: { sourceChannel: "vellum", trustClass: "unknown" },
572
- signal: controller.signal,
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(provider, "system", {
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([userMessage], () => {}, {
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(provider, "system", {
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([userMessage], () => {}, {
145
+ await loop.run({
146
+ messages: [userMessage],
147
+ onEvent: () => {},
140
148
  trust: { sourceChannel: "vellum", trustClass: "unknown" },
141
149
  callSite: "mainAgent",
142
150
  });