@livekit/agents 1.0.34 → 1.0.36

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 (117) hide show
  1. package/dist/cli.cjs.map +1 -1
  2. package/dist/inference/api_protos.d.cts +4 -4
  3. package/dist/inference/api_protos.d.ts +4 -4
  4. package/dist/inference/llm.cjs +30 -3
  5. package/dist/inference/llm.cjs.map +1 -1
  6. package/dist/inference/llm.d.cts +3 -1
  7. package/dist/inference/llm.d.ts +3 -1
  8. package/dist/inference/llm.d.ts.map +1 -1
  9. package/dist/inference/llm.js +30 -3
  10. package/dist/inference/llm.js.map +1 -1
  11. package/dist/ipc/inference_proc_executor.cjs.map +1 -1
  12. package/dist/ipc/job_proc_executor.cjs.map +1 -1
  13. package/dist/ipc/job_proc_lazy_main.cjs +1 -1
  14. package/dist/ipc/job_proc_lazy_main.cjs.map +1 -1
  15. package/dist/ipc/job_proc_lazy_main.js +1 -1
  16. package/dist/ipc/job_proc_lazy_main.js.map +1 -1
  17. package/dist/llm/chat_context.cjs +20 -2
  18. package/dist/llm/chat_context.cjs.map +1 -1
  19. package/dist/llm/chat_context.d.cts +9 -0
  20. package/dist/llm/chat_context.d.ts +9 -0
  21. package/dist/llm/chat_context.d.ts.map +1 -1
  22. package/dist/llm/chat_context.js +20 -2
  23. package/dist/llm/chat_context.js.map +1 -1
  24. package/dist/llm/llm.cjs.map +1 -1
  25. package/dist/llm/llm.d.cts +1 -0
  26. package/dist/llm/llm.d.ts +1 -0
  27. package/dist/llm/llm.d.ts.map +1 -1
  28. package/dist/llm/llm.js.map +1 -1
  29. package/dist/llm/provider_format/openai.cjs +43 -20
  30. package/dist/llm/provider_format/openai.cjs.map +1 -1
  31. package/dist/llm/provider_format/openai.d.ts.map +1 -1
  32. package/dist/llm/provider_format/openai.js +43 -20
  33. package/dist/llm/provider_format/openai.js.map +1 -1
  34. package/dist/llm/provider_format/openai.test.cjs +35 -0
  35. package/dist/llm/provider_format/openai.test.cjs.map +1 -1
  36. package/dist/llm/provider_format/openai.test.js +35 -0
  37. package/dist/llm/provider_format/openai.test.js.map +1 -1
  38. package/dist/llm/provider_format/utils.cjs +1 -1
  39. package/dist/llm/provider_format/utils.cjs.map +1 -1
  40. package/dist/llm/provider_format/utils.d.ts.map +1 -1
  41. package/dist/llm/provider_format/utils.js +1 -1
  42. package/dist/llm/provider_format/utils.js.map +1 -1
  43. package/dist/voice/agent_activity.cjs +19 -19
  44. package/dist/voice/agent_activity.cjs.map +1 -1
  45. package/dist/voice/agent_activity.d.ts.map +1 -1
  46. package/dist/voice/agent_activity.js +19 -19
  47. package/dist/voice/agent_activity.js.map +1 -1
  48. package/dist/voice/agent_session.cjs +64 -25
  49. package/dist/voice/agent_session.cjs.map +1 -1
  50. package/dist/voice/agent_session.d.cts +25 -1
  51. package/dist/voice/agent_session.d.ts +25 -1
  52. package/dist/voice/agent_session.d.ts.map +1 -1
  53. package/dist/voice/agent_session.js +64 -25
  54. package/dist/voice/agent_session.js.map +1 -1
  55. package/dist/voice/background_audio.cjs.map +1 -1
  56. package/dist/voice/generation.cjs +2 -1
  57. package/dist/voice/generation.cjs.map +1 -1
  58. package/dist/voice/generation.d.ts.map +1 -1
  59. package/dist/voice/generation.js +2 -1
  60. package/dist/voice/generation.js.map +1 -1
  61. package/dist/voice/index.cjs +14 -1
  62. package/dist/voice/index.cjs.map +1 -1
  63. package/dist/voice/index.d.cts +1 -0
  64. package/dist/voice/index.d.ts +1 -0
  65. package/dist/voice/index.d.ts.map +1 -1
  66. package/dist/voice/index.js +3 -1
  67. package/dist/voice/index.js.map +1 -1
  68. package/dist/voice/room_io/room_io.cjs +1 -0
  69. package/dist/voice/room_io/room_io.cjs.map +1 -1
  70. package/dist/voice/room_io/room_io.d.ts.map +1 -1
  71. package/dist/voice/room_io/room_io.js +1 -0
  72. package/dist/voice/room_io/room_io.js.map +1 -1
  73. package/dist/voice/speech_handle.cjs +12 -3
  74. package/dist/voice/speech_handle.cjs.map +1 -1
  75. package/dist/voice/speech_handle.d.cts +12 -2
  76. package/dist/voice/speech_handle.d.ts +12 -2
  77. package/dist/voice/speech_handle.d.ts.map +1 -1
  78. package/dist/voice/speech_handle.js +10 -2
  79. package/dist/voice/speech_handle.js.map +1 -1
  80. package/dist/voice/testing/index.cjs +52 -0
  81. package/dist/voice/testing/index.cjs.map +1 -0
  82. package/dist/voice/testing/index.d.cts +20 -0
  83. package/dist/voice/testing/index.d.ts +20 -0
  84. package/dist/voice/testing/index.d.ts.map +1 -0
  85. package/dist/voice/testing/index.js +31 -0
  86. package/dist/voice/testing/index.js.map +1 -0
  87. package/dist/voice/testing/run_result.cjs +477 -0
  88. package/dist/voice/testing/run_result.cjs.map +1 -0
  89. package/dist/voice/testing/run_result.d.cts +226 -0
  90. package/dist/voice/testing/run_result.d.ts +226 -0
  91. package/dist/voice/testing/run_result.d.ts.map +1 -0
  92. package/dist/voice/testing/run_result.js +451 -0
  93. package/dist/voice/testing/run_result.js.map +1 -0
  94. package/dist/voice/testing/types.cjs +46 -0
  95. package/dist/voice/testing/types.cjs.map +1 -0
  96. package/dist/voice/testing/types.d.cts +83 -0
  97. package/dist/voice/testing/types.d.ts +83 -0
  98. package/dist/voice/testing/types.d.ts.map +1 -0
  99. package/dist/voice/testing/types.js +19 -0
  100. package/dist/voice/testing/types.js.map +1 -0
  101. package/package.json +3 -3
  102. package/src/inference/llm.ts +42 -3
  103. package/src/ipc/job_proc_lazy_main.ts +1 -1
  104. package/src/llm/chat_context.ts +32 -2
  105. package/src/llm/llm.ts +1 -0
  106. package/src/llm/provider_format/openai.test.ts +40 -0
  107. package/src/llm/provider_format/openai.ts +46 -19
  108. package/src/llm/provider_format/utils.ts +5 -1
  109. package/src/voice/agent_activity.ts +24 -22
  110. package/src/voice/agent_session.ts +73 -28
  111. package/src/voice/generation.ts +1 -0
  112. package/src/voice/index.ts +1 -0
  113. package/src/voice/room_io/room_io.ts +1 -0
  114. package/src/voice/speech_handle.ts +24 -4
  115. package/src/voice/testing/index.ts +49 -0
  116. package/src/voice/testing/run_result.ts +576 -0
  117. package/src/voice/testing/types.ts +118 -0
@@ -0,0 +1,477 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var run_result_exports = {};
20
+ __export(run_result_exports, {
21
+ AgentHandoffAssert: () => AgentHandoffAssert,
22
+ AssertionError: () => AssertionError,
23
+ EventAssert: () => EventAssert,
24
+ FunctionCallAssert: () => FunctionCallAssert,
25
+ FunctionCallOutputAssert: () => FunctionCallOutputAssert,
26
+ MessageAssert: () => MessageAssert,
27
+ RunAssert: () => RunAssert,
28
+ RunResult: () => RunResult
29
+ });
30
+ module.exports = __toCommonJS(run_result_exports);
31
+ var import_utils = require("../../utils.cjs");
32
+ var import_speech_handle = require("../speech_handle.cjs");
33
+ var import_types = require("./types.cjs");
34
+ const evalsVerbose = parseInt(process.env.LIVEKIT_EVALS_VERBOSE || "0", 10);
35
+ class RunResult {
36
+ _events = [];
37
+ doneFut = new import_utils.Future();
38
+ userInput;
39
+ handles = /* @__PURE__ */ new Set();
40
+ lastSpeechHandle;
41
+ runAssert;
42
+ // TODO(brian): Add typed output support for parity with Python
43
+ // - Add outputType?: new (...args: unknown[]) => T
44
+ // - Add finalOutput?: T
45
+ // - Implement markDone() to extract final_output from SpeechHandle.maybeRunFinalOutput
46
+ // - See Python: run_result.py lines 182-201
47
+ constructor(options) {
48
+ this.userInput = options == null ? void 0 : options.userInput;
49
+ }
50
+ /**
51
+ * List of all recorded events generated during the run.
52
+ */
53
+ get events() {
54
+ return this._events;
55
+ }
56
+ /**
57
+ * Provides an assertion helper for verifying the run events.
58
+ */
59
+ get expect() {
60
+ if (evalsVerbose) {
61
+ const eventsStr = formatEvents(this._events).map((line) => ` ${line}`).join("\n");
62
+ console.log(
63
+ `
64
+ + RunResult {
65
+ userInput: "${this.userInput}"
66
+ events: [
67
+ ${eventsStr}
68
+ ]
69
+ }`
70
+ );
71
+ }
72
+ if (!this.runAssert) {
73
+ this.runAssert = new RunAssert(this);
74
+ }
75
+ return this.runAssert;
76
+ }
77
+ /**
78
+ * Returns the final output of the run after completion.
79
+ *
80
+ * @throws Error - Not implemented yet.
81
+ */
82
+ get finalOutput() {
83
+ throw new Error("finalOutput is not yet implemented in JS.");
84
+ }
85
+ /**
86
+ * Indicates whether the run has finished processing all events.
87
+ */
88
+ done() {
89
+ return this.doneFut.done;
90
+ }
91
+ /**
92
+ * Wait for the RunResult to complete. Returns `this` for method chaining.
93
+ *
94
+ * @example
95
+ * ```ts
96
+ * const result = session.run({ userInput: 'Hi!' });
97
+ * await result.wait(); // waits for completion
98
+ * result.expect.nextEvent().isMessage({ role: 'assistant' });
99
+ * ```
100
+ */
101
+ async wait() {
102
+ await this.doneFut.await;
103
+ return this;
104
+ }
105
+ /**
106
+ * @internal
107
+ * Records an agent handoff event.
108
+ */
109
+ _agentHandoff(params) {
110
+ const event = {
111
+ type: "agent_handoff",
112
+ item: params.item,
113
+ oldAgent: params.oldAgent,
114
+ newAgent: params.newAgent
115
+ };
116
+ const index = this._findInsertionIndex(event.item.createdAt);
117
+ this._events.splice(index, 0, event);
118
+ }
119
+ /**
120
+ * @internal
121
+ * Called when a chat item is added during the run.
122
+ */
123
+ _itemAdded(item) {
124
+ if (this.doneFut.done) {
125
+ return;
126
+ }
127
+ let event;
128
+ if (item.type === "message") {
129
+ event = { type: "message", item };
130
+ } else if (item.type === "function_call") {
131
+ event = { type: "function_call", item };
132
+ } else if (item.type === "function_call_output") {
133
+ event = { type: "function_call_output", item };
134
+ }
135
+ if (event) {
136
+ const index = this._findInsertionIndex(item.createdAt);
137
+ this._events.splice(index, 0, event);
138
+ }
139
+ }
140
+ /**
141
+ * @internal
142
+ * Watch a speech handle or task for completion.
143
+ */
144
+ _watchHandle(handle) {
145
+ this.handles.add(handle);
146
+ if ((0, import_speech_handle.isSpeechHandle)(handle)) {
147
+ handle._addItemAddedCallback(this._itemAdded.bind(this));
148
+ }
149
+ handle.addDoneCallback(() => {
150
+ this._markDoneIfNeeded(handle);
151
+ });
152
+ }
153
+ /**
154
+ * @internal
155
+ * Unwatch a handle.
156
+ */
157
+ _unwatchHandle(handle) {
158
+ this.handles.delete(handle);
159
+ if ((0, import_speech_handle.isSpeechHandle)(handle)) {
160
+ handle._removeItemAddedCallback(this._itemAdded.bind(this));
161
+ }
162
+ }
163
+ _markDoneIfNeeded(handle) {
164
+ if ((0, import_speech_handle.isSpeechHandle)(handle)) {
165
+ this.lastSpeechHandle = handle;
166
+ }
167
+ if ([...this.handles].every((h) => (0, import_speech_handle.isSpeechHandle)(h) ? h.done() : h.done)) {
168
+ this._markDone();
169
+ }
170
+ }
171
+ _markDone() {
172
+ if (!this.doneFut.done) {
173
+ this.doneFut.resolve();
174
+ }
175
+ }
176
+ /**
177
+ * Find the correct insertion index to maintain chronological order.
178
+ */
179
+ _findInsertionIndex(createdAt) {
180
+ for (let i = this._events.length - 1; i >= 0; i--) {
181
+ if (this._events[i].item.createdAt <= createdAt) {
182
+ return i + 1;
183
+ }
184
+ }
185
+ return 0;
186
+ }
187
+ }
188
+ class RunAssert {
189
+ _events;
190
+ _currentIndex = 0;
191
+ // TODO(brian): Add range access for parity with Python __getitem__ slice support.
192
+ // - Add range(start?, end?) method returning EventRangeAssert
193
+ // - EventRangeAssert should have containsFunctionCall(), containsMessage() methods
194
+ // See Python run_result.py lines 247-251 for reference.
195
+ constructor(runResult) {
196
+ this._events = runResult.events;
197
+ }
198
+ /**
199
+ * Access a specific event by index for assertions.
200
+ * Supports negative indices (e.g., -1 for last event).
201
+ *
202
+ * @example
203
+ * ```typescript
204
+ * result.expect.at(0).isMessage({ role: 'user' });
205
+ * result.expect.at(-1).isMessage({ role: 'assistant' });
206
+ * ```
207
+ */
208
+ at(index) {
209
+ let normalizedIndex = index;
210
+ if (index < 0) {
211
+ normalizedIndex = this._events.length + index;
212
+ }
213
+ if (normalizedIndex < 0 || normalizedIndex >= this._events.length) {
214
+ this._raiseWithDebugInfo(
215
+ `at(${index}) out of range (total events: ${this._events.length})`,
216
+ normalizedIndex
217
+ );
218
+ }
219
+ return new EventAssert(this._events[normalizedIndex], this, normalizedIndex);
220
+ }
221
+ /**
222
+ * Advance to the next event, optionally filtering by type.
223
+ *
224
+ * @example
225
+ * ```typescript
226
+ * result.expect.nextEvent().isMessage({ role: 'assistant' });
227
+ * result.expect.nextEvent({ type: 'function_call' }).isFunctionCall({ name: 'foo' });
228
+ * ```
229
+ */
230
+ nextEvent(options) {
231
+ while (true) {
232
+ const evAssert = this._currentEvent();
233
+ this._currentIndex++;
234
+ if (!(options == null ? void 0 : options.type) || evAssert.event().type === options.type) {
235
+ return evAssert;
236
+ }
237
+ }
238
+ }
239
+ /**
240
+ * Skip a specified number of upcoming events without assertions.
241
+ *
242
+ * @example
243
+ * ```typescript
244
+ * result.expect.skipNext(2);
245
+ * ```
246
+ */
247
+ skipNext(count = 1) {
248
+ for (let i = 0; i < count; i++) {
249
+ if (this._currentIndex >= this._events.length) {
250
+ this._raiseWithDebugInfo(`Tried to skip ${count} event(s), but only ${i} were available.`);
251
+ }
252
+ this._currentIndex++;
253
+ }
254
+ return this;
255
+ }
256
+ /**
257
+ * Assert that there are no further events.
258
+ *
259
+ * @example
260
+ * ```typescript
261
+ * result.expect.noMoreEvents();
262
+ * ```
263
+ */
264
+ noMoreEvents() {
265
+ if (this._currentIndex < this._events.length) {
266
+ const event = this._events[this._currentIndex];
267
+ this._raiseWithDebugInfo(`Expected no more events, but found: ${event.type}`);
268
+ }
269
+ }
270
+ _currentEvent() {
271
+ if (this._currentIndex >= this._events.length) {
272
+ this._raiseWithDebugInfo("Expected another event, but none left.");
273
+ }
274
+ return this.at(this._currentIndex);
275
+ }
276
+ /** @internal */
277
+ _raiseWithDebugInfo(message, index) {
278
+ const markerIndex = index ?? this._currentIndex;
279
+ const eventsStr = formatEvents(this._events, markerIndex).join("\n");
280
+ throw new AssertionError(`${message}
281
+ Context around failure:
282
+ ${eventsStr}`);
283
+ }
284
+ }
285
+ class EventAssert {
286
+ _event;
287
+ _parent;
288
+ _index;
289
+ constructor(event, parent, index) {
290
+ this._event = event;
291
+ this._parent = parent;
292
+ this._index = index;
293
+ }
294
+ /**
295
+ * Get the underlying event.
296
+ */
297
+ event() {
298
+ return this._event;
299
+ }
300
+ _raise(message) {
301
+ this._parent._raiseWithDebugInfo(message, this._index);
302
+ }
303
+ /**
304
+ * Verify this event is a message with optional role matching.
305
+ *
306
+ * @example
307
+ * ```typescript
308
+ * result.expect.nextEvent().isMessage({ role: 'assistant' });
309
+ * ```
310
+ */
311
+ isMessage(options) {
312
+ if (!(0, import_types.isChatMessageEvent)(this._event)) {
313
+ this._raise(`Expected ChatMessageEvent, got ${this._event.type}`);
314
+ }
315
+ if ((options == null ? void 0 : options.role) && this._event.item.role !== options.role) {
316
+ this._raise(`Expected role '${options.role}', got '${this._event.item.role}'`);
317
+ }
318
+ return new MessageAssert(this._event, this._parent, this._index);
319
+ }
320
+ /**
321
+ * Verify this event is a function call with optional name/args matching.
322
+ *
323
+ * @example
324
+ * ```typescript
325
+ * result.expect.nextEvent().isFunctionCall({ name: 'order_item', args: { id: 'big_mac' } });
326
+ * ```
327
+ */
328
+ isFunctionCall(options) {
329
+ if (!(0, import_types.isFunctionCallEvent)(this._event)) {
330
+ this._raise(`Expected FunctionCallEvent, got ${this._event.type}`);
331
+ }
332
+ if ((options == null ? void 0 : options.name) && this._event.item.name !== options.name) {
333
+ this._raise(`Expected call name '${options.name}', got '${this._event.item.name}'`);
334
+ }
335
+ if (options == null ? void 0 : options.args) {
336
+ let actual;
337
+ try {
338
+ actual = JSON.parse(this._event.item.args);
339
+ } catch {
340
+ this._raise(`Failed to parse function call arguments: ${this._event.item.args}`);
341
+ }
342
+ for (const [key, value] of Object.entries(options.args)) {
343
+ if (!(key in actual) || actual[key] !== value) {
344
+ this._raise(
345
+ `For key '${key}', expected ${JSON.stringify(value)}, got ${JSON.stringify(actual[key])}`
346
+ );
347
+ }
348
+ }
349
+ }
350
+ return new FunctionCallAssert(this._event, this._parent, this._index);
351
+ }
352
+ /**
353
+ * Verify this event is a function call output with optional matching.
354
+ *
355
+ * @example
356
+ * ```typescript
357
+ * result.expect.nextEvent().isFunctionCallOutput({ isError: false });
358
+ * ```
359
+ */
360
+ isFunctionCallOutput(options) {
361
+ if (!(0, import_types.isFunctionCallOutputEvent)(this._event)) {
362
+ this._raise(`Expected FunctionCallOutputEvent, got ${this._event.type}`);
363
+ }
364
+ if ((options == null ? void 0 : options.output) !== void 0 && this._event.item.output !== options.output) {
365
+ this._raise(`Expected output '${options.output}', got '${this._event.item.output}'`);
366
+ }
367
+ if ((options == null ? void 0 : options.isError) !== void 0 && this._event.item.isError !== options.isError) {
368
+ this._raise(`Expected isError=${options.isError}, got ${this._event.item.isError}`);
369
+ }
370
+ return new FunctionCallOutputAssert(this._event, this._parent, this._index);
371
+ }
372
+ /**
373
+ * Verify this event is an agent handoff with optional type matching.
374
+ *
375
+ * @example
376
+ * ```typescript
377
+ * result.expect.nextEvent().isAgentHandoff({ newAgentType: MyAgent });
378
+ * ```
379
+ */
380
+ isAgentHandoff(options) {
381
+ if (!(0, import_types.isAgentHandoffEvent)(this._event)) {
382
+ this._raise(`Expected AgentHandoffEvent, got ${this._event.type}`);
383
+ }
384
+ const event = this._event;
385
+ if (options == null ? void 0 : options.newAgentType) {
386
+ const actualType = event.newAgent.constructor.name;
387
+ if (!(event.newAgent instanceof options.newAgentType)) {
388
+ this._raise(`Expected new_agent '${options.newAgentType.name}', got '${actualType}'`);
389
+ }
390
+ }
391
+ return new AgentHandoffAssert(event, this._parent, this._index);
392
+ }
393
+ }
394
+ class MessageAssert extends EventAssert {
395
+ constructor(event, parent, index) {
396
+ super(event, parent, index);
397
+ }
398
+ event() {
399
+ return this._event;
400
+ }
401
+ // Phase 3: judge() method will be added here
402
+ }
403
+ class FunctionCallAssert extends EventAssert {
404
+ constructor(event, parent, index) {
405
+ super(event, parent, index);
406
+ }
407
+ event() {
408
+ return this._event;
409
+ }
410
+ }
411
+ class FunctionCallOutputAssert extends EventAssert {
412
+ constructor(event, parent, index) {
413
+ super(event, parent, index);
414
+ }
415
+ event() {
416
+ return this._event;
417
+ }
418
+ }
419
+ class AgentHandoffAssert extends EventAssert {
420
+ constructor(event, parent, index) {
421
+ super(event, parent, index);
422
+ }
423
+ event() {
424
+ return this._event;
425
+ }
426
+ }
427
+ class AssertionError extends Error {
428
+ constructor(message) {
429
+ var _a;
430
+ super(message);
431
+ this.name = "AssertionError";
432
+ (_a = Error.captureStackTrace) == null ? void 0 : _a.call(Error, this, AssertionError);
433
+ }
434
+ }
435
+ function formatEvents(events, selectedIndex) {
436
+ var _a;
437
+ const lines = [];
438
+ for (let i = 0; i < events.length; i++) {
439
+ const event = events[i];
440
+ let prefix = "";
441
+ if (selectedIndex !== void 0) {
442
+ prefix = i === selectedIndex ? ">>>" : " ";
443
+ }
444
+ let line;
445
+ if ((0, import_types.isChatMessageEvent)(event)) {
446
+ const { role, content, interrupted } = event.item;
447
+ const textContent = typeof content === "string" ? content : Array.isArray(content) ? content.filter((c) => typeof c === "string").join(" ") : "";
448
+ const truncated = textContent.length > 50 ? textContent.slice(0, 50) + "..." : textContent;
449
+ line = `${prefix}[${i}] { type: "message", role: "${role}", content: "${truncated}", interrupted: ${interrupted} }`;
450
+ } else if ((0, import_types.isFunctionCallEvent)(event)) {
451
+ const { name, args } = event.item;
452
+ line = `${prefix}[${i}] { type: "function_call", name: "${name}", args: ${args} }`;
453
+ } else if ((0, import_types.isFunctionCallOutputEvent)(event)) {
454
+ const { output, isError } = event.item;
455
+ const truncated = output.length > 50 ? output.slice(0, 50) + "..." : output;
456
+ line = `${prefix}[${i}] { type: "function_call_output", output: "${truncated}", isError: ${isError} }`;
457
+ } else if ((0, import_types.isAgentHandoffEvent)(event)) {
458
+ line = `${prefix}[${i}] { type: "agent_handoff", oldAgent: "${(_a = event.oldAgent) == null ? void 0 : _a.constructor.name}", newAgent: "${event.newAgent.constructor.name}" }`;
459
+ } else {
460
+ line = `${prefix}[${i}] ${event}`;
461
+ }
462
+ lines.push(line);
463
+ }
464
+ return lines;
465
+ }
466
+ // Annotate the CommonJS export names for ESM import in node:
467
+ 0 && (module.exports = {
468
+ AgentHandoffAssert,
469
+ AssertionError,
470
+ EventAssert,
471
+ FunctionCallAssert,
472
+ FunctionCallOutputAssert,
473
+ MessageAssert,
474
+ RunAssert,
475
+ RunResult
476
+ });
477
+ //# sourceMappingURL=run_result.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/voice/testing/run_result.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { AgentHandoffItem, ChatItem } from '../../llm/chat_context.js';\nimport type { Task } from '../../utils.js';\nimport { Future } from '../../utils.js';\nimport type { Agent } from '../agent.js';\nimport { type SpeechHandle, isSpeechHandle } from '../speech_handle.js';\nimport {\n type AgentHandoffAssertOptions,\n type AgentHandoffEvent,\n type ChatMessageEvent,\n type EventType,\n type FunctionCallAssertOptions,\n type FunctionCallEvent,\n type FunctionCallOutputAssertOptions,\n type FunctionCallOutputEvent,\n type MessageAssertOptions,\n type RunEvent,\n isAgentHandoffEvent,\n isChatMessageEvent,\n isFunctionCallEvent,\n isFunctionCallOutputEvent,\n} from './types.js';\n\n// Environment variable for verbose output\nconst evalsVerbose = parseInt(process.env.LIVEKIT_EVALS_VERBOSE || '0', 10);\n\n/**\n * Result of a test run containing recorded events and assertion utilities.\n *\n * @example\n * ```typescript\n * const result = await session.run({ userInput: 'Hello' });\n * result.expect.nextEvent().isMessage({ role: 'assistant' });\n * result.expect.noMoreEvents();\n * ```\n */\nexport class RunResult<T = unknown> {\n private _events: RunEvent[] = [];\n private doneFut = new Future<void>();\n private userInput?: string;\n\n private handles: Set<SpeechHandle | Task<void>> = new Set();\n private lastSpeechHandle?: SpeechHandle;\n private runAssert?: RunAssert;\n\n // TODO(brian): Add typed output support for parity with Python\n // - Add outputType?: new (...args: unknown[]) => T\n // - Add finalOutput?: T\n // - Implement markDone() to extract final_output from SpeechHandle.maybeRunFinalOutput\n // - See Python: run_result.py lines 182-201\n\n constructor(options?: { userInput?: string }) {\n this.userInput = options?.userInput;\n }\n\n /**\n * List of all recorded events generated during the run.\n */\n get events(): RunEvent[] {\n return this._events;\n }\n\n /**\n * Provides an assertion helper for verifying the run events.\n */\n get expect(): RunAssert {\n if (evalsVerbose) {\n const eventsStr = formatEvents(this._events)\n .map((line) => ` ${line}`)\n .join('\\n');\n console.log(\n `\\n+ RunResult {\\n userInput: \"${this.userInput}\"\\n events: [\\n${eventsStr}\\n ]\\n }`,\n );\n }\n\n // Cache the RunAssert so cursor position persists across multiple .expect accesses\n if (!this.runAssert) {\n this.runAssert = new RunAssert(this);\n }\n return this.runAssert;\n }\n\n /**\n * Returns the final output of the run after completion.\n *\n * @throws Error - Not implemented yet.\n */\n get finalOutput(): T {\n // TODO(brian): Implement typed output support after AgentTask is implemented.\n throw new Error('finalOutput is not yet implemented in JS.');\n }\n\n /**\n * Indicates whether the run has finished processing all events.\n */\n done(): boolean {\n return this.doneFut.done;\n }\n\n /**\n * Wait for the RunResult to complete. Returns `this` for method chaining.\n *\n * @example\n * ```ts\n * const result = session.run({ userInput: 'Hi!' });\n * await result.wait(); // waits for completion\n * result.expect.nextEvent().isMessage({ role: 'assistant' });\n * ```\n */\n async wait(): Promise<this> {\n await this.doneFut.await;\n return this;\n }\n\n /**\n * @internal\n * Records an agent handoff event.\n */\n _agentHandoff(params: { item: AgentHandoffItem; oldAgent?: Agent; newAgent: Agent }): void {\n const event: AgentHandoffEvent = {\n type: 'agent_handoff',\n item: params.item,\n oldAgent: params.oldAgent,\n newAgent: params.newAgent,\n };\n const index = this._findInsertionIndex(event.item.createdAt);\n this._events.splice(index, 0, event);\n }\n\n /**\n * @internal\n * Called when a chat item is added during the run.\n */\n _itemAdded(item: ChatItem): void {\n if (this.doneFut.done) {\n return;\n }\n\n let event: RunEvent | undefined;\n\n if (item.type === 'message') {\n event = { type: 'message', item } as ChatMessageEvent;\n } else if (item.type === 'function_call') {\n event = { type: 'function_call', item } as FunctionCallEvent;\n } else if (item.type === 'function_call_output') {\n event = { type: 'function_call_output', item } as FunctionCallOutputEvent;\n }\n\n if (event) {\n const index = this._findInsertionIndex(item.createdAt);\n this._events.splice(index, 0, event);\n }\n }\n\n /**\n * @internal\n * Watch a speech handle or task for completion.\n */\n _watchHandle(handle: SpeechHandle | Task<void>): void {\n this.handles.add(handle);\n\n if (isSpeechHandle(handle)) {\n handle._addItemAddedCallback(this._itemAdded.bind(this));\n }\n\n handle.addDoneCallback(() => {\n this._markDoneIfNeeded(handle);\n });\n }\n\n /**\n * @internal\n * Unwatch a handle.\n */\n _unwatchHandle(handle: SpeechHandle | Task<void>): void {\n this.handles.delete(handle);\n\n if (isSpeechHandle(handle)) {\n handle._removeItemAddedCallback(this._itemAdded.bind(this));\n }\n }\n\n private _markDoneIfNeeded(handle: SpeechHandle | Task<void>): void {\n if (isSpeechHandle(handle)) {\n this.lastSpeechHandle = handle;\n }\n\n if ([...this.handles].every((h) => (isSpeechHandle(h) ? h.done() : h.done))) {\n this._markDone();\n }\n }\n\n private _markDone(): void {\n // TODO(brian): Implement final output support after AgentTask is implemented.\n // See Python run_result.py _mark_done() for reference:\n // - Check lastSpeechHandle._maybeRunFinalOutput\n // - Validate output type matches expected type\n // - Set exception or resolve based on output\n if (!this.doneFut.done) {\n this.doneFut.resolve();\n }\n }\n\n /**\n * Find the correct insertion index to maintain chronological order.\n */\n private _findInsertionIndex(createdAt: number): number {\n for (let i = this._events.length - 1; i >= 0; i--) {\n if (this._events[i]!.item.createdAt <= createdAt) {\n return i + 1;\n }\n }\n return 0;\n }\n}\n\n/**\n * Assertion helper for verifying run events in sequence.\n */\nexport class RunAssert {\n private _events: RunEvent[];\n private _currentIndex = 0;\n\n // TODO(brian): Add range access for parity with Python __getitem__ slice support.\n // - Add range(start?, end?) method returning EventRangeAssert\n // - EventRangeAssert should have containsFunctionCall(), containsMessage() methods\n // See Python run_result.py lines 247-251 for reference.\n\n constructor(runResult: RunResult) {\n this._events = runResult.events;\n }\n\n /**\n * Access a specific event by index for assertions.\n * Supports negative indices (e.g., -1 for last event).\n *\n * @example\n * ```typescript\n * result.expect.at(0).isMessage({ role: 'user' });\n * result.expect.at(-1).isMessage({ role: 'assistant' });\n * ```\n */\n at(index: number): EventAssert {\n let normalizedIndex = index;\n if (index < 0) {\n normalizedIndex = this._events.length + index;\n }\n\n if (normalizedIndex < 0 || normalizedIndex >= this._events.length) {\n this._raiseWithDebugInfo(\n `at(${index}) out of range (total events: ${this._events.length})`,\n normalizedIndex,\n );\n }\n\n return new EventAssert(this._events[normalizedIndex]!, this, normalizedIndex);\n }\n\n /**\n * Advance to the next event, optionally filtering by type.\n *\n * @example\n * ```typescript\n * result.expect.nextEvent().isMessage({ role: 'assistant' });\n * result.expect.nextEvent({ type: 'function_call' }).isFunctionCall({ name: 'foo' });\n * ```\n */\n nextEvent(options?: { type?: EventType }): EventAssert {\n while (true) {\n const evAssert = this._currentEvent();\n this._currentIndex++;\n\n if (!options?.type || evAssert.event().type === options.type) {\n return evAssert;\n }\n }\n }\n\n /**\n * Skip a specified number of upcoming events without assertions.\n *\n * @example\n * ```typescript\n * result.expect.skipNext(2);\n * ```\n */\n skipNext(count: number = 1): this {\n for (let i = 0; i < count; i++) {\n if (this._currentIndex >= this._events.length) {\n this._raiseWithDebugInfo(`Tried to skip ${count} event(s), but only ${i} were available.`);\n }\n this._currentIndex++;\n }\n return this;\n }\n\n /**\n * Assert that there are no further events.\n *\n * @example\n * ```typescript\n * result.expect.noMoreEvents();\n * ```\n */\n noMoreEvents(): void {\n if (this._currentIndex < this._events.length) {\n const event = this._events[this._currentIndex]!;\n this._raiseWithDebugInfo(`Expected no more events, but found: ${event.type}`);\n }\n }\n\n private _currentEvent(): EventAssert {\n if (this._currentIndex >= this._events.length) {\n this._raiseWithDebugInfo('Expected another event, but none left.');\n }\n return this.at(this._currentIndex);\n }\n\n /** @internal */\n _raiseWithDebugInfo(message: string, index?: number): never {\n const markerIndex = index ?? this._currentIndex;\n const eventsStr = formatEvents(this._events, markerIndex).join('\\n');\n throw new AssertionError(`${message}\\nContext around failure:\\n${eventsStr}`);\n }\n}\n\n/**\n * Assertion wrapper for a single event.\n */\nexport class EventAssert {\n protected _event: RunEvent;\n protected _parent: RunAssert;\n protected _index: number;\n\n constructor(event: RunEvent, parent: RunAssert, index: number) {\n this._event = event;\n this._parent = parent;\n this._index = index;\n }\n\n /**\n * Get the underlying event.\n */\n event(): RunEvent {\n return this._event;\n }\n\n protected _raise(message: string): never {\n this._parent._raiseWithDebugInfo(message, this._index);\n }\n\n /**\n * Verify this event is a message with optional role matching.\n *\n * @example\n * ```typescript\n * result.expect.nextEvent().isMessage({ role: 'assistant' });\n * ```\n */\n isMessage(options?: MessageAssertOptions): MessageAssert {\n if (!isChatMessageEvent(this._event)) {\n this._raise(`Expected ChatMessageEvent, got ${this._event.type}`);\n }\n\n if (options?.role && this._event.item.role !== options.role) {\n this._raise(`Expected role '${options.role}', got '${this._event.item.role}'`);\n }\n\n return new MessageAssert(this._event, this._parent, this._index);\n }\n\n /**\n * Verify this event is a function call with optional name/args matching.\n *\n * @example\n * ```typescript\n * result.expect.nextEvent().isFunctionCall({ name: 'order_item', args: { id: 'big_mac' } });\n * ```\n */\n isFunctionCall(options?: FunctionCallAssertOptions): FunctionCallAssert {\n if (!isFunctionCallEvent(this._event)) {\n this._raise(`Expected FunctionCallEvent, got ${this._event.type}`);\n }\n\n if (options?.name && this._event.item.name !== options.name) {\n this._raise(`Expected call name '${options.name}', got '${this._event.item.name}'`);\n }\n\n if (options?.args) {\n let actual: Record<string, unknown>;\n try {\n actual = JSON.parse(this._event.item.args);\n } catch {\n this._raise(`Failed to parse function call arguments: ${this._event.item.args}`);\n }\n\n for (const [key, value] of Object.entries(options.args)) {\n if (!(key in actual) || actual[key] !== value) {\n this._raise(\n `For key '${key}', expected ${JSON.stringify(value)}, got ${JSON.stringify(actual[key])}`,\n );\n }\n }\n }\n\n return new FunctionCallAssert(this._event, this._parent, this._index);\n }\n\n /**\n * Verify this event is a function call output with optional matching.\n *\n * @example\n * ```typescript\n * result.expect.nextEvent().isFunctionCallOutput({ isError: false });\n * ```\n */\n isFunctionCallOutput(options?: FunctionCallOutputAssertOptions): FunctionCallOutputAssert {\n if (!isFunctionCallOutputEvent(this._event)) {\n this._raise(`Expected FunctionCallOutputEvent, got ${this._event.type}`);\n }\n\n if (options?.output !== undefined && this._event.item.output !== options.output) {\n this._raise(`Expected output '${options.output}', got '${this._event.item.output}'`);\n }\n\n if (options?.isError !== undefined && this._event.item.isError !== options.isError) {\n this._raise(`Expected isError=${options.isError}, got ${this._event.item.isError}`);\n }\n\n return new FunctionCallOutputAssert(this._event, this._parent, this._index);\n }\n\n /**\n * Verify this event is an agent handoff with optional type matching.\n *\n * @example\n * ```typescript\n * result.expect.nextEvent().isAgentHandoff({ newAgentType: MyAgent });\n * ```\n */\n isAgentHandoff(options?: AgentHandoffAssertOptions): AgentHandoffAssert {\n if (!isAgentHandoffEvent(this._event)) {\n this._raise(`Expected AgentHandoffEvent, got ${this._event.type}`);\n }\n\n // Cast to the correct type after validation\n const event = this._event as AgentHandoffEvent;\n\n if (options?.newAgentType) {\n const actualType = event.newAgent.constructor.name;\n if (!(event.newAgent instanceof options.newAgentType)) {\n this._raise(`Expected new_agent '${options.newAgentType.name}', got '${actualType}'`);\n }\n }\n\n return new AgentHandoffAssert(event, this._parent, this._index);\n }\n}\n\n/**\n * Assertion wrapper for message events.\n */\nexport class MessageAssert extends EventAssert {\n protected declare _event: ChatMessageEvent;\n\n constructor(event: ChatMessageEvent, parent: RunAssert, index: number) {\n super(event, parent, index);\n }\n\n override event(): ChatMessageEvent {\n return this._event;\n }\n\n // Phase 3: judge() method will be added here\n}\n\n/**\n * Assertion wrapper for function call events.\n */\nexport class FunctionCallAssert extends EventAssert {\n protected declare _event: FunctionCallEvent;\n\n constructor(event: FunctionCallEvent, parent: RunAssert, index: number) {\n super(event, parent, index);\n }\n\n override event(): FunctionCallEvent {\n return this._event;\n }\n}\n\n/**\n * Assertion wrapper for function call output events.\n */\nexport class FunctionCallOutputAssert extends EventAssert {\n protected declare _event: FunctionCallOutputEvent;\n\n constructor(event: FunctionCallOutputEvent, parent: RunAssert, index: number) {\n super(event, parent, index);\n }\n\n override event(): FunctionCallOutputEvent {\n return this._event;\n }\n}\n\n/**\n * Assertion wrapper for agent handoff events.\n */\nexport class AgentHandoffAssert extends EventAssert {\n protected declare _event: AgentHandoffEvent;\n\n constructor(event: AgentHandoffEvent, parent: RunAssert, index: number) {\n super(event, parent, index);\n }\n\n override event(): AgentHandoffEvent {\n return this._event;\n }\n}\n\n/**\n * Custom assertion error for test failures.\n */\nexport class AssertionError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'AssertionError';\n Error.captureStackTrace?.(this, AssertionError);\n }\n}\n\n/**\n * Format events for debug output, optionally marking a selected index.\n */\nfunction formatEvents(events: RunEvent[], selectedIndex?: number): string[] {\n const lines: string[] = [];\n\n for (let i = 0; i < events.length; i++) {\n const event = events[i]!;\n let prefix = '';\n if (selectedIndex !== undefined) {\n prefix = i === selectedIndex ? '>>>' : ' ';\n }\n\n let line: string;\n if (isChatMessageEvent(event)) {\n const { role, content, interrupted } = event.item;\n const textContent =\n typeof content === 'string'\n ? content\n : Array.isArray(content)\n ? content.filter((c): c is string => typeof c === 'string').join(' ')\n : '';\n const truncated = textContent.length > 50 ? textContent.slice(0, 50) + '...' : textContent;\n line = `${prefix}[${i}] { type: \"message\", role: \"${role}\", content: \"${truncated}\", interrupted: ${interrupted} }`;\n } else if (isFunctionCallEvent(event)) {\n const { name, args } = event.item;\n line = `${prefix}[${i}] { type: \"function_call\", name: \"${name}\", args: ${args} }`;\n } else if (isFunctionCallOutputEvent(event)) {\n const { output, isError } = event.item;\n const truncated = output.length > 50 ? output.slice(0, 50) + '...' : output;\n line = `${prefix}[${i}] { type: \"function_call_output\", output: \"${truncated}\", isError: ${isError} }`;\n } else if (isAgentHandoffEvent(event)) {\n line = `${prefix}[${i}] { type: \"agent_handoff\", oldAgent: \"${event.oldAgent?.constructor.name}\", newAgent: \"${event.newAgent.constructor.name}\" }`;\n } else {\n line = `${prefix}[${i}] ${event}`;\n }\n\n lines.push(line);\n }\n\n return lines;\n}\n"],"mappings":"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","names":[]}