@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.
@@ -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;
@@ -251,6 +259,7 @@ var pendingPlayPoseAcks = /* @__PURE__ */ new Map();
251
259
  var MIX_CONTROL_ACK_TIMEOUT_MS = 5e3;
252
260
  var pendingMixAcks = /* @__PURE__ */ new Map();
253
261
  var pendingSttAcks = /* @__PURE__ */ new Map();
262
+ var pendingVoiceLanguageAcks = /* @__PURE__ */ new Map();
254
263
  function handleRecordingControlAck(message) {
255
264
  const pending = pendingRecordingAcks.get(message.requestId);
256
265
  if (!pending)
@@ -353,6 +362,27 @@ function handleSttControlAck(message) {
353
362
  requestId: message.requestId
354
363
  });
355
364
  }
365
+ function handleVoiceLanguageControlAck(message) {
366
+ const pending = pendingVoiceLanguageAcks.get(message.requestId);
367
+ if (!pending)
368
+ return;
369
+ clearTimeout(pending.timer);
370
+ pendingVoiceLanguageAcks.delete(message.requestId);
371
+ if (message.ok && message.language?.trim()) {
372
+ lastVoiceLanguageBySessionId.set(message.sessionId, message.language.trim());
373
+ }
374
+ pending.resolve({
375
+ ok: message.ok,
376
+ reason: message.reason,
377
+ requestId: message.requestId,
378
+ ...message.language ? { language: message.language } : {},
379
+ ...message.voice ? { voice: message.voice } : {},
380
+ ...message.stt ? { stt: message.stt } : {},
381
+ ...message.scope ? { scope: message.scope } : {},
382
+ ...message.sttProvider ? { sttProvider: message.sttProvider } : {},
383
+ ...message.ttsProvider ? { ttsProvider: message.ttsProvider } : {}
384
+ });
385
+ }
356
386
  function isTtsPoseAvailableInProcess() {
357
387
  for (const available of ttsPoseAvailableBySessionId.values()) {
358
388
  if (available)
@@ -433,7 +463,7 @@ function allowOutboundForSession(sessionId) {
433
463
  }
434
464
  function sendParentMessage(message) {
435
465
  const msgType = message && typeof message === "object" && "type" in message ? message.type : void 0;
436
- if (msgType === "mix_control" || msgType === "stt_control") {
466
+ if (msgType === "mix_control" || msgType === "stt_control" || msgType === "voice_language_control") {
437
467
  process.send?.(message);
438
468
  return;
439
469
  }
@@ -534,6 +564,7 @@ async function handleParentMessage(message, handlers) {
534
564
  recordingAvailableBySessionId.set(message.sessionId, message.recordingAvailable ?? false);
535
565
  conversationHistoryAvailableBySessionId.set(message.sessionId, message.conversationHistoryAvailable ?? false);
536
566
  mixAvailableBySessionId.set(message.sessionId, message.mixAvailable ?? false);
567
+ voiceLanguageSwitchAvailableBySessionId.set(message.sessionId, message.voiceLanguageSwitchAvailable ?? false);
537
568
  ttsPoseAvailableBySessionId.set(message.sessionId, message.ttsPoseAvailable ?? false);
538
569
  const sessionStartInitDelayMs = resolveSessionStartInitDelayMs();
539
570
  if (sessionStartInitDelayMs > 0) {
@@ -545,6 +576,7 @@ async function handleParentMessage(message, handlers) {
545
576
  recordingAvailable: message.recordingAvailable ?? false,
546
577
  conversationHistoryAvailable: message.conversationHistoryAvailable ?? false,
547
578
  mixAvailable: message.mixAvailable ?? false,
579
+ voiceLanguageSwitchAvailable: message.voiceLanguageSwitchAvailable ?? false,
548
580
  ttsPoseAvailable: message.ttsPoseAvailable ?? false
549
581
  });
550
582
  sendParentMessage({
@@ -563,12 +595,23 @@ async function handleParentMessage(message, handlers) {
563
595
  if (message.event.type === "user_language") {
564
596
  const language = resolveUserLanguageCode(message.event);
565
597
  if (language) {
598
+ lastVoiceLanguageBySessionId.set(message.sessionId, language);
566
599
  await handlers.onUserLanguage?.({
567
600
  sessionId: message.sessionId,
568
601
  language
569
602
  });
570
603
  }
571
604
  }
605
+ if (message.event.type === "voice_language_changed") {
606
+ const language = resolveUserLanguageCode(message.event);
607
+ if (language) {
608
+ lastVoiceLanguageBySessionId.set(message.sessionId, language);
609
+ await handlers.onVoiceLanguageChanged?.({
610
+ sessionId: message.sessionId,
611
+ language
612
+ });
613
+ }
614
+ }
572
615
  break;
573
616
  case "data_channel_message":
574
617
  await handlers.onDataChannelMessage?.({
@@ -595,6 +638,8 @@ async function handleParentMessage(message, handlers) {
595
638
  recordingAvailableBySessionId.delete(message.sessionId);
596
639
  conversationHistoryAvailableBySessionId.delete(message.sessionId);
597
640
  mixAvailableBySessionId.delete(message.sessionId);
641
+ voiceLanguageSwitchAvailableBySessionId.delete(message.sessionId);
642
+ lastVoiceLanguageBySessionId.delete(message.sessionId);
598
643
  ttsPoseAvailableBySessionId.delete(message.sessionId);
599
644
  await (handlers.onClientLeave ?? handlers.onSessionEnd)?.({
600
645
  sessionId: message.sessionId
@@ -643,6 +688,10 @@ function defineAgent(handlers) {
643
688
  handleSttControlAck(message);
644
689
  return;
645
690
  }
691
+ if (isVoiceLanguageControlAckMessage(message)) {
692
+ handleVoiceLanguageControlAck(message);
693
+ return;
694
+ }
646
695
  if (isWebhookMessage(message)) {
647
696
  void agentStartReady.then(() => handleWebhookMessage(message, handlers));
648
697
  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 RECORDING_CONTROL_ACK_TIMEOUT_MS = 5e3;
@@ -248,6 +256,7 @@ var pendingPlayStopAcks = /* @__PURE__ */ new Map();
248
256
  var pendingPlayPoseAcks = /* @__PURE__ */ new Map();
249
257
  var pendingMixAcks = /* @__PURE__ */ new Map();
250
258
  var pendingSttAcks = /* @__PURE__ */ new Map();
259
+ var pendingVoiceLanguageAcks = /* @__PURE__ */ new Map();
251
260
  function handleRecordingControlAck(message) {
252
261
  const pending = pendingRecordingAcks.get(message.requestId);
253
262
  if (!pending)
@@ -350,6 +359,27 @@ function handleSttControlAck(message) {
350
359
  requestId: message.requestId
351
360
  });
352
361
  }
362
+ function handleVoiceLanguageControlAck(message) {
363
+ const pending = pendingVoiceLanguageAcks.get(message.requestId);
364
+ if (!pending)
365
+ return;
366
+ clearTimeout(pending.timer);
367
+ pendingVoiceLanguageAcks.delete(message.requestId);
368
+ if (message.ok && message.language?.trim()) {
369
+ lastVoiceLanguageBySessionId.set(message.sessionId, message.language.trim());
370
+ }
371
+ pending.resolve({
372
+ ok: message.ok,
373
+ reason: message.reason,
374
+ requestId: message.requestId,
375
+ ...message.language ? { language: message.language } : {},
376
+ ...message.voice ? { voice: message.voice } : {},
377
+ ...message.stt ? { stt: message.stt } : {},
378
+ ...message.scope ? { scope: message.scope } : {},
379
+ ...message.sttProvider ? { sttProvider: message.sttProvider } : {},
380
+ ...message.ttsProvider ? { ttsProvider: message.ttsProvider } : {}
381
+ });
382
+ }
353
383
  function clearPendingRecordingAcksForSession(sessionId, reason) {
354
384
  for (const [requestId, pending] of pendingRecordingAcks) {
355
385
  if (pending.sessionId !== sessionId)
@@ -418,7 +448,7 @@ function allowOutboundForSession(sessionId) {
418
448
  }
419
449
  function sendParentMessage(message) {
420
450
  const msgType = message && typeof message === "object" && "type" in message ? message.type : void 0;
421
- if (msgType === "mix_control" || msgType === "stt_control") {
451
+ if (msgType === "mix_control" || msgType === "stt_control" || msgType === "voice_language_control") {
422
452
  process.send?.(message);
423
453
  return;
424
454
  }
@@ -519,6 +549,7 @@ async function handleParentMessage(message, handlers) {
519
549
  recordingAvailableBySessionId.set(message.sessionId, message.recordingAvailable ?? false);
520
550
  conversationHistoryAvailableBySessionId.set(message.sessionId, message.conversationHistoryAvailable ?? false);
521
551
  mixAvailableBySessionId.set(message.sessionId, message.mixAvailable ?? false);
552
+ voiceLanguageSwitchAvailableBySessionId.set(message.sessionId, message.voiceLanguageSwitchAvailable ?? false);
522
553
  ttsPoseAvailableBySessionId.set(message.sessionId, message.ttsPoseAvailable ?? false);
523
554
  const sessionStartInitDelayMs = resolveSessionStartInitDelayMs();
524
555
  if (sessionStartInitDelayMs > 0) {
@@ -530,6 +561,7 @@ async function handleParentMessage(message, handlers) {
530
561
  recordingAvailable: message.recordingAvailable ?? false,
531
562
  conversationHistoryAvailable: message.conversationHistoryAvailable ?? false,
532
563
  mixAvailable: message.mixAvailable ?? false,
564
+ voiceLanguageSwitchAvailable: message.voiceLanguageSwitchAvailable ?? false,
533
565
  ttsPoseAvailable: message.ttsPoseAvailable ?? false
534
566
  });
535
567
  sendParentMessage({
@@ -548,12 +580,23 @@ async function handleParentMessage(message, handlers) {
548
580
  if (message.event.type === "user_language") {
549
581
  const language = resolveUserLanguageCode(message.event);
550
582
  if (language) {
583
+ lastVoiceLanguageBySessionId.set(message.sessionId, language);
551
584
  await handlers.onUserLanguage?.({
552
585
  sessionId: message.sessionId,
553
586
  language
554
587
  });
555
588
  }
556
589
  }
590
+ if (message.event.type === "voice_language_changed") {
591
+ const language = resolveUserLanguageCode(message.event);
592
+ if (language) {
593
+ lastVoiceLanguageBySessionId.set(message.sessionId, language);
594
+ await handlers.onVoiceLanguageChanged?.({
595
+ sessionId: message.sessionId,
596
+ language
597
+ });
598
+ }
599
+ }
557
600
  break;
558
601
  case "data_channel_message":
559
602
  await handlers.onDataChannelMessage?.({
@@ -580,6 +623,8 @@ async function handleParentMessage(message, handlers) {
580
623
  recordingAvailableBySessionId.delete(message.sessionId);
581
624
  conversationHistoryAvailableBySessionId.delete(message.sessionId);
582
625
  mixAvailableBySessionId.delete(message.sessionId);
626
+ voiceLanguageSwitchAvailableBySessionId.delete(message.sessionId);
627
+ lastVoiceLanguageBySessionId.delete(message.sessionId);
583
628
  ttsPoseAvailableBySessionId.delete(message.sessionId);
584
629
  await (handlers.onClientLeave ?? handlers.onSessionEnd)?.({
585
630
  sessionId: message.sessionId
@@ -628,6 +673,10 @@ function defineAgent(handlers) {
628
673
  handleSttControlAck(message);
629
674
  return;
630
675
  }
676
+ if (isVoiceLanguageControlAckMessage(message)) {
677
+ handleVoiceLanguageControlAck(message);
678
+ return;
679
+ }
631
680
  if (isWebhookMessage(message)) {
632
681
  void agentStartReady.then(() => handleWebhookMessage(message, handlers));
633
682
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/templates/registry.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,KAAK,CAAC;AAE7C,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,mFAAmF;IACnF,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,YAAY,CAAC;IACnB,mFAAmF;IACnF,YAAY,EAAE,OAAO,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,yEAAyE;IACzE,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,oFAAoF;IACpF,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C;AAED,eAAO,MAAM,eAAe,EAAE,SAAS,uBAAuB,EAqLpD,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC;AAMrE,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,EAAE,IAAI,eAAe,CAEnE;AAED,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,uBAAuB,CAMnE;AAED,wBAAgB,yBAAyB,IAAI,uBAAuB,EAAE,CAErE"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/templates/registry.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,KAAK,CAAC;AAE7C,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,mFAAmF;IACnF,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,YAAY,CAAC;IACnB,mFAAmF;IACnF,YAAY,EAAE,OAAO,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,yEAAyE;IACzE,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,oFAAoF;IACpF,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C;AAED,eAAO,MAAM,eAAe,EAAE,SAAS,uBAAuB,EA8LpD,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC;AAMrE,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,EAAE,IAAI,eAAe,CAEnE;AAED,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,uBAAuB,CAMnE;AAED,wBAAgB,yBAAyB,IAAI,uBAAuB,EAAE,CAErE"}
@@ -15,6 +15,14 @@ export const AGENT_TEMPLATES = [
15
15
  description: "Data-channel-only echo — relays speech events and chat without TTS.",
16
16
  sourceFiles: ["echo-dc/agent.ts"],
17
17
  },
18
+ {
19
+ id: "language-switch",
20
+ entry: "language-switch/agent.ts",
21
+ kind: "product",
22
+ seedOnCreate: true,
23
+ description: "Switches STT and TTS independently from onUserLanguage, and can change one vendor mid-conversation. Detection does not change either side until this agent calls setVoiceLanguage.",
24
+ sourceFiles: ["language-switch/agent.ts"],
25
+ },
18
26
  {
19
27
  id: "voice-starter",
20
28
  entry: "voice-starter/agent.ts",
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/templates/registry.ts"],"names":[],"mappings":"AAgBA,MAAM,CAAC,MAAM,eAAe,GAAuC;IACjE;QACE,EAAE,EAAE,MAAM;QACV,KAAK,EAAE,eAAe;QACtB,IAAI,EAAE,SAAS;QACf,YAAY,EAAE,IAAI;QAClB,WAAW,EACT,8EAA8E;QAChF,WAAW,EAAE,CAAC,eAAe,CAAC;KAC/B;IACD;QACE,EAAE,EAAE,SAAS;QACb,KAAK,EAAE,kBAAkB;QACzB,IAAI,EAAE,SAAS;QACf,YAAY,EAAE,IAAI;QAClB,WAAW,EACT,qEAAqE;QACvE,WAAW,EAAE,CAAC,kBAAkB,CAAC;KAClC;IACD;QACE,EAAE,EAAE,eAAe;QACnB,KAAK,EAAE,wBAAwB;QAC/B,IAAI,EAAE,SAAS;QACf,YAAY,EAAE,IAAI;QAClB,WAAW,EACT,uFAAuF;QACzF,WAAW,EAAE,CAAC,wBAAwB,CAAC;KACxC;IACD;QACE,EAAE,EAAE,YAAY;QAChB,KAAK,EAAE,qBAAqB;QAC5B,IAAI,EAAE,SAAS;QACf,YAAY,EAAE,IAAI;QAClB,WAAW,EACT,wFAAwF;QAC1F,WAAW,EAAE,CAAC,qBAAqB,CAAC;KACrC;IACD;QACE,EAAE,EAAE,mBAAmB;QACvB,KAAK,EAAE,4BAA4B;QACnC,IAAI,EAAE,SAAS;QACf,YAAY,EAAE,IAAI;QAClB,WAAW,EACT,wGAAwG;QAC1G,WAAW,EAAE,CAAC,4BAA4B,EAAE,+BAA+B,CAAC;KAC7E;IACD;QACE,EAAE,EAAE,WAAW;QACf,KAAK,EAAE,oBAAoB;QAC3B,IAAI,EAAE,SAAS;QACf,YAAY,EAAE,IAAI;QAClB,WAAW,EACT,sGAAsG;QACxG,WAAW,EAAE;YACX,oBAAoB;YACpB,uBAAuB;YACvB,2BAA2B;YAC3B,kBAAkB;YAClB,oBAAoB;SACrB;QACD,eAAe,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE;KACxC;IACD;QACE,EAAE,EAAE,gBAAgB;QACpB,KAAK,EAAE,yBAAyB;QAChC,IAAI,EAAE,SAAS;QACf,YAAY,EAAE,IAAI;QAClB,WAAW,EACT,0FAA0F;QAC5F,WAAW,EAAE;YACX,yBAAyB;YACzB,gCAAgC;YAChC,4BAA4B;YAC5B,2BAA2B;YAC3B,2BAA2B;YAC3B,6BAA6B;SAC9B;KACF;IACD;QACE,EAAE,EAAE,mBAAmB;QACvB,KAAK,EAAE,4BAA4B;QACnC,IAAI,EAAE,SAAS;QACf,YAAY,EAAE,IAAI;QAClB,WAAW,EACT,mFAAmF;QACrF,WAAW,EAAE;YACX,4BAA4B;YAC5B,mCAAmC;SACpC;KACF;IACD;QACE,EAAE,EAAE,gBAAgB;QACpB,KAAK,EAAE,yBAAyB;QAChC,IAAI,EAAE,SAAS;QACf,YAAY,EAAE,IAAI;QAClB,WAAW,EACT,gFAAgF;QAClF,WAAW,EAAE,CAAC,yBAAyB,EAAE,yBAAyB,CAAC;KACpE;IACD;QACE,EAAE,EAAE,kBAAkB;QACtB,KAAK,EAAE,2BAA2B;QAClC,IAAI,EAAE,SAAS;QACf,YAAY,EAAE,IAAI;QAClB,WAAW,EACT,oHAAoH;QACtH,WAAW,EAAE;YACX,2BAA2B;YAC3B,8BAA8B;YAC9B,4BAA4B;YAC5B,0BAA0B;YAC1B,2BAA2B;YAC3B,mCAAmC;YACnC,0BAA0B;SAC3B;KACF;IACD;QACE,EAAE,EAAE,UAAU;QACd,KAAK,EAAE,mBAAmB;QAC1B,IAAI,EAAE,SAAS;QACf,YAAY,EAAE,IAAI;QAClB,WAAW,EACT,sFAAsF;QACxF,WAAW,EAAE,CAAC,mBAAmB,CAAC;KACnC;IACD;QACE,EAAE,EAAE,gBAAgB;QACpB,KAAK,EAAE,yBAAyB;QAChC,IAAI,EAAE,SAAS;QACf,YAAY,EAAE,IAAI;QAClB,WAAW,EACT,4EAA4E;QAC9E,WAAW,EAAE,CAAC,yBAAyB,CAAC;QACxC,eAAe,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE;KACxC;IACD;QACE,EAAE,EAAE,YAAY;QAChB,KAAK,EAAE,qBAAqB;QAC5B,IAAI,EAAE,KAAK;QACX,YAAY,EAAE,KAAK;QACnB,WAAW,EACT,6EAA6E;QAC/E,WAAW,EAAE,CAAC,qBAAqB,CAAC;KACrC;IACD;QACE,EAAE,EAAE,OAAO;QACX,KAAK,EAAE,gBAAgB;QACvB,IAAI,EAAE,KAAK;QACX,YAAY,EAAE,KAAK;QACnB,WAAW,EACT,4EAA4E;QAC9E,WAAW,EAAE,CAAC,gBAAgB,CAAC;KAChC;IACD;QACE,EAAE,EAAE,iBAAiB;QACrB,KAAK,EAAE,0BAA0B;QACjC,IAAI,EAAE,KAAK;QACX,YAAY,EAAE,KAAK;QACnB,WAAW,EACT,6EAA6E;QAC/E,WAAW,EAAE,CAAC,0BAA0B,CAAC;KAC1C;IACD;QACE,EAAE,EAAE,YAAY;QAChB,KAAK,EAAE,qBAAqB;QAC5B,IAAI,EAAE,KAAK;QACX,YAAY,EAAE,KAAK;QACnB,WAAW,EACT,uGAAuG;QACzG,WAAW,EAAE,CAAC,qBAAqB,EAAE,4BAA4B,CAAC;QAClE,eAAe,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE;KACxC;IACD;QACE,EAAE,EAAE,WAAW;QACf,KAAK,EAAE,oBAAoB;QAC3B,IAAI,EAAE,KAAK;QACX,YAAY,EAAE,KAAK;QACnB,WAAW,EACT,iFAAiF;QACnF,WAAW,EAAE,CAAC,oBAAoB,CAAC;KACpC;CACO,CAAC;AAIX,MAAM,cAAc,GAAG,IAAI,GAAG,CAC5B,eAAe,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC,CAC3D,CAAC;AAEF,MAAM,UAAU,iBAAiB,CAAC,EAAU;IAC1C,OAAO,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,EAAU;IACxC,MAAM,QAAQ,GAAG,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACxC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,8BAA8B,EAAE,EAAE,CAAC,CAAC;IACtD,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,yBAAyB;IACvC,OAAO,eAAe,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;AACrE,CAAC"}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/templates/registry.ts"],"names":[],"mappings":"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"}
@@ -182,6 +182,12 @@ function isSttControlAckMessage(value) {
182
182
  const msg = value;
183
183
  return msg.type === "stt_control_ack" && typeof msg.requestId === "string";
184
184
  }
185
+ function isVoiceLanguageControlAckMessage(value) {
186
+ if (!value || typeof value !== "object")
187
+ return false;
188
+ const msg = value;
189
+ return msg.type === "voice_language_control_ack" && typeof msg.requestId === "string";
190
+ }
185
191
  function isWebhookMessage(value) {
186
192
  if (!value || typeof value !== "object")
187
193
  return false;
@@ -224,7 +230,7 @@ function isParentMessage(value) {
224
230
  if (!value || typeof value !== "object")
225
231
  return false;
226
232
  const msg = value;
227
- 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";
233
+ 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";
228
234
  }
229
235
  function isSessionScopedParentMessage(value) {
230
236
  return isParentMessage(value) && !isWebhookMessage(value);
@@ -240,6 +246,8 @@ var peerEnvBySessionId = /* @__PURE__ */ new Map();
240
246
  var recordingAvailableBySessionId = /* @__PURE__ */ new Map();
241
247
  var conversationHistoryAvailableBySessionId = /* @__PURE__ */ new Map();
242
248
  var mixAvailableBySessionId = /* @__PURE__ */ new Map();
249
+ var voiceLanguageSwitchAvailableBySessionId = /* @__PURE__ */ new Map();
250
+ var lastVoiceLanguageBySessionId = /* @__PURE__ */ new Map();
243
251
  var ttsPoseAvailableBySessionId = /* @__PURE__ */ new Map();
244
252
  var endedSessionIds = /* @__PURE__ */ new Set();
245
253
  var PLAY_CONTROL_ACK_TIMEOUT_MS = 5e3;
@@ -254,6 +262,7 @@ var MIX_CONTROL_ACK_TIMEOUT_MS = 5e3;
254
262
  var STT_CONTROL_ACK_TIMEOUT_MS = 5e3;
255
263
  var pendingMixAcks = /* @__PURE__ */ new Map();
256
264
  var pendingSttAcks = /* @__PURE__ */ new Map();
265
+ var pendingVoiceLanguageAcks = /* @__PURE__ */ new Map();
257
266
  function handleRecordingControlAck(message) {
258
267
  const pending = pendingRecordingAcks.get(message.requestId);
259
268
  if (!pending)
@@ -356,6 +365,27 @@ function handleSttControlAck(message) {
356
365
  requestId: message.requestId
357
366
  });
358
367
  }
368
+ function handleVoiceLanguageControlAck(message) {
369
+ const pending = pendingVoiceLanguageAcks.get(message.requestId);
370
+ if (!pending)
371
+ return;
372
+ clearTimeout(pending.timer);
373
+ pendingVoiceLanguageAcks.delete(message.requestId);
374
+ if (message.ok && message.language?.trim()) {
375
+ lastVoiceLanguageBySessionId.set(message.sessionId, message.language.trim());
376
+ }
377
+ pending.resolve({
378
+ ok: message.ok,
379
+ reason: message.reason,
380
+ requestId: message.requestId,
381
+ ...message.language ? { language: message.language } : {},
382
+ ...message.voice ? { voice: message.voice } : {},
383
+ ...message.stt ? { stt: message.stt } : {},
384
+ ...message.scope ? { scope: message.scope } : {},
385
+ ...message.sttProvider ? { sttProvider: message.sttProvider } : {},
386
+ ...message.ttsProvider ? { ttsProvider: message.ttsProvider } : {}
387
+ });
388
+ }
359
389
  function isMixAvailableInProcess() {
360
390
  for (const available of mixAvailableBySessionId.values()) {
361
391
  if (available)
@@ -448,7 +478,7 @@ function allowOutboundForSession(sessionId) {
448
478
  }
449
479
  function sendParentMessage(message) {
450
480
  const msgType = message && typeof message === "object" && "type" in message ? message.type : void 0;
451
- if (msgType === "mix_control" || msgType === "stt_control") {
481
+ if (msgType === "mix_control" || msgType === "stt_control" || msgType === "voice_language_control") {
452
482
  process.send?.(message);
453
483
  return;
454
484
  }
@@ -549,6 +579,7 @@ async function handleParentMessage(message, handlers) {
549
579
  recordingAvailableBySessionId.set(message.sessionId, message.recordingAvailable ?? false);
550
580
  conversationHistoryAvailableBySessionId.set(message.sessionId, message.conversationHistoryAvailable ?? false);
551
581
  mixAvailableBySessionId.set(message.sessionId, message.mixAvailable ?? false);
582
+ voiceLanguageSwitchAvailableBySessionId.set(message.sessionId, message.voiceLanguageSwitchAvailable ?? false);
552
583
  ttsPoseAvailableBySessionId.set(message.sessionId, message.ttsPoseAvailable ?? false);
553
584
  const sessionStartInitDelayMs = resolveSessionStartInitDelayMs();
554
585
  if (sessionStartInitDelayMs > 0) {
@@ -560,6 +591,7 @@ async function handleParentMessage(message, handlers) {
560
591
  recordingAvailable: message.recordingAvailable ?? false,
561
592
  conversationHistoryAvailable: message.conversationHistoryAvailable ?? false,
562
593
  mixAvailable: message.mixAvailable ?? false,
594
+ voiceLanguageSwitchAvailable: message.voiceLanguageSwitchAvailable ?? false,
563
595
  ttsPoseAvailable: message.ttsPoseAvailable ?? false
564
596
  });
565
597
  sendParentMessage({
@@ -578,12 +610,23 @@ async function handleParentMessage(message, handlers) {
578
610
  if (message.event.type === "user_language") {
579
611
  const language = resolveUserLanguageCode(message.event);
580
612
  if (language) {
613
+ lastVoiceLanguageBySessionId.set(message.sessionId, language);
581
614
  await handlers.onUserLanguage?.({
582
615
  sessionId: message.sessionId,
583
616
  language
584
617
  });
585
618
  }
586
619
  }
620
+ if (message.event.type === "voice_language_changed") {
621
+ const language = resolveUserLanguageCode(message.event);
622
+ if (language) {
623
+ lastVoiceLanguageBySessionId.set(message.sessionId, language);
624
+ await handlers.onVoiceLanguageChanged?.({
625
+ sessionId: message.sessionId,
626
+ language
627
+ });
628
+ }
629
+ }
587
630
  break;
588
631
  case "data_channel_message":
589
632
  await handlers.onDataChannelMessage?.({
@@ -610,6 +653,8 @@ async function handleParentMessage(message, handlers) {
610
653
  recordingAvailableBySessionId.delete(message.sessionId);
611
654
  conversationHistoryAvailableBySessionId.delete(message.sessionId);
612
655
  mixAvailableBySessionId.delete(message.sessionId);
656
+ voiceLanguageSwitchAvailableBySessionId.delete(message.sessionId);
657
+ lastVoiceLanguageBySessionId.delete(message.sessionId);
613
658
  ttsPoseAvailableBySessionId.delete(message.sessionId);
614
659
  await (handlers.onClientLeave ?? handlers.onSessionEnd)?.({
615
660
  sessionId: message.sessionId
@@ -658,6 +703,10 @@ function defineAgent(handlers) {
658
703
  handleSttControlAck(message);
659
704
  return;
660
705
  }
706
+ if (isVoiceLanguageControlAckMessage(message)) {
707
+ handleVoiceLanguageControlAck(message);
708
+ return;
709
+ }
661
710
  if (isWebhookMessage(message)) {
662
711
  void agentStartReady.then(() => handleWebhookMessage(message, handlers));
663
712
  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;