@livekit/agents 1.0.45 → 1.0.47

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 (225) hide show
  1. package/dist/cli.cjs +14 -20
  2. package/dist/cli.cjs.map +1 -1
  3. package/dist/cli.d.ts.map +1 -1
  4. package/dist/cli.js +14 -20
  5. package/dist/cli.js.map +1 -1
  6. package/dist/ipc/job_proc_lazy_main.cjs +14 -5
  7. package/dist/ipc/job_proc_lazy_main.cjs.map +1 -1
  8. package/dist/ipc/job_proc_lazy_main.js +14 -5
  9. package/dist/ipc/job_proc_lazy_main.js.map +1 -1
  10. package/dist/llm/chat_context.cjs +19 -0
  11. package/dist/llm/chat_context.cjs.map +1 -1
  12. package/dist/llm/chat_context.d.cts +4 -0
  13. package/dist/llm/chat_context.d.ts +4 -0
  14. package/dist/llm/chat_context.d.ts.map +1 -1
  15. package/dist/llm/chat_context.js +19 -0
  16. package/dist/llm/chat_context.js.map +1 -1
  17. package/dist/llm/provider_format/index.cjs +2 -0
  18. package/dist/llm/provider_format/index.cjs.map +1 -1
  19. package/dist/llm/provider_format/index.d.cts +1 -1
  20. package/dist/llm/provider_format/index.d.ts +1 -1
  21. package/dist/llm/provider_format/index.d.ts.map +1 -1
  22. package/dist/llm/provider_format/index.js +6 -1
  23. package/dist/llm/provider_format/index.js.map +1 -1
  24. package/dist/llm/provider_format/openai.cjs +82 -2
  25. package/dist/llm/provider_format/openai.cjs.map +1 -1
  26. package/dist/llm/provider_format/openai.d.cts +1 -0
  27. package/dist/llm/provider_format/openai.d.ts +1 -0
  28. package/dist/llm/provider_format/openai.d.ts.map +1 -1
  29. package/dist/llm/provider_format/openai.js +80 -1
  30. package/dist/llm/provider_format/openai.js.map +1 -1
  31. package/dist/llm/provider_format/openai.test.cjs +326 -0
  32. package/dist/llm/provider_format/openai.test.cjs.map +1 -1
  33. package/dist/llm/provider_format/openai.test.js +327 -1
  34. package/dist/llm/provider_format/openai.test.js.map +1 -1
  35. package/dist/llm/provider_format/utils.cjs +4 -3
  36. package/dist/llm/provider_format/utils.cjs.map +1 -1
  37. package/dist/llm/provider_format/utils.d.ts.map +1 -1
  38. package/dist/llm/provider_format/utils.js +4 -3
  39. package/dist/llm/provider_format/utils.js.map +1 -1
  40. package/dist/llm/realtime.cjs.map +1 -1
  41. package/dist/llm/realtime.d.cts +1 -0
  42. package/dist/llm/realtime.d.ts +1 -0
  43. package/dist/llm/realtime.d.ts.map +1 -1
  44. package/dist/llm/realtime.js.map +1 -1
  45. package/dist/log.cjs +5 -2
  46. package/dist/log.cjs.map +1 -1
  47. package/dist/log.d.ts.map +1 -1
  48. package/dist/log.js +5 -2
  49. package/dist/log.js.map +1 -1
  50. package/dist/stream/deferred_stream.cjs +15 -6
  51. package/dist/stream/deferred_stream.cjs.map +1 -1
  52. package/dist/stream/deferred_stream.d.ts.map +1 -1
  53. package/dist/stream/deferred_stream.js +15 -6
  54. package/dist/stream/deferred_stream.js.map +1 -1
  55. package/dist/stream/index.cjs +3 -0
  56. package/dist/stream/index.cjs.map +1 -1
  57. package/dist/stream/index.d.cts +1 -0
  58. package/dist/stream/index.d.ts +1 -0
  59. package/dist/stream/index.d.ts.map +1 -1
  60. package/dist/stream/index.js +2 -0
  61. package/dist/stream/index.js.map +1 -1
  62. package/dist/stream/multi_input_stream.cjs +139 -0
  63. package/dist/stream/multi_input_stream.cjs.map +1 -0
  64. package/dist/stream/multi_input_stream.d.cts +55 -0
  65. package/dist/stream/multi_input_stream.d.ts +55 -0
  66. package/dist/stream/multi_input_stream.d.ts.map +1 -0
  67. package/dist/stream/multi_input_stream.js +115 -0
  68. package/dist/stream/multi_input_stream.js.map +1 -0
  69. package/dist/stream/multi_input_stream.test.cjs +340 -0
  70. package/dist/stream/multi_input_stream.test.cjs.map +1 -0
  71. package/dist/stream/multi_input_stream.test.js +339 -0
  72. package/dist/stream/multi_input_stream.test.js.map +1 -0
  73. package/dist/telemetry/trace_types.cjs +42 -0
  74. package/dist/telemetry/trace_types.cjs.map +1 -1
  75. package/dist/telemetry/trace_types.d.cts +14 -0
  76. package/dist/telemetry/trace_types.d.ts +14 -0
  77. package/dist/telemetry/trace_types.d.ts.map +1 -1
  78. package/dist/telemetry/trace_types.js +28 -0
  79. package/dist/telemetry/trace_types.js.map +1 -1
  80. package/dist/utils.cjs +44 -2
  81. package/dist/utils.cjs.map +1 -1
  82. package/dist/utils.d.cts +8 -0
  83. package/dist/utils.d.ts +8 -0
  84. package/dist/utils.d.ts.map +1 -1
  85. package/dist/utils.js +44 -2
  86. package/dist/utils.js.map +1 -1
  87. package/dist/utils.test.cjs +71 -0
  88. package/dist/utils.test.cjs.map +1 -1
  89. package/dist/utils.test.js +71 -0
  90. package/dist/utils.test.js.map +1 -1
  91. package/dist/version.cjs +1 -1
  92. package/dist/version.cjs.map +1 -1
  93. package/dist/version.d.cts +1 -1
  94. package/dist/version.d.ts +1 -1
  95. package/dist/version.d.ts.map +1 -1
  96. package/dist/version.js +1 -1
  97. package/dist/version.js.map +1 -1
  98. package/dist/voice/agent.cjs +144 -12
  99. package/dist/voice/agent.cjs.map +1 -1
  100. package/dist/voice/agent.d.cts +29 -4
  101. package/dist/voice/agent.d.ts +29 -4
  102. package/dist/voice/agent.d.ts.map +1 -1
  103. package/dist/voice/agent.js +140 -11
  104. package/dist/voice/agent.js.map +1 -1
  105. package/dist/voice/agent.test.cjs +120 -0
  106. package/dist/voice/agent.test.cjs.map +1 -1
  107. package/dist/voice/agent.test.js +122 -2
  108. package/dist/voice/agent.test.js.map +1 -1
  109. package/dist/voice/agent_activity.cjs +402 -292
  110. package/dist/voice/agent_activity.cjs.map +1 -1
  111. package/dist/voice/agent_activity.d.cts +35 -7
  112. package/dist/voice/agent_activity.d.ts +35 -7
  113. package/dist/voice/agent_activity.d.ts.map +1 -1
  114. package/dist/voice/agent_activity.js +402 -287
  115. package/dist/voice/agent_activity.js.map +1 -1
  116. package/dist/voice/agent_session.cjs +156 -44
  117. package/dist/voice/agent_session.cjs.map +1 -1
  118. package/dist/voice/agent_session.d.cts +22 -9
  119. package/dist/voice/agent_session.d.ts +22 -9
  120. package/dist/voice/agent_session.d.ts.map +1 -1
  121. package/dist/voice/agent_session.js +156 -44
  122. package/dist/voice/agent_session.js.map +1 -1
  123. package/dist/voice/audio_recognition.cjs +89 -36
  124. package/dist/voice/audio_recognition.cjs.map +1 -1
  125. package/dist/voice/audio_recognition.d.cts +22 -1
  126. package/dist/voice/audio_recognition.d.ts +22 -1
  127. package/dist/voice/audio_recognition.d.ts.map +1 -1
  128. package/dist/voice/audio_recognition.js +93 -36
  129. package/dist/voice/audio_recognition.js.map +1 -1
  130. package/dist/voice/audio_recognition_span.test.cjs +233 -0
  131. package/dist/voice/audio_recognition_span.test.cjs.map +1 -0
  132. package/dist/voice/audio_recognition_span.test.js +232 -0
  133. package/dist/voice/audio_recognition_span.test.js.map +1 -0
  134. package/dist/voice/generation.cjs +39 -19
  135. package/dist/voice/generation.cjs.map +1 -1
  136. package/dist/voice/generation.d.ts.map +1 -1
  137. package/dist/voice/generation.js +44 -20
  138. package/dist/voice/generation.js.map +1 -1
  139. package/dist/voice/index.cjs +2 -0
  140. package/dist/voice/index.cjs.map +1 -1
  141. package/dist/voice/index.d.cts +1 -1
  142. package/dist/voice/index.d.ts +1 -1
  143. package/dist/voice/index.d.ts.map +1 -1
  144. package/dist/voice/index.js +2 -1
  145. package/dist/voice/index.js.map +1 -1
  146. package/dist/voice/io.cjs +6 -3
  147. package/dist/voice/io.cjs.map +1 -1
  148. package/dist/voice/io.d.cts +3 -2
  149. package/dist/voice/io.d.ts +3 -2
  150. package/dist/voice/io.d.ts.map +1 -1
  151. package/dist/voice/io.js +6 -3
  152. package/dist/voice/io.js.map +1 -1
  153. package/dist/voice/recorder_io/recorder_io.cjs +3 -1
  154. package/dist/voice/recorder_io/recorder_io.cjs.map +1 -1
  155. package/dist/voice/recorder_io/recorder_io.d.ts.map +1 -1
  156. package/dist/voice/recorder_io/recorder_io.js +3 -1
  157. package/dist/voice/recorder_io/recorder_io.js.map +1 -1
  158. package/dist/voice/room_io/_input.cjs +17 -17
  159. package/dist/voice/room_io/_input.cjs.map +1 -1
  160. package/dist/voice/room_io/_input.d.cts +2 -2
  161. package/dist/voice/room_io/_input.d.ts +2 -2
  162. package/dist/voice/room_io/_input.d.ts.map +1 -1
  163. package/dist/voice/room_io/_input.js +7 -6
  164. package/dist/voice/room_io/_input.js.map +1 -1
  165. package/dist/voice/room_io/room_io.cjs +9 -0
  166. package/dist/voice/room_io/room_io.cjs.map +1 -1
  167. package/dist/voice/room_io/room_io.d.cts +3 -1
  168. package/dist/voice/room_io/room_io.d.ts +3 -1
  169. package/dist/voice/room_io/room_io.d.ts.map +1 -1
  170. package/dist/voice/room_io/room_io.js +9 -0
  171. package/dist/voice/room_io/room_io.js.map +1 -1
  172. package/dist/voice/speech_handle.cjs +7 -1
  173. package/dist/voice/speech_handle.cjs.map +1 -1
  174. package/dist/voice/speech_handle.d.cts +2 -0
  175. package/dist/voice/speech_handle.d.ts +2 -0
  176. package/dist/voice/speech_handle.d.ts.map +1 -1
  177. package/dist/voice/speech_handle.js +8 -2
  178. package/dist/voice/speech_handle.js.map +1 -1
  179. package/dist/voice/testing/run_result.cjs +66 -15
  180. package/dist/voice/testing/run_result.cjs.map +1 -1
  181. package/dist/voice/testing/run_result.d.cts +14 -3
  182. package/dist/voice/testing/run_result.d.ts +14 -3
  183. package/dist/voice/testing/run_result.d.ts.map +1 -1
  184. package/dist/voice/testing/run_result.js +66 -15
  185. package/dist/voice/testing/run_result.js.map +1 -1
  186. package/dist/voice/utils.cjs +47 -0
  187. package/dist/voice/utils.cjs.map +1 -0
  188. package/dist/voice/utils.d.cts +4 -0
  189. package/dist/voice/utils.d.ts +4 -0
  190. package/dist/voice/utils.d.ts.map +1 -0
  191. package/dist/voice/utils.js +23 -0
  192. package/dist/voice/utils.js.map +1 -0
  193. package/package.json +1 -1
  194. package/src/cli.ts +20 -33
  195. package/src/ipc/job_proc_lazy_main.ts +16 -5
  196. package/src/llm/chat_context.ts +35 -0
  197. package/src/llm/provider_format/index.ts +7 -2
  198. package/src/llm/provider_format/openai.test.ts +385 -1
  199. package/src/llm/provider_format/openai.ts +103 -0
  200. package/src/llm/provider_format/utils.ts +6 -4
  201. package/src/llm/realtime.ts +1 -0
  202. package/src/log.ts +5 -2
  203. package/src/stream/deferred_stream.ts +17 -6
  204. package/src/stream/index.ts +1 -0
  205. package/src/stream/multi_input_stream.test.ts +540 -0
  206. package/src/stream/multi_input_stream.ts +172 -0
  207. package/src/telemetry/trace_types.ts +18 -0
  208. package/src/utils.test.ts +87 -0
  209. package/src/utils.ts +52 -2
  210. package/src/version.ts +1 -1
  211. package/src/voice/agent.test.ts +140 -2
  212. package/src/voice/agent.ts +189 -10
  213. package/src/voice/agent_activity.ts +449 -286
  214. package/src/voice/agent_session.ts +195 -51
  215. package/src/voice/audio_recognition.ts +118 -38
  216. package/src/voice/audio_recognition_span.test.ts +261 -0
  217. package/src/voice/generation.ts +52 -23
  218. package/src/voice/index.ts +1 -1
  219. package/src/voice/io.ts +7 -4
  220. package/src/voice/recorder_io/recorder_io.ts +2 -1
  221. package/src/voice/room_io/_input.ts +11 -7
  222. package/src/voice/room_io/room_io.ts +12 -0
  223. package/src/voice/speech_handle.ts +9 -2
  224. package/src/voice/testing/run_result.ts +81 -23
  225. package/src/voice/utils.ts +29 -0
@@ -30,6 +30,8 @@ import {
30
30
  // Type for agent constructor (used in assertions)
31
31
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
32
32
  type AgentConstructor = new (...args: any[]) => Agent;
33
+ // In JS we use a zod schema so runtime validation and TS generic inference stay aligned.
34
+ type OutputSchema<T> = z.ZodType<T>;
33
35
 
34
36
  // Environment variable for verbose output
35
37
  const evalsVerbose = parseInt(process.env.LIVEKIT_EVALS_VERBOSE || '0', 10);
@@ -48,19 +50,21 @@ export class RunResult<T = unknown> {
48
50
  private _events: RunEvent[] = [];
49
51
  private doneFut = new Future<void>();
50
52
  private userInput?: string;
53
+ private outputType?: OutputSchema<T>;
54
+ private finalOutputValue?: T;
55
+ private hasFinalOutput = false;
51
56
 
52
57
  private handles: Set<SpeechHandle | Task<void>> = new Set();
53
58
  private lastSpeechHandle?: SpeechHandle;
54
59
  private runAssert?: RunAssert;
60
+ // Store per-handle closures so _unwatchHandle can remove callbacks symmetrically.
61
+ private doneCallbacks = new Map<SpeechHandle | Task<void>, () => void>();
55
62
 
56
- // TODO(brian): Add typed output support for parity with Python
57
- // - Add outputType?: new (...args: unknown[]) => T
58
- // - Add finalOutput?: T
59
- // - Implement markDone() to extract final_output from SpeechHandle.maybeRunFinalOutput
60
- // - See Python: run_result.py lines 182-201
63
+ private readonly itemAddedCallback = (item: ChatItem) => this._itemAdded(item);
61
64
 
62
- constructor(options?: { userInput?: string }) {
65
+ constructor(options?: { userInput?: string; outputType?: OutputSchema<T> }) {
63
66
  this.userInput = options?.userInput;
67
+ this.outputType = options?.outputType;
64
68
  }
65
69
 
66
70
  /**
@@ -92,12 +96,17 @@ export class RunResult<T = unknown> {
92
96
 
93
97
  /**
94
98
  * Returns the final output of the run after completion.
95
- *
96
- * @throws Error - Not implemented yet.
97
99
  */
98
100
  get finalOutput(): T {
99
- // TODO(brian): Implement typed output support after AgentTask is implemented.
100
- throw new Error('finalOutput is not yet implemented in JS.');
101
+ if (!this.doneFut.done) {
102
+ throw new Error('cannot retrieve finalOutput, RunResult is not done');
103
+ }
104
+
105
+ if (!this.hasFinalOutput) {
106
+ throw new Error('no final output');
107
+ }
108
+
109
+ return this.finalOutputValue as T;
101
110
  }
102
111
 
103
112
  /**
@@ -167,15 +176,18 @@ export class RunResult<T = unknown> {
167
176
  * Watch a speech handle or task for completion.
168
177
  */
169
178
  _watchHandle(handle: SpeechHandle | Task<void>): void {
179
+ if (this.handles.has(handle)) return;
180
+
170
181
  this.handles.add(handle);
171
182
 
172
183
  if (isSpeechHandle(handle)) {
173
- handle._addItemAddedCallback(this._itemAdded.bind(this));
184
+ handle._addItemAddedCallback(this.itemAddedCallback);
174
185
  }
175
186
 
176
- handle.addDoneCallback(() => {
177
- this._markDoneIfNeeded(handle);
178
- });
187
+ const doneCallback = () => this._markDoneIfNeeded(handle);
188
+
189
+ this.doneCallbacks.set(handle, doneCallback);
190
+ handle.addDoneCallback(doneCallback);
179
191
  }
180
192
 
181
193
  /**
@@ -184,31 +196,77 @@ export class RunResult<T = unknown> {
184
196
  */
185
197
  _unwatchHandle(handle: SpeechHandle | Task<void>): void {
186
198
  this.handles.delete(handle);
199
+ const doneCallback = this.doneCallbacks.get(handle);
200
+
201
+ if (doneCallback) {
202
+ handle.removeDoneCallback(doneCallback);
203
+ this.doneCallbacks.delete(handle);
204
+ }
187
205
 
188
206
  if (isSpeechHandle(handle)) {
189
- handle._removeItemAddedCallback(this._itemAdded.bind(this));
207
+ handle._removeItemAddedCallback(this.itemAddedCallback);
208
+ }
209
+ }
210
+
211
+ /** @internal */
212
+ _watchedHandleCount(): number {
213
+ return this.handles.size;
214
+ }
215
+
216
+ /** @internal – Reject the run with an error (e.g. when deferred generateReply fails). */
217
+ _reject(error: Error): void {
218
+ if (!this.doneFut.done) {
219
+ this.doneFut.reject(error);
190
220
  }
191
221
  }
192
222
 
193
- private _markDoneIfNeeded(handle: SpeechHandle | Task<void>): void {
223
+ /** @internal */
224
+ _markDoneIfNeeded(handle?: SpeechHandle | Task<void> | null): void {
194
225
  if (isSpeechHandle(handle)) {
195
226
  this.lastSpeechHandle = handle;
196
227
  }
197
228
 
198
- if ([...this.handles].every((h) => (isSpeechHandle(h) ? h.done() : h.done))) {
229
+ const allDone = [...this.handles].every((h) => (isSpeechHandle(h) ? h.done() : h.done));
230
+ if (allDone) {
199
231
  this._markDone();
200
232
  }
201
233
  }
202
234
 
203
235
  private _markDone(): void {
204
- // TODO(brian): Implement final output support after AgentTask is implemented.
205
- // See Python run_result.py _mark_done() for reference:
206
- // - Check lastSpeechHandle._maybeRunFinalOutput
207
- // - Validate output type matches expected type
208
- // - Set exception or resolve based on output
209
- if (!this.doneFut.done) {
236
+ if (this.doneFut.done) {
237
+ return;
238
+ }
239
+
240
+ if (!this.lastSpeechHandle) {
210
241
  this.doneFut.resolve();
242
+ return;
243
+ }
244
+
245
+ const finalOutput = this.lastSpeechHandle._maybeRunFinalOutput;
246
+ if (finalOutput instanceof Error) {
247
+ this.doneFut.reject(finalOutput);
248
+ return;
249
+ }
250
+
251
+ if (this.outputType) {
252
+ const result = this.outputType.safeParse(finalOutput);
253
+ if (!result.success) {
254
+ this.doneFut.reject(
255
+ new Error(`Expected output matching provided zod schema: ${result.error.message}`),
256
+ );
257
+ return;
258
+ }
259
+ this.finalOutputValue = result.data;
260
+ this.hasFinalOutput = true;
261
+ this.doneFut.resolve();
262
+ return;
263
+ }
264
+
265
+ if (finalOutput !== undefined) {
266
+ this.finalOutputValue = finalOutput as T;
267
+ this.hasFinalOutput = true;
211
268
  }
269
+ this.doneFut.resolve();
212
270
  }
213
271
 
214
272
  /**
@@ -0,0 +1,29 @@
1
+ // SPDX-FileCopyrightText: 2025 LiveKit, Inc.
2
+ //
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ import type { Participant, ParticipantKind } from '@livekit/rtc-node';
5
+ import type { Span } from '@opentelemetry/api';
6
+ import { traceTypes } from '../telemetry/index.js';
7
+
8
+ export function setParticipantSpanAttributes(
9
+ span: Span,
10
+ participant: Pick<Participant, 'sid' | 'identity' | 'kind'>,
11
+ ): void {
12
+ if (participant.sid) {
13
+ span.setAttribute(traceTypes.ATTR_PARTICIPANT_ID, participant.sid);
14
+ }
15
+ span.setAttribute(traceTypes.ATTR_PARTICIPANT_IDENTITY, participant.identity);
16
+ span.setAttribute(traceTypes.ATTR_PARTICIPANT_KIND, participantKindName(participant.kind));
17
+ }
18
+
19
+ function participantKindName(kind: ParticipantKind): string {
20
+ const names: Record<number, string> = {
21
+ 0: 'STANDARD',
22
+ 1: 'INGRESS',
23
+ 2: 'EGRESS',
24
+ 3: 'SIP',
25
+ 4: 'AGENT',
26
+ 5: 'CONNECTOR',
27
+ };
28
+ return names[kind as number] ?? String(kind);
29
+ }