@livekit/agents 1.0.24 → 1.0.27

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 (184) hide show
  1. package/dist/inference/llm.cjs +1 -2
  2. package/dist/inference/llm.cjs.map +1 -1
  3. package/dist/inference/llm.d.ts.map +1 -1
  4. package/dist/inference/llm.js +1 -2
  5. package/dist/inference/llm.js.map +1 -1
  6. package/dist/inference/stt.cjs +1 -1
  7. package/dist/inference/stt.cjs.map +1 -1
  8. package/dist/inference/stt.d.ts.map +1 -1
  9. package/dist/inference/stt.js +1 -1
  10. package/dist/inference/stt.js.map +1 -1
  11. package/dist/inference/tts.cjs +4 -4
  12. package/dist/inference/tts.cjs.map +1 -1
  13. package/dist/inference/tts.d.cts +0 -1
  14. package/dist/inference/tts.d.ts +0 -1
  15. package/dist/inference/tts.d.ts.map +1 -1
  16. package/dist/inference/tts.js +4 -4
  17. package/dist/inference/tts.js.map +1 -1
  18. package/dist/ipc/job_proc_lazy_main.cjs +1 -1
  19. package/dist/ipc/job_proc_lazy_main.cjs.map +1 -1
  20. package/dist/ipc/job_proc_lazy_main.js +1 -1
  21. package/dist/ipc/job_proc_lazy_main.js.map +1 -1
  22. package/dist/job.cjs +29 -2
  23. package/dist/job.cjs.map +1 -1
  24. package/dist/job.d.cts +6 -0
  25. package/dist/job.d.ts +6 -0
  26. package/dist/job.d.ts.map +1 -1
  27. package/dist/job.js +19 -2
  28. package/dist/job.js.map +1 -1
  29. package/dist/llm/llm.cjs +2 -1
  30. package/dist/llm/llm.cjs.map +1 -1
  31. package/dist/llm/llm.d.cts +1 -1
  32. package/dist/llm/llm.d.ts +1 -1
  33. package/dist/llm/llm.d.ts.map +1 -1
  34. package/dist/llm/llm.js +2 -1
  35. package/dist/llm/llm.js.map +1 -1
  36. package/dist/stream/deferred_stream.cjs +12 -4
  37. package/dist/stream/deferred_stream.cjs.map +1 -1
  38. package/dist/stream/deferred_stream.d.cts +6 -1
  39. package/dist/stream/deferred_stream.d.ts +6 -1
  40. package/dist/stream/deferred_stream.d.ts.map +1 -1
  41. package/dist/stream/deferred_stream.js +12 -4
  42. package/dist/stream/deferred_stream.js.map +1 -1
  43. package/dist/stream/deferred_stream.test.cjs +2 -2
  44. package/dist/stream/deferred_stream.test.cjs.map +1 -1
  45. package/dist/stream/deferred_stream.test.js +2 -2
  46. package/dist/stream/deferred_stream.test.js.map +1 -1
  47. package/dist/stt/stream_adapter.cjs +15 -8
  48. package/dist/stt/stream_adapter.cjs.map +1 -1
  49. package/dist/stt/stream_adapter.d.cts +7 -3
  50. package/dist/stt/stream_adapter.d.ts +7 -3
  51. package/dist/stt/stream_adapter.d.ts.map +1 -1
  52. package/dist/stt/stream_adapter.js +15 -8
  53. package/dist/stt/stream_adapter.js.map +1 -1
  54. package/dist/stt/stt.cjs +8 -3
  55. package/dist/stt/stt.cjs.map +1 -1
  56. package/dist/stt/stt.d.cts +9 -3
  57. package/dist/stt/stt.d.ts +9 -3
  58. package/dist/stt/stt.d.ts.map +1 -1
  59. package/dist/stt/stt.js +9 -4
  60. package/dist/stt/stt.js.map +1 -1
  61. package/dist/telemetry/traces.cjs +23 -2
  62. package/dist/telemetry/traces.cjs.map +1 -1
  63. package/dist/telemetry/traces.d.ts.map +1 -1
  64. package/dist/telemetry/traces.js +23 -2
  65. package/dist/telemetry/traces.js.map +1 -1
  66. package/dist/tts/stream_adapter.cjs +10 -7
  67. package/dist/tts/stream_adapter.cjs.map +1 -1
  68. package/dist/tts/stream_adapter.d.cts +6 -3
  69. package/dist/tts/stream_adapter.d.ts +6 -3
  70. package/dist/tts/stream_adapter.d.ts.map +1 -1
  71. package/dist/tts/stream_adapter.js +10 -7
  72. package/dist/tts/stream_adapter.js.map +1 -1
  73. package/dist/tts/tts.cjs +27 -16
  74. package/dist/tts/tts.cjs.map +1 -1
  75. package/dist/tts/tts.d.cts +12 -5
  76. package/dist/tts/tts.d.ts +12 -5
  77. package/dist/tts/tts.d.ts.map +1 -1
  78. package/dist/tts/tts.js +28 -17
  79. package/dist/tts/tts.js.map +1 -1
  80. package/dist/types.cjs +21 -32
  81. package/dist/types.cjs.map +1 -1
  82. package/dist/types.d.cts +41 -10
  83. package/dist/types.d.ts +41 -10
  84. package/dist/types.d.ts.map +1 -1
  85. package/dist/types.js +18 -30
  86. package/dist/types.js.map +1 -1
  87. package/dist/voice/agent.cjs +54 -19
  88. package/dist/voice/agent.cjs.map +1 -1
  89. package/dist/voice/agent.d.ts.map +1 -1
  90. package/dist/voice/agent.js +54 -19
  91. package/dist/voice/agent.js.map +1 -1
  92. package/dist/voice/agent_activity.cjs +0 -3
  93. package/dist/voice/agent_activity.cjs.map +1 -1
  94. package/dist/voice/agent_activity.d.ts.map +1 -1
  95. package/dist/voice/agent_activity.js +0 -3
  96. package/dist/voice/agent_activity.js.map +1 -1
  97. package/dist/voice/agent_session.cjs +107 -27
  98. package/dist/voice/agent_session.cjs.map +1 -1
  99. package/dist/voice/agent_session.d.cts +16 -2
  100. package/dist/voice/agent_session.d.ts +16 -2
  101. package/dist/voice/agent_session.d.ts.map +1 -1
  102. package/dist/voice/agent_session.js +110 -27
  103. package/dist/voice/agent_session.js.map +1 -1
  104. package/dist/voice/events.cjs.map +1 -1
  105. package/dist/voice/events.d.cts +4 -4
  106. package/dist/voice/events.d.ts +4 -4
  107. package/dist/voice/events.d.ts.map +1 -1
  108. package/dist/voice/events.js.map +1 -1
  109. package/dist/voice/generation.cjs +6 -7
  110. package/dist/voice/generation.cjs.map +1 -1
  111. package/dist/voice/generation.d.ts.map +1 -1
  112. package/dist/voice/generation.js +7 -8
  113. package/dist/voice/generation.js.map +1 -1
  114. package/dist/voice/io.cjs +16 -0
  115. package/dist/voice/io.cjs.map +1 -1
  116. package/dist/voice/io.d.cts +8 -0
  117. package/dist/voice/io.d.ts +8 -0
  118. package/dist/voice/io.d.ts.map +1 -1
  119. package/dist/voice/io.js +16 -0
  120. package/dist/voice/io.js.map +1 -1
  121. package/dist/voice/recorder_io/index.cjs +23 -0
  122. package/dist/voice/recorder_io/index.cjs.map +1 -0
  123. package/dist/voice/recorder_io/index.d.cts +2 -0
  124. package/dist/voice/recorder_io/index.d.ts +2 -0
  125. package/dist/voice/recorder_io/index.d.ts.map +1 -0
  126. package/dist/voice/recorder_io/index.js +2 -0
  127. package/dist/voice/recorder_io/index.js.map +1 -0
  128. package/dist/voice/recorder_io/recorder_io.cjs +542 -0
  129. package/dist/voice/recorder_io/recorder_io.cjs.map +1 -0
  130. package/dist/voice/recorder_io/recorder_io.d.cts +100 -0
  131. package/dist/voice/recorder_io/recorder_io.d.ts +100 -0
  132. package/dist/voice/recorder_io/recorder_io.d.ts.map +1 -0
  133. package/dist/voice/recorder_io/recorder_io.js +508 -0
  134. package/dist/voice/recorder_io/recorder_io.js.map +1 -0
  135. package/dist/voice/report.cjs +7 -2
  136. package/dist/voice/report.cjs.map +1 -1
  137. package/dist/voice/report.d.cts +11 -1
  138. package/dist/voice/report.d.ts +11 -1
  139. package/dist/voice/report.d.ts.map +1 -1
  140. package/dist/voice/report.js +7 -2
  141. package/dist/voice/report.js.map +1 -1
  142. package/dist/voice/room_io/_input.cjs +2 -1
  143. package/dist/voice/room_io/_input.cjs.map +1 -1
  144. package/dist/voice/room_io/_input.d.ts.map +1 -1
  145. package/dist/voice/room_io/_input.js +2 -1
  146. package/dist/voice/room_io/_input.js.map +1 -1
  147. package/dist/voice/room_io/_output.cjs +8 -7
  148. package/dist/voice/room_io/_output.cjs.map +1 -1
  149. package/dist/voice/room_io/_output.d.cts +2 -1
  150. package/dist/voice/room_io/_output.d.ts +2 -1
  151. package/dist/voice/room_io/_output.d.ts.map +1 -1
  152. package/dist/voice/room_io/_output.js +8 -7
  153. package/dist/voice/room_io/_output.js.map +1 -1
  154. package/dist/worker.cjs +4 -3
  155. package/dist/worker.cjs.map +1 -1
  156. package/dist/worker.js +4 -3
  157. package/dist/worker.js.map +1 -1
  158. package/package.json +1 -1
  159. package/src/inference/llm.ts +0 -1
  160. package/src/inference/stt.ts +1 -2
  161. package/src/inference/tts.ts +5 -4
  162. package/src/ipc/job_proc_lazy_main.ts +1 -1
  163. package/src/job.ts +21 -2
  164. package/src/llm/llm.ts +2 -2
  165. package/src/stream/deferred_stream.test.ts +3 -3
  166. package/src/stream/deferred_stream.ts +22 -5
  167. package/src/stt/stream_adapter.ts +18 -8
  168. package/src/stt/stt.ts +19 -6
  169. package/src/telemetry/traces.ts +25 -3
  170. package/src/tts/stream_adapter.ts +15 -7
  171. package/src/tts/tts.ts +46 -21
  172. package/src/types.ts +57 -33
  173. package/src/voice/agent.ts +59 -19
  174. package/src/voice/agent_activity.ts +0 -3
  175. package/src/voice/agent_session.ts +142 -35
  176. package/src/voice/events.ts +6 -3
  177. package/src/voice/generation.ts +10 -8
  178. package/src/voice/io.ts +19 -0
  179. package/src/voice/recorder_io/index.ts +4 -0
  180. package/src/voice/recorder_io/recorder_io.ts +690 -0
  181. package/src/voice/report.ts +20 -3
  182. package/src/voice/room_io/_input.ts +2 -1
  183. package/src/voice/room_io/_output.ts +10 -7
  184. package/src/worker.ts +1 -1
@@ -9,6 +9,10 @@ import { getJobContext } from "../job.js";
9
9
  import { AgentHandoffItem, ChatContext, ChatMessage } from "../llm/chat_context.js";
10
10
  import { log } from "../log.js";
11
11
  import { traceTypes, tracer } from "../telemetry/index.js";
12
+ import {
13
+ DEFAULT_API_CONNECT_OPTIONS,
14
+ DEFAULT_SESSION_CONNECT_OPTIONS
15
+ } from "../types.js";
12
16
  import { AgentActivity } from "./agent_activity.js";
13
17
  import {
14
18
  AgentSessionEventTypes,
@@ -19,6 +23,7 @@ import {
19
23
  createUserStateChangedEvent
20
24
  } from "./events.js";
21
25
  import { AgentInput, AgentOutput } from "./io.js";
26
+ import { RecorderIO } from "./recorder_io/index.js";
22
27
  import { RoomIO } from "./room_io/index.js";
23
28
  const defaultVoiceOptions = {
24
29
  allowInterruptions: true,
@@ -52,10 +57,17 @@ class AgentSession extends EventEmitter {
52
57
  _output;
53
58
  closingTask = null;
54
59
  userAwayTimer = null;
60
+ // Connection options for STT, LLM, and TTS
61
+ _connOptions;
62
+ // Unrecoverable error counts, reset after agent speaking
63
+ llmErrorCounts = 0;
64
+ ttsErrorCounts = 0;
55
65
  sessionSpan;
56
66
  userSpeakingSpan;
57
67
  agentSpeakingSpan;
58
68
  /** @internal */
69
+ _recorderIO;
70
+ /** @internal */
59
71
  rootSpanContext;
60
72
  /** @internal */
61
73
  _recordedEvents = [];
@@ -72,8 +84,15 @@ class AgentSession extends EventEmitter {
72
84
  tts,
73
85
  turnDetection,
74
86
  userData,
75
- voiceOptions = defaultVoiceOptions
87
+ voiceOptions = defaultVoiceOptions,
88
+ connOptions
76
89
  } = opts;
90
+ this._connOptions = {
91
+ sttConnOptions: { ...DEFAULT_API_CONNECT_OPTIONS, ...connOptions == null ? void 0 : connOptions.sttConnOptions },
92
+ llmConnOptions: { ...DEFAULT_API_CONNECT_OPTIONS, ...connOptions == null ? void 0 : connOptions.llmConnOptions },
93
+ ttsConnOptions: { ...DEFAULT_API_CONNECT_OPTIONS, ...connOptions == null ? void 0 : connOptions.ttsConnOptions },
94
+ maxUnrecoverableErrors: (connOptions == null ? void 0 : connOptions.maxUnrecoverableErrors) ?? DEFAULT_SESSION_CONNECT_OPTIONS.maxUnrecoverableErrors
95
+ };
77
96
  this.vad = vad;
78
97
  if (typeof stt === "string") {
79
98
  this.stt = InferenceSTT.fromModelString(stt);
@@ -119,6 +138,10 @@ class AgentSession extends EventEmitter {
119
138
  get history() {
120
139
  return this._chatCtx;
121
140
  }
141
+ /** Connection options for STT, LLM, and TTS. */
142
+ get connOptions() {
143
+ return this._connOptions;
144
+ }
122
145
  set userData(value) {
123
146
  this._userData = value;
124
147
  }
@@ -127,7 +150,6 @@ class AgentSession extends EventEmitter {
127
150
  room,
128
151
  inputOptions,
129
152
  outputOptions,
130
- record,
131
153
  span
132
154
  }) {
133
155
  span.setAttribute(traceTypes.ATTR_AGENT_LABEL, agent.id);
@@ -154,19 +176,33 @@ class AgentSession extends EventEmitter {
154
176
  outputOptions
155
177
  });
156
178
  this.roomIO.start();
157
- const ctx = getJobContext();
158
- if (ctx && ctx.room === room && !room.isConnected) {
159
- this.logger.debug("Auto-connecting to room via job context");
160
- tasks.push(ctx.connect());
161
- }
162
- if (record) {
179
+ let ctx = void 0;
180
+ try {
181
+ ctx = getJobContext();
182
+ } catch (error) {
183
+ this.logger.warn("JobContext is not available");
184
+ }
185
+ if (ctx) {
186
+ if (ctx.room === room && !room.isConnected) {
187
+ this.logger.debug("Auto-connecting to room via job context");
188
+ tasks.push(ctx.connect());
189
+ }
163
190
  if (ctx._primaryAgentSession === void 0) {
164
191
  ctx._primaryAgentSession = this;
165
- } else {
192
+ } else if (this._enableRecording) {
166
193
  throw new Error(
167
- "Only one `AgentSession` can be the primary at a time. If you want to ignore primary designation, use session.start(record=False)."
194
+ "Only one `AgentSession` can be the primary at a time. If you want to ignore primary designation, use `session.start({ record: false })`."
168
195
  );
169
196
  }
197
+ if (this.input.audio && this.output.audio && this._enableRecording) {
198
+ this._recorderIO = new RecorderIO({ agentSession: this });
199
+ this.input.audio = this._recorderIO.recordInput(this.input.audio);
200
+ this.output.audio = this._recorderIO.recordOutput(this.output.audio);
201
+ const sessionDir = ctx.sessionDirectory;
202
+ if (sessionDir) {
203
+ tasks.push(this._recorderIO.start(`${sessionDir}/audio.ogg`));
204
+ }
205
+ }
170
206
  }
171
207
  tasks.push(this.updateActivity(this.agent));
172
208
  await Promise.allSettled(tasks);
@@ -190,15 +226,18 @@ class AgentSession extends EventEmitter {
190
226
  if (this.started) {
191
227
  return;
192
228
  }
193
- const ctx = getJobContext();
194
- this.logger.info(
195
- { record, enableRecording: ctx.info.job.enableRecording },
196
- "Configuring session recording"
197
- );
198
- record = record ?? ctx.info.job.enableRecording;
199
- this._enableRecording = record;
200
- if (this._enableRecording) {
201
- await ctx.initRecording();
229
+ let ctx = void 0;
230
+ try {
231
+ ctx = getJobContext();
232
+ if (record === void 0) {
233
+ record = ctx.job.enableRecording;
234
+ }
235
+ this._enableRecording = record;
236
+ if (this._enableRecording) {
237
+ ctx.initRecording();
238
+ }
239
+ } catch (error) {
240
+ this.logger.warn("JobContext is not available");
202
241
  }
203
242
  this.sessionSpan = tracer.startSpan({
204
243
  name: "agent_session",
@@ -210,7 +249,6 @@ class AgentSession extends EventEmitter {
210
249
  room,
211
250
  inputOptions,
212
251
  outputOptions,
213
- record,
214
252
  span: this.sessionSpan
215
253
  });
216
254
  }
@@ -236,7 +274,14 @@ class AgentSession extends EventEmitter {
236
274
  if (!this.activity) {
237
275
  throw new Error("AgentSession is not running");
238
276
  }
239
- return this.activity.say(text, options);
277
+ const doSay = (activity) => {
278
+ return activity.say(text, options);
279
+ };
280
+ const activeSpan = trace.getActiveSpan();
281
+ if (!activeSpan && this.rootSpanContext) {
282
+ return otelContext.with(this.rootSpanContext, () => doSay(this.activity));
283
+ }
284
+ return doSay(this.activity);
240
285
  }
241
286
  interrupt() {
242
287
  if (!this.activity) {
@@ -252,13 +297,23 @@ class AgentSession extends EventEmitter {
252
297
  role: "user",
253
298
  content: options.userInput
254
299
  }) : void 0;
255
- if (this.activity.draining) {
256
- if (!this.nextActivity) {
257
- throw new Error("AgentSession is closing, cannot use generateReply()");
300
+ const doGenerateReply = (activity, nextActivity) => {
301
+ if (activity.draining) {
302
+ if (!nextActivity) {
303
+ throw new Error("AgentSession is closing, cannot use generateReply()");
304
+ }
305
+ return nextActivity.generateReply({ userMessage, ...options });
258
306
  }
259
- return this.nextActivity.generateReply({ userMessage, ...options });
307
+ return activity.generateReply({ userMessage, ...options });
308
+ };
309
+ const activeSpan = trace.getActiveSpan();
310
+ if (!activeSpan && this.rootSpanContext) {
311
+ return otelContext.with(
312
+ this.rootSpanContext,
313
+ () => doGenerateReply(this.activity, this.nextActivity)
314
+ );
260
315
  }
261
- return this.activity.generateReply({ userMessage, ...options });
316
+ return doGenerateReply(this.activity, this.nextActivity);
262
317
  }
263
318
  async updateActivity(agent) {
264
319
  const runWithContext = async () => {
@@ -302,6 +357,13 @@ class AgentSession extends EventEmitter {
302
357
  async close() {
303
358
  await this.closeImpl(CloseReason.USER_INITIATED);
304
359
  }
360
+ shutdown(options) {
361
+ const { drain = true, reason = CloseReason.USER_INITIATED } = options ?? {};
362
+ this._closeSoon({
363
+ reason,
364
+ drain
365
+ });
366
+ }
305
367
  /** @internal */
306
368
  _closeSoon({
307
369
  reason,
@@ -318,6 +380,17 @@ class AgentSession extends EventEmitter {
318
380
  if (this.closingTask || error.recoverable) {
319
381
  return;
320
382
  }
383
+ if (error.type === "llm_error") {
384
+ this.llmErrorCounts += 1;
385
+ if (this.llmErrorCounts <= this._connOptions.maxUnrecoverableErrors) {
386
+ return;
387
+ }
388
+ } else if (error.type === "tts_error") {
389
+ this.ttsErrorCounts += 1;
390
+ if (this.ttsErrorCounts <= this._connOptions.maxUnrecoverableErrors) {
391
+ return;
392
+ }
393
+ }
321
394
  this.logger.error(error, "AgentSession is closing due to unrecoverable error");
322
395
  this.closingTask = (async () => {
323
396
  await this.closeImpl(CloseReason.ERROR, error);
@@ -340,6 +413,8 @@ class AgentSession extends EventEmitter {
340
413
  return;
341
414
  }
342
415
  if (state === "speaking") {
416
+ this.llmErrorCounts = 0;
417
+ this.ttsErrorCounts = 0;
343
418
  if (this.agentSpeakingSpan === void 0) {
344
419
  this.agentSpeakingSpan = tracer.startSpan({
345
420
  name: "agent_speaking",
@@ -450,7 +525,13 @@ class AgentSession extends EventEmitter {
450
525
  }
451
526
  await this.activity.drain();
452
527
  await ((_a = this.activity.currentSpeech) == null ? void 0 : _a.waitForPlayout());
453
- this.activity.detachAudioInput();
528
+ try {
529
+ this.activity.detachAudioInput();
530
+ } catch (error2) {
531
+ }
532
+ }
533
+ if (this._recorderIO) {
534
+ await this._recorderIO.close();
454
535
  }
455
536
  this.input.audio = null;
456
537
  this.output.audio = null;
@@ -476,6 +557,8 @@ class AgentSession extends EventEmitter {
476
557
  this.userState = "listening";
477
558
  this._agentState = "initializing";
478
559
  this.rootSpanContext = void 0;
560
+ this.llmErrorCounts = 0;
561
+ this.ttsErrorCounts = 0;
479
562
  this.logger.info({ reason, error }, "AgentSession closed");
480
563
  }
481
564
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/voice/agent_session.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { AudioFrame, Room } from '@livekit/rtc-node';\nimport type { TypedEventEmitter as TypedEmitter } from '@livekit/typed-emitter';\nimport type { Context, Span } from '@opentelemetry/api';\nimport { ROOT_CONTEXT, context as otelContext, trace } from '@opentelemetry/api';\nimport { EventEmitter } from 'node:events';\nimport type { ReadableStream } from 'node:stream/web';\nimport {\n LLM as InferenceLLM,\n STT as InferenceSTT,\n TTS as InferenceTTS,\n type LLMModels,\n type STTModelString,\n type TTSModelString,\n} from '../inference/index.js';\nimport { getJobContext } from '../job.js';\nimport type { FunctionCall, FunctionCallOutput } from '../llm/chat_context.js';\nimport { AgentHandoffItem, ChatContext, ChatMessage } from '../llm/chat_context.js';\nimport type { LLM, RealtimeModel, RealtimeModelError, ToolChoice } from '../llm/index.js';\nimport type { LLMError } from '../llm/llm.js';\nimport { log } from '../log.js';\nimport type { STT } from '../stt/index.js';\nimport type { STTError } from '../stt/stt.js';\nimport { traceTypes, tracer } from '../telemetry/index.js';\nimport type { TTS, TTSError } from '../tts/tts.js';\nimport type { VAD } from '../vad.js';\nimport type { Agent } from './agent.js';\nimport { AgentActivity } from './agent_activity.js';\nimport type { _TurnDetector } from './audio_recognition.js';\nimport {\n type AgentEvent,\n AgentSessionEventTypes,\n type AgentState,\n type AgentStateChangedEvent,\n type CloseEvent,\n CloseReason,\n type ConversationItemAddedEvent,\n type ErrorEvent,\n type FunctionToolsExecutedEvent,\n type MetricsCollectedEvent,\n type SpeechCreatedEvent,\n type UserInputTranscribedEvent,\n type UserState,\n type UserStateChangedEvent,\n createAgentStateChangedEvent,\n createCloseEvent,\n createConversationItemAddedEvent,\n createUserStateChangedEvent,\n} from './events.js';\nimport { AgentInput, AgentOutput } from './io.js';\nimport { RoomIO, type RoomInputOptions, type RoomOutputOptions } from './room_io/index.js';\nimport type { UnknownUserData } from './run_context.js';\nimport type { SpeechHandle } from './speech_handle.js';\n\nexport interface VoiceOptions {\n allowInterruptions: boolean;\n discardAudioIfUninterruptible: boolean;\n minInterruptionDuration: number;\n minInterruptionWords: number;\n minEndpointingDelay: number;\n maxEndpointingDelay: number;\n maxToolSteps: number;\n preemptiveGeneration: boolean;\n userAwayTimeout?: number | null;\n}\n\nconst defaultVoiceOptions: VoiceOptions = {\n allowInterruptions: true,\n discardAudioIfUninterruptible: true,\n minInterruptionDuration: 500,\n minInterruptionWords: 0,\n minEndpointingDelay: 500,\n maxEndpointingDelay: 6000,\n maxToolSteps: 3,\n preemptiveGeneration: false,\n userAwayTimeout: 15.0,\n} as const;\n\nexport type TurnDetectionMode = 'stt' | 'vad' | 'realtime_llm' | 'manual' | _TurnDetector;\n\nexport type AgentSessionCallbacks = {\n [AgentSessionEventTypes.UserInputTranscribed]: (ev: UserInputTranscribedEvent) => void;\n [AgentSessionEventTypes.AgentStateChanged]: (ev: AgentStateChangedEvent) => void;\n [AgentSessionEventTypes.UserStateChanged]: (ev: UserStateChangedEvent) => void;\n [AgentSessionEventTypes.ConversationItemAdded]: (ev: ConversationItemAddedEvent) => void;\n [AgentSessionEventTypes.FunctionToolsExecuted]: (ev: FunctionToolsExecutedEvent) => void;\n [AgentSessionEventTypes.MetricsCollected]: (ev: MetricsCollectedEvent) => void;\n [AgentSessionEventTypes.SpeechCreated]: (ev: SpeechCreatedEvent) => void;\n [AgentSessionEventTypes.Error]: (ev: ErrorEvent) => void;\n [AgentSessionEventTypes.Close]: (ev: CloseEvent) => void;\n};\n\nexport type AgentSessionOptions<UserData = UnknownUserData> = {\n turnDetection?: TurnDetectionMode;\n stt?: STT | STTModelString;\n vad?: VAD;\n llm?: LLM | RealtimeModel | LLMModels;\n tts?: TTS | TTSModelString;\n userData?: UserData;\n voiceOptions?: Partial<VoiceOptions>;\n};\n\nexport class AgentSession<\n UserData = UnknownUserData,\n> extends (EventEmitter as new () => TypedEmitter<AgentSessionCallbacks>) {\n vad?: VAD;\n stt?: STT;\n llm?: LLM | RealtimeModel;\n tts?: TTS;\n turnDetection?: TurnDetectionMode;\n\n readonly options: VoiceOptions;\n\n private agent?: Agent;\n private activity?: AgentActivity;\n private nextActivity?: AgentActivity;\n private started = false;\n private userState: UserState = 'listening';\n\n private roomIO?: RoomIO;\n private logger = log();\n\n private _chatCtx: ChatContext;\n private _userData: UserData | undefined;\n private _agentState: AgentState = 'initializing';\n\n private _input: AgentInput;\n private _output: AgentOutput;\n\n private closingTask: Promise<void> | null = null;\n private userAwayTimer: NodeJS.Timeout | null = null;\n\n private sessionSpan?: Span;\n private userSpeakingSpan?: Span;\n private agentSpeakingSpan?: Span;\n\n /** @internal */\n rootSpanContext?: Context;\n\n /** @internal */\n _recordedEvents: AgentEvent[] = [];\n\n /** @internal */\n _enableRecording = false;\n\n /** @internal - Timestamp when the session started (milliseconds) */\n _startedAt?: number;\n\n constructor(opts: AgentSessionOptions<UserData>) {\n super();\n\n const {\n vad,\n stt,\n llm,\n tts,\n turnDetection,\n userData,\n voiceOptions = defaultVoiceOptions,\n } = opts;\n\n this.vad = vad;\n\n if (typeof stt === 'string') {\n this.stt = InferenceSTT.fromModelString(stt);\n } else {\n this.stt = stt;\n }\n\n if (typeof llm === 'string') {\n this.llm = InferenceLLM.fromModelString(llm);\n } else {\n this.llm = llm;\n }\n\n if (typeof tts === 'string') {\n this.tts = InferenceTTS.fromModelString(tts);\n } else {\n this.tts = tts;\n }\n\n this.turnDetection = turnDetection;\n this._userData = userData;\n\n // configurable IO\n this._input = new AgentInput(this.onAudioInputChanged);\n this._output = new AgentOutput(this.onAudioOutputChanged, this.onTextOutputChanged);\n\n // This is the \"global\" chat context, it holds the entire conversation history\n this._chatCtx = ChatContext.empty();\n this.options = { ...defaultVoiceOptions, ...voiceOptions };\n\n this._onUserInputTranscribed = this._onUserInputTranscribed.bind(this);\n this.on(AgentSessionEventTypes.UserInputTranscribed, this._onUserInputTranscribed);\n }\n\n emit<K extends keyof AgentSessionCallbacks>(\n event: K,\n ...args: Parameters<AgentSessionCallbacks[K]>\n ): boolean {\n const eventData = args[0] as AgentEvent;\n this._recordedEvents.push(eventData);\n return super.emit(event, ...args);\n }\n\n get input(): AgentInput {\n return this._input;\n }\n\n get output(): AgentOutput {\n return this._output;\n }\n\n get userData(): UserData {\n if (this._userData === undefined) {\n throw new Error('Voice agent userData is not set');\n }\n\n return this._userData;\n }\n\n get history(): ChatContext {\n return this._chatCtx;\n }\n\n set userData(value: UserData) {\n this._userData = value;\n }\n\n private async _startImpl({\n agent,\n room,\n inputOptions,\n outputOptions,\n record,\n span,\n }: {\n agent: Agent;\n room: Room;\n inputOptions?: Partial<RoomInputOptions>;\n outputOptions?: Partial<RoomOutputOptions>;\n record: boolean;\n span: Span;\n }): Promise<void> {\n span.setAttribute(traceTypes.ATTR_AGENT_LABEL, agent.id);\n\n this.agent = agent;\n this._updateAgentState('initializing');\n\n const tasks: Promise<void>[] = [];\n // Check for existing input/output configuration and warn if needed\n if (this.input.audio && inputOptions?.audioEnabled !== false) {\n this.logger.warn('RoomIO audio input is enabled but input.audio is already set, ignoring..');\n }\n\n if (this.output.audio && outputOptions?.audioEnabled !== false) {\n this.logger.warn(\n 'RoomIO audio output is enabled but output.audio is already set, ignoring..',\n );\n }\n\n if (this.output.transcription && outputOptions?.transcriptionEnabled !== false) {\n this.logger.warn(\n 'RoomIO transcription output is enabled but output.transcription is already set, ignoring..',\n );\n }\n\n this.roomIO = new RoomIO({\n agentSession: this,\n room,\n inputOptions,\n outputOptions,\n });\n this.roomIO.start();\n\n const ctx = getJobContext();\n if (ctx && ctx.room === room && !room.isConnected) {\n this.logger.debug('Auto-connecting to room via job context');\n tasks.push(ctx.connect());\n }\n\n if (record) {\n if (ctx._primaryAgentSession === undefined) {\n ctx._primaryAgentSession = this;\n } else {\n throw new Error(\n 'Only one `AgentSession` can be the primary at a time. If you want to ignore primary designation, use session.start(record=False).',\n );\n }\n }\n\n // TODO(AJS-265): add shutdown callback to job context\n tasks.push(this.updateActivity(this.agent));\n\n await Promise.allSettled(tasks);\n\n // Log used IO configuration\n this.logger.debug(\n `using audio io: ${this.input.audio ? '`' + this.input.audio.constructor.name + '`' : '(none)'} -> \\`AgentSession\\` -> ${this.output.audio ? '`' + this.output.audio.constructor.name + '`' : '(none)'}`,\n );\n\n this.logger.debug(\n `using transcript io: \\`AgentSession\\` -> ${this.output.transcription ? '`' + this.output.transcription.constructor.name + '`' : '(none)'}`,\n );\n\n this.started = true;\n this._startedAt = Date.now();\n this._updateAgentState('listening');\n }\n\n async start({\n agent,\n room,\n inputOptions,\n outputOptions,\n record,\n }: {\n agent: Agent;\n room: Room;\n inputOptions?: Partial<RoomInputOptions>;\n outputOptions?: Partial<RoomOutputOptions>;\n record?: boolean;\n }): Promise<void> {\n if (this.started) {\n return;\n }\n\n const ctx = getJobContext();\n\n this.logger.info(\n { record, enableRecording: ctx.info.job.enableRecording },\n 'Configuring session recording',\n );\n\n record = record ?? ctx.info.job.enableRecording;\n this._enableRecording = record;\n\n if (this._enableRecording) {\n await ctx.initRecording();\n }\n\n // Create agent_session as a ROOT span (new trace) to match Python behavior\n // This creates a separate trace for better cloud dashboard organization\n this.sessionSpan = tracer.startSpan({\n name: 'agent_session',\n context: ROOT_CONTEXT,\n });\n\n // Set the session span as the active span in the context\n // This ensures all child spans (agent_turn, user_turn, etc.) are parented to it\n this.rootSpanContext = trace.setSpan(ROOT_CONTEXT, this.sessionSpan);\n\n await this._startImpl({\n agent,\n room,\n inputOptions,\n outputOptions,\n record,\n span: this.sessionSpan,\n });\n }\n\n updateAgent(agent: Agent): void {\n this.agent = agent;\n\n if (this.started) {\n this.updateActivity(agent);\n }\n }\n\n commitUserTurn() {\n if (!this.activity) {\n throw new Error('AgentSession is not running');\n }\n\n this.activity.commitUserTurn();\n }\n\n clearUserTurn() {\n if (!this.activity) {\n throw new Error('AgentSession is not running');\n }\n this.activity.clearUserTurn();\n }\n\n say(\n text: string | ReadableStream<string>,\n options?: {\n audio?: ReadableStream<AudioFrame>;\n allowInterruptions?: boolean;\n addToChatCtx?: boolean;\n },\n ): SpeechHandle {\n if (!this.activity) {\n throw new Error('AgentSession is not running');\n }\n\n return this.activity.say(text, options);\n }\n\n interrupt() {\n if (!this.activity) {\n throw new Error('AgentSession is not running');\n }\n return this.activity.interrupt();\n }\n\n generateReply(options?: {\n userInput?: string;\n instructions?: string;\n toolChoice?: ToolChoice;\n allowInterruptions?: boolean;\n }): SpeechHandle {\n if (!this.activity) {\n throw new Error('AgentSession is not running');\n }\n\n const userMessage = options?.userInput\n ? new ChatMessage({\n role: 'user',\n content: options.userInput,\n })\n : undefined;\n\n if (this.activity.draining) {\n if (!this.nextActivity) {\n throw new Error('AgentSession is closing, cannot use generateReply()');\n }\n return this.nextActivity.generateReply({ userMessage, ...options });\n }\n\n return this.activity.generateReply({ userMessage, ...options });\n }\n\n private async updateActivity(agent: Agent): Promise<void> {\n const runWithContext = async () => {\n // TODO(AJS-129): add lock to agent activity core lifecycle\n this.nextActivity = new AgentActivity(agent, this);\n\n const previousActivity = this.activity;\n\n if (this.activity) {\n await this.activity.drain();\n await this.activity.close();\n }\n\n this.activity = this.nextActivity;\n this.nextActivity = undefined;\n\n this._chatCtx.insert(\n new AgentHandoffItem({\n oldAgentId: previousActivity?.agent.id,\n newAgentId: agent.id,\n }),\n );\n this.logger.debug({ previousActivity, agent }, 'Agent handoff inserted into chat context');\n\n await this.activity.start();\n\n if (this._input.audio) {\n this.activity.attachAudioInput(this._input.audio.stream);\n }\n };\n\n // Run within session span context if available\n if (this.rootSpanContext) {\n return otelContext.with(this.rootSpanContext, runWithContext);\n }\n\n return runWithContext();\n }\n\n get chatCtx(): ChatContext {\n return this._chatCtx.copy();\n }\n\n get agentState(): AgentState {\n return this._agentState;\n }\n\n get currentAgent(): Agent {\n if (!this.agent) {\n throw new Error('AgentSession is not running');\n }\n\n return this.agent;\n }\n\n async close(): Promise<void> {\n await this.closeImpl(CloseReason.USER_INITIATED);\n }\n\n /** @internal */\n _closeSoon({\n reason,\n drain = false,\n error = null,\n }: {\n reason: CloseReason;\n drain?: boolean;\n error?: RealtimeModelError | STTError | TTSError | LLMError | null;\n }): void {\n if (this.closingTask) {\n return;\n }\n this.closeImpl(reason, error, drain);\n }\n\n /** @internal */\n _onError(error: RealtimeModelError | STTError | TTSError | LLMError): void {\n if (this.closingTask || error.recoverable) {\n return;\n }\n\n this.logger.error(error, 'AgentSession is closing due to unrecoverable error');\n\n this.closingTask = (async () => {\n await this.closeImpl(CloseReason.ERROR, error);\n })().then(() => {\n this.closingTask = null;\n });\n }\n\n /** @internal */\n _conversationItemAdded(item: ChatMessage): void {\n this._chatCtx.insert(item);\n this.emit(AgentSessionEventTypes.ConversationItemAdded, createConversationItemAddedEvent(item));\n }\n\n /** @internal */\n _toolItemsAdded(items: (FunctionCall | FunctionCallOutput)[]): void {\n this._chatCtx.insert(items);\n }\n\n /** @internal */\n _updateAgentState(state: AgentState) {\n if (this._agentState === state) {\n return;\n }\n\n if (state === 'speaking') {\n // TODO(brian): PR4 - Track error counts\n\n if (this.agentSpeakingSpan === undefined) {\n this.agentSpeakingSpan = tracer.startSpan({\n name: 'agent_speaking',\n context: this.rootSpanContext,\n });\n\n // TODO(brian): PR4 - Set participant attributes if roomIO.room.localParticipant is available\n // (Ref: Python agent_session.py line 1161-1164)\n }\n } else if (this.agentSpeakingSpan !== undefined) {\n // TODO(brian): PR4 - Set ATTR_END_TIME attribute if available\n this.agentSpeakingSpan.end();\n this.agentSpeakingSpan = undefined;\n }\n\n const oldState = this._agentState;\n this._agentState = state;\n\n // Handle user away timer based on state changes\n if (state === 'listening' && this.userState === 'listening') {\n this._setUserAwayTimer();\n } else {\n this._cancelUserAwayTimer();\n }\n\n this.emit(\n AgentSessionEventTypes.AgentStateChanged,\n createAgentStateChangedEvent(oldState, state),\n );\n }\n\n /** @internal */\n _updateUserState(state: UserState, _lastSpeakingTime?: number) {\n if (this.userState === state) {\n return;\n }\n\n if (state === 'speaking' && this.userSpeakingSpan === undefined) {\n this.userSpeakingSpan = tracer.startSpan({\n name: 'user_speaking',\n context: this.rootSpanContext,\n });\n\n // TODO(brian): PR4 - Set participant attributes if roomIO.linkedParticipant is available\n // (Ref: Python agent_session.py line 1192-1195)\n } else if (this.userSpeakingSpan !== undefined) {\n // TODO(brian): PR4 - Set ATTR_END_TIME attribute with lastSpeakingTime if available\n this.userSpeakingSpan.end();\n this.userSpeakingSpan = undefined;\n }\n\n const oldState = this.userState;\n this.userState = state;\n\n // Handle user away timer based on state changes\n if (state === 'listening' && this._agentState === 'listening') {\n this._setUserAwayTimer();\n } else {\n this._cancelUserAwayTimer();\n }\n\n this.emit(\n AgentSessionEventTypes.UserStateChanged,\n createUserStateChangedEvent(oldState, state),\n );\n }\n\n // -- User changed input/output streams/sinks --\n private onAudioInputChanged(): void {\n if (!this.started) {\n return;\n }\n\n if (this.activity && this._input.audio) {\n this.activity.attachAudioInput(this._input.audio.stream);\n }\n }\n\n private onAudioOutputChanged(): void {}\n\n private onTextOutputChanged(): void {}\n\n private _setUserAwayTimer(): void {\n this._cancelUserAwayTimer();\n\n if (this.options.userAwayTimeout === null || this.options.userAwayTimeout === undefined) {\n return;\n }\n\n if (this.roomIO && !this.roomIO.isParticipantAvailable) {\n return;\n }\n\n this.userAwayTimer = setTimeout(() => {\n this.logger.debug('User away timeout triggered');\n this._updateUserState('away');\n }, this.options.userAwayTimeout * 1000);\n }\n\n private _cancelUserAwayTimer(): void {\n if (this.userAwayTimer !== null) {\n clearTimeout(this.userAwayTimer);\n this.userAwayTimer = null;\n }\n }\n\n private _onUserInputTranscribed(ev: UserInputTranscribedEvent): void {\n if (this.userState === 'away' && ev.isFinal) {\n this.logger.debug('User returned from away state due to speech input');\n this._updateUserState('listening');\n }\n }\n\n private async closeImpl(\n reason: CloseReason,\n error: RealtimeModelError | LLMError | TTSError | STTError | null = null,\n drain: boolean = false,\n ): Promise<void> {\n if (this.rootSpanContext) {\n return otelContext.with(this.rootSpanContext, async () => {\n await this.closeImplInner(reason, error, drain);\n });\n }\n\n return this.closeImplInner(reason, error, drain);\n }\n\n private async closeImplInner(\n reason: CloseReason,\n error: RealtimeModelError | LLMError | TTSError | STTError | null = null,\n drain: boolean = false,\n ): Promise<void> {\n if (!this.started) {\n return;\n }\n\n this._cancelUserAwayTimer();\n this.off(AgentSessionEventTypes.UserInputTranscribed, this._onUserInputTranscribed);\n\n if (this.activity) {\n if (!drain) {\n try {\n this.activity.interrupt();\n } catch (error) {\n // TODO(shubhra): force interrupt or wait for it to finish?\n // it might be an audio played from the error callback\n }\n }\n await this.activity.drain();\n // wait any uninterruptible speech to finish\n await this.activity.currentSpeech?.waitForPlayout();\n this.activity.detachAudioInput();\n }\n\n // detach the inputs and outputs\n this.input.audio = null;\n this.output.audio = null;\n this.output.transcription = null;\n\n await this.roomIO?.close();\n this.roomIO = undefined;\n\n await this.activity?.close();\n this.activity = undefined;\n\n if (this.sessionSpan) {\n this.sessionSpan.end();\n this.sessionSpan = undefined;\n }\n\n if (this.userSpeakingSpan) {\n this.userSpeakingSpan.end();\n this.userSpeakingSpan = undefined;\n }\n\n if (this.agentSpeakingSpan) {\n this.agentSpeakingSpan.end();\n this.agentSpeakingSpan = undefined;\n }\n\n this.started = false;\n\n this.emit(AgentSessionEventTypes.Close, createCloseEvent(reason, error));\n\n this.userState = 'listening';\n this._agentState = 'initializing';\n this.rootSpanContext = undefined;\n\n this.logger.info({ reason, error }, 'AgentSession closed');\n }\n}\n"],"mappings":"AAMA,SAAS,cAAc,WAAW,aAAa,aAAa;AAC5D,SAAS,oBAAoB;AAE7B;AAAA,EACE,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,OAIF;AACP,SAAS,qBAAqB;AAE9B,SAAS,kBAAkB,aAAa,mBAAmB;AAG3D,SAAS,WAAW;AAGpB,SAAS,YAAY,cAAc;AAInC,SAAS,qBAAqB;AAE9B;AAAA,EAEE;AAAA,EAIA;AAAA,EASA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,YAAY,mBAAmB;AACxC,SAAS,cAA6D;AAgBtE,MAAM,sBAAoC;AAAA,EACxC,oBAAoB;AAAA,EACpB,+BAA+B;AAAA,EAC/B,yBAAyB;AAAA,EACzB,sBAAsB;AAAA,EACtB,qBAAqB;AAAA,EACrB,qBAAqB;AAAA,EACrB,cAAc;AAAA,EACd,sBAAsB;AAAA,EACtB,iBAAiB;AACnB;AA0BO,MAAM,qBAEF,aAA+D;AAAA,EACxE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAES;AAAA,EAED;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,YAAuB;AAAA,EAEvB;AAAA,EACA,SAAS,IAAI;AAAA,EAEb;AAAA,EACA;AAAA,EACA,cAA0B;AAAA,EAE1B;AAAA,EACA;AAAA,EAEA,cAAoC;AAAA,EACpC,gBAAuC;AAAA,EAEvC;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGR;AAAA;AAAA,EAGA,kBAAgC,CAAC;AAAA;AAAA,EAGjC,mBAAmB;AAAA;AAAA,EAGnB;AAAA,EAEA,YAAY,MAAqC;AAC/C,UAAM;AAEN,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,eAAe;AAAA,IACjB,IAAI;AAEJ,SAAK,MAAM;AAEX,QAAI,OAAO,QAAQ,UAAU;AAC3B,WAAK,MAAM,aAAa,gBAAgB,GAAG;AAAA,IAC7C,OAAO;AACL,WAAK,MAAM;AAAA,IACb;AAEA,QAAI,OAAO,QAAQ,UAAU;AAC3B,WAAK,MAAM,aAAa,gBAAgB,GAAG;AAAA,IAC7C,OAAO;AACL,WAAK,MAAM;AAAA,IACb;AAEA,QAAI,OAAO,QAAQ,UAAU;AAC3B,WAAK,MAAM,aAAa,gBAAgB,GAAG;AAAA,IAC7C,OAAO;AACL,WAAK,MAAM;AAAA,IACb;AAEA,SAAK,gBAAgB;AACrB,SAAK,YAAY;AAGjB,SAAK,SAAS,IAAI,WAAW,KAAK,mBAAmB;AACrD,SAAK,UAAU,IAAI,YAAY,KAAK,sBAAsB,KAAK,mBAAmB;AAGlF,SAAK,WAAW,YAAY,MAAM;AAClC,SAAK,UAAU,EAAE,GAAG,qBAAqB,GAAG,aAAa;AAEzD,SAAK,0BAA0B,KAAK,wBAAwB,KAAK,IAAI;AACrE,SAAK,GAAG,uBAAuB,sBAAsB,KAAK,uBAAuB;AAAA,EACnF;AAAA,EAEA,KACE,UACG,MACM;AACT,UAAM,YAAY,KAAK,CAAC;AACxB,SAAK,gBAAgB,KAAK,SAAS;AACnC,WAAO,MAAM,KAAK,OAAO,GAAG,IAAI;AAAA,EAClC;AAAA,EAEA,IAAI,QAAoB;AACtB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,SAAsB;AACxB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,WAAqB;AACvB,QAAI,KAAK,cAAc,QAAW;AAChC,YAAM,IAAI,MAAM,iCAAiC;AAAA,IACnD;AAEA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,UAAuB;AACzB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,SAAS,OAAiB;AAC5B,SAAK,YAAY;AAAA,EACnB;AAAA,EAEA,MAAc,WAAW;AAAA,IACvB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAOkB;AAChB,SAAK,aAAa,WAAW,kBAAkB,MAAM,EAAE;AAEvD,SAAK,QAAQ;AACb,SAAK,kBAAkB,cAAc;AAErC,UAAM,QAAyB,CAAC;AAEhC,QAAI,KAAK,MAAM,UAAS,6CAAc,kBAAiB,OAAO;AAC5D,WAAK,OAAO,KAAK,0EAA0E;AAAA,IAC7F;AAEA,QAAI,KAAK,OAAO,UAAS,+CAAe,kBAAiB,OAAO;AAC9D,WAAK,OAAO;AAAA,QACV;AAAA,MACF;AAAA,IACF;AAEA,QAAI,KAAK,OAAO,kBAAiB,+CAAe,0BAAyB,OAAO;AAC9E,WAAK,OAAO;AAAA,QACV;AAAA,MACF;AAAA,IACF;AAEA,SAAK,SAAS,IAAI,OAAO;AAAA,MACvB,cAAc;AAAA,MACd;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AACD,SAAK,OAAO,MAAM;AAElB,UAAM,MAAM,cAAc;AAC1B,QAAI,OAAO,IAAI,SAAS,QAAQ,CAAC,KAAK,aAAa;AACjD,WAAK,OAAO,MAAM,yCAAyC;AAC3D,YAAM,KAAK,IAAI,QAAQ,CAAC;AAAA,IAC1B;AAEA,QAAI,QAAQ;AACV,UAAI,IAAI,yBAAyB,QAAW;AAC1C,YAAI,uBAAuB;AAAA,MAC7B,OAAO;AACL,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,UAAM,KAAK,KAAK,eAAe,KAAK,KAAK,CAAC;AAE1C,UAAM,QAAQ,WAAW,KAAK;AAG9B,SAAK,OAAO;AAAA,MACV,mBAAmB,KAAK,MAAM,QAAQ,MAAM,KAAK,MAAM,MAAM,YAAY,OAAO,MAAM,QAAQ,2BAA2B,KAAK,OAAO,QAAQ,MAAM,KAAK,OAAO,MAAM,YAAY,OAAO,MAAM,QAAQ;AAAA,IACxM;AAEA,SAAK,OAAO;AAAA,MACV,4CAA4C,KAAK,OAAO,gBAAgB,MAAM,KAAK,OAAO,cAAc,YAAY,OAAO,MAAM,QAAQ;AAAA,IAC3I;AAEA,SAAK,UAAU;AACf,SAAK,aAAa,KAAK,IAAI;AAC3B,SAAK,kBAAkB,WAAW;AAAA,EACpC;AAAA,EAEA,MAAM,MAAM;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAMkB;AAChB,QAAI,KAAK,SAAS;AAChB;AAAA,IACF;AAEA,UAAM,MAAM,cAAc;AAE1B,SAAK,OAAO;AAAA,MACV,EAAE,QAAQ,iBAAiB,IAAI,KAAK,IAAI,gBAAgB;AAAA,MACxD;AAAA,IACF;AAEA,aAAS,UAAU,IAAI,KAAK,IAAI;AAChC,SAAK,mBAAmB;AAExB,QAAI,KAAK,kBAAkB;AACzB,YAAM,IAAI,cAAc;AAAA,IAC1B;AAIA,SAAK,cAAc,OAAO,UAAU;AAAA,MAClC,MAAM;AAAA,MACN,SAAS;AAAA,IACX,CAAC;AAID,SAAK,kBAAkB,MAAM,QAAQ,cAAc,KAAK,WAAW;AAEnE,UAAM,KAAK,WAAW;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,MAAM,KAAK;AAAA,IACb,CAAC;AAAA,EACH;AAAA,EAEA,YAAY,OAAoB;AAC9B,SAAK,QAAQ;AAEb,QAAI,KAAK,SAAS;AAChB,WAAK,eAAe,KAAK;AAAA,IAC3B;AAAA,EACF;AAAA,EAEA,iBAAiB;AACf,QAAI,CAAC,KAAK,UAAU;AAClB,YAAM,IAAI,MAAM,6BAA6B;AAAA,IAC/C;AAEA,SAAK,SAAS,eAAe;AAAA,EAC/B;AAAA,EAEA,gBAAgB;AACd,QAAI,CAAC,KAAK,UAAU;AAClB,YAAM,IAAI,MAAM,6BAA6B;AAAA,IAC/C;AACA,SAAK,SAAS,cAAc;AAAA,EAC9B;AAAA,EAEA,IACE,MACA,SAKc;AACd,QAAI,CAAC,KAAK,UAAU;AAClB,YAAM,IAAI,MAAM,6BAA6B;AAAA,IAC/C;AAEA,WAAO,KAAK,SAAS,IAAI,MAAM,OAAO;AAAA,EACxC;AAAA,EAEA,YAAY;AACV,QAAI,CAAC,KAAK,UAAU;AAClB,YAAM,IAAI,MAAM,6BAA6B;AAAA,IAC/C;AACA,WAAO,KAAK,SAAS,UAAU;AAAA,EACjC;AAAA,EAEA,cAAc,SAKG;AACf,QAAI,CAAC,KAAK,UAAU;AAClB,YAAM,IAAI,MAAM,6BAA6B;AAAA,IAC/C;AAEA,UAAM,eAAc,mCAAS,aACzB,IAAI,YAAY;AAAA,MACd,MAAM;AAAA,MACN,SAAS,QAAQ;AAAA,IACnB,CAAC,IACD;AAEJ,QAAI,KAAK,SAAS,UAAU;AAC1B,UAAI,CAAC,KAAK,cAAc;AACtB,cAAM,IAAI,MAAM,qDAAqD;AAAA,MACvE;AACA,aAAO,KAAK,aAAa,cAAc,EAAE,aAAa,GAAG,QAAQ,CAAC;AAAA,IACpE;AAEA,WAAO,KAAK,SAAS,cAAc,EAAE,aAAa,GAAG,QAAQ,CAAC;AAAA,EAChE;AAAA,EAEA,MAAc,eAAe,OAA6B;AACxD,UAAM,iBAAiB,YAAY;AAEjC,WAAK,eAAe,IAAI,cAAc,OAAO,IAAI;AAEjD,YAAM,mBAAmB,KAAK;AAE9B,UAAI,KAAK,UAAU;AACjB,cAAM,KAAK,SAAS,MAAM;AAC1B,cAAM,KAAK,SAAS,MAAM;AAAA,MAC5B;AAEA,WAAK,WAAW,KAAK;AACrB,WAAK,eAAe;AAEpB,WAAK,SAAS;AAAA,QACZ,IAAI,iBAAiB;AAAA,UACnB,YAAY,qDAAkB,MAAM;AAAA,UACpC,YAAY,MAAM;AAAA,QACpB,CAAC;AAAA,MACH;AACA,WAAK,OAAO,MAAM,EAAE,kBAAkB,MAAM,GAAG,0CAA0C;AAEzF,YAAM,KAAK,SAAS,MAAM;AAE1B,UAAI,KAAK,OAAO,OAAO;AACrB,aAAK,SAAS,iBAAiB,KAAK,OAAO,MAAM,MAAM;AAAA,MACzD;AAAA,IACF;AAGA,QAAI,KAAK,iBAAiB;AACxB,aAAO,YAAY,KAAK,KAAK,iBAAiB,cAAc;AAAA,IAC9D;AAEA,WAAO,eAAe;AAAA,EACxB;AAAA,EAEA,IAAI,UAAuB;AACzB,WAAO,KAAK,SAAS,KAAK;AAAA,EAC5B;AAAA,EAEA,IAAI,aAAyB;AAC3B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,eAAsB;AACxB,QAAI,CAAC,KAAK,OAAO;AACf,YAAM,IAAI,MAAM,6BAA6B;AAAA,IAC/C;AAEA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,QAAuB;AAC3B,UAAM,KAAK,UAAU,YAAY,cAAc;AAAA,EACjD;AAAA;AAAA,EAGA,WAAW;AAAA,IACT;AAAA,IACA,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV,GAIS;AACP,QAAI,KAAK,aAAa;AACpB;AAAA,IACF;AACA,SAAK,UAAU,QAAQ,OAAO,KAAK;AAAA,EACrC;AAAA;AAAA,EAGA,SAAS,OAAkE;AACzE,QAAI,KAAK,eAAe,MAAM,aAAa;AACzC;AAAA,IACF;AAEA,SAAK,OAAO,MAAM,OAAO,oDAAoD;AAE7E,SAAK,eAAe,YAAY;AAC9B,YAAM,KAAK,UAAU,YAAY,OAAO,KAAK;AAAA,IAC/C,GAAG,EAAE,KAAK,MAAM;AACd,WAAK,cAAc;AAAA,IACrB,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,uBAAuB,MAAyB;AAC9C,SAAK,SAAS,OAAO,IAAI;AACzB,SAAK,KAAK,uBAAuB,uBAAuB,iCAAiC,IAAI,CAAC;AAAA,EAChG;AAAA;AAAA,EAGA,gBAAgB,OAAoD;AAClE,SAAK,SAAS,OAAO,KAAK;AAAA,EAC5B;AAAA;AAAA,EAGA,kBAAkB,OAAmB;AACnC,QAAI,KAAK,gBAAgB,OAAO;AAC9B;AAAA,IACF;AAEA,QAAI,UAAU,YAAY;AAGxB,UAAI,KAAK,sBAAsB,QAAW;AACxC,aAAK,oBAAoB,OAAO,UAAU;AAAA,UACxC,MAAM;AAAA,UACN,SAAS,KAAK;AAAA,QAChB,CAAC;AAAA,MAIH;AAAA,IACF,WAAW,KAAK,sBAAsB,QAAW;AAE/C,WAAK,kBAAkB,IAAI;AAC3B,WAAK,oBAAoB;AAAA,IAC3B;AAEA,UAAM,WAAW,KAAK;AACtB,SAAK,cAAc;AAGnB,QAAI,UAAU,eAAe,KAAK,cAAc,aAAa;AAC3D,WAAK,kBAAkB;AAAA,IACzB,OAAO;AACL,WAAK,qBAAqB;AAAA,IAC5B;AAEA,SAAK;AAAA,MACH,uBAAuB;AAAA,MACvB,6BAA6B,UAAU,KAAK;AAAA,IAC9C;AAAA,EACF;AAAA;AAAA,EAGA,iBAAiB,OAAkB,mBAA4B;AAC7D,QAAI,KAAK,cAAc,OAAO;AAC5B;AAAA,IACF;AAEA,QAAI,UAAU,cAAc,KAAK,qBAAqB,QAAW;AAC/D,WAAK,mBAAmB,OAAO,UAAU;AAAA,QACvC,MAAM;AAAA,QACN,SAAS,KAAK;AAAA,MAChB,CAAC;AAAA,IAIH,WAAW,KAAK,qBAAqB,QAAW;AAE9C,WAAK,iBAAiB,IAAI;AAC1B,WAAK,mBAAmB;AAAA,IAC1B;AAEA,UAAM,WAAW,KAAK;AACtB,SAAK,YAAY;AAGjB,QAAI,UAAU,eAAe,KAAK,gBAAgB,aAAa;AAC7D,WAAK,kBAAkB;AAAA,IACzB,OAAO;AACL,WAAK,qBAAqB;AAAA,IAC5B;AAEA,SAAK;AAAA,MACH,uBAAuB;AAAA,MACvB,4BAA4B,UAAU,KAAK;AAAA,IAC7C;AAAA,EACF;AAAA;AAAA,EAGQ,sBAA4B;AAClC,QAAI,CAAC,KAAK,SAAS;AACjB;AAAA,IACF;AAEA,QAAI,KAAK,YAAY,KAAK,OAAO,OAAO;AACtC,WAAK,SAAS,iBAAiB,KAAK,OAAO,MAAM,MAAM;AAAA,IACzD;AAAA,EACF;AAAA,EAEQ,uBAA6B;AAAA,EAAC;AAAA,EAE9B,sBAA4B;AAAA,EAAC;AAAA,EAE7B,oBAA0B;AAChC,SAAK,qBAAqB;AAE1B,QAAI,KAAK,QAAQ,oBAAoB,QAAQ,KAAK,QAAQ,oBAAoB,QAAW;AACvF;AAAA,IACF;AAEA,QAAI,KAAK,UAAU,CAAC,KAAK,OAAO,wBAAwB;AACtD;AAAA,IACF;AAEA,SAAK,gBAAgB,WAAW,MAAM;AACpC,WAAK,OAAO,MAAM,6BAA6B;AAC/C,WAAK,iBAAiB,MAAM;AAAA,IAC9B,GAAG,KAAK,QAAQ,kBAAkB,GAAI;AAAA,EACxC;AAAA,EAEQ,uBAA6B;AACnC,QAAI,KAAK,kBAAkB,MAAM;AAC/B,mBAAa,KAAK,aAAa;AAC/B,WAAK,gBAAgB;AAAA,IACvB;AAAA,EACF;AAAA,EAEQ,wBAAwB,IAAqC;AACnE,QAAI,KAAK,cAAc,UAAU,GAAG,SAAS;AAC3C,WAAK,OAAO,MAAM,mDAAmD;AACrE,WAAK,iBAAiB,WAAW;AAAA,IACnC;AAAA,EACF;AAAA,EAEA,MAAc,UACZ,QACA,QAAoE,MACpE,QAAiB,OACF;AACf,QAAI,KAAK,iBAAiB;AACxB,aAAO,YAAY,KAAK,KAAK,iBAAiB,YAAY;AACxD,cAAM,KAAK,eAAe,QAAQ,OAAO,KAAK;AAAA,MAChD,CAAC;AAAA,IACH;AAEA,WAAO,KAAK,eAAe,QAAQ,OAAO,KAAK;AAAA,EACjD;AAAA,EAEA,MAAc,eACZ,QACA,QAAoE,MACpE,QAAiB,OACF;AApqBnB;AAqqBI,QAAI,CAAC,KAAK,SAAS;AACjB;AAAA,IACF;AAEA,SAAK,qBAAqB;AAC1B,SAAK,IAAI,uBAAuB,sBAAsB,KAAK,uBAAuB;AAElF,QAAI,KAAK,UAAU;AACjB,UAAI,CAAC,OAAO;AACV,YAAI;AACF,eAAK,SAAS,UAAU;AAAA,QAC1B,SAASA,QAAO;AAAA,QAGhB;AAAA,MACF;AACA,YAAM,KAAK,SAAS,MAAM;AAE1B,cAAM,UAAK,SAAS,kBAAd,mBAA6B;AACnC,WAAK,SAAS,iBAAiB;AAAA,IACjC;AAGA,SAAK,MAAM,QAAQ;AACnB,SAAK,OAAO,QAAQ;AACpB,SAAK,OAAO,gBAAgB;AAE5B,YAAM,UAAK,WAAL,mBAAa;AACnB,SAAK,SAAS;AAEd,YAAM,UAAK,aAAL,mBAAe;AACrB,SAAK,WAAW;AAEhB,QAAI,KAAK,aAAa;AACpB,WAAK,YAAY,IAAI;AACrB,WAAK,cAAc;AAAA,IACrB;AAEA,QAAI,KAAK,kBAAkB;AACzB,WAAK,iBAAiB,IAAI;AAC1B,WAAK,mBAAmB;AAAA,IAC1B;AAEA,QAAI,KAAK,mBAAmB;AAC1B,WAAK,kBAAkB,IAAI;AAC3B,WAAK,oBAAoB;AAAA,IAC3B;AAEA,SAAK,UAAU;AAEf,SAAK,KAAK,uBAAuB,OAAO,iBAAiB,QAAQ,KAAK,CAAC;AAEvE,SAAK,YAAY;AACjB,SAAK,cAAc;AACnB,SAAK,kBAAkB;AAEvB,SAAK,OAAO,KAAK,EAAE,QAAQ,MAAM,GAAG,qBAAqB;AAAA,EAC3D;AACF;","names":["error"]}
1
+ {"version":3,"sources":["../../src/voice/agent_session.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { AudioFrame, Room } from '@livekit/rtc-node';\nimport type { TypedEventEmitter as TypedEmitter } from '@livekit/typed-emitter';\nimport type { Context, Span } from '@opentelemetry/api';\nimport { ROOT_CONTEXT, context as otelContext, trace } from '@opentelemetry/api';\nimport { EventEmitter } from 'node:events';\nimport type { ReadableStream } from 'node:stream/web';\nimport {\n LLM as InferenceLLM,\n STT as InferenceSTT,\n TTS as InferenceTTS,\n type LLMModels,\n type STTModelString,\n type TTSModelString,\n} from '../inference/index.js';\nimport { type JobContext, getJobContext } from '../job.js';\nimport type { FunctionCall, FunctionCallOutput } from '../llm/chat_context.js';\nimport { AgentHandoffItem, ChatContext, ChatMessage } from '../llm/chat_context.js';\nimport type { LLM, RealtimeModel, RealtimeModelError, ToolChoice } from '../llm/index.js';\nimport type { LLMError } from '../llm/llm.js';\nimport { log } from '../log.js';\nimport type { STT } from '../stt/index.js';\nimport type { STTError } from '../stt/stt.js';\nimport { traceTypes, tracer } from '../telemetry/index.js';\nimport type { TTS, TTSError } from '../tts/tts.js';\nimport {\n DEFAULT_API_CONNECT_OPTIONS,\n DEFAULT_SESSION_CONNECT_OPTIONS,\n type ResolvedSessionConnectOptions,\n type SessionConnectOptions,\n} from '../types.js';\nimport type { VAD } from '../vad.js';\nimport type { Agent } from './agent.js';\nimport { AgentActivity } from './agent_activity.js';\nimport type { _TurnDetector } from './audio_recognition.js';\nimport {\n type AgentEvent,\n AgentSessionEventTypes,\n type AgentState,\n type AgentStateChangedEvent,\n type CloseEvent,\n CloseReason,\n type ConversationItemAddedEvent,\n type ErrorEvent,\n type FunctionToolsExecutedEvent,\n type MetricsCollectedEvent,\n type ShutdownReason,\n type SpeechCreatedEvent,\n type UserInputTranscribedEvent,\n type UserState,\n type UserStateChangedEvent,\n createAgentStateChangedEvent,\n createCloseEvent,\n createConversationItemAddedEvent,\n createUserStateChangedEvent,\n} from './events.js';\nimport { AgentInput, AgentOutput } from './io.js';\nimport { RecorderIO } from './recorder_io/index.js';\nimport { RoomIO, type RoomInputOptions, type RoomOutputOptions } from './room_io/index.js';\nimport type { UnknownUserData } from './run_context.js';\nimport type { SpeechHandle } from './speech_handle.js';\n\nexport interface VoiceOptions {\n allowInterruptions: boolean;\n discardAudioIfUninterruptible: boolean;\n minInterruptionDuration: number;\n minInterruptionWords: number;\n minEndpointingDelay: number;\n maxEndpointingDelay: number;\n maxToolSteps: number;\n preemptiveGeneration: boolean;\n userAwayTimeout?: number | null;\n}\n\nconst defaultVoiceOptions: VoiceOptions = {\n allowInterruptions: true,\n discardAudioIfUninterruptible: true,\n minInterruptionDuration: 500,\n minInterruptionWords: 0,\n minEndpointingDelay: 500,\n maxEndpointingDelay: 6000,\n maxToolSteps: 3,\n preemptiveGeneration: false,\n userAwayTimeout: 15.0,\n} as const;\n\nexport type TurnDetectionMode = 'stt' | 'vad' | 'realtime_llm' | 'manual' | _TurnDetector;\n\nexport type AgentSessionCallbacks = {\n [AgentSessionEventTypes.UserInputTranscribed]: (ev: UserInputTranscribedEvent) => void;\n [AgentSessionEventTypes.AgentStateChanged]: (ev: AgentStateChangedEvent) => void;\n [AgentSessionEventTypes.UserStateChanged]: (ev: UserStateChangedEvent) => void;\n [AgentSessionEventTypes.ConversationItemAdded]: (ev: ConversationItemAddedEvent) => void;\n [AgentSessionEventTypes.FunctionToolsExecuted]: (ev: FunctionToolsExecutedEvent) => void;\n [AgentSessionEventTypes.MetricsCollected]: (ev: MetricsCollectedEvent) => void;\n [AgentSessionEventTypes.SpeechCreated]: (ev: SpeechCreatedEvent) => void;\n [AgentSessionEventTypes.Error]: (ev: ErrorEvent) => void;\n [AgentSessionEventTypes.Close]: (ev: CloseEvent) => void;\n};\n\nexport type AgentSessionOptions<UserData = UnknownUserData> = {\n turnDetection?: TurnDetectionMode;\n stt?: STT | STTModelString;\n vad?: VAD;\n llm?: LLM | RealtimeModel | LLMModels;\n tts?: TTS | TTSModelString;\n userData?: UserData;\n voiceOptions?: Partial<VoiceOptions>;\n connOptions?: SessionConnectOptions;\n};\n\nexport class AgentSession<\n UserData = UnknownUserData,\n> extends (EventEmitter as new () => TypedEmitter<AgentSessionCallbacks>) {\n vad?: VAD;\n stt?: STT;\n llm?: LLM | RealtimeModel;\n tts?: TTS;\n turnDetection?: TurnDetectionMode;\n\n readonly options: VoiceOptions;\n\n private agent?: Agent;\n private activity?: AgentActivity;\n private nextActivity?: AgentActivity;\n private started = false;\n private userState: UserState = 'listening';\n\n private roomIO?: RoomIO;\n private logger = log();\n\n private _chatCtx: ChatContext;\n private _userData: UserData | undefined;\n private _agentState: AgentState = 'initializing';\n\n private _input: AgentInput;\n private _output: AgentOutput;\n\n private closingTask: Promise<void> | null = null;\n private userAwayTimer: NodeJS.Timeout | null = null;\n\n // Connection options for STT, LLM, and TTS\n private _connOptions: ResolvedSessionConnectOptions;\n\n // Unrecoverable error counts, reset after agent speaking\n private llmErrorCounts = 0;\n private ttsErrorCounts = 0;\n\n private sessionSpan?: Span;\n private userSpeakingSpan?: Span;\n private agentSpeakingSpan?: Span;\n\n /** @internal */\n _recorderIO?: RecorderIO;\n\n /** @internal */\n rootSpanContext?: Context;\n\n /** @internal */\n _recordedEvents: AgentEvent[] = [];\n\n /** @internal */\n _enableRecording = false;\n\n /** @internal - Timestamp when the session started (milliseconds) */\n _startedAt?: number;\n\n constructor(opts: AgentSessionOptions<UserData>) {\n super();\n\n const {\n vad,\n stt,\n llm,\n tts,\n turnDetection,\n userData,\n voiceOptions = defaultVoiceOptions,\n connOptions,\n } = opts;\n\n // Merge user-provided connOptions with defaults\n this._connOptions = {\n sttConnOptions: { ...DEFAULT_API_CONNECT_OPTIONS, ...connOptions?.sttConnOptions },\n llmConnOptions: { ...DEFAULT_API_CONNECT_OPTIONS, ...connOptions?.llmConnOptions },\n ttsConnOptions: { ...DEFAULT_API_CONNECT_OPTIONS, ...connOptions?.ttsConnOptions },\n maxUnrecoverableErrors:\n connOptions?.maxUnrecoverableErrors ??\n DEFAULT_SESSION_CONNECT_OPTIONS.maxUnrecoverableErrors,\n };\n\n this.vad = vad;\n\n if (typeof stt === 'string') {\n this.stt = InferenceSTT.fromModelString(stt);\n } else {\n this.stt = stt;\n }\n\n if (typeof llm === 'string') {\n this.llm = InferenceLLM.fromModelString(llm);\n } else {\n this.llm = llm;\n }\n\n if (typeof tts === 'string') {\n this.tts = InferenceTTS.fromModelString(tts);\n } else {\n this.tts = tts;\n }\n\n this.turnDetection = turnDetection;\n this._userData = userData;\n\n // configurable IO\n this._input = new AgentInput(this.onAudioInputChanged);\n this._output = new AgentOutput(this.onAudioOutputChanged, this.onTextOutputChanged);\n\n // This is the \"global\" chat context, it holds the entire conversation history\n this._chatCtx = ChatContext.empty();\n this.options = { ...defaultVoiceOptions, ...voiceOptions };\n\n this._onUserInputTranscribed = this._onUserInputTranscribed.bind(this);\n this.on(AgentSessionEventTypes.UserInputTranscribed, this._onUserInputTranscribed);\n }\n\n emit<K extends keyof AgentSessionCallbacks>(\n event: K,\n ...args: Parameters<AgentSessionCallbacks[K]>\n ): boolean {\n const eventData = args[0] as AgentEvent;\n this._recordedEvents.push(eventData);\n return super.emit(event, ...args);\n }\n\n get input(): AgentInput {\n return this._input;\n }\n\n get output(): AgentOutput {\n return this._output;\n }\n\n get userData(): UserData {\n if (this._userData === undefined) {\n throw new Error('Voice agent userData is not set');\n }\n\n return this._userData;\n }\n\n get history(): ChatContext {\n return this._chatCtx;\n }\n\n /** Connection options for STT, LLM, and TTS. */\n get connOptions(): ResolvedSessionConnectOptions {\n return this._connOptions;\n }\n\n set userData(value: UserData) {\n this._userData = value;\n }\n\n private async _startImpl({\n agent,\n room,\n inputOptions,\n outputOptions,\n span,\n }: {\n agent: Agent;\n room: Room;\n inputOptions?: Partial<RoomInputOptions>;\n outputOptions?: Partial<RoomOutputOptions>;\n span: Span;\n }): Promise<void> {\n span.setAttribute(traceTypes.ATTR_AGENT_LABEL, agent.id);\n\n this.agent = agent;\n this._updateAgentState('initializing');\n\n const tasks: Promise<void>[] = [];\n // Check for existing input/output configuration and warn if needed\n if (this.input.audio && inputOptions?.audioEnabled !== false) {\n this.logger.warn('RoomIO audio input is enabled but input.audio is already set, ignoring..');\n }\n\n if (this.output.audio && outputOptions?.audioEnabled !== false) {\n this.logger.warn(\n 'RoomIO audio output is enabled but output.audio is already set, ignoring..',\n );\n }\n\n if (this.output.transcription && outputOptions?.transcriptionEnabled !== false) {\n this.logger.warn(\n 'RoomIO transcription output is enabled but output.transcription is already set, ignoring..',\n );\n }\n\n this.roomIO = new RoomIO({\n agentSession: this,\n room,\n inputOptions,\n outputOptions,\n });\n this.roomIO.start();\n\n let ctx: JobContext | undefined = undefined;\n try {\n ctx = getJobContext();\n } catch (error) {\n // JobContext is not available in evals\n this.logger.warn('JobContext is not available');\n }\n\n if (ctx) {\n if (ctx.room === room && !room.isConnected) {\n this.logger.debug('Auto-connecting to room via job context');\n tasks.push(ctx.connect());\n }\n\n if (ctx._primaryAgentSession === undefined) {\n ctx._primaryAgentSession = this;\n } else if (this._enableRecording) {\n throw new Error(\n 'Only one `AgentSession` can be the primary at a time. If you want to ignore primary designation, use `session.start({ record: false })`.',\n );\n }\n\n if (this.input.audio && this.output.audio && this._enableRecording) {\n this._recorderIO = new RecorderIO({ agentSession: this });\n this.input.audio = this._recorderIO.recordInput(this.input.audio);\n this.output.audio = this._recorderIO.recordOutput(this.output.audio);\n\n // Start recording to session directory\n const sessionDir = ctx.sessionDirectory;\n if (sessionDir) {\n tasks.push(this._recorderIO.start(`${sessionDir}/audio.ogg`));\n }\n }\n }\n\n // TODO(AJS-265): add shutdown callback to job context\n tasks.push(this.updateActivity(this.agent));\n\n await Promise.allSettled(tasks);\n\n // Log used IO configuration\n this.logger.debug(\n `using audio io: ${this.input.audio ? '`' + this.input.audio.constructor.name + '`' : '(none)'} -> \\`AgentSession\\` -> ${this.output.audio ? '`' + this.output.audio.constructor.name + '`' : '(none)'}`,\n );\n\n this.logger.debug(\n `using transcript io: \\`AgentSession\\` -> ${this.output.transcription ? '`' + this.output.transcription.constructor.name + '`' : '(none)'}`,\n );\n\n this.started = true;\n this._startedAt = Date.now();\n this._updateAgentState('listening');\n }\n\n async start({\n agent,\n room,\n inputOptions,\n outputOptions,\n record,\n }: {\n agent: Agent;\n room: Room;\n inputOptions?: Partial<RoomInputOptions>;\n outputOptions?: Partial<RoomOutputOptions>;\n record?: boolean;\n }): Promise<void> {\n if (this.started) {\n return;\n }\n\n let ctx: JobContext | undefined = undefined;\n try {\n ctx = getJobContext();\n\n if (record === undefined) {\n record = ctx.job.enableRecording;\n }\n\n this._enableRecording = record;\n\n if (this._enableRecording) {\n ctx.initRecording();\n }\n } catch (error) {\n // JobContext is not available in evals\n this.logger.warn('JobContext is not available');\n }\n\n this.sessionSpan = tracer.startSpan({\n name: 'agent_session',\n context: ROOT_CONTEXT,\n });\n\n this.rootSpanContext = trace.setSpan(ROOT_CONTEXT, this.sessionSpan);\n\n await this._startImpl({\n agent,\n room,\n inputOptions,\n outputOptions,\n span: this.sessionSpan,\n });\n }\n\n updateAgent(agent: Agent): void {\n this.agent = agent;\n\n if (this.started) {\n this.updateActivity(agent);\n }\n }\n\n commitUserTurn() {\n if (!this.activity) {\n throw new Error('AgentSession is not running');\n }\n\n this.activity.commitUserTurn();\n }\n\n clearUserTurn() {\n if (!this.activity) {\n throw new Error('AgentSession is not running');\n }\n this.activity.clearUserTurn();\n }\n\n say(\n text: string | ReadableStream<string>,\n options?: {\n audio?: ReadableStream<AudioFrame>;\n allowInterruptions?: boolean;\n addToChatCtx?: boolean;\n },\n ): SpeechHandle {\n if (!this.activity) {\n throw new Error('AgentSession is not running');\n }\n\n const doSay = (activity: AgentActivity) => {\n return activity.say(text, options);\n };\n\n // attach to the session span if called outside of the AgentSession\n const activeSpan = trace.getActiveSpan();\n if (!activeSpan && this.rootSpanContext) {\n return otelContext.with(this.rootSpanContext, () => doSay(this.activity!));\n }\n\n return doSay(this.activity);\n }\n\n interrupt() {\n if (!this.activity) {\n throw new Error('AgentSession is not running');\n }\n return this.activity.interrupt();\n }\n\n generateReply(options?: {\n userInput?: string;\n instructions?: string;\n toolChoice?: ToolChoice;\n allowInterruptions?: boolean;\n }): SpeechHandle {\n if (!this.activity) {\n throw new Error('AgentSession is not running');\n }\n\n const userMessage = options?.userInput\n ? new ChatMessage({\n role: 'user',\n content: options.userInput,\n })\n : undefined;\n\n const doGenerateReply = (activity: AgentActivity, nextActivity?: AgentActivity) => {\n if (activity.draining) {\n if (!nextActivity) {\n throw new Error('AgentSession is closing, cannot use generateReply()');\n }\n return nextActivity.generateReply({ userMessage, ...options });\n }\n return activity.generateReply({ userMessage, ...options });\n };\n\n // attach to the session span if called outside of the AgentSession\n const activeSpan = trace.getActiveSpan();\n if (!activeSpan && this.rootSpanContext) {\n return otelContext.with(this.rootSpanContext, () =>\n doGenerateReply(this.activity!, this.nextActivity),\n );\n }\n\n return doGenerateReply(this.activity!, this.nextActivity);\n }\n\n private async updateActivity(agent: Agent): Promise<void> {\n const runWithContext = async () => {\n // TODO(AJS-129): add lock to agent activity core lifecycle\n this.nextActivity = new AgentActivity(agent, this);\n\n const previousActivity = this.activity;\n\n if (this.activity) {\n await this.activity.drain();\n await this.activity.close();\n }\n\n this.activity = this.nextActivity;\n this.nextActivity = undefined;\n\n this._chatCtx.insert(\n new AgentHandoffItem({\n oldAgentId: previousActivity?.agent.id,\n newAgentId: agent.id,\n }),\n );\n this.logger.debug({ previousActivity, agent }, 'Agent handoff inserted into chat context');\n\n await this.activity.start();\n\n if (this._input.audio) {\n this.activity.attachAudioInput(this._input.audio.stream);\n }\n };\n\n // Run within session span context if available\n if (this.rootSpanContext) {\n return otelContext.with(this.rootSpanContext, runWithContext);\n }\n\n return runWithContext();\n }\n\n get chatCtx(): ChatContext {\n return this._chatCtx.copy();\n }\n\n get agentState(): AgentState {\n return this._agentState;\n }\n\n get currentAgent(): Agent {\n if (!this.agent) {\n throw new Error('AgentSession is not running');\n }\n\n return this.agent;\n }\n\n async close(): Promise<void> {\n await this.closeImpl(CloseReason.USER_INITIATED);\n }\n\n shutdown(options?: { drain?: boolean; reason?: ShutdownReason }): void {\n const { drain = true, reason = CloseReason.USER_INITIATED } = options ?? {};\n\n this._closeSoon({\n reason,\n drain,\n });\n }\n\n /** @internal */\n _closeSoon({\n reason,\n drain = false,\n error = null,\n }: {\n reason: ShutdownReason;\n drain?: boolean;\n error?: RealtimeModelError | STTError | TTSError | LLMError | null;\n }): void {\n if (this.closingTask) {\n return;\n }\n this.closeImpl(reason, error, drain);\n }\n\n /** @internal */\n _onError(error: RealtimeModelError | STTError | TTSError | LLMError): void {\n if (this.closingTask || error.recoverable) {\n return;\n }\n\n // Track error counts per type to implement max_unrecoverable_errors logic\n if (error.type === 'llm_error') {\n this.llmErrorCounts += 1;\n if (this.llmErrorCounts <= this._connOptions.maxUnrecoverableErrors) {\n return;\n }\n } else if (error.type === 'tts_error') {\n this.ttsErrorCounts += 1;\n if (this.ttsErrorCounts <= this._connOptions.maxUnrecoverableErrors) {\n return;\n }\n }\n\n this.logger.error(error, 'AgentSession is closing due to unrecoverable error');\n\n this.closingTask = (async () => {\n await this.closeImpl(CloseReason.ERROR, error);\n })().then(() => {\n this.closingTask = null;\n });\n }\n\n /** @internal */\n _conversationItemAdded(item: ChatMessage): void {\n this._chatCtx.insert(item);\n this.emit(AgentSessionEventTypes.ConversationItemAdded, createConversationItemAddedEvent(item));\n }\n\n /** @internal */\n _toolItemsAdded(items: (FunctionCall | FunctionCallOutput)[]): void {\n this._chatCtx.insert(items);\n }\n\n /** @internal */\n _updateAgentState(state: AgentState) {\n if (this._agentState === state) {\n return;\n }\n\n if (state === 'speaking') {\n // Reset error counts when agent starts speaking\n this.llmErrorCounts = 0;\n this.ttsErrorCounts = 0;\n\n if (this.agentSpeakingSpan === undefined) {\n this.agentSpeakingSpan = tracer.startSpan({\n name: 'agent_speaking',\n context: this.rootSpanContext,\n });\n\n // TODO(brian): PR4 - Set participant attributes if roomIO.room.localParticipant is available\n // (Ref: Python agent_session.py line 1161-1164)\n }\n } else if (this.agentSpeakingSpan !== undefined) {\n // TODO(brian): PR4 - Set ATTR_END_TIME attribute if available\n this.agentSpeakingSpan.end();\n this.agentSpeakingSpan = undefined;\n }\n\n const oldState = this._agentState;\n this._agentState = state;\n\n // Handle user away timer based on state changes\n if (state === 'listening' && this.userState === 'listening') {\n this._setUserAwayTimer();\n } else {\n this._cancelUserAwayTimer();\n }\n\n this.emit(\n AgentSessionEventTypes.AgentStateChanged,\n createAgentStateChangedEvent(oldState, state),\n );\n }\n\n /** @internal */\n _updateUserState(state: UserState, _lastSpeakingTime?: number) {\n if (this.userState === state) {\n return;\n }\n\n if (state === 'speaking' && this.userSpeakingSpan === undefined) {\n this.userSpeakingSpan = tracer.startSpan({\n name: 'user_speaking',\n context: this.rootSpanContext,\n });\n\n // TODO(brian): PR4 - Set participant attributes if roomIO.linkedParticipant is available\n // (Ref: Python agent_session.py line 1192-1195)\n } else if (this.userSpeakingSpan !== undefined) {\n // TODO(brian): PR4 - Set ATTR_END_TIME attribute with lastSpeakingTime if available\n this.userSpeakingSpan.end();\n this.userSpeakingSpan = undefined;\n }\n\n const oldState = this.userState;\n this.userState = state;\n\n // Handle user away timer based on state changes\n if (state === 'listening' && this._agentState === 'listening') {\n this._setUserAwayTimer();\n } else {\n this._cancelUserAwayTimer();\n }\n\n this.emit(\n AgentSessionEventTypes.UserStateChanged,\n createUserStateChangedEvent(oldState, state),\n );\n }\n\n // -- User changed input/output streams/sinks --\n private onAudioInputChanged(): void {\n if (!this.started) {\n return;\n }\n\n if (this.activity && this._input.audio) {\n this.activity.attachAudioInput(this._input.audio.stream);\n }\n }\n\n private onAudioOutputChanged(): void {}\n\n private onTextOutputChanged(): void {}\n\n private _setUserAwayTimer(): void {\n this._cancelUserAwayTimer();\n\n if (this.options.userAwayTimeout === null || this.options.userAwayTimeout === undefined) {\n return;\n }\n\n if (this.roomIO && !this.roomIO.isParticipantAvailable) {\n return;\n }\n\n this.userAwayTimer = setTimeout(() => {\n this.logger.debug('User away timeout triggered');\n this._updateUserState('away');\n }, this.options.userAwayTimeout * 1000);\n }\n\n private _cancelUserAwayTimer(): void {\n if (this.userAwayTimer !== null) {\n clearTimeout(this.userAwayTimer);\n this.userAwayTimer = null;\n }\n }\n\n private _onUserInputTranscribed(ev: UserInputTranscribedEvent): void {\n if (this.userState === 'away' && ev.isFinal) {\n this.logger.debug('User returned from away state due to speech input');\n this._updateUserState('listening');\n }\n }\n\n private async closeImpl(\n reason: ShutdownReason,\n error: RealtimeModelError | LLMError | TTSError | STTError | null = null,\n drain: boolean = false,\n ): Promise<void> {\n if (this.rootSpanContext) {\n return otelContext.with(this.rootSpanContext, async () => {\n await this.closeImplInner(reason, error, drain);\n });\n }\n\n return this.closeImplInner(reason, error, drain);\n }\n\n private async closeImplInner(\n reason: ShutdownReason,\n error: RealtimeModelError | LLMError | TTSError | STTError | null = null,\n drain: boolean = false,\n ): Promise<void> {\n if (!this.started) {\n return;\n }\n\n this._cancelUserAwayTimer();\n this.off(AgentSessionEventTypes.UserInputTranscribed, this._onUserInputTranscribed);\n\n if (this.activity) {\n if (!drain) {\n try {\n this.activity.interrupt();\n } catch (error) {\n // TODO(shubhra): force interrupt or wait for it to finish?\n // it might be an audio played from the error callback\n }\n }\n await this.activity.drain();\n // wait any uninterruptible speech to finish\n await this.activity.currentSpeech?.waitForPlayout();\n try {\n this.activity.detachAudioInput();\n } catch (error) {\n // Ignore detach errors during cleanup - source may not have been set\n }\n }\n\n // Close recorder before detaching inputs/outputs (keep reference for session report)\n if (this._recorderIO) {\n await this._recorderIO.close();\n }\n\n // detach the inputs and outputs\n this.input.audio = null;\n this.output.audio = null;\n this.output.transcription = null;\n\n await this.roomIO?.close();\n this.roomIO = undefined;\n\n await this.activity?.close();\n this.activity = undefined;\n\n if (this.sessionSpan) {\n this.sessionSpan.end();\n this.sessionSpan = undefined;\n }\n\n if (this.userSpeakingSpan) {\n this.userSpeakingSpan.end();\n this.userSpeakingSpan = undefined;\n }\n\n if (this.agentSpeakingSpan) {\n this.agentSpeakingSpan.end();\n this.agentSpeakingSpan = undefined;\n }\n\n this.started = false;\n\n this.emit(AgentSessionEventTypes.Close, createCloseEvent(reason, error));\n\n this.userState = 'listening';\n this._agentState = 'initializing';\n this.rootSpanContext = undefined;\n this.llmErrorCounts = 0;\n this.ttsErrorCounts = 0;\n\n this.logger.info({ reason, error }, 'AgentSession closed');\n }\n}\n"],"mappings":"AAMA,SAAS,cAAc,WAAW,aAAa,aAAa;AAC5D,SAAS,oBAAoB;AAE7B;AAAA,EACE,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,OAIF;AACP,SAA0B,qBAAqB;AAE/C,SAAS,kBAAkB,aAAa,mBAAmB;AAG3D,SAAS,WAAW;AAGpB,SAAS,YAAY,cAAc;AAEnC;AAAA,EACE;AAAA,EACA;AAAA,OAGK;AAGP,SAAS,qBAAqB;AAE9B;AAAA,EAEE;AAAA,EAIA;AAAA,EAUA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,YAAY,mBAAmB;AACxC,SAAS,kBAAkB;AAC3B,SAAS,cAA6D;AAgBtE,MAAM,sBAAoC;AAAA,EACxC,oBAAoB;AAAA,EACpB,+BAA+B;AAAA,EAC/B,yBAAyB;AAAA,EACzB,sBAAsB;AAAA,EACtB,qBAAqB;AAAA,EACrB,qBAAqB;AAAA,EACrB,cAAc;AAAA,EACd,sBAAsB;AAAA,EACtB,iBAAiB;AACnB;AA2BO,MAAM,qBAEF,aAA+D;AAAA,EACxE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAES;AAAA,EAED;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,YAAuB;AAAA,EAEvB;AAAA,EACA,SAAS,IAAI;AAAA,EAEb;AAAA,EACA;AAAA,EACA,cAA0B;AAAA,EAE1B;AAAA,EACA;AAAA,EAEA,cAAoC;AAAA,EACpC,gBAAuC;AAAA;AAAA,EAGvC;AAAA;AAAA,EAGA,iBAAiB;AAAA,EACjB,iBAAiB;AAAA,EAEjB;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGR;AAAA;AAAA,EAGA;AAAA;AAAA,EAGA,kBAAgC,CAAC;AAAA;AAAA,EAGjC,mBAAmB;AAAA;AAAA,EAGnB;AAAA,EAEA,YAAY,MAAqC;AAC/C,UAAM;AAEN,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,eAAe;AAAA,MACf;AAAA,IACF,IAAI;AAGJ,SAAK,eAAe;AAAA,MAClB,gBAAgB,EAAE,GAAG,6BAA6B,GAAG,2CAAa,eAAe;AAAA,MACjF,gBAAgB,EAAE,GAAG,6BAA6B,GAAG,2CAAa,eAAe;AAAA,MACjF,gBAAgB,EAAE,GAAG,6BAA6B,GAAG,2CAAa,eAAe;AAAA,MACjF,yBACE,2CAAa,2BACb,gCAAgC;AAAA,IACpC;AAEA,SAAK,MAAM;AAEX,QAAI,OAAO,QAAQ,UAAU;AAC3B,WAAK,MAAM,aAAa,gBAAgB,GAAG;AAAA,IAC7C,OAAO;AACL,WAAK,MAAM;AAAA,IACb;AAEA,QAAI,OAAO,QAAQ,UAAU;AAC3B,WAAK,MAAM,aAAa,gBAAgB,GAAG;AAAA,IAC7C,OAAO;AACL,WAAK,MAAM;AAAA,IACb;AAEA,QAAI,OAAO,QAAQ,UAAU;AAC3B,WAAK,MAAM,aAAa,gBAAgB,GAAG;AAAA,IAC7C,OAAO;AACL,WAAK,MAAM;AAAA,IACb;AAEA,SAAK,gBAAgB;AACrB,SAAK,YAAY;AAGjB,SAAK,SAAS,IAAI,WAAW,KAAK,mBAAmB;AACrD,SAAK,UAAU,IAAI,YAAY,KAAK,sBAAsB,KAAK,mBAAmB;AAGlF,SAAK,WAAW,YAAY,MAAM;AAClC,SAAK,UAAU,EAAE,GAAG,qBAAqB,GAAG,aAAa;AAEzD,SAAK,0BAA0B,KAAK,wBAAwB,KAAK,IAAI;AACrE,SAAK,GAAG,uBAAuB,sBAAsB,KAAK,uBAAuB;AAAA,EACnF;AAAA,EAEA,KACE,UACG,MACM;AACT,UAAM,YAAY,KAAK,CAAC;AACxB,SAAK,gBAAgB,KAAK,SAAS;AACnC,WAAO,MAAM,KAAK,OAAO,GAAG,IAAI;AAAA,EAClC;AAAA,EAEA,IAAI,QAAoB;AACtB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,SAAsB;AACxB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,WAAqB;AACvB,QAAI,KAAK,cAAc,QAAW;AAChC,YAAM,IAAI,MAAM,iCAAiC;AAAA,IACnD;AAEA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,UAAuB;AACzB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,IAAI,cAA6C;AAC/C,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,SAAS,OAAiB;AAC5B,SAAK,YAAY;AAAA,EACnB;AAAA,EAEA,MAAc,WAAW;AAAA,IACvB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAMkB;AAChB,SAAK,aAAa,WAAW,kBAAkB,MAAM,EAAE;AAEvD,SAAK,QAAQ;AACb,SAAK,kBAAkB,cAAc;AAErC,UAAM,QAAyB,CAAC;AAEhC,QAAI,KAAK,MAAM,UAAS,6CAAc,kBAAiB,OAAO;AAC5D,WAAK,OAAO,KAAK,0EAA0E;AAAA,IAC7F;AAEA,QAAI,KAAK,OAAO,UAAS,+CAAe,kBAAiB,OAAO;AAC9D,WAAK,OAAO;AAAA,QACV;AAAA,MACF;AAAA,IACF;AAEA,QAAI,KAAK,OAAO,kBAAiB,+CAAe,0BAAyB,OAAO;AAC9E,WAAK,OAAO;AAAA,QACV;AAAA,MACF;AAAA,IACF;AAEA,SAAK,SAAS,IAAI,OAAO;AAAA,MACvB,cAAc;AAAA,MACd;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AACD,SAAK,OAAO,MAAM;AAElB,QAAI,MAA8B;AAClC,QAAI;AACF,YAAM,cAAc;AAAA,IACtB,SAAS,OAAO;AAEd,WAAK,OAAO,KAAK,6BAA6B;AAAA,IAChD;AAEA,QAAI,KAAK;AACP,UAAI,IAAI,SAAS,QAAQ,CAAC,KAAK,aAAa;AAC1C,aAAK,OAAO,MAAM,yCAAyC;AAC3D,cAAM,KAAK,IAAI,QAAQ,CAAC;AAAA,MAC1B;AAEA,UAAI,IAAI,yBAAyB,QAAW;AAC1C,YAAI,uBAAuB;AAAA,MAC7B,WAAW,KAAK,kBAAkB;AAChC,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAEA,UAAI,KAAK,MAAM,SAAS,KAAK,OAAO,SAAS,KAAK,kBAAkB;AAClE,aAAK,cAAc,IAAI,WAAW,EAAE,cAAc,KAAK,CAAC;AACxD,aAAK,MAAM,QAAQ,KAAK,YAAY,YAAY,KAAK,MAAM,KAAK;AAChE,aAAK,OAAO,QAAQ,KAAK,YAAY,aAAa,KAAK,OAAO,KAAK;AAGnE,cAAM,aAAa,IAAI;AACvB,YAAI,YAAY;AACd,gBAAM,KAAK,KAAK,YAAY,MAAM,GAAG,UAAU,YAAY,CAAC;AAAA,QAC9D;AAAA,MACF;AAAA,IACF;AAGA,UAAM,KAAK,KAAK,eAAe,KAAK,KAAK,CAAC;AAE1C,UAAM,QAAQ,WAAW,KAAK;AAG9B,SAAK,OAAO;AAAA,MACV,mBAAmB,KAAK,MAAM,QAAQ,MAAM,KAAK,MAAM,MAAM,YAAY,OAAO,MAAM,QAAQ,2BAA2B,KAAK,OAAO,QAAQ,MAAM,KAAK,OAAO,MAAM,YAAY,OAAO,MAAM,QAAQ;AAAA,IACxM;AAEA,SAAK,OAAO;AAAA,MACV,4CAA4C,KAAK,OAAO,gBAAgB,MAAM,KAAK,OAAO,cAAc,YAAY,OAAO,MAAM,QAAQ;AAAA,IAC3I;AAEA,SAAK,UAAU;AACf,SAAK,aAAa,KAAK,IAAI;AAC3B,SAAK,kBAAkB,WAAW;AAAA,EACpC;AAAA,EAEA,MAAM,MAAM;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAMkB;AAChB,QAAI,KAAK,SAAS;AAChB;AAAA,IACF;AAEA,QAAI,MAA8B;AAClC,QAAI;AACF,YAAM,cAAc;AAEpB,UAAI,WAAW,QAAW;AACxB,iBAAS,IAAI,IAAI;AAAA,MACnB;AAEA,WAAK,mBAAmB;AAExB,UAAI,KAAK,kBAAkB;AACzB,YAAI,cAAc;AAAA,MACpB;AAAA,IACF,SAAS,OAAO;AAEd,WAAK,OAAO,KAAK,6BAA6B;AAAA,IAChD;AAEA,SAAK,cAAc,OAAO,UAAU;AAAA,MAClC,MAAM;AAAA,MACN,SAAS;AAAA,IACX,CAAC;AAED,SAAK,kBAAkB,MAAM,QAAQ,cAAc,KAAK,WAAW;AAEnE,UAAM,KAAK,WAAW;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,MAAM,KAAK;AAAA,IACb,CAAC;AAAA,EACH;AAAA,EAEA,YAAY,OAAoB;AAC9B,SAAK,QAAQ;AAEb,QAAI,KAAK,SAAS;AAChB,WAAK,eAAe,KAAK;AAAA,IAC3B;AAAA,EACF;AAAA,EAEA,iBAAiB;AACf,QAAI,CAAC,KAAK,UAAU;AAClB,YAAM,IAAI,MAAM,6BAA6B;AAAA,IAC/C;AAEA,SAAK,SAAS,eAAe;AAAA,EAC/B;AAAA,EAEA,gBAAgB;AACd,QAAI,CAAC,KAAK,UAAU;AAClB,YAAM,IAAI,MAAM,6BAA6B;AAAA,IAC/C;AACA,SAAK,SAAS,cAAc;AAAA,EAC9B;AAAA,EAEA,IACE,MACA,SAKc;AACd,QAAI,CAAC,KAAK,UAAU;AAClB,YAAM,IAAI,MAAM,6BAA6B;AAAA,IAC/C;AAEA,UAAM,QAAQ,CAAC,aAA4B;AACzC,aAAO,SAAS,IAAI,MAAM,OAAO;AAAA,IACnC;AAGA,UAAM,aAAa,MAAM,cAAc;AACvC,QAAI,CAAC,cAAc,KAAK,iBAAiB;AACvC,aAAO,YAAY,KAAK,KAAK,iBAAiB,MAAM,MAAM,KAAK,QAAS,CAAC;AAAA,IAC3E;AAEA,WAAO,MAAM,KAAK,QAAQ;AAAA,EAC5B;AAAA,EAEA,YAAY;AACV,QAAI,CAAC,KAAK,UAAU;AAClB,YAAM,IAAI,MAAM,6BAA6B;AAAA,IAC/C;AACA,WAAO,KAAK,SAAS,UAAU;AAAA,EACjC;AAAA,EAEA,cAAc,SAKG;AACf,QAAI,CAAC,KAAK,UAAU;AAClB,YAAM,IAAI,MAAM,6BAA6B;AAAA,IAC/C;AAEA,UAAM,eAAc,mCAAS,aACzB,IAAI,YAAY;AAAA,MACd,MAAM;AAAA,MACN,SAAS,QAAQ;AAAA,IACnB,CAAC,IACD;AAEJ,UAAM,kBAAkB,CAAC,UAAyB,iBAAiC;AACjF,UAAI,SAAS,UAAU;AACrB,YAAI,CAAC,cAAc;AACjB,gBAAM,IAAI,MAAM,qDAAqD;AAAA,QACvE;AACA,eAAO,aAAa,cAAc,EAAE,aAAa,GAAG,QAAQ,CAAC;AAAA,MAC/D;AACA,aAAO,SAAS,cAAc,EAAE,aAAa,GAAG,QAAQ,CAAC;AAAA,IAC3D;AAGA,UAAM,aAAa,MAAM,cAAc;AACvC,QAAI,CAAC,cAAc,KAAK,iBAAiB;AACvC,aAAO,YAAY;AAAA,QAAK,KAAK;AAAA,QAAiB,MAC5C,gBAAgB,KAAK,UAAW,KAAK,YAAY;AAAA,MACnD;AAAA,IACF;AAEA,WAAO,gBAAgB,KAAK,UAAW,KAAK,YAAY;AAAA,EAC1D;AAAA,EAEA,MAAc,eAAe,OAA6B;AACxD,UAAM,iBAAiB,YAAY;AAEjC,WAAK,eAAe,IAAI,cAAc,OAAO,IAAI;AAEjD,YAAM,mBAAmB,KAAK;AAE9B,UAAI,KAAK,UAAU;AACjB,cAAM,KAAK,SAAS,MAAM;AAC1B,cAAM,KAAK,SAAS,MAAM;AAAA,MAC5B;AAEA,WAAK,WAAW,KAAK;AACrB,WAAK,eAAe;AAEpB,WAAK,SAAS;AAAA,QACZ,IAAI,iBAAiB;AAAA,UACnB,YAAY,qDAAkB,MAAM;AAAA,UACpC,YAAY,MAAM;AAAA,QACpB,CAAC;AAAA,MACH;AACA,WAAK,OAAO,MAAM,EAAE,kBAAkB,MAAM,GAAG,0CAA0C;AAEzF,YAAM,KAAK,SAAS,MAAM;AAE1B,UAAI,KAAK,OAAO,OAAO;AACrB,aAAK,SAAS,iBAAiB,KAAK,OAAO,MAAM,MAAM;AAAA,MACzD;AAAA,IACF;AAGA,QAAI,KAAK,iBAAiB;AACxB,aAAO,YAAY,KAAK,KAAK,iBAAiB,cAAc;AAAA,IAC9D;AAEA,WAAO,eAAe;AAAA,EACxB;AAAA,EAEA,IAAI,UAAuB;AACzB,WAAO,KAAK,SAAS,KAAK;AAAA,EAC5B;AAAA,EAEA,IAAI,aAAyB;AAC3B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,eAAsB;AACxB,QAAI,CAAC,KAAK,OAAO;AACf,YAAM,IAAI,MAAM,6BAA6B;AAAA,IAC/C;AAEA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,QAAuB;AAC3B,UAAM,KAAK,UAAU,YAAY,cAAc;AAAA,EACjD;AAAA,EAEA,SAAS,SAA8D;AACrE,UAAM,EAAE,QAAQ,MAAM,SAAS,YAAY,eAAe,IAAI,WAAW,CAAC;AAE1E,SAAK,WAAW;AAAA,MACd;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,WAAW;AAAA,IACT;AAAA,IACA,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV,GAIS;AACP,QAAI,KAAK,aAAa;AACpB;AAAA,IACF;AACA,SAAK,UAAU,QAAQ,OAAO,KAAK;AAAA,EACrC;AAAA;AAAA,EAGA,SAAS,OAAkE;AACzE,QAAI,KAAK,eAAe,MAAM,aAAa;AACzC;AAAA,IACF;AAGA,QAAI,MAAM,SAAS,aAAa;AAC9B,WAAK,kBAAkB;AACvB,UAAI,KAAK,kBAAkB,KAAK,aAAa,wBAAwB;AACnE;AAAA,MACF;AAAA,IACF,WAAW,MAAM,SAAS,aAAa;AACrC,WAAK,kBAAkB;AACvB,UAAI,KAAK,kBAAkB,KAAK,aAAa,wBAAwB;AACnE;AAAA,MACF;AAAA,IACF;AAEA,SAAK,OAAO,MAAM,OAAO,oDAAoD;AAE7E,SAAK,eAAe,YAAY;AAC9B,YAAM,KAAK,UAAU,YAAY,OAAO,KAAK;AAAA,IAC/C,GAAG,EAAE,KAAK,MAAM;AACd,WAAK,cAAc;AAAA,IACrB,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,uBAAuB,MAAyB;AAC9C,SAAK,SAAS,OAAO,IAAI;AACzB,SAAK,KAAK,uBAAuB,uBAAuB,iCAAiC,IAAI,CAAC;AAAA,EAChG;AAAA;AAAA,EAGA,gBAAgB,OAAoD;AAClE,SAAK,SAAS,OAAO,KAAK;AAAA,EAC5B;AAAA;AAAA,EAGA,kBAAkB,OAAmB;AACnC,QAAI,KAAK,gBAAgB,OAAO;AAC9B;AAAA,IACF;AAEA,QAAI,UAAU,YAAY;AAExB,WAAK,iBAAiB;AACtB,WAAK,iBAAiB;AAEtB,UAAI,KAAK,sBAAsB,QAAW;AACxC,aAAK,oBAAoB,OAAO,UAAU;AAAA,UACxC,MAAM;AAAA,UACN,SAAS,KAAK;AAAA,QAChB,CAAC;AAAA,MAIH;AAAA,IACF,WAAW,KAAK,sBAAsB,QAAW;AAE/C,WAAK,kBAAkB,IAAI;AAC3B,WAAK,oBAAoB;AAAA,IAC3B;AAEA,UAAM,WAAW,KAAK;AACtB,SAAK,cAAc;AAGnB,QAAI,UAAU,eAAe,KAAK,cAAc,aAAa;AAC3D,WAAK,kBAAkB;AAAA,IACzB,OAAO;AACL,WAAK,qBAAqB;AAAA,IAC5B;AAEA,SAAK;AAAA,MACH,uBAAuB;AAAA,MACvB,6BAA6B,UAAU,KAAK;AAAA,IAC9C;AAAA,EACF;AAAA;AAAA,EAGA,iBAAiB,OAAkB,mBAA4B;AAC7D,QAAI,KAAK,cAAc,OAAO;AAC5B;AAAA,IACF;AAEA,QAAI,UAAU,cAAc,KAAK,qBAAqB,QAAW;AAC/D,WAAK,mBAAmB,OAAO,UAAU;AAAA,QACvC,MAAM;AAAA,QACN,SAAS,KAAK;AAAA,MAChB,CAAC;AAAA,IAIH,WAAW,KAAK,qBAAqB,QAAW;AAE9C,WAAK,iBAAiB,IAAI;AAC1B,WAAK,mBAAmB;AAAA,IAC1B;AAEA,UAAM,WAAW,KAAK;AACtB,SAAK,YAAY;AAGjB,QAAI,UAAU,eAAe,KAAK,gBAAgB,aAAa;AAC7D,WAAK,kBAAkB;AAAA,IACzB,OAAO;AACL,WAAK,qBAAqB;AAAA,IAC5B;AAEA,SAAK;AAAA,MACH,uBAAuB;AAAA,MACvB,4BAA4B,UAAU,KAAK;AAAA,IAC7C;AAAA,EACF;AAAA;AAAA,EAGQ,sBAA4B;AAClC,QAAI,CAAC,KAAK,SAAS;AACjB;AAAA,IACF;AAEA,QAAI,KAAK,YAAY,KAAK,OAAO,OAAO;AACtC,WAAK,SAAS,iBAAiB,KAAK,OAAO,MAAM,MAAM;AAAA,IACzD;AAAA,EACF;AAAA,EAEQ,uBAA6B;AAAA,EAAC;AAAA,EAE9B,sBAA4B;AAAA,EAAC;AAAA,EAE7B,oBAA0B;AAChC,SAAK,qBAAqB;AAE1B,QAAI,KAAK,QAAQ,oBAAoB,QAAQ,KAAK,QAAQ,oBAAoB,QAAW;AACvF;AAAA,IACF;AAEA,QAAI,KAAK,UAAU,CAAC,KAAK,OAAO,wBAAwB;AACtD;AAAA,IACF;AAEA,SAAK,gBAAgB,WAAW,MAAM;AACpC,WAAK,OAAO,MAAM,6BAA6B;AAC/C,WAAK,iBAAiB,MAAM;AAAA,IAC9B,GAAG,KAAK,QAAQ,kBAAkB,GAAI;AAAA,EACxC;AAAA,EAEQ,uBAA6B;AACnC,QAAI,KAAK,kBAAkB,MAAM;AAC/B,mBAAa,KAAK,aAAa;AAC/B,WAAK,gBAAgB;AAAA,IACvB;AAAA,EACF;AAAA,EAEQ,wBAAwB,IAAqC;AACnE,QAAI,KAAK,cAAc,UAAU,GAAG,SAAS;AAC3C,WAAK,OAAO,MAAM,mDAAmD;AACrE,WAAK,iBAAiB,WAAW;AAAA,IACnC;AAAA,EACF;AAAA,EAEA,MAAc,UACZ,QACA,QAAoE,MACpE,QAAiB,OACF;AACf,QAAI,KAAK,iBAAiB;AACxB,aAAO,YAAY,KAAK,KAAK,iBAAiB,YAAY;AACxD,cAAM,KAAK,eAAe,QAAQ,OAAO,KAAK;AAAA,MAChD,CAAC;AAAA,IACH;AAEA,WAAO,KAAK,eAAe,QAAQ,OAAO,KAAK;AAAA,EACjD;AAAA,EAEA,MAAc,eACZ,QACA,QAAoE,MACpE,QAAiB,OACF;AApwBnB;AAqwBI,QAAI,CAAC,KAAK,SAAS;AACjB;AAAA,IACF;AAEA,SAAK,qBAAqB;AAC1B,SAAK,IAAI,uBAAuB,sBAAsB,KAAK,uBAAuB;AAElF,QAAI,KAAK,UAAU;AACjB,UAAI,CAAC,OAAO;AACV,YAAI;AACF,eAAK,SAAS,UAAU;AAAA,QAC1B,SAASA,QAAO;AAAA,QAGhB;AAAA,MACF;AACA,YAAM,KAAK,SAAS,MAAM;AAE1B,cAAM,UAAK,SAAS,kBAAd,mBAA6B;AACnC,UAAI;AACF,aAAK,SAAS,iBAAiB;AAAA,MACjC,SAASA,QAAO;AAAA,MAEhB;AAAA,IACF;AAGA,QAAI,KAAK,aAAa;AACpB,YAAM,KAAK,YAAY,MAAM;AAAA,IAC/B;AAGA,SAAK,MAAM,QAAQ;AACnB,SAAK,OAAO,QAAQ;AACpB,SAAK,OAAO,gBAAgB;AAE5B,YAAM,UAAK,WAAL,mBAAa;AACnB,SAAK,SAAS;AAEd,YAAM,UAAK,aAAL,mBAAe;AACrB,SAAK,WAAW;AAEhB,QAAI,KAAK,aAAa;AACpB,WAAK,YAAY,IAAI;AACrB,WAAK,cAAc;AAAA,IACrB;AAEA,QAAI,KAAK,kBAAkB;AACzB,WAAK,iBAAiB,IAAI;AAC1B,WAAK,mBAAmB;AAAA,IAC1B;AAEA,QAAI,KAAK,mBAAmB;AAC1B,WAAK,kBAAkB,IAAI;AAC3B,WAAK,oBAAoB;AAAA,IAC3B;AAEA,SAAK,UAAU;AAEf,SAAK,KAAK,uBAAuB,OAAO,iBAAiB,QAAQ,KAAK,CAAC;AAEvE,SAAK,YAAY;AACjB,SAAK,cAAc;AACnB,SAAK,kBAAkB;AACvB,SAAK,iBAAiB;AACtB,SAAK,iBAAiB;AAEtB,SAAK,OAAO,KAAK,EAAE,QAAQ,MAAM,GAAG,qBAAqB;AAAA,EAC3D;AACF;","names":["error"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/voice/events.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type {\n ChatMessage,\n FunctionCall,\n FunctionCallOutput,\n RealtimeModelError,\n} from '../llm/index.js';\nimport type { LLM, RealtimeModel } from '../llm/index.js';\nimport type { LLMError } from '../llm/llm.js';\nimport type { AgentMetrics } from '../metrics/base.js';\nimport type { STT } from '../stt/index.js';\nimport type { STTError } from '../stt/stt.js';\nimport type { TTS } from '../tts/index.js';\nimport type { TTSError } from '../tts/tts.js';\nimport type { SpeechHandle } from './speech_handle.js';\n\nexport enum AgentSessionEventTypes {\n UserInputTranscribed = 'user_input_transcribed',\n AgentStateChanged = 'agent_state_changed',\n UserStateChanged = 'user_state_changed',\n ConversationItemAdded = 'conversation_item_added',\n FunctionToolsExecuted = 'function_tools_executed',\n MetricsCollected = 'metrics_collected',\n SpeechCreated = 'speech_created',\n Error = 'error',\n Close = 'close',\n}\n\nexport type UserState = 'speaking' | 'listening' | 'away';\nexport type AgentState = 'initializing' | 'idle' | 'listening' | 'thinking' | 'speaking';\n\nexport enum CloseReason {\n ERROR = 'error',\n JOB_SHUTDOWN = 'job_shutdown',\n PARTICIPANT_DISCONNECTED = 'participant_disconnected',\n USER_INITIATED = 'user_initiated',\n}\n\nexport type SpeechSource = 'say' | 'generate_reply' | 'tool_response';\n\nexport type UserStateChangedEvent = {\n type: 'user_state_changed';\n oldState: UserState;\n newState: UserState;\n createdAt: number;\n};\n\nexport const createUserStateChangedEvent = (\n oldState: UserState,\n newState: UserState,\n createdAt: number = Date.now(),\n): UserStateChangedEvent => ({\n type: 'user_state_changed',\n oldState,\n newState,\n createdAt,\n});\n\nexport type AgentStateChangedEvent = {\n type: 'agent_state_changed';\n oldState: AgentState;\n newState: AgentState;\n createdAt: number;\n};\n\nexport const createAgentStateChangedEvent = (\n oldState: AgentState,\n newState: AgentState,\n createdAt: number = Date.now(),\n): AgentStateChangedEvent => ({\n type: 'agent_state_changed',\n oldState,\n newState,\n createdAt,\n});\n\nexport type UserInputTranscribedEvent = {\n type: 'user_input_transcribed';\n transcript: string;\n isFinal: boolean;\n // TODO(AJS-106): add multi participant support\n /** Not supported yet. Always null by default. */\n speakerId: string | null;\n createdAt: number;\n language: string | null;\n};\n\nexport const createUserInputTranscribedEvent = ({\n transcript,\n isFinal,\n speakerId = null,\n language = null,\n createdAt = Date.now(),\n}: {\n transcript: string;\n isFinal: boolean;\n speakerId?: string | null;\n language?: string | null;\n createdAt?: number;\n}): UserInputTranscribedEvent => ({\n type: 'user_input_transcribed',\n transcript,\n isFinal,\n speakerId,\n language,\n createdAt,\n});\n\nexport type MetricsCollectedEvent = {\n type: 'metrics_collected';\n metrics: AgentMetrics;\n createdAt: number;\n};\n\nexport const createMetricsCollectedEvent = ({\n metrics,\n createdAt = Date.now(),\n}: {\n metrics: AgentMetrics;\n createdAt?: number;\n}): MetricsCollectedEvent => ({\n type: 'metrics_collected',\n metrics,\n createdAt,\n});\n\nexport type ConversationItemAddedEvent = {\n type: 'conversation_item_added';\n item: ChatMessage;\n createdAt: number;\n};\n\nexport const createConversationItemAddedEvent = (\n item: ChatMessage,\n createdAt: number = Date.now(),\n): ConversationItemAddedEvent => ({\n type: 'conversation_item_added',\n item,\n createdAt,\n});\n\nexport type FunctionToolsExecutedEvent = {\n type: 'function_tools_executed';\n functionCalls: FunctionCall[];\n functionCallOutputs: FunctionCallOutput[];\n createdAt: number;\n};\n\nexport const createFunctionToolsExecutedEvent = ({\n functionCalls,\n functionCallOutputs,\n createdAt = Date.now(),\n}: {\n functionCalls: FunctionCall[];\n functionCallOutputs: FunctionCallOutput[];\n createdAt?: number;\n}): FunctionToolsExecutedEvent => {\n return {\n type: 'function_tools_executed',\n functionCalls,\n functionCallOutputs,\n createdAt,\n };\n};\n\nexport const zipFunctionCallsAndOutputs = (\n event: FunctionToolsExecutedEvent,\n): Array<[FunctionCall, FunctionCallOutput]> => {\n return event.functionCalls.map((call, index) => [call, event.functionCallOutputs[index]!]);\n};\n\nexport type SpeechCreatedEvent = {\n type: 'speech_created';\n /**\n * True if the speech was created using public methods like `say` or `generate_reply`\n */\n userInitiated: boolean;\n /**\n * Source indicating how the speech handle was created\n */\n source: SpeechSource;\n /**\n * The speech handle that was created\n */\n // TODO(shubhra): we need to make sure this doesn't get serialized\n speechHandle: SpeechHandle;\n /**\n * The timestamp when the speech handle was created\n */\n createdAt: number;\n};\n\nexport const createSpeechCreatedEvent = ({\n userInitiated,\n source,\n speechHandle,\n createdAt = Date.now(),\n}: {\n userInitiated: boolean;\n source: SpeechSource;\n speechHandle: SpeechHandle;\n createdAt?: number;\n}): SpeechCreatedEvent => ({\n type: 'speech_created',\n userInitiated,\n source,\n speechHandle,\n createdAt,\n});\n\nexport type ErrorEvent = {\n type: 'error';\n error: RealtimeModelError | STTError | TTSError | LLMError | unknown;\n source: LLM | STT | TTS | RealtimeModel | unknown;\n createdAt: number;\n};\n\nexport const createErrorEvent = (\n error: RealtimeModelError | STTError | TTSError | LLMError | unknown,\n source: LLM | STT | TTS | RealtimeModel | unknown,\n createdAt: number = Date.now(),\n): ErrorEvent => ({\n type: 'error',\n error,\n source,\n createdAt,\n});\n\nexport type CloseEvent = {\n type: 'close';\n error: RealtimeModelError | STTError | TTSError | LLMError | null;\n reason: CloseReason;\n createdAt: number;\n};\n\nexport const createCloseEvent = (\n reason: CloseReason,\n error: RealtimeModelError | STTError | TTSError | LLMError | null = null,\n createdAt: number = Date.now(),\n): CloseEvent => ({\n type: 'close',\n error,\n reason,\n createdAt,\n});\n\nexport type AgentEvent =\n | UserInputTranscribedEvent\n | UserStateChangedEvent\n | AgentStateChangedEvent\n | MetricsCollectedEvent\n | ConversationItemAddedEvent\n | FunctionToolsExecutedEvent\n | SpeechCreatedEvent\n | ErrorEvent\n | CloseEvent;\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAkBO,IAAK,yBAAL,kBAAKA,4BAAL;AACL,EAAAA,wBAAA,0BAAuB;AACvB,EAAAA,wBAAA,uBAAoB;AACpB,EAAAA,wBAAA,sBAAmB;AACnB,EAAAA,wBAAA,2BAAwB;AACxB,EAAAA,wBAAA,2BAAwB;AACxB,EAAAA,wBAAA,sBAAmB;AACnB,EAAAA,wBAAA,mBAAgB;AAChB,EAAAA,wBAAA,WAAQ;AACR,EAAAA,wBAAA,WAAQ;AATE,SAAAA;AAAA,GAAA;AAeL,IAAK,cAAL,kBAAKC,iBAAL;AACL,EAAAA,aAAA,WAAQ;AACR,EAAAA,aAAA,kBAAe;AACf,EAAAA,aAAA,8BAA2B;AAC3B,EAAAA,aAAA,oBAAiB;AAJP,SAAAA;AAAA,GAAA;AAgBL,MAAM,8BAA8B,CACzC,UACA,UACA,YAAoB,KAAK,IAAI,OACF;AAAA,EAC3B,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AACF;AASO,MAAM,+BAA+B,CAC1C,UACA,UACA,YAAoB,KAAK,IAAI,OACD;AAAA,EAC5B,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AACF;AAaO,MAAM,kCAAkC,CAAC;AAAA,EAC9C;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,YAAY,KAAK,IAAI;AACvB,OAMkC;AAAA,EAChC,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAQO,MAAM,8BAA8B,CAAC;AAAA,EAC1C;AAAA,EACA,YAAY,KAAK,IAAI;AACvB,OAG8B;AAAA,EAC5B,MAAM;AAAA,EACN;AAAA,EACA;AACF;AAQO,MAAM,mCAAmC,CAC9C,MACA,YAAoB,KAAK,IAAI,OACG;AAAA,EAChC,MAAM;AAAA,EACN;AAAA,EACA;AACF;AASO,MAAM,mCAAmC,CAAC;AAAA,EAC/C;AAAA,EACA;AAAA,EACA,YAAY,KAAK,IAAI;AACvB,MAIkC;AAChC,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEO,MAAM,6BAA6B,CACxC,UAC8C;AAC9C,SAAO,MAAM,cAAc,IAAI,CAAC,MAAM,UAAU,CAAC,MAAM,MAAM,oBAAoB,KAAK,CAAE,CAAC;AAC3F;AAuBO,MAAM,2BAA2B,CAAC;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY,KAAK,IAAI;AACvB,OAK2B;AAAA,EACzB,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AASO,MAAM,mBAAmB,CAC9B,OACA,QACA,YAAoB,KAAK,IAAI,OACb;AAAA,EAChB,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AACF;AASO,MAAM,mBAAmB,CAC9B,QACA,QAAoE,MACpE,YAAoB,KAAK,IAAI,OACb;AAAA,EAChB,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AACF;","names":["AgentSessionEventTypes","CloseReason"]}
1
+ {"version":3,"sources":["../../src/voice/events.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type {\n ChatMessage,\n FunctionCall,\n FunctionCallOutput,\n LLM,\n RealtimeModel,\n RealtimeModelError,\n} from '../llm/index.js';\nimport type { LLMError } from '../llm/llm.js';\nimport type { AgentMetrics } from '../metrics/base.js';\nimport type { STT } from '../stt/index.js';\nimport type { STTError } from '../stt/stt.js';\nimport type { TTS } from '../tts/index.js';\nimport type { TTSError } from '../tts/tts.js';\nimport type { SpeechHandle } from './speech_handle.js';\n\nexport enum AgentSessionEventTypes {\n UserInputTranscribed = 'user_input_transcribed',\n AgentStateChanged = 'agent_state_changed',\n UserStateChanged = 'user_state_changed',\n ConversationItemAdded = 'conversation_item_added',\n FunctionToolsExecuted = 'function_tools_executed',\n MetricsCollected = 'metrics_collected',\n SpeechCreated = 'speech_created',\n Error = 'error',\n Close = 'close',\n}\n\nexport type UserState = 'speaking' | 'listening' | 'away';\nexport type AgentState = 'initializing' | 'idle' | 'listening' | 'thinking' | 'speaking';\n\nexport enum CloseReason {\n ERROR = 'error',\n JOB_SHUTDOWN = 'job_shutdown',\n PARTICIPANT_DISCONNECTED = 'participant_disconnected',\n USER_INITIATED = 'user_initiated',\n}\n\nexport type ShutdownReason = CloseReason | string;\n\nexport type SpeechSource = 'say' | 'generate_reply' | 'tool_response';\n\nexport type UserStateChangedEvent = {\n type: 'user_state_changed';\n oldState: UserState;\n newState: UserState;\n createdAt: number;\n};\n\nexport const createUserStateChangedEvent = (\n oldState: UserState,\n newState: UserState,\n createdAt: number = Date.now(),\n): UserStateChangedEvent => ({\n type: 'user_state_changed',\n oldState,\n newState,\n createdAt,\n});\n\nexport type AgentStateChangedEvent = {\n type: 'agent_state_changed';\n oldState: AgentState;\n newState: AgentState;\n createdAt: number;\n};\n\nexport const createAgentStateChangedEvent = (\n oldState: AgentState,\n newState: AgentState,\n createdAt: number = Date.now(),\n): AgentStateChangedEvent => ({\n type: 'agent_state_changed',\n oldState,\n newState,\n createdAt,\n});\n\nexport type UserInputTranscribedEvent = {\n type: 'user_input_transcribed';\n transcript: string;\n isFinal: boolean;\n // TODO(AJS-106): add multi participant support\n /** Not supported yet. Always null by default. */\n speakerId: string | null;\n createdAt: number;\n language: string | null;\n};\n\nexport const createUserInputTranscribedEvent = ({\n transcript,\n isFinal,\n speakerId = null,\n language = null,\n createdAt = Date.now(),\n}: {\n transcript: string;\n isFinal: boolean;\n speakerId?: string | null;\n language?: string | null;\n createdAt?: number;\n}): UserInputTranscribedEvent => ({\n type: 'user_input_transcribed',\n transcript,\n isFinal,\n speakerId,\n language,\n createdAt,\n});\n\nexport type MetricsCollectedEvent = {\n type: 'metrics_collected';\n metrics: AgentMetrics;\n createdAt: number;\n};\n\nexport const createMetricsCollectedEvent = ({\n metrics,\n createdAt = Date.now(),\n}: {\n metrics: AgentMetrics;\n createdAt?: number;\n}): MetricsCollectedEvent => ({\n type: 'metrics_collected',\n metrics,\n createdAt,\n});\n\nexport type ConversationItemAddedEvent = {\n type: 'conversation_item_added';\n item: ChatMessage;\n createdAt: number;\n};\n\nexport const createConversationItemAddedEvent = (\n item: ChatMessage,\n createdAt: number = Date.now(),\n): ConversationItemAddedEvent => ({\n type: 'conversation_item_added',\n item,\n createdAt,\n});\n\nexport type FunctionToolsExecutedEvent = {\n type: 'function_tools_executed';\n functionCalls: FunctionCall[];\n functionCallOutputs: FunctionCallOutput[];\n createdAt: number;\n};\n\nexport const createFunctionToolsExecutedEvent = ({\n functionCalls,\n functionCallOutputs,\n createdAt = Date.now(),\n}: {\n functionCalls: FunctionCall[];\n functionCallOutputs: FunctionCallOutput[];\n createdAt?: number;\n}): FunctionToolsExecutedEvent => {\n return {\n type: 'function_tools_executed',\n functionCalls,\n functionCallOutputs,\n createdAt,\n };\n};\n\nexport const zipFunctionCallsAndOutputs = (\n event: FunctionToolsExecutedEvent,\n): Array<[FunctionCall, FunctionCallOutput]> => {\n return event.functionCalls.map((call, index) => [call, event.functionCallOutputs[index]!]);\n};\n\nexport type SpeechCreatedEvent = {\n type: 'speech_created';\n /**\n * True if the speech was created using public methods like `say` or `generate_reply`\n */\n userInitiated: boolean;\n /**\n * Source indicating how the speech handle was created\n */\n source: SpeechSource;\n /**\n * The speech handle that was created\n */\n // TODO(shubhra): we need to make sure this doesn't get serialized\n speechHandle: SpeechHandle;\n /**\n * The timestamp when the speech handle was created\n */\n createdAt: number;\n};\n\nexport const createSpeechCreatedEvent = ({\n userInitiated,\n source,\n speechHandle,\n createdAt = Date.now(),\n}: {\n userInitiated: boolean;\n source: SpeechSource;\n speechHandle: SpeechHandle;\n createdAt?: number;\n}): SpeechCreatedEvent => ({\n type: 'speech_created',\n userInitiated,\n source,\n speechHandle,\n createdAt,\n});\n\nexport type ErrorEvent = {\n type: 'error';\n error: RealtimeModelError | STTError | TTSError | LLMError | unknown;\n source: LLM | STT | TTS | RealtimeModel | unknown;\n createdAt: number;\n};\n\nexport const createErrorEvent = (\n error: RealtimeModelError | STTError | TTSError | LLMError | unknown,\n source: LLM | STT | TTS | RealtimeModel | unknown,\n createdAt: number = Date.now(),\n): ErrorEvent => ({\n type: 'error',\n error,\n source,\n createdAt,\n});\n\nexport type CloseEvent = {\n type: 'close';\n error: RealtimeModelError | STTError | TTSError | LLMError | null;\n reason: ShutdownReason;\n createdAt: number;\n};\n\nexport const createCloseEvent = (\n reason: ShutdownReason,\n error: RealtimeModelError | STTError | TTSError | LLMError | null = null,\n createdAt: number = Date.now(),\n): CloseEvent => ({\n type: 'close',\n error,\n reason,\n createdAt,\n});\n\nexport type AgentEvent =\n | UserInputTranscribedEvent\n | UserStateChangedEvent\n | AgentStateChangedEvent\n | MetricsCollectedEvent\n | ConversationItemAddedEvent\n | FunctionToolsExecutedEvent\n | SpeechCreatedEvent\n | ErrorEvent\n | CloseEvent;\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmBO,IAAK,yBAAL,kBAAKA,4BAAL;AACL,EAAAA,wBAAA,0BAAuB;AACvB,EAAAA,wBAAA,uBAAoB;AACpB,EAAAA,wBAAA,sBAAmB;AACnB,EAAAA,wBAAA,2BAAwB;AACxB,EAAAA,wBAAA,2BAAwB;AACxB,EAAAA,wBAAA,sBAAmB;AACnB,EAAAA,wBAAA,mBAAgB;AAChB,EAAAA,wBAAA,WAAQ;AACR,EAAAA,wBAAA,WAAQ;AATE,SAAAA;AAAA,GAAA;AAeL,IAAK,cAAL,kBAAKC,iBAAL;AACL,EAAAA,aAAA,WAAQ;AACR,EAAAA,aAAA,kBAAe;AACf,EAAAA,aAAA,8BAA2B;AAC3B,EAAAA,aAAA,oBAAiB;AAJP,SAAAA;AAAA,GAAA;AAkBL,MAAM,8BAA8B,CACzC,UACA,UACA,YAAoB,KAAK,IAAI,OACF;AAAA,EAC3B,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AACF;AASO,MAAM,+BAA+B,CAC1C,UACA,UACA,YAAoB,KAAK,IAAI,OACD;AAAA,EAC5B,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AACF;AAaO,MAAM,kCAAkC,CAAC;AAAA,EAC9C;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,YAAY,KAAK,IAAI;AACvB,OAMkC;AAAA,EAChC,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAQO,MAAM,8BAA8B,CAAC;AAAA,EAC1C;AAAA,EACA,YAAY,KAAK,IAAI;AACvB,OAG8B;AAAA,EAC5B,MAAM;AAAA,EACN;AAAA,EACA;AACF;AAQO,MAAM,mCAAmC,CAC9C,MACA,YAAoB,KAAK,IAAI,OACG;AAAA,EAChC,MAAM;AAAA,EACN;AAAA,EACA;AACF;AASO,MAAM,mCAAmC,CAAC;AAAA,EAC/C;AAAA,EACA;AAAA,EACA,YAAY,KAAK,IAAI;AACvB,MAIkC;AAChC,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEO,MAAM,6BAA6B,CACxC,UAC8C;AAC9C,SAAO,MAAM,cAAc,IAAI,CAAC,MAAM,UAAU,CAAC,MAAM,MAAM,oBAAoB,KAAK,CAAE,CAAC;AAC3F;AAuBO,MAAM,2BAA2B,CAAC;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY,KAAK,IAAI;AACvB,OAK2B;AAAA,EACzB,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AASO,MAAM,mBAAmB,CAC9B,OACA,QACA,YAAoB,KAAK,IAAI,OACb;AAAA,EAChB,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AACF;AASO,MAAM,mBAAmB,CAC9B,QACA,QAAoE,MACpE,YAAoB,KAAK,IAAI,OACb;AAAA,EAChB,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AACF;","names":["AgentSessionEventTypes","CloseReason"]}
@@ -1,5 +1,4 @@
1
- import type { ChatMessage, FunctionCall, FunctionCallOutput, RealtimeModelError } from '../llm/index.js';
2
- import type { LLM, RealtimeModel } from '../llm/index.js';
1
+ import type { ChatMessage, FunctionCall, FunctionCallOutput, LLM, RealtimeModel, RealtimeModelError } from '../llm/index.js';
3
2
  import type { LLMError } from '../llm/llm.js';
4
3
  import type { AgentMetrics } from '../metrics/base.js';
5
4
  import type { STT } from '../stt/index.js';
@@ -26,6 +25,7 @@ export declare enum CloseReason {
26
25
  PARTICIPANT_DISCONNECTED = "participant_disconnected",
27
26
  USER_INITIATED = "user_initiated"
28
27
  }
28
+ export type ShutdownReason = CloseReason | string;
29
29
  export type SpeechSource = 'say' | 'generate_reply' | 'tool_response';
30
30
  export type UserStateChangedEvent = {
31
31
  type: 'user_state_changed';
@@ -119,9 +119,9 @@ export declare const createErrorEvent: (error: RealtimeModelError | STTError | T
119
119
  export type CloseEvent = {
120
120
  type: 'close';
121
121
  error: RealtimeModelError | STTError | TTSError | LLMError | null;
122
- reason: CloseReason;
122
+ reason: ShutdownReason;
123
123
  createdAt: number;
124
124
  };
125
- export declare const createCloseEvent: (reason: CloseReason, error?: RealtimeModelError | STTError | TTSError | LLMError | null, createdAt?: number) => CloseEvent;
125
+ export declare const createCloseEvent: (reason: ShutdownReason, error?: RealtimeModelError | STTError | TTSError | LLMError | null, createdAt?: number) => CloseEvent;
126
126
  export type AgentEvent = UserInputTranscribedEvent | UserStateChangedEvent | AgentStateChangedEvent | MetricsCollectedEvent | ConversationItemAddedEvent | FunctionToolsExecutedEvent | SpeechCreatedEvent | ErrorEvent | CloseEvent;
127
127
  //# sourceMappingURL=events.d.ts.map
@@ -1,5 +1,4 @@
1
- import type { ChatMessage, FunctionCall, FunctionCallOutput, RealtimeModelError } from '../llm/index.js';
2
- import type { LLM, RealtimeModel } from '../llm/index.js';
1
+ import type { ChatMessage, FunctionCall, FunctionCallOutput, LLM, RealtimeModel, RealtimeModelError } from '../llm/index.js';
3
2
  import type { LLMError } from '../llm/llm.js';
4
3
  import type { AgentMetrics } from '../metrics/base.js';
5
4
  import type { STT } from '../stt/index.js';
@@ -26,6 +25,7 @@ export declare enum CloseReason {
26
25
  PARTICIPANT_DISCONNECTED = "participant_disconnected",
27
26
  USER_INITIATED = "user_initiated"
28
27
  }
28
+ export type ShutdownReason = CloseReason | string;
29
29
  export type SpeechSource = 'say' | 'generate_reply' | 'tool_response';
30
30
  export type UserStateChangedEvent = {
31
31
  type: 'user_state_changed';
@@ -119,9 +119,9 @@ export declare const createErrorEvent: (error: RealtimeModelError | STTError | T
119
119
  export type CloseEvent = {
120
120
  type: 'close';
121
121
  error: RealtimeModelError | STTError | TTSError | LLMError | null;
122
- reason: CloseReason;
122
+ reason: ShutdownReason;
123
123
  createdAt: number;
124
124
  };
125
- export declare const createCloseEvent: (reason: CloseReason, error?: RealtimeModelError | STTError | TTSError | LLMError | null, createdAt?: number) => CloseEvent;
125
+ export declare const createCloseEvent: (reason: ShutdownReason, error?: RealtimeModelError | STTError | TTSError | LLMError | null, createdAt?: number) => CloseEvent;
126
126
  export type AgentEvent = UserInputTranscribedEvent | UserStateChangedEvent | AgentStateChangedEvent | MetricsCollectedEvent | ConversationItemAddedEvent | FunctionToolsExecutedEvent | SpeechCreatedEvent | ErrorEvent | CloseEvent;
127
127
  //# sourceMappingURL=events.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/voice/events.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/voice/events.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/voice/events.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type {\n ChatMessage,\n FunctionCall,\n FunctionCallOutput,\n RealtimeModelError,\n} from '../llm/index.js';\nimport type { LLM, RealtimeModel } from '../llm/index.js';\nimport type { LLMError } from '../llm/llm.js';\nimport type { AgentMetrics } from '../metrics/base.js';\nimport type { STT } from '../stt/index.js';\nimport type { STTError } from '../stt/stt.js';\nimport type { TTS } from '../tts/index.js';\nimport type { TTSError } from '../tts/tts.js';\nimport type { SpeechHandle } from './speech_handle.js';\n\nexport enum AgentSessionEventTypes {\n UserInputTranscribed = 'user_input_transcribed',\n AgentStateChanged = 'agent_state_changed',\n UserStateChanged = 'user_state_changed',\n ConversationItemAdded = 'conversation_item_added',\n FunctionToolsExecuted = 'function_tools_executed',\n MetricsCollected = 'metrics_collected',\n SpeechCreated = 'speech_created',\n Error = 'error',\n Close = 'close',\n}\n\nexport type UserState = 'speaking' | 'listening' | 'away';\nexport type AgentState = 'initializing' | 'idle' | 'listening' | 'thinking' | 'speaking';\n\nexport enum CloseReason {\n ERROR = 'error',\n JOB_SHUTDOWN = 'job_shutdown',\n PARTICIPANT_DISCONNECTED = 'participant_disconnected',\n USER_INITIATED = 'user_initiated',\n}\n\nexport type SpeechSource = 'say' | 'generate_reply' | 'tool_response';\n\nexport type UserStateChangedEvent = {\n type: 'user_state_changed';\n oldState: UserState;\n newState: UserState;\n createdAt: number;\n};\n\nexport const createUserStateChangedEvent = (\n oldState: UserState,\n newState: UserState,\n createdAt: number = Date.now(),\n): UserStateChangedEvent => ({\n type: 'user_state_changed',\n oldState,\n newState,\n createdAt,\n});\n\nexport type AgentStateChangedEvent = {\n type: 'agent_state_changed';\n oldState: AgentState;\n newState: AgentState;\n createdAt: number;\n};\n\nexport const createAgentStateChangedEvent = (\n oldState: AgentState,\n newState: AgentState,\n createdAt: number = Date.now(),\n): AgentStateChangedEvent => ({\n type: 'agent_state_changed',\n oldState,\n newState,\n createdAt,\n});\n\nexport type UserInputTranscribedEvent = {\n type: 'user_input_transcribed';\n transcript: string;\n isFinal: boolean;\n // TODO(AJS-106): add multi participant support\n /** Not supported yet. Always null by default. */\n speakerId: string | null;\n createdAt: number;\n language: string | null;\n};\n\nexport const createUserInputTranscribedEvent = ({\n transcript,\n isFinal,\n speakerId = null,\n language = null,\n createdAt = Date.now(),\n}: {\n transcript: string;\n isFinal: boolean;\n speakerId?: string | null;\n language?: string | null;\n createdAt?: number;\n}): UserInputTranscribedEvent => ({\n type: 'user_input_transcribed',\n transcript,\n isFinal,\n speakerId,\n language,\n createdAt,\n});\n\nexport type MetricsCollectedEvent = {\n type: 'metrics_collected';\n metrics: AgentMetrics;\n createdAt: number;\n};\n\nexport const createMetricsCollectedEvent = ({\n metrics,\n createdAt = Date.now(),\n}: {\n metrics: AgentMetrics;\n createdAt?: number;\n}): MetricsCollectedEvent => ({\n type: 'metrics_collected',\n metrics,\n createdAt,\n});\n\nexport type ConversationItemAddedEvent = {\n type: 'conversation_item_added';\n item: ChatMessage;\n createdAt: number;\n};\n\nexport const createConversationItemAddedEvent = (\n item: ChatMessage,\n createdAt: number = Date.now(),\n): ConversationItemAddedEvent => ({\n type: 'conversation_item_added',\n item,\n createdAt,\n});\n\nexport type FunctionToolsExecutedEvent = {\n type: 'function_tools_executed';\n functionCalls: FunctionCall[];\n functionCallOutputs: FunctionCallOutput[];\n createdAt: number;\n};\n\nexport const createFunctionToolsExecutedEvent = ({\n functionCalls,\n functionCallOutputs,\n createdAt = Date.now(),\n}: {\n functionCalls: FunctionCall[];\n functionCallOutputs: FunctionCallOutput[];\n createdAt?: number;\n}): FunctionToolsExecutedEvent => {\n return {\n type: 'function_tools_executed',\n functionCalls,\n functionCallOutputs,\n createdAt,\n };\n};\n\nexport const zipFunctionCallsAndOutputs = (\n event: FunctionToolsExecutedEvent,\n): Array<[FunctionCall, FunctionCallOutput]> => {\n return event.functionCalls.map((call, index) => [call, event.functionCallOutputs[index]!]);\n};\n\nexport type SpeechCreatedEvent = {\n type: 'speech_created';\n /**\n * True if the speech was created using public methods like `say` or `generate_reply`\n */\n userInitiated: boolean;\n /**\n * Source indicating how the speech handle was created\n */\n source: SpeechSource;\n /**\n * The speech handle that was created\n */\n // TODO(shubhra): we need to make sure this doesn't get serialized\n speechHandle: SpeechHandle;\n /**\n * The timestamp when the speech handle was created\n */\n createdAt: number;\n};\n\nexport const createSpeechCreatedEvent = ({\n userInitiated,\n source,\n speechHandle,\n createdAt = Date.now(),\n}: {\n userInitiated: boolean;\n source: SpeechSource;\n speechHandle: SpeechHandle;\n createdAt?: number;\n}): SpeechCreatedEvent => ({\n type: 'speech_created',\n userInitiated,\n source,\n speechHandle,\n createdAt,\n});\n\nexport type ErrorEvent = {\n type: 'error';\n error: RealtimeModelError | STTError | TTSError | LLMError | unknown;\n source: LLM | STT | TTS | RealtimeModel | unknown;\n createdAt: number;\n};\n\nexport const createErrorEvent = (\n error: RealtimeModelError | STTError | TTSError | LLMError | unknown,\n source: LLM | STT | TTS | RealtimeModel | unknown,\n createdAt: number = Date.now(),\n): ErrorEvent => ({\n type: 'error',\n error,\n source,\n createdAt,\n});\n\nexport type CloseEvent = {\n type: 'close';\n error: RealtimeModelError | STTError | TTSError | LLMError | null;\n reason: CloseReason;\n createdAt: number;\n};\n\nexport const createCloseEvent = (\n reason: CloseReason,\n error: RealtimeModelError | STTError | TTSError | LLMError | null = null,\n createdAt: number = Date.now(),\n): CloseEvent => ({\n type: 'close',\n error,\n reason,\n createdAt,\n});\n\nexport type AgentEvent =\n | UserInputTranscribedEvent\n | UserStateChangedEvent\n | AgentStateChangedEvent\n | MetricsCollectedEvent\n | ConversationItemAddedEvent\n | FunctionToolsExecutedEvent\n | SpeechCreatedEvent\n | ErrorEvent\n | CloseEvent;\n"],"mappings":"AAkBO,IAAK,yBAAL,kBAAKA,4BAAL;AACL,EAAAA,wBAAA,0BAAuB;AACvB,EAAAA,wBAAA,uBAAoB;AACpB,EAAAA,wBAAA,sBAAmB;AACnB,EAAAA,wBAAA,2BAAwB;AACxB,EAAAA,wBAAA,2BAAwB;AACxB,EAAAA,wBAAA,sBAAmB;AACnB,EAAAA,wBAAA,mBAAgB;AAChB,EAAAA,wBAAA,WAAQ;AACR,EAAAA,wBAAA,WAAQ;AATE,SAAAA;AAAA,GAAA;AAeL,IAAK,cAAL,kBAAKC,iBAAL;AACL,EAAAA,aAAA,WAAQ;AACR,EAAAA,aAAA,kBAAe;AACf,EAAAA,aAAA,8BAA2B;AAC3B,EAAAA,aAAA,oBAAiB;AAJP,SAAAA;AAAA,GAAA;AAgBL,MAAM,8BAA8B,CACzC,UACA,UACA,YAAoB,KAAK,IAAI,OACF;AAAA,EAC3B,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AACF;AASO,MAAM,+BAA+B,CAC1C,UACA,UACA,YAAoB,KAAK,IAAI,OACD;AAAA,EAC5B,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AACF;AAaO,MAAM,kCAAkC,CAAC;AAAA,EAC9C;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,YAAY,KAAK,IAAI;AACvB,OAMkC;AAAA,EAChC,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAQO,MAAM,8BAA8B,CAAC;AAAA,EAC1C;AAAA,EACA,YAAY,KAAK,IAAI;AACvB,OAG8B;AAAA,EAC5B,MAAM;AAAA,EACN;AAAA,EACA;AACF;AAQO,MAAM,mCAAmC,CAC9C,MACA,YAAoB,KAAK,IAAI,OACG;AAAA,EAChC,MAAM;AAAA,EACN;AAAA,EACA;AACF;AASO,MAAM,mCAAmC,CAAC;AAAA,EAC/C;AAAA,EACA;AAAA,EACA,YAAY,KAAK,IAAI;AACvB,MAIkC;AAChC,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEO,MAAM,6BAA6B,CACxC,UAC8C;AAC9C,SAAO,MAAM,cAAc,IAAI,CAAC,MAAM,UAAU,CAAC,MAAM,MAAM,oBAAoB,KAAK,CAAE,CAAC;AAC3F;AAuBO,MAAM,2BAA2B,CAAC;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY,KAAK,IAAI;AACvB,OAK2B;AAAA,EACzB,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AASO,MAAM,mBAAmB,CAC9B,OACA,QACA,YAAoB,KAAK,IAAI,OACb;AAAA,EAChB,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AACF;AASO,MAAM,mBAAmB,CAC9B,QACA,QAAoE,MACpE,YAAoB,KAAK,IAAI,OACb;AAAA,EAChB,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AACF;","names":["AgentSessionEventTypes","CloseReason"]}
1
+ {"version":3,"sources":["../../src/voice/events.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type {\n ChatMessage,\n FunctionCall,\n FunctionCallOutput,\n LLM,\n RealtimeModel,\n RealtimeModelError,\n} from '../llm/index.js';\nimport type { LLMError } from '../llm/llm.js';\nimport type { AgentMetrics } from '../metrics/base.js';\nimport type { STT } from '../stt/index.js';\nimport type { STTError } from '../stt/stt.js';\nimport type { TTS } from '../tts/index.js';\nimport type { TTSError } from '../tts/tts.js';\nimport type { SpeechHandle } from './speech_handle.js';\n\nexport enum AgentSessionEventTypes {\n UserInputTranscribed = 'user_input_transcribed',\n AgentStateChanged = 'agent_state_changed',\n UserStateChanged = 'user_state_changed',\n ConversationItemAdded = 'conversation_item_added',\n FunctionToolsExecuted = 'function_tools_executed',\n MetricsCollected = 'metrics_collected',\n SpeechCreated = 'speech_created',\n Error = 'error',\n Close = 'close',\n}\n\nexport type UserState = 'speaking' | 'listening' | 'away';\nexport type AgentState = 'initializing' | 'idle' | 'listening' | 'thinking' | 'speaking';\n\nexport enum CloseReason {\n ERROR = 'error',\n JOB_SHUTDOWN = 'job_shutdown',\n PARTICIPANT_DISCONNECTED = 'participant_disconnected',\n USER_INITIATED = 'user_initiated',\n}\n\nexport type ShutdownReason = CloseReason | string;\n\nexport type SpeechSource = 'say' | 'generate_reply' | 'tool_response';\n\nexport type UserStateChangedEvent = {\n type: 'user_state_changed';\n oldState: UserState;\n newState: UserState;\n createdAt: number;\n};\n\nexport const createUserStateChangedEvent = (\n oldState: UserState,\n newState: UserState,\n createdAt: number = Date.now(),\n): UserStateChangedEvent => ({\n type: 'user_state_changed',\n oldState,\n newState,\n createdAt,\n});\n\nexport type AgentStateChangedEvent = {\n type: 'agent_state_changed';\n oldState: AgentState;\n newState: AgentState;\n createdAt: number;\n};\n\nexport const createAgentStateChangedEvent = (\n oldState: AgentState,\n newState: AgentState,\n createdAt: number = Date.now(),\n): AgentStateChangedEvent => ({\n type: 'agent_state_changed',\n oldState,\n newState,\n createdAt,\n});\n\nexport type UserInputTranscribedEvent = {\n type: 'user_input_transcribed';\n transcript: string;\n isFinal: boolean;\n // TODO(AJS-106): add multi participant support\n /** Not supported yet. Always null by default. */\n speakerId: string | null;\n createdAt: number;\n language: string | null;\n};\n\nexport const createUserInputTranscribedEvent = ({\n transcript,\n isFinal,\n speakerId = null,\n language = null,\n createdAt = Date.now(),\n}: {\n transcript: string;\n isFinal: boolean;\n speakerId?: string | null;\n language?: string | null;\n createdAt?: number;\n}): UserInputTranscribedEvent => ({\n type: 'user_input_transcribed',\n transcript,\n isFinal,\n speakerId,\n language,\n createdAt,\n});\n\nexport type MetricsCollectedEvent = {\n type: 'metrics_collected';\n metrics: AgentMetrics;\n createdAt: number;\n};\n\nexport const createMetricsCollectedEvent = ({\n metrics,\n createdAt = Date.now(),\n}: {\n metrics: AgentMetrics;\n createdAt?: number;\n}): MetricsCollectedEvent => ({\n type: 'metrics_collected',\n metrics,\n createdAt,\n});\n\nexport type ConversationItemAddedEvent = {\n type: 'conversation_item_added';\n item: ChatMessage;\n createdAt: number;\n};\n\nexport const createConversationItemAddedEvent = (\n item: ChatMessage,\n createdAt: number = Date.now(),\n): ConversationItemAddedEvent => ({\n type: 'conversation_item_added',\n item,\n createdAt,\n});\n\nexport type FunctionToolsExecutedEvent = {\n type: 'function_tools_executed';\n functionCalls: FunctionCall[];\n functionCallOutputs: FunctionCallOutput[];\n createdAt: number;\n};\n\nexport const createFunctionToolsExecutedEvent = ({\n functionCalls,\n functionCallOutputs,\n createdAt = Date.now(),\n}: {\n functionCalls: FunctionCall[];\n functionCallOutputs: FunctionCallOutput[];\n createdAt?: number;\n}): FunctionToolsExecutedEvent => {\n return {\n type: 'function_tools_executed',\n functionCalls,\n functionCallOutputs,\n createdAt,\n };\n};\n\nexport const zipFunctionCallsAndOutputs = (\n event: FunctionToolsExecutedEvent,\n): Array<[FunctionCall, FunctionCallOutput]> => {\n return event.functionCalls.map((call, index) => [call, event.functionCallOutputs[index]!]);\n};\n\nexport type SpeechCreatedEvent = {\n type: 'speech_created';\n /**\n * True if the speech was created using public methods like `say` or `generate_reply`\n */\n userInitiated: boolean;\n /**\n * Source indicating how the speech handle was created\n */\n source: SpeechSource;\n /**\n * The speech handle that was created\n */\n // TODO(shubhra): we need to make sure this doesn't get serialized\n speechHandle: SpeechHandle;\n /**\n * The timestamp when the speech handle was created\n */\n createdAt: number;\n};\n\nexport const createSpeechCreatedEvent = ({\n userInitiated,\n source,\n speechHandle,\n createdAt = Date.now(),\n}: {\n userInitiated: boolean;\n source: SpeechSource;\n speechHandle: SpeechHandle;\n createdAt?: number;\n}): SpeechCreatedEvent => ({\n type: 'speech_created',\n userInitiated,\n source,\n speechHandle,\n createdAt,\n});\n\nexport type ErrorEvent = {\n type: 'error';\n error: RealtimeModelError | STTError | TTSError | LLMError | unknown;\n source: LLM | STT | TTS | RealtimeModel | unknown;\n createdAt: number;\n};\n\nexport const createErrorEvent = (\n error: RealtimeModelError | STTError | TTSError | LLMError | unknown,\n source: LLM | STT | TTS | RealtimeModel | unknown,\n createdAt: number = Date.now(),\n): ErrorEvent => ({\n type: 'error',\n error,\n source,\n createdAt,\n});\n\nexport type CloseEvent = {\n type: 'close';\n error: RealtimeModelError | STTError | TTSError | LLMError | null;\n reason: ShutdownReason;\n createdAt: number;\n};\n\nexport const createCloseEvent = (\n reason: ShutdownReason,\n error: RealtimeModelError | STTError | TTSError | LLMError | null = null,\n createdAt: number = Date.now(),\n): CloseEvent => ({\n type: 'close',\n error,\n reason,\n createdAt,\n});\n\nexport type AgentEvent =\n | UserInputTranscribedEvent\n | UserStateChangedEvent\n | AgentStateChangedEvent\n | MetricsCollectedEvent\n | ConversationItemAddedEvent\n | FunctionToolsExecutedEvent\n | SpeechCreatedEvent\n | ErrorEvent\n | CloseEvent;\n"],"mappings":"AAmBO,IAAK,yBAAL,kBAAKA,4BAAL;AACL,EAAAA,wBAAA,0BAAuB;AACvB,EAAAA,wBAAA,uBAAoB;AACpB,EAAAA,wBAAA,sBAAmB;AACnB,EAAAA,wBAAA,2BAAwB;AACxB,EAAAA,wBAAA,2BAAwB;AACxB,EAAAA,wBAAA,sBAAmB;AACnB,EAAAA,wBAAA,mBAAgB;AAChB,EAAAA,wBAAA,WAAQ;AACR,EAAAA,wBAAA,WAAQ;AATE,SAAAA;AAAA,GAAA;AAeL,IAAK,cAAL,kBAAKC,iBAAL;AACL,EAAAA,aAAA,WAAQ;AACR,EAAAA,aAAA,kBAAe;AACf,EAAAA,aAAA,8BAA2B;AAC3B,EAAAA,aAAA,oBAAiB;AAJP,SAAAA;AAAA,GAAA;AAkBL,MAAM,8BAA8B,CACzC,UACA,UACA,YAAoB,KAAK,IAAI,OACF;AAAA,EAC3B,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AACF;AASO,MAAM,+BAA+B,CAC1C,UACA,UACA,YAAoB,KAAK,IAAI,OACD;AAAA,EAC5B,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AACF;AAaO,MAAM,kCAAkC,CAAC;AAAA,EAC9C;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,YAAY,KAAK,IAAI;AACvB,OAMkC;AAAA,EAChC,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAQO,MAAM,8BAA8B,CAAC;AAAA,EAC1C;AAAA,EACA,YAAY,KAAK,IAAI;AACvB,OAG8B;AAAA,EAC5B,MAAM;AAAA,EACN;AAAA,EACA;AACF;AAQO,MAAM,mCAAmC,CAC9C,MACA,YAAoB,KAAK,IAAI,OACG;AAAA,EAChC,MAAM;AAAA,EACN;AAAA,EACA;AACF;AASO,MAAM,mCAAmC,CAAC;AAAA,EAC/C;AAAA,EACA;AAAA,EACA,YAAY,KAAK,IAAI;AACvB,MAIkC;AAChC,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEO,MAAM,6BAA6B,CACxC,UAC8C;AAC9C,SAAO,MAAM,cAAc,IAAI,CAAC,MAAM,UAAU,CAAC,MAAM,MAAM,oBAAoB,KAAK,CAAE,CAAC;AAC3F;AAuBO,MAAM,2BAA2B,CAAC;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY,KAAK,IAAI;AACvB,OAK2B;AAAA,EACzB,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AASO,MAAM,mBAAmB,CAC9B,OACA,QACA,YAAoB,KAAK,IAAI,OACb;AAAA,EAChB,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AACF;AASO,MAAM,mBAAmB,CAC9B,QACA,QAAoE,MACpE,YAAoB,KAAK,IAAI,OACb;AAAA,EAChB,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AACF;","names":["AgentSessionEventTypes","CloseReason"]}
@@ -332,15 +332,14 @@ function performLLMInference(node, chatCtx, toolCtx, modelSettings, controller)
332
332
  await textWriter.close();
333
333
  return;
334
334
  }
335
+ const abortPromise = (0, import_utils.waitForAbort)(signal);
335
336
  llmStreamReader = llmStream.getReader();
336
337
  while (true) {
337
- if (signal.aborted) {
338
- break;
339
- }
340
- const { done, value: chunk } = await llmStreamReader.read();
341
- if (done) {
342
- break;
343
- }
338
+ if (signal.aborted) break;
339
+ const result = await Promise.race([llmStreamReader.read(), abortPromise]);
340
+ if (result === void 0) break;
341
+ const { done, value: chunk } = result;
342
+ if (done) break;
344
343
  if (typeof chunk === "string") {
345
344
  data.generatedText += chunk;
346
345
  await textWriter.write(chunk);