@voicethere/agent 0.8.3 → 0.9.1

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.
@@ -178,6 +178,12 @@ function isSttControlAckMessage(value) {
178
178
  const msg = value;
179
179
  return msg.type === "stt_control_ack" && typeof msg.requestId === "string";
180
180
  }
181
+ function isVoiceLanguageControlAckMessage(value) {
182
+ if (!value || typeof value !== "object")
183
+ return false;
184
+ const msg = value;
185
+ return msg.type === "voice_language_control_ack" && typeof msg.requestId === "string";
186
+ }
181
187
  function isWebhookMessage(value) {
182
188
  if (!value || typeof value !== "object")
183
189
  return false;
@@ -220,7 +226,7 @@ function isParentMessage(value) {
220
226
  if (!value || typeof value !== "object")
221
227
  return false;
222
228
  const msg = value;
223
- return msg.type === "session_start" || msg.type === "speech_event" || msg.type === "session_end" || msg.type === "data_channel_message" || msg.type === "data_channel_binary" || msg.type === "idle_timeout" || msg.type === "recording_control_ack" || msg.type === "conversation_history_control_ack" || msg.type === "play_ack" || msg.type === "play_status_ack" || msg.type === "play_stop_ack" || msg.type === "play_pose_ack" || msg.type === "mix_control_ack" || msg.type === "stt_control_ack" || msg.type === "webhook";
229
+ return msg.type === "session_start" || msg.type === "speech_event" || msg.type === "session_end" || msg.type === "data_channel_message" || msg.type === "data_channel_binary" || msg.type === "idle_timeout" || msg.type === "recording_control_ack" || msg.type === "conversation_history_control_ack" || msg.type === "play_ack" || msg.type === "play_status_ack" || msg.type === "play_stop_ack" || msg.type === "play_pose_ack" || msg.type === "mix_control_ack" || msg.type === "stt_control_ack" || msg.type === "voice_language_control_ack" || msg.type === "webhook";
224
230
  }
225
231
  function isSessionScopedParentMessage(value) {
226
232
  return isParentMessage(value) && !isWebhookMessage(value);
@@ -236,6 +242,8 @@ var peerEnvBySessionId = /* @__PURE__ */ new Map();
236
242
  var recordingAvailableBySessionId = /* @__PURE__ */ new Map();
237
243
  var conversationHistoryAvailableBySessionId = /* @__PURE__ */ new Map();
238
244
  var mixAvailableBySessionId = /* @__PURE__ */ new Map();
245
+ var voiceLanguageSwitchAvailableBySessionId = /* @__PURE__ */ new Map();
246
+ var lastVoiceLanguageBySessionId = /* @__PURE__ */ new Map();
239
247
  var ttsPoseAvailableBySessionId = /* @__PURE__ */ new Map();
240
248
  var endedSessionIds = /* @__PURE__ */ new Set();
241
249
  var PLAY_BYTES_MAX_DECODED_LENGTH = 64 * 1024;
@@ -247,6 +255,7 @@ var pendingPlayStopAcks = /* @__PURE__ */ new Map();
247
255
  var pendingPlayPoseAcks = /* @__PURE__ */ new Map();
248
256
  var pendingMixAcks = /* @__PURE__ */ new Map();
249
257
  var pendingSttAcks = /* @__PURE__ */ new Map();
258
+ var pendingVoiceLanguageAcks = /* @__PURE__ */ new Map();
250
259
  function handleRecordingControlAck(message) {
251
260
  const pending = pendingRecordingAcks.get(message.requestId);
252
261
  if (!pending)
@@ -349,6 +358,27 @@ function handleSttControlAck(message) {
349
358
  requestId: message.requestId
350
359
  });
351
360
  }
361
+ function handleVoiceLanguageControlAck(message) {
362
+ const pending = pendingVoiceLanguageAcks.get(message.requestId);
363
+ if (!pending)
364
+ return;
365
+ clearTimeout(pending.timer);
366
+ pendingVoiceLanguageAcks.delete(message.requestId);
367
+ if (message.ok && message.language?.trim()) {
368
+ lastVoiceLanguageBySessionId.set(message.sessionId, message.language.trim());
369
+ }
370
+ pending.resolve({
371
+ ok: message.ok,
372
+ reason: message.reason,
373
+ requestId: message.requestId,
374
+ ...message.language ? { language: message.language } : {},
375
+ ...message.voice ? { voice: message.voice } : {},
376
+ ...message.stt ? { stt: message.stt } : {},
377
+ ...message.scope ? { scope: message.scope } : {},
378
+ ...message.sttProvider ? { sttProvider: message.sttProvider } : {},
379
+ ...message.ttsProvider ? { ttsProvider: message.ttsProvider } : {}
380
+ });
381
+ }
352
382
  function clearPendingRecordingAcksForSession(sessionId, reason) {
353
383
  for (const [requestId, pending] of pendingRecordingAcks) {
354
384
  if (pending.sessionId !== sessionId)
@@ -414,7 +444,7 @@ function allowOutboundForSession(sessionId) {
414
444
  }
415
445
  function sendParentMessage(message) {
416
446
  const msgType = message && typeof message === "object" && "type" in message ? message.type : void 0;
417
- if (msgType === "mix_control" || msgType === "stt_control") {
447
+ if (msgType === "mix_control" || msgType === "stt_control" || msgType === "voice_language_control") {
418
448
  process.send?.(message);
419
449
  return;
420
450
  }
@@ -515,6 +545,7 @@ async function handleParentMessage(message, handlers) {
515
545
  recordingAvailableBySessionId.set(message.sessionId, message.recordingAvailable ?? false);
516
546
  conversationHistoryAvailableBySessionId.set(message.sessionId, message.conversationHistoryAvailable ?? false);
517
547
  mixAvailableBySessionId.set(message.sessionId, message.mixAvailable ?? false);
548
+ voiceLanguageSwitchAvailableBySessionId.set(message.sessionId, message.voiceLanguageSwitchAvailable ?? false);
518
549
  ttsPoseAvailableBySessionId.set(message.sessionId, message.ttsPoseAvailable ?? false);
519
550
  const sessionStartInitDelayMs = resolveSessionStartInitDelayMs();
520
551
  if (sessionStartInitDelayMs > 0) {
@@ -526,6 +557,7 @@ async function handleParentMessage(message, handlers) {
526
557
  recordingAvailable: message.recordingAvailable ?? false,
527
558
  conversationHistoryAvailable: message.conversationHistoryAvailable ?? false,
528
559
  mixAvailable: message.mixAvailable ?? false,
560
+ voiceLanguageSwitchAvailable: message.voiceLanguageSwitchAvailable ?? false,
529
561
  ttsPoseAvailable: message.ttsPoseAvailable ?? false
530
562
  });
531
563
  sendParentMessage({
@@ -544,12 +576,23 @@ async function handleParentMessage(message, handlers) {
544
576
  if (message.event.type === "user_language") {
545
577
  const language = resolveUserLanguageCode(message.event);
546
578
  if (language) {
579
+ lastVoiceLanguageBySessionId.set(message.sessionId, language);
547
580
  await handlers.onUserLanguage?.({
548
581
  sessionId: message.sessionId,
549
582
  language
550
583
  });
551
584
  }
552
585
  }
586
+ if (message.event.type === "voice_language_changed") {
587
+ const language = resolveUserLanguageCode(message.event);
588
+ if (language) {
589
+ lastVoiceLanguageBySessionId.set(message.sessionId, language);
590
+ await handlers.onVoiceLanguageChanged?.({
591
+ sessionId: message.sessionId,
592
+ language
593
+ });
594
+ }
595
+ }
553
596
  break;
554
597
  case "data_channel_message":
555
598
  await handlers.onDataChannelMessage?.({
@@ -576,6 +619,8 @@ async function handleParentMessage(message, handlers) {
576
619
  recordingAvailableBySessionId.delete(message.sessionId);
577
620
  conversationHistoryAvailableBySessionId.delete(message.sessionId);
578
621
  mixAvailableBySessionId.delete(message.sessionId);
622
+ voiceLanguageSwitchAvailableBySessionId.delete(message.sessionId);
623
+ lastVoiceLanguageBySessionId.delete(message.sessionId);
579
624
  ttsPoseAvailableBySessionId.delete(message.sessionId);
580
625
  await (handlers.onClientLeave ?? handlers.onSessionEnd)?.({
581
626
  sessionId: message.sessionId
@@ -624,6 +669,10 @@ function defineAgent(handlers) {
624
669
  handleSttControlAck(message);
625
670
  return;
626
671
  }
672
+ if (isVoiceLanguageControlAckMessage(message)) {
673
+ handleVoiceLanguageControlAck(message);
674
+ return;
675
+ }
627
676
  if (isWebhookMessage(message)) {
628
677
  void agentStartReady.then(() => handleWebhookMessage(message, handlers));
629
678
  return;
@@ -181,6 +181,12 @@ function isSttControlAckMessage(value) {
181
181
  const msg = value;
182
182
  return msg.type === "stt_control_ack" && typeof msg.requestId === "string";
183
183
  }
184
+ function isVoiceLanguageControlAckMessage(value) {
185
+ if (!value || typeof value !== "object")
186
+ return false;
187
+ const msg = value;
188
+ return msg.type === "voice_language_control_ack" && typeof msg.requestId === "string";
189
+ }
184
190
  function isWebhookMessage(value) {
185
191
  if (!value || typeof value !== "object")
186
192
  return false;
@@ -223,7 +229,7 @@ function isParentMessage(value) {
223
229
  if (!value || typeof value !== "object")
224
230
  return false;
225
231
  const msg = value;
226
- return msg.type === "session_start" || msg.type === "speech_event" || msg.type === "session_end" || msg.type === "data_channel_message" || msg.type === "data_channel_binary" || msg.type === "idle_timeout" || msg.type === "recording_control_ack" || msg.type === "conversation_history_control_ack" || msg.type === "play_ack" || msg.type === "play_status_ack" || msg.type === "play_stop_ack" || msg.type === "play_pose_ack" || msg.type === "mix_control_ack" || msg.type === "stt_control_ack" || msg.type === "webhook";
232
+ return msg.type === "session_start" || msg.type === "speech_event" || msg.type === "session_end" || msg.type === "data_channel_message" || msg.type === "data_channel_binary" || msg.type === "idle_timeout" || msg.type === "recording_control_ack" || msg.type === "conversation_history_control_ack" || msg.type === "play_ack" || msg.type === "play_status_ack" || msg.type === "play_stop_ack" || msg.type === "play_pose_ack" || msg.type === "mix_control_ack" || msg.type === "stt_control_ack" || msg.type === "voice_language_control_ack" || msg.type === "webhook";
227
233
  }
228
234
  function isSessionScopedParentMessage(value) {
229
235
  return isParentMessage(value) && !isWebhookMessage(value);
@@ -239,6 +245,8 @@ var peerEnvBySessionId = /* @__PURE__ */ new Map();
239
245
  var recordingAvailableBySessionId = /* @__PURE__ */ new Map();
240
246
  var conversationHistoryAvailableBySessionId = /* @__PURE__ */ new Map();
241
247
  var mixAvailableBySessionId = /* @__PURE__ */ new Map();
248
+ var voiceLanguageSwitchAvailableBySessionId = /* @__PURE__ */ new Map();
249
+ var lastVoiceLanguageBySessionId = /* @__PURE__ */ new Map();
242
250
  var ttsPoseAvailableBySessionId = /* @__PURE__ */ new Map();
243
251
  var endedSessionIds = /* @__PURE__ */ new Set();
244
252
  var PLAY_BYTES_MAX_DECODED_LENGTH = 64 * 1024;
@@ -250,6 +258,7 @@ var pendingPlayStopAcks = /* @__PURE__ */ new Map();
250
258
  var pendingPlayPoseAcks = /* @__PURE__ */ new Map();
251
259
  var pendingMixAcks = /* @__PURE__ */ new Map();
252
260
  var pendingSttAcks = /* @__PURE__ */ new Map();
261
+ var pendingVoiceLanguageAcks = /* @__PURE__ */ new Map();
253
262
  function handleRecordingControlAck(message) {
254
263
  const pending = pendingRecordingAcks.get(message.requestId);
255
264
  if (!pending)
@@ -352,6 +361,27 @@ function handleSttControlAck(message) {
352
361
  requestId: message.requestId
353
362
  });
354
363
  }
364
+ function handleVoiceLanguageControlAck(message) {
365
+ const pending = pendingVoiceLanguageAcks.get(message.requestId);
366
+ if (!pending)
367
+ return;
368
+ clearTimeout(pending.timer);
369
+ pendingVoiceLanguageAcks.delete(message.requestId);
370
+ if (message.ok && message.language?.trim()) {
371
+ lastVoiceLanguageBySessionId.set(message.sessionId, message.language.trim());
372
+ }
373
+ pending.resolve({
374
+ ok: message.ok,
375
+ reason: message.reason,
376
+ requestId: message.requestId,
377
+ ...message.language ? { language: message.language } : {},
378
+ ...message.voice ? { voice: message.voice } : {},
379
+ ...message.stt ? { stt: message.stt } : {},
380
+ ...message.scope ? { scope: message.scope } : {},
381
+ ...message.sttProvider ? { sttProvider: message.sttProvider } : {},
382
+ ...message.ttsProvider ? { ttsProvider: message.ttsProvider } : {}
383
+ });
384
+ }
355
385
  function clearPendingRecordingAcksForSession(sessionId, reason) {
356
386
  for (const [requestId, pending] of pendingRecordingAcks) {
357
387
  if (pending.sessionId !== sessionId)
@@ -417,7 +447,7 @@ function allowOutboundForSession(sessionId) {
417
447
  }
418
448
  function sendParentMessage(message) {
419
449
  const msgType = message && typeof message === "object" && "type" in message ? message.type : void 0;
420
- if (msgType === "mix_control" || msgType === "stt_control") {
450
+ if (msgType === "mix_control" || msgType === "stt_control" || msgType === "voice_language_control") {
421
451
  process.send?.(message);
422
452
  return;
423
453
  }
@@ -518,6 +548,7 @@ async function handleParentMessage(message, handlers) {
518
548
  recordingAvailableBySessionId.set(message.sessionId, message.recordingAvailable ?? false);
519
549
  conversationHistoryAvailableBySessionId.set(message.sessionId, message.conversationHistoryAvailable ?? false);
520
550
  mixAvailableBySessionId.set(message.sessionId, message.mixAvailable ?? false);
551
+ voiceLanguageSwitchAvailableBySessionId.set(message.sessionId, message.voiceLanguageSwitchAvailable ?? false);
521
552
  ttsPoseAvailableBySessionId.set(message.sessionId, message.ttsPoseAvailable ?? false);
522
553
  const sessionStartInitDelayMs = resolveSessionStartInitDelayMs();
523
554
  if (sessionStartInitDelayMs > 0) {
@@ -529,6 +560,7 @@ async function handleParentMessage(message, handlers) {
529
560
  recordingAvailable: message.recordingAvailable ?? false,
530
561
  conversationHistoryAvailable: message.conversationHistoryAvailable ?? false,
531
562
  mixAvailable: message.mixAvailable ?? false,
563
+ voiceLanguageSwitchAvailable: message.voiceLanguageSwitchAvailable ?? false,
532
564
  ttsPoseAvailable: message.ttsPoseAvailable ?? false
533
565
  });
534
566
  sendParentMessage({
@@ -547,12 +579,23 @@ async function handleParentMessage(message, handlers) {
547
579
  if (message.event.type === "user_language") {
548
580
  const language = resolveUserLanguageCode(message.event);
549
581
  if (language) {
582
+ lastVoiceLanguageBySessionId.set(message.sessionId, language);
550
583
  await handlers.onUserLanguage?.({
551
584
  sessionId: message.sessionId,
552
585
  language
553
586
  });
554
587
  }
555
588
  }
589
+ if (message.event.type === "voice_language_changed") {
590
+ const language = resolveUserLanguageCode(message.event);
591
+ if (language) {
592
+ lastVoiceLanguageBySessionId.set(message.sessionId, language);
593
+ await handlers.onVoiceLanguageChanged?.({
594
+ sessionId: message.sessionId,
595
+ language
596
+ });
597
+ }
598
+ }
556
599
  break;
557
600
  case "data_channel_message":
558
601
  await handlers.onDataChannelMessage?.({
@@ -579,6 +622,8 @@ async function handleParentMessage(message, handlers) {
579
622
  recordingAvailableBySessionId.delete(message.sessionId);
580
623
  conversationHistoryAvailableBySessionId.delete(message.sessionId);
581
624
  mixAvailableBySessionId.delete(message.sessionId);
625
+ voiceLanguageSwitchAvailableBySessionId.delete(message.sessionId);
626
+ lastVoiceLanguageBySessionId.delete(message.sessionId);
582
627
  ttsPoseAvailableBySessionId.delete(message.sessionId);
583
628
  await (handlers.onClientLeave ?? handlers.onSessionEnd)?.({
584
629
  sessionId: message.sessionId
@@ -627,6 +672,10 @@ function defineAgent(handlers) {
627
672
  handleSttControlAck(message);
628
673
  return;
629
674
  }
675
+ if (isVoiceLanguageControlAckMessage(message)) {
676
+ handleVoiceLanguageControlAck(message);
677
+ return;
678
+ }
630
679
  if (isWebhookMessage(message)) {
631
680
  void agentStartReady.then(() => handleWebhookMessage(message, handlers));
632
681
  return;
@@ -10933,6 +10933,12 @@ function isSttControlAckMessage(value) {
10933
10933
  const msg = value;
10934
10934
  return msg.type === "stt_control_ack" && typeof msg.requestId === "string";
10935
10935
  }
10936
+ function isVoiceLanguageControlAckMessage(value) {
10937
+ if (!value || typeof value !== "object")
10938
+ return false;
10939
+ const msg = value;
10940
+ return msg.type === "voice_language_control_ack" && typeof msg.requestId === "string";
10941
+ }
10936
10942
  function isWebhookMessage(value) {
10937
10943
  if (!value || typeof value !== "object")
10938
10944
  return false;
@@ -10975,7 +10981,7 @@ function isParentMessage(value) {
10975
10981
  if (!value || typeof value !== "object")
10976
10982
  return false;
10977
10983
  const msg = value;
10978
- return msg.type === "session_start" || msg.type === "speech_event" || msg.type === "session_end" || msg.type === "data_channel_message" || msg.type === "data_channel_binary" || msg.type === "idle_timeout" || msg.type === "recording_control_ack" || msg.type === "conversation_history_control_ack" || msg.type === "play_ack" || msg.type === "play_status_ack" || msg.type === "play_stop_ack" || msg.type === "play_pose_ack" || msg.type === "mix_control_ack" || msg.type === "stt_control_ack" || msg.type === "webhook";
10984
+ return msg.type === "session_start" || msg.type === "speech_event" || msg.type === "session_end" || msg.type === "data_channel_message" || msg.type === "data_channel_binary" || msg.type === "idle_timeout" || msg.type === "recording_control_ack" || msg.type === "conversation_history_control_ack" || msg.type === "play_ack" || msg.type === "play_status_ack" || msg.type === "play_stop_ack" || msg.type === "play_pose_ack" || msg.type === "mix_control_ack" || msg.type === "stt_control_ack" || msg.type === "voice_language_control_ack" || msg.type === "webhook";
10979
10985
  }
10980
10986
  function isSessionScopedParentMessage(value) {
10981
10987
  return isParentMessage(value) && !isWebhookMessage(value);
@@ -10991,6 +10997,8 @@ var peerEnvBySessionId = /* @__PURE__ */ new Map();
10991
10997
  var recordingAvailableBySessionId = /* @__PURE__ */ new Map();
10992
10998
  var conversationHistoryAvailableBySessionId = /* @__PURE__ */ new Map();
10993
10999
  var mixAvailableBySessionId = /* @__PURE__ */ new Map();
11000
+ var voiceLanguageSwitchAvailableBySessionId = /* @__PURE__ */ new Map();
11001
+ var lastVoiceLanguageBySessionId = /* @__PURE__ */ new Map();
10994
11002
  var ttsPoseAvailableBySessionId = /* @__PURE__ */ new Map();
10995
11003
  var endedSessionIds = /* @__PURE__ */ new Set();
10996
11004
  var PLAY_BYTES_MAX_DECODED_LENGTH = 64 * 1024;
@@ -11002,6 +11010,7 @@ var pendingPlayStopAcks = /* @__PURE__ */ new Map();
11002
11010
  var pendingPlayPoseAcks = /* @__PURE__ */ new Map();
11003
11011
  var pendingMixAcks = /* @__PURE__ */ new Map();
11004
11012
  var pendingSttAcks = /* @__PURE__ */ new Map();
11013
+ var pendingVoiceLanguageAcks = /* @__PURE__ */ new Map();
11005
11014
  function handleRecordingControlAck(message) {
11006
11015
  const pending = pendingRecordingAcks.get(message.requestId);
11007
11016
  if (!pending)
@@ -11104,6 +11113,27 @@ function handleSttControlAck(message) {
11104
11113
  requestId: message.requestId
11105
11114
  });
11106
11115
  }
11116
+ function handleVoiceLanguageControlAck(message) {
11117
+ const pending = pendingVoiceLanguageAcks.get(message.requestId);
11118
+ if (!pending)
11119
+ return;
11120
+ clearTimeout(pending.timer);
11121
+ pendingVoiceLanguageAcks.delete(message.requestId);
11122
+ if (message.ok && message.language?.trim()) {
11123
+ lastVoiceLanguageBySessionId.set(message.sessionId, message.language.trim());
11124
+ }
11125
+ pending.resolve({
11126
+ ok: message.ok,
11127
+ reason: message.reason,
11128
+ requestId: message.requestId,
11129
+ ...message.language ? { language: message.language } : {},
11130
+ ...message.voice ? { voice: message.voice } : {},
11131
+ ...message.stt ? { stt: message.stt } : {},
11132
+ ...message.scope ? { scope: message.scope } : {},
11133
+ ...message.sttProvider ? { sttProvider: message.sttProvider } : {},
11134
+ ...message.ttsProvider ? { ttsProvider: message.ttsProvider } : {}
11135
+ });
11136
+ }
11107
11137
  function clearPendingRecordingAcksForSession(sessionId, reason) {
11108
11138
  for (const [requestId, pending] of pendingRecordingAcks) {
11109
11139
  if (pending.sessionId !== sessionId)
@@ -11169,7 +11199,7 @@ function allowOutboundForSession(sessionId) {
11169
11199
  }
11170
11200
  function sendParentMessage(message) {
11171
11201
  const msgType = message && typeof message === "object" && "type" in message ? message.type : void 0;
11172
- if (msgType === "mix_control" || msgType === "stt_control") {
11202
+ if (msgType === "mix_control" || msgType === "stt_control" || msgType === "voice_language_control") {
11173
11203
  process.send?.(message);
11174
11204
  return;
11175
11205
  }
@@ -11270,6 +11300,7 @@ async function handleParentMessage(message, handlers) {
11270
11300
  recordingAvailableBySessionId.set(message.sessionId, message.recordingAvailable ?? false);
11271
11301
  conversationHistoryAvailableBySessionId.set(message.sessionId, message.conversationHistoryAvailable ?? false);
11272
11302
  mixAvailableBySessionId.set(message.sessionId, message.mixAvailable ?? false);
11303
+ voiceLanguageSwitchAvailableBySessionId.set(message.sessionId, message.voiceLanguageSwitchAvailable ?? false);
11273
11304
  ttsPoseAvailableBySessionId.set(message.sessionId, message.ttsPoseAvailable ?? false);
11274
11305
  const sessionStartInitDelayMs = resolveSessionStartInitDelayMs();
11275
11306
  if (sessionStartInitDelayMs > 0) {
@@ -11281,6 +11312,7 @@ async function handleParentMessage(message, handlers) {
11281
11312
  recordingAvailable: message.recordingAvailable ?? false,
11282
11313
  conversationHistoryAvailable: message.conversationHistoryAvailable ?? false,
11283
11314
  mixAvailable: message.mixAvailable ?? false,
11315
+ voiceLanguageSwitchAvailable: message.voiceLanguageSwitchAvailable ?? false,
11284
11316
  ttsPoseAvailable: message.ttsPoseAvailable ?? false
11285
11317
  });
11286
11318
  sendParentMessage({
@@ -11299,12 +11331,23 @@ async function handleParentMessage(message, handlers) {
11299
11331
  if (message.event.type === "user_language") {
11300
11332
  const language = resolveUserLanguageCode(message.event);
11301
11333
  if (language) {
11334
+ lastVoiceLanguageBySessionId.set(message.sessionId, language);
11302
11335
  await handlers.onUserLanguage?.({
11303
11336
  sessionId: message.sessionId,
11304
11337
  language
11305
11338
  });
11306
11339
  }
11307
11340
  }
11341
+ if (message.event.type === "voice_language_changed") {
11342
+ const language = resolveUserLanguageCode(message.event);
11343
+ if (language) {
11344
+ lastVoiceLanguageBySessionId.set(message.sessionId, language);
11345
+ await handlers.onVoiceLanguageChanged?.({
11346
+ sessionId: message.sessionId,
11347
+ language
11348
+ });
11349
+ }
11350
+ }
11308
11351
  break;
11309
11352
  case "data_channel_message":
11310
11353
  await handlers.onDataChannelMessage?.({
@@ -11331,6 +11374,8 @@ async function handleParentMessage(message, handlers) {
11331
11374
  recordingAvailableBySessionId.delete(message.sessionId);
11332
11375
  conversationHistoryAvailableBySessionId.delete(message.sessionId);
11333
11376
  mixAvailableBySessionId.delete(message.sessionId);
11377
+ voiceLanguageSwitchAvailableBySessionId.delete(message.sessionId);
11378
+ lastVoiceLanguageBySessionId.delete(message.sessionId);
11334
11379
  ttsPoseAvailableBySessionId.delete(message.sessionId);
11335
11380
  await (handlers.onClientLeave ?? handlers.onSessionEnd)?.({
11336
11381
  sessionId: message.sessionId
@@ -11379,6 +11424,10 @@ function defineAgent(handlers) {
11379
11424
  handleSttControlAck(message);
11380
11425
  return;
11381
11426
  }
11427
+ if (isVoiceLanguageControlAckMessage(message)) {
11428
+ handleVoiceLanguageControlAck(message);
11429
+ return;
11430
+ }
11382
11431
  if (isWebhookMessage(message)) {
11383
11432
  void agentStartReady.then(() => handleWebhookMessage(message, handlers));
11384
11433
  return;
@@ -178,6 +178,12 @@ function isSttControlAckMessage(value) {
178
178
  const msg = value;
179
179
  return msg.type === "stt_control_ack" && typeof msg.requestId === "string";
180
180
  }
181
+ function isVoiceLanguageControlAckMessage(value) {
182
+ if (!value || typeof value !== "object")
183
+ return false;
184
+ const msg = value;
185
+ return msg.type === "voice_language_control_ack" && typeof msg.requestId === "string";
186
+ }
181
187
  function isWebhookMessage(value) {
182
188
  if (!value || typeof value !== "object")
183
189
  return false;
@@ -220,7 +226,7 @@ function isParentMessage(value) {
220
226
  if (!value || typeof value !== "object")
221
227
  return false;
222
228
  const msg = value;
223
- return msg.type === "session_start" || msg.type === "speech_event" || msg.type === "session_end" || msg.type === "data_channel_message" || msg.type === "data_channel_binary" || msg.type === "idle_timeout" || msg.type === "recording_control_ack" || msg.type === "conversation_history_control_ack" || msg.type === "play_ack" || msg.type === "play_status_ack" || msg.type === "play_stop_ack" || msg.type === "play_pose_ack" || msg.type === "mix_control_ack" || msg.type === "stt_control_ack" || msg.type === "webhook";
229
+ return msg.type === "session_start" || msg.type === "speech_event" || msg.type === "session_end" || msg.type === "data_channel_message" || msg.type === "data_channel_binary" || msg.type === "idle_timeout" || msg.type === "recording_control_ack" || msg.type === "conversation_history_control_ack" || msg.type === "play_ack" || msg.type === "play_status_ack" || msg.type === "play_stop_ack" || msg.type === "play_pose_ack" || msg.type === "mix_control_ack" || msg.type === "stt_control_ack" || msg.type === "voice_language_control_ack" || msg.type === "webhook";
224
230
  }
225
231
  function isSessionScopedParentMessage(value) {
226
232
  return isParentMessage(value) && !isWebhookMessage(value);
@@ -236,6 +242,8 @@ var peerEnvBySessionId = /* @__PURE__ */ new Map();
236
242
  var recordingAvailableBySessionId = /* @__PURE__ */ new Map();
237
243
  var conversationHistoryAvailableBySessionId = /* @__PURE__ */ new Map();
238
244
  var mixAvailableBySessionId = /* @__PURE__ */ new Map();
245
+ var voiceLanguageSwitchAvailableBySessionId = /* @__PURE__ */ new Map();
246
+ var lastVoiceLanguageBySessionId = /* @__PURE__ */ new Map();
239
247
  var ttsPoseAvailableBySessionId = /* @__PURE__ */ new Map();
240
248
  var endedSessionIds = /* @__PURE__ */ new Set();
241
249
  var PLAY_BYTES_MAX_DECODED_LENGTH = 64 * 1024;
@@ -247,6 +255,7 @@ var pendingPlayStopAcks = /* @__PURE__ */ new Map();
247
255
  var pendingPlayPoseAcks = /* @__PURE__ */ new Map();
248
256
  var pendingMixAcks = /* @__PURE__ */ new Map();
249
257
  var pendingSttAcks = /* @__PURE__ */ new Map();
258
+ var pendingVoiceLanguageAcks = /* @__PURE__ */ new Map();
250
259
  function handleRecordingControlAck(message) {
251
260
  const pending = pendingRecordingAcks.get(message.requestId);
252
261
  if (!pending)
@@ -349,6 +358,27 @@ function handleSttControlAck(message) {
349
358
  requestId: message.requestId
350
359
  });
351
360
  }
361
+ function handleVoiceLanguageControlAck(message) {
362
+ const pending = pendingVoiceLanguageAcks.get(message.requestId);
363
+ if (!pending)
364
+ return;
365
+ clearTimeout(pending.timer);
366
+ pendingVoiceLanguageAcks.delete(message.requestId);
367
+ if (message.ok && message.language?.trim()) {
368
+ lastVoiceLanguageBySessionId.set(message.sessionId, message.language.trim());
369
+ }
370
+ pending.resolve({
371
+ ok: message.ok,
372
+ reason: message.reason,
373
+ requestId: message.requestId,
374
+ ...message.language ? { language: message.language } : {},
375
+ ...message.voice ? { voice: message.voice } : {},
376
+ ...message.stt ? { stt: message.stt } : {},
377
+ ...message.scope ? { scope: message.scope } : {},
378
+ ...message.sttProvider ? { sttProvider: message.sttProvider } : {},
379
+ ...message.ttsProvider ? { ttsProvider: message.ttsProvider } : {}
380
+ });
381
+ }
352
382
  function clearPendingRecordingAcksForSession(sessionId, reason) {
353
383
  for (const [requestId, pending] of pendingRecordingAcks) {
354
384
  if (pending.sessionId !== sessionId)
@@ -414,7 +444,7 @@ function allowOutboundForSession(sessionId) {
414
444
  }
415
445
  function sendParentMessage(message) {
416
446
  const msgType = message && typeof message === "object" && "type" in message ? message.type : void 0;
417
- if (msgType === "mix_control" || msgType === "stt_control") {
447
+ if (msgType === "mix_control" || msgType === "stt_control" || msgType === "voice_language_control") {
418
448
  process.send?.(message);
419
449
  return;
420
450
  }
@@ -515,6 +545,7 @@ async function handleParentMessage(message, handlers) {
515
545
  recordingAvailableBySessionId.set(message.sessionId, message.recordingAvailable ?? false);
516
546
  conversationHistoryAvailableBySessionId.set(message.sessionId, message.conversationHistoryAvailable ?? false);
517
547
  mixAvailableBySessionId.set(message.sessionId, message.mixAvailable ?? false);
548
+ voiceLanguageSwitchAvailableBySessionId.set(message.sessionId, message.voiceLanguageSwitchAvailable ?? false);
518
549
  ttsPoseAvailableBySessionId.set(message.sessionId, message.ttsPoseAvailable ?? false);
519
550
  const sessionStartInitDelayMs = resolveSessionStartInitDelayMs();
520
551
  if (sessionStartInitDelayMs > 0) {
@@ -526,6 +557,7 @@ async function handleParentMessage(message, handlers) {
526
557
  recordingAvailable: message.recordingAvailable ?? false,
527
558
  conversationHistoryAvailable: message.conversationHistoryAvailable ?? false,
528
559
  mixAvailable: message.mixAvailable ?? false,
560
+ voiceLanguageSwitchAvailable: message.voiceLanguageSwitchAvailable ?? false,
529
561
  ttsPoseAvailable: message.ttsPoseAvailable ?? false
530
562
  });
531
563
  sendParentMessage({
@@ -544,12 +576,23 @@ async function handleParentMessage(message, handlers) {
544
576
  if (message.event.type === "user_language") {
545
577
  const language = resolveUserLanguageCode(message.event);
546
578
  if (language) {
579
+ lastVoiceLanguageBySessionId.set(message.sessionId, language);
547
580
  await handlers.onUserLanguage?.({
548
581
  sessionId: message.sessionId,
549
582
  language
550
583
  });
551
584
  }
552
585
  }
586
+ if (message.event.type === "voice_language_changed") {
587
+ const language = resolveUserLanguageCode(message.event);
588
+ if (language) {
589
+ lastVoiceLanguageBySessionId.set(message.sessionId, language);
590
+ await handlers.onVoiceLanguageChanged?.({
591
+ sessionId: message.sessionId,
592
+ language
593
+ });
594
+ }
595
+ }
553
596
  break;
554
597
  case "data_channel_message":
555
598
  await handlers.onDataChannelMessage?.({
@@ -576,6 +619,8 @@ async function handleParentMessage(message, handlers) {
576
619
  recordingAvailableBySessionId.delete(message.sessionId);
577
620
  conversationHistoryAvailableBySessionId.delete(message.sessionId);
578
621
  mixAvailableBySessionId.delete(message.sessionId);
622
+ voiceLanguageSwitchAvailableBySessionId.delete(message.sessionId);
623
+ lastVoiceLanguageBySessionId.delete(message.sessionId);
579
624
  ttsPoseAvailableBySessionId.delete(message.sessionId);
580
625
  await (handlers.onClientLeave ?? handlers.onSessionEnd)?.({
581
626
  sessionId: message.sessionId
@@ -624,6 +669,10 @@ function defineAgent(handlers) {
624
669
  handleSttControlAck(message);
625
670
  return;
626
671
  }
672
+ if (isVoiceLanguageControlAckMessage(message)) {
673
+ handleVoiceLanguageControlAck(message);
674
+ return;
675
+ }
627
676
  if (isWebhookMessage(message)) {
628
677
  void agentStartReady.then(() => handleWebhookMessage(message, handlers));
629
678
  return;
@@ -178,6 +178,12 @@ function isSttControlAckMessage(value) {
178
178
  const msg = value;
179
179
  return msg.type === "stt_control_ack" && typeof msg.requestId === "string";
180
180
  }
181
+ function isVoiceLanguageControlAckMessage(value) {
182
+ if (!value || typeof value !== "object")
183
+ return false;
184
+ const msg = value;
185
+ return msg.type === "voice_language_control_ack" && typeof msg.requestId === "string";
186
+ }
181
187
  function isWebhookMessage(value) {
182
188
  if (!value || typeof value !== "object")
183
189
  return false;
@@ -220,7 +226,7 @@ function isParentMessage(value) {
220
226
  if (!value || typeof value !== "object")
221
227
  return false;
222
228
  const msg = value;
223
- return msg.type === "session_start" || msg.type === "speech_event" || msg.type === "session_end" || msg.type === "data_channel_message" || msg.type === "data_channel_binary" || msg.type === "idle_timeout" || msg.type === "recording_control_ack" || msg.type === "conversation_history_control_ack" || msg.type === "play_ack" || msg.type === "play_status_ack" || msg.type === "play_stop_ack" || msg.type === "play_pose_ack" || msg.type === "mix_control_ack" || msg.type === "stt_control_ack" || msg.type === "webhook";
229
+ return msg.type === "session_start" || msg.type === "speech_event" || msg.type === "session_end" || msg.type === "data_channel_message" || msg.type === "data_channel_binary" || msg.type === "idle_timeout" || msg.type === "recording_control_ack" || msg.type === "conversation_history_control_ack" || msg.type === "play_ack" || msg.type === "play_status_ack" || msg.type === "play_stop_ack" || msg.type === "play_pose_ack" || msg.type === "mix_control_ack" || msg.type === "stt_control_ack" || msg.type === "voice_language_control_ack" || msg.type === "webhook";
224
230
  }
225
231
  function isSessionScopedParentMessage(value) {
226
232
  return isParentMessage(value) && !isWebhookMessage(value);
@@ -236,6 +242,8 @@ var peerEnvBySessionId = /* @__PURE__ */ new Map();
236
242
  var recordingAvailableBySessionId = /* @__PURE__ */ new Map();
237
243
  var conversationHistoryAvailableBySessionId = /* @__PURE__ */ new Map();
238
244
  var mixAvailableBySessionId = /* @__PURE__ */ new Map();
245
+ var voiceLanguageSwitchAvailableBySessionId = /* @__PURE__ */ new Map();
246
+ var lastVoiceLanguageBySessionId = /* @__PURE__ */ new Map();
239
247
  var ttsPoseAvailableBySessionId = /* @__PURE__ */ new Map();
240
248
  var endedSessionIds = /* @__PURE__ */ new Set();
241
249
  var PLAY_BYTES_MAX_DECODED_LENGTH = 64 * 1024;
@@ -247,6 +255,7 @@ var pendingPlayStopAcks = /* @__PURE__ */ new Map();
247
255
  var pendingPlayPoseAcks = /* @__PURE__ */ new Map();
248
256
  var pendingMixAcks = /* @__PURE__ */ new Map();
249
257
  var pendingSttAcks = /* @__PURE__ */ new Map();
258
+ var pendingVoiceLanguageAcks = /* @__PURE__ */ new Map();
250
259
  function handleRecordingControlAck(message) {
251
260
  const pending = pendingRecordingAcks.get(message.requestId);
252
261
  if (!pending)
@@ -349,6 +358,27 @@ function handleSttControlAck(message) {
349
358
  requestId: message.requestId
350
359
  });
351
360
  }
361
+ function handleVoiceLanguageControlAck(message) {
362
+ const pending = pendingVoiceLanguageAcks.get(message.requestId);
363
+ if (!pending)
364
+ return;
365
+ clearTimeout(pending.timer);
366
+ pendingVoiceLanguageAcks.delete(message.requestId);
367
+ if (message.ok && message.language?.trim()) {
368
+ lastVoiceLanguageBySessionId.set(message.sessionId, message.language.trim());
369
+ }
370
+ pending.resolve({
371
+ ok: message.ok,
372
+ reason: message.reason,
373
+ requestId: message.requestId,
374
+ ...message.language ? { language: message.language } : {},
375
+ ...message.voice ? { voice: message.voice } : {},
376
+ ...message.stt ? { stt: message.stt } : {},
377
+ ...message.scope ? { scope: message.scope } : {},
378
+ ...message.sttProvider ? { sttProvider: message.sttProvider } : {},
379
+ ...message.ttsProvider ? { ttsProvider: message.ttsProvider } : {}
380
+ });
381
+ }
352
382
  function clearPendingRecordingAcksForSession(sessionId, reason) {
353
383
  for (const [requestId, pending] of pendingRecordingAcks) {
354
384
  if (pending.sessionId !== sessionId)
@@ -414,7 +444,7 @@ function allowOutboundForSession(sessionId) {
414
444
  }
415
445
  function sendParentMessage(message) {
416
446
  const msgType = message && typeof message === "object" && "type" in message ? message.type : void 0;
417
- if (msgType === "mix_control" || msgType === "stt_control") {
447
+ if (msgType === "mix_control" || msgType === "stt_control" || msgType === "voice_language_control") {
418
448
  process.send?.(message);
419
449
  return;
420
450
  }
@@ -515,6 +545,7 @@ async function handleParentMessage(message, handlers) {
515
545
  recordingAvailableBySessionId.set(message.sessionId, message.recordingAvailable ?? false);
516
546
  conversationHistoryAvailableBySessionId.set(message.sessionId, message.conversationHistoryAvailable ?? false);
517
547
  mixAvailableBySessionId.set(message.sessionId, message.mixAvailable ?? false);
548
+ voiceLanguageSwitchAvailableBySessionId.set(message.sessionId, message.voiceLanguageSwitchAvailable ?? false);
518
549
  ttsPoseAvailableBySessionId.set(message.sessionId, message.ttsPoseAvailable ?? false);
519
550
  const sessionStartInitDelayMs = resolveSessionStartInitDelayMs();
520
551
  if (sessionStartInitDelayMs > 0) {
@@ -526,6 +557,7 @@ async function handleParentMessage(message, handlers) {
526
557
  recordingAvailable: message.recordingAvailable ?? false,
527
558
  conversationHistoryAvailable: message.conversationHistoryAvailable ?? false,
528
559
  mixAvailable: message.mixAvailable ?? false,
560
+ voiceLanguageSwitchAvailable: message.voiceLanguageSwitchAvailable ?? false,
529
561
  ttsPoseAvailable: message.ttsPoseAvailable ?? false
530
562
  });
531
563
  sendParentMessage({
@@ -544,12 +576,23 @@ async function handleParentMessage(message, handlers) {
544
576
  if (message.event.type === "user_language") {
545
577
  const language = resolveUserLanguageCode(message.event);
546
578
  if (language) {
579
+ lastVoiceLanguageBySessionId.set(message.sessionId, language);
547
580
  await handlers.onUserLanguage?.({
548
581
  sessionId: message.sessionId,
549
582
  language
550
583
  });
551
584
  }
552
585
  }
586
+ if (message.event.type === "voice_language_changed") {
587
+ const language = resolveUserLanguageCode(message.event);
588
+ if (language) {
589
+ lastVoiceLanguageBySessionId.set(message.sessionId, language);
590
+ await handlers.onVoiceLanguageChanged?.({
591
+ sessionId: message.sessionId,
592
+ language
593
+ });
594
+ }
595
+ }
553
596
  break;
554
597
  case "data_channel_message":
555
598
  await handlers.onDataChannelMessage?.({
@@ -576,6 +619,8 @@ async function handleParentMessage(message, handlers) {
576
619
  recordingAvailableBySessionId.delete(message.sessionId);
577
620
  conversationHistoryAvailableBySessionId.delete(message.sessionId);
578
621
  mixAvailableBySessionId.delete(message.sessionId);
622
+ voiceLanguageSwitchAvailableBySessionId.delete(message.sessionId);
623
+ lastVoiceLanguageBySessionId.delete(message.sessionId);
579
624
  ttsPoseAvailableBySessionId.delete(message.sessionId);
580
625
  await (handlers.onClientLeave ?? handlers.onSessionEnd)?.({
581
626
  sessionId: message.sessionId
@@ -624,6 +669,10 @@ function defineAgent(handlers) {
624
669
  handleSttControlAck(message);
625
670
  return;
626
671
  }
672
+ if (isVoiceLanguageControlAckMessage(message)) {
673
+ handleVoiceLanguageControlAck(message);
674
+ return;
675
+ }
627
676
  if (isWebhookMessage(message)) {
628
677
  void agentStartReady.then(() => handleWebhookMessage(message, handlers));
629
678
  return;