@shogo-ai/voice 1.9.13 → 2.4.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.
Files changed (68) hide show
  1. package/README.md +89 -0
  2. package/dist/{chunk-S3S2RNO6.js → chunk-BI6SL35K.js} +1 -184
  3. package/dist/chunk-CLF25CZC.js +987 -0
  4. package/dist/chunk-KMSL5PWK.js +540 -0
  5. package/dist/chunk-ME3SIZZU.js +581 -0
  6. package/dist/chunk-TQOBJMEK.js +17 -0
  7. package/dist/{chunk-T3T4EBWY.js → chunk-UH75UVM2.js} +6 -2
  8. package/dist/chunk-UW7VQ3S6.js +148 -0
  9. package/dist/chunk-XE4LLC7Z.js +1067 -0
  10. package/dist/chunk-ZAW6F3YT.js +172 -0
  11. package/dist/index.cjs +735 -25
  12. package/dist/index.d.cts +373 -3
  13. package/dist/index.d.ts +373 -3
  14. package/dist/index.js +59 -3
  15. package/dist/live/client.cjs +173 -0
  16. package/dist/live/client.d.cts +132 -0
  17. package/dist/live/client.d.ts +132 -0
  18. package/dist/live/client.js +9 -0
  19. package/dist/native/index.d.cts +5 -2
  20. package/dist/native/index.d.ts +5 -2
  21. package/dist/native/index.js +15 -11
  22. package/dist/{organicParticlesShaders-DIva0vBO.d.ts → organicParticlesShaders-seZq7jYX.d.cts} +1 -421
  23. package/dist/{organicParticlesShaders-DIva0vBO.d.cts → organicParticlesShaders-seZq7jYX.d.ts} +1 -421
  24. package/dist/particlesConfig-0YbdPOdY.d.cts +223 -0
  25. package/dist/particlesConfig-0YbdPOdY.d.ts +223 -0
  26. package/dist/react/conversation.cjs +789 -0
  27. package/dist/react/conversation.d.cts +134 -0
  28. package/dist/react/conversation.d.ts +134 -0
  29. package/dist/react/conversation.js +13 -0
  30. package/dist/react/index.cjs +374 -36
  31. package/dist/react/index.d.cts +10 -141
  32. package/dist/react/index.d.ts +10 -141
  33. package/dist/react/index.js +23 -770
  34. package/dist/react/visuals.cjs +1048 -0
  35. package/dist/react/visuals.d.cts +70 -0
  36. package/dist/react/visuals.d.ts +70 -0
  37. package/dist/react/visuals.js +10 -0
  38. package/dist/route/agent.cjs +1038 -85
  39. package/dist/route/agent.js +3 -3
  40. package/dist/route/audio-tags.cjs +1038 -85
  41. package/dist/route/audio-tags.js +3 -3
  42. package/dist/route/index.cjs +1042 -85
  43. package/dist/route/index.d.cts +19 -3
  44. package/dist/route/index.d.ts +19 -3
  45. package/dist/route/index.js +3 -3
  46. package/dist/route/music.cjs +1038 -85
  47. package/dist/route/music.js +3 -3
  48. package/dist/route/op.cjs +2118 -0
  49. package/dist/route/op.d.cts +43 -0
  50. package/dist/route/op.d.ts +43 -0
  51. package/dist/route/op.js +27 -0
  52. package/dist/route/signed-url.cjs +1038 -85
  53. package/dist/route/signed-url.js +3 -3
  54. package/dist/route/tts-preview.cjs +1038 -85
  55. package/dist/route/tts-preview.d.cts +6 -4
  56. package/dist/route/tts-preview.d.ts +6 -4
  57. package/dist/route/tts-preview.js +3 -3
  58. package/dist/server.cjs +1038 -85
  59. package/dist/server.d.cts +40 -8
  60. package/dist/server.d.ts +40 -8
  61. package/dist/server.js +2 -2
  62. package/dist/types-Bfhu-aQH.d.cts +199 -0
  63. package/dist/types-Bfhu-aQH.d.ts +199 -0
  64. package/dist/{types-W9y6eMj3.d.ts → types-CadjTXNH.d.cts} +193 -12
  65. package/dist/{types-W9y6eMj3.d.cts → types-CadjTXNH.d.ts} +193 -12
  66. package/package.json +21 -1
  67. package/dist/chunk-B4JC3DK2.js +0 -529
  68. package/dist/chunk-O362EJQR.js +0 -524
@@ -43,6 +43,7 @@ __export(react_exports, {
43
43
  resolveOrganicParticlesConfig: () => resolveOrganicParticlesConfig,
44
44
  resolveOrganicSphereConfig: () => resolveOrganicSphereConfig,
45
45
  useChatConversation: () => useChatConversation,
46
+ useLiveVoiceConversation: () => useLiveVoiceConversation,
46
47
  useShogoChat: () => useShogoChat,
47
48
  useShogoVoice: () => useShogoVoice,
48
49
  useVoiceConversation: () => useVoiceConversation
@@ -244,6 +245,25 @@ function withProjectQuery(signedUrlPath, params) {
244
245
  return `${signedUrlPath}${sep}${tail.join("&")}`;
245
246
  }
246
247
 
248
+ // src/react/mic-access.ts
249
+ var MIC_BLOCKED_MESSAGE = "Microphone access is blocked. Allow it in your system or browser settings (on macOS: System Settings > Privacy & Security > Microphone), then try again.";
250
+ var MIC_NOT_FOUND_MESSAGE = "No microphone was found. Connect one and try again.";
251
+ async function requestMicStream(constraints = { audio: true }) {
252
+ const desktop = globalThis.shogoDesktop;
253
+ if (desktop?.isDesktop && desktop.ensureMicAccess) {
254
+ const access = await desktop.ensureMicAccess().catch(() => "granted");
255
+ if (access !== "granted") throw new Error(MIC_BLOCKED_MESSAGE);
256
+ }
257
+ try {
258
+ return await navigator.mediaDevices.getUserMedia(constraints);
259
+ } catch (err) {
260
+ const name = err?.name;
261
+ if (name === "NotAllowedError" || name === "SecurityError") throw new Error(MIC_BLOCKED_MESSAGE);
262
+ if (name === "NotFoundError" || name === "OverconstrainedError") throw new Error(MIC_NOT_FOUND_MESSAGE);
263
+ throw err;
264
+ }
265
+ }
266
+
247
267
  // src/react/useVoiceConversation.ts
248
268
  function useVoiceConversation(options) {
249
269
  const {
@@ -359,7 +379,8 @@ function useVoiceConversation(options) {
359
379
  } catch {
360
380
  }
361
381
  }
362
- await navigator.mediaDevices.getUserMedia({ audio: true });
382
+ const micStream = await requestMicStream({ audio: true });
383
+ micStream.getTracks().forEach((track) => track.stop());
363
384
  const data = await fetchSignedUrl({
364
385
  path: resolvedSignedUrlPath,
365
386
  fetchCredentials,
@@ -461,6 +482,322 @@ function useVoiceConversation(options) {
461
482
  };
462
483
  }
463
484
 
485
+ // src/react/useLiveVoiceConversation.ts
486
+ var import_react3 = require("react");
487
+ function parseEvent(data) {
488
+ try {
489
+ const text = typeof data === "string" ? data : String(data);
490
+ const event = JSON.parse(text);
491
+ return event && typeof event === "object" ? event : null;
492
+ } catch {
493
+ return null;
494
+ }
495
+ }
496
+ function waitForIceGathering(pc) {
497
+ if (pc.iceGatheringState === "complete") return Promise.resolve();
498
+ return new Promise((resolve) => {
499
+ const onStateChange = () => {
500
+ if (pc.iceGatheringState === "complete") {
501
+ pc.removeEventListener("icegatheringstatechange", onStateChange);
502
+ resolve();
503
+ }
504
+ };
505
+ pc.addEventListener("icegatheringstatechange", onStateChange);
506
+ window.setTimeout(() => {
507
+ pc.removeEventListener("icegatheringstatechange", onStateChange);
508
+ resolve();
509
+ }, 2e3);
510
+ });
511
+ }
512
+ function splitContext(text) {
513
+ const chunks = [];
514
+ for (let offset = 0; offset < text.length; offset += 1800) {
515
+ chunks.push(text.slice(offset, offset + 1800));
516
+ }
517
+ return chunks.length ? chunks : [""];
518
+ }
519
+ var TRANSCRIPT_HISTORY_MAX = 30;
520
+ function useLiveVoiceConversation(options) {
521
+ const { mintSession } = options;
522
+ const [status, setStatus] = (0, import_react3.useState)("disconnected");
523
+ const [isSpeaking, setIsSpeaking] = (0, import_react3.useState)(false);
524
+ const [isListening, setIsListening] = (0, import_react3.useState)(false);
525
+ const [isMuted, setIsMuted] = (0, import_react3.useState)(false);
526
+ const [sessionId, setSessionId] = (0, import_react3.useState)(null);
527
+ const optionsRef = (0, import_react3.useRef)(options);
528
+ optionsRef.current = options;
529
+ const pcRef = (0, import_react3.useRef)(null);
530
+ const dataChannelRef = (0, import_react3.useRef)(null);
531
+ const mediaStreamRef = (0, import_react3.useRef)(null);
532
+ const audioRef = (0, import_react3.useRef)(null);
533
+ const analyserRef = (0, import_react3.useRef)(null);
534
+ const frequencyRef = (0, import_react3.useRef)(null);
535
+ const audioContextRef = (0, import_react3.useRef)(null);
536
+ const speakingFrameRef = (0, import_react3.useRef)(null);
537
+ const inputTranscriptRef = (0, import_react3.useRef)("");
538
+ const outputTranscriptRef = (0, import_react3.useRef)("");
539
+ const historyRef = (0, import_react3.useRef)([]);
540
+ const closingRef = (0, import_react3.useRef)(false);
541
+ const mutedRef = (0, import_react3.useRef)(false);
542
+ const emit = (0, import_react3.useCallback)((source, message) => {
543
+ const text = message.trim();
544
+ if (!text) return;
545
+ const history = historyRef.current;
546
+ history.push({ role: source === "user" ? "user" : "assistant", text });
547
+ if (history.length > TRANSCRIPT_HISTORY_MAX) history.splice(0, history.length - TRANSCRIPT_HISTORY_MAX);
548
+ optionsRef.current.onMessage?.({ source, message: text });
549
+ }, []);
550
+ const flushTranscripts = (0, import_react3.useCallback)(() => {
551
+ const input = inputTranscriptRef.current.trim();
552
+ const output = outputTranscriptRef.current.trim();
553
+ inputTranscriptRef.current = "";
554
+ outputTranscriptRef.current = "";
555
+ if (input) emit("user", input);
556
+ if (output) emit("agent", output);
557
+ }, [emit]);
558
+ const sendEvent = (0, import_react3.useCallback)((event) => {
559
+ const channel = dataChannelRef.current;
560
+ if (channel?.readyState === "open") channel.send(JSON.stringify(event));
561
+ }, []);
562
+ const updateSpeaking = (0, import_react3.useCallback)(() => {
563
+ const analyser = analyserRef.current;
564
+ if (analyser) {
565
+ const data = frequencyRef.current ?? new Uint8Array(analyser.frequencyBinCount);
566
+ frequencyRef.current = data;
567
+ analyser.getByteFrequencyData(data);
568
+ let sum = 0;
569
+ for (const value of data) sum += value;
570
+ setIsSpeaking(data.length > 0 && sum / data.length > 8);
571
+ }
572
+ if (pcRef.current) speakingFrameRef.current = requestAnimationFrame(updateSpeaking);
573
+ }, []);
574
+ const handleEvent = (0, import_react3.useCallback)(async (event) => {
575
+ const nested = event.type === "response.event" && event.event ? event.event : event;
576
+ const type = nested.type ?? "";
577
+ if (type === "session.started" || type === "session.created") {
578
+ setStatus("connected");
579
+ setIsListening(!mutedRef.current);
580
+ const id = typeof nested.session?.id === "string" ? nested.session.id : null;
581
+ if (id) setSessionId(id);
582
+ }
583
+ if (type === "session.closed") {
584
+ flushTranscripts();
585
+ setStatus("disconnected");
586
+ setIsListening(false);
587
+ }
588
+ if (type === "error") {
589
+ optionsRef.current.onError?.(new Error(event.error?.message || "GPT-Live error"));
590
+ }
591
+ if (type === "session.input_transcript.delta" || type === "input_audio_transcription.delta") {
592
+ inputTranscriptRef.current += event.delta ?? "";
593
+ }
594
+ if (type === "session.output_transcript.delta" || type === "response.audio_transcript.delta") {
595
+ outputTranscriptRef.current += event.delta ?? "";
596
+ }
597
+ if (type === "session.input_transcript.done" || type === "input_audio_transcription.completed" || type === "session.output_transcript.done" || type === "response.audio_transcript.done" || type === "response.done" || type === "response.completed") {
598
+ flushTranscripts();
599
+ }
600
+ if (type === "session.delegation.created" && nested.delegation?.target !== "responses" && typeof nested.delegation?.id === "string") {
601
+ const onDelegation = optionsRef.current.onDelegation;
602
+ if (!onDelegation) return;
603
+ const delegationId = nested.delegation.id;
604
+ flushTranscripts();
605
+ let result;
606
+ try {
607
+ result = await onDelegation({ delegationId, transcript: [...historyRef.current] });
608
+ } catch (error) {
609
+ optionsRef.current.onError?.(error);
610
+ result = "That request failed before it could finish. Nothing was confirmed.";
611
+ }
612
+ const text = typeof result === "string" ? result.trim() : "";
613
+ if (!text) return;
614
+ for (const content of splitContext(text)) {
615
+ sendEvent({
616
+ type: "session.commentary.append",
617
+ delegation_id: delegationId,
618
+ content
619
+ });
620
+ }
621
+ return;
622
+ }
623
+ const item = nested.item;
624
+ if (type === "response.output_item.done" && item?.type === "function_call") {
625
+ const tool = optionsRef.current.clientTools?.[item.name ?? ""];
626
+ if (!tool || !item.call_id) return;
627
+ let args = {};
628
+ try {
629
+ const parsed = JSON.parse(item.arguments || "{}");
630
+ if (parsed && typeof parsed === "object") args = parsed;
631
+ } catch {
632
+ }
633
+ let output;
634
+ try {
635
+ output = String(await tool(args));
636
+ } catch (error) {
637
+ output = `Tool failed: ${error instanceof Error ? error.message : String(error)}`;
638
+ }
639
+ sendEvent({
640
+ type: "response.item.create",
641
+ item: {
642
+ type: "function_call_output",
643
+ call_id: item.call_id,
644
+ output
645
+ }
646
+ });
647
+ sendEvent({ type: "response.create" });
648
+ }
649
+ }, [flushTranscripts, sendEvent]);
650
+ const end = (0, import_react3.useCallback)(() => {
651
+ closingRef.current = true;
652
+ flushTranscripts();
653
+ sendEvent({ type: "session.close" });
654
+ dataChannelRef.current?.close();
655
+ pcRef.current?.close();
656
+ mediaStreamRef.current?.getTracks().forEach((track) => track.stop());
657
+ audioRef.current?.pause();
658
+ if (speakingFrameRef.current !== null) cancelAnimationFrame(speakingFrameRef.current);
659
+ speakingFrameRef.current = null;
660
+ pcRef.current = null;
661
+ dataChannelRef.current = null;
662
+ mediaStreamRef.current = null;
663
+ analyserRef.current = null;
664
+ frequencyRef.current = null;
665
+ audioContextRef.current?.close().catch(() => {
666
+ });
667
+ audioContextRef.current = null;
668
+ setIsSpeaking(false);
669
+ setIsListening(false);
670
+ setSessionId(null);
671
+ setStatus("disconnected");
672
+ }, [flushTranscripts, sendEvent]);
673
+ const startInternal = (0, import_react3.useCallback)(async () => {
674
+ if (status === "connected" || status === "connecting") end();
675
+ closingRef.current = false;
676
+ setStatus("connecting");
677
+ try {
678
+ const stream = await requestMicStream({ audio: true });
679
+ mediaStreamRef.current = stream;
680
+ const pc = new RTCPeerConnection();
681
+ pcRef.current = pc;
682
+ stream.getTracks().forEach((track) => pc.addTrack(track, stream));
683
+ const channel = pc.createDataChannel("oai-events");
684
+ dataChannelRef.current = channel;
685
+ channel.onopen = () => {
686
+ if (!closingRef.current) setIsListening(!mutedRef.current);
687
+ };
688
+ channel.onmessage = (message) => {
689
+ const event = parseEvent(message.data);
690
+ if (event) void handleEvent(event);
691
+ };
692
+ channel.onerror = (event) => optionsRef.current.onError?.(event);
693
+ pc.ontrack = (event) => {
694
+ const remoteStream = event.streams[0];
695
+ if (!remoteStream) return;
696
+ const audio = new Audio();
697
+ audio.autoplay = true;
698
+ audio.srcObject = remoteStream;
699
+ audioRef.current = audio;
700
+ void audio.play().catch(() => {
701
+ });
702
+ try {
703
+ const AudioContextImpl = window.AudioContext || window.webkitAudioContext;
704
+ if (AudioContextImpl) {
705
+ const context = new AudioContextImpl();
706
+ const source = context.createMediaStreamSource(remoteStream);
707
+ const analyser = context.createAnalyser();
708
+ analyser.fftSize = 256;
709
+ source.connect(analyser);
710
+ audioContextRef.current = context;
711
+ analyserRef.current = analyser;
712
+ frequencyRef.current = new Uint8Array(analyser.frequencyBinCount);
713
+ if (speakingFrameRef.current === null) {
714
+ speakingFrameRef.current = requestAnimationFrame(updateSpeaking);
715
+ }
716
+ }
717
+ } catch {
718
+ }
719
+ };
720
+ pc.onconnectionstatechange = () => {
721
+ if (["failed", "disconnected", "closed"].includes(pc.connectionState) && !closingRef.current) {
722
+ optionsRef.current.onError?.(new Error(`GPT-Live connection ${pc.connectionState}`));
723
+ end();
724
+ }
725
+ };
726
+ const offer = await pc.createOffer();
727
+ await pc.setLocalDescription(offer);
728
+ await waitForIceGathering(pc);
729
+ const localSdp = pc.localDescription?.sdp;
730
+ if (!localSdp) throw new Error("Failed to create a WebRTC offer");
731
+ const answer = await mintSession(localSdp);
732
+ await pc.setRemoteDescription({ type: "answer", sdp: answer.sdp });
733
+ setSessionId(answer.sessionId);
734
+ setStatus("connected");
735
+ } catch (error) {
736
+ end();
737
+ optionsRef.current.onError?.(error);
738
+ throw error;
739
+ }
740
+ }, [end, handleEvent, mintSession, status, updateSpeaking]);
741
+ const start = (0, import_react3.useCallback)(async () => {
742
+ await startInternal();
743
+ }, [startInternal]);
744
+ const restart = (0, import_react3.useCallback)(async () => {
745
+ end();
746
+ await new Promise((resolve) => window.setTimeout(resolve, 120));
747
+ await startInternal();
748
+ }, [end, startInternal]);
749
+ const setMuted = (0, import_react3.useCallback)((muted) => {
750
+ mutedRef.current = muted;
751
+ mediaStreamRef.current?.getAudioTracks().forEach((track) => {
752
+ track.enabled = !muted;
753
+ });
754
+ sendEvent({ type: muted ? "session.input_audio.mute" : "session.input_audio.unmute" });
755
+ setIsMuted(muted);
756
+ setIsListening(!muted && status === "connected");
757
+ }, [sendEvent, status]);
758
+ const sendContextualUpdate = (0, import_react3.useCallback)((text) => {
759
+ for (const content of splitContext(text)) {
760
+ sendEvent({
761
+ type: "session.thinking.append",
762
+ delegation_id: null,
763
+ content
764
+ });
765
+ }
766
+ }, [sendEvent]);
767
+ const sendUserMessage = (0, import_react3.useCallback)((text) => {
768
+ sendEvent({
769
+ type: "session.commentary.append",
770
+ delegation_id: null,
771
+ content: text
772
+ });
773
+ }, [sendEvent]);
774
+ const sendUserActivity = (0, import_react3.useCallback)(() => {
775
+ sendEvent({ type: "session.input_audio.commit" });
776
+ }, [sendEvent]);
777
+ const getOutputByteFrequencyData = (0, import_react3.useCallback)(() => {
778
+ return frequencyRef.current;
779
+ }, []);
780
+ const getTranscript = (0, import_react3.useCallback)(() => [...historyRef.current], []);
781
+ (0, import_react3.useEffect)(() => () => end(), [end]);
782
+ return {
783
+ start,
784
+ end,
785
+ restart,
786
+ status,
787
+ isSpeaking,
788
+ isListening,
789
+ isMuted,
790
+ setMuted,
791
+ getOutputByteFrequencyData,
792
+ sendContextualUpdate,
793
+ sendUserMessage,
794
+ sendUserActivity,
795
+ getTranscript,
796
+ conversationId: sessionId,
797
+ convaiConversationId: sessionId
798
+ };
799
+ }
800
+
464
801
  // src/react/useShogoVoice.ts
465
802
  function useShogoVoice(opts = {}) {
466
803
  return useVoiceConversation({
@@ -472,8 +809,8 @@ function useShogoVoice(opts = {}) {
472
809
  }
473
810
 
474
811
  // src/react/useChatConversation.ts
475
- var import_react3 = require("react");
476
- var import_react4 = require("@ai-sdk/react");
812
+ var import_react4 = require("react");
813
+ var import_react5 = require("@ai-sdk/react");
477
814
  var import_ai = require("ai");
478
815
 
479
816
  // src/shared/chatUrl.ts
@@ -510,16 +847,16 @@ function useChatConversation(options = {}) {
510
847
  onError,
511
848
  dynamicVariables
512
849
  } = options;
513
- const resolvedApi = (0, import_react3.useMemo)(
850
+ const resolvedApi = (0, import_react4.useMemo)(
514
851
  () => appendChatQuery(api, { projectId, conversationId, agentName }),
515
852
  [api, projectId, conversationId, agentName]
516
853
  );
517
- const headers = (0, import_react3.useMemo)(() => {
854
+ const headers = (0, import_react4.useMemo)(() => {
518
855
  const h = {};
519
856
  if (shogoApiKey) h.authorization = `Bearer ${shogoApiKey}`;
520
857
  return h;
521
858
  }, [shogoApiKey]);
522
- const body = (0, import_react3.useMemo)(() => {
859
+ const body = (0, import_react4.useMemo)(() => {
523
860
  const b = {};
524
861
  if (projectId) b.projectId = projectId;
525
862
  if (agentName) b.agentName = agentName;
@@ -530,7 +867,7 @@ function useChatConversation(options = {}) {
530
867
  }
531
868
  return b;
532
869
  }, [projectId, agentName, conversationId, tools, dynamicVariables]);
533
- const transport = (0, import_react3.useMemo)(
870
+ const transport = (0, import_react4.useMemo)(
534
871
  () => new import_ai.DefaultChatTransport({
535
872
  api: resolvedApi,
536
873
  credentials: fetchCredentials,
@@ -539,11 +876,11 @@ function useChatConversation(options = {}) {
539
876
  }),
540
877
  [resolvedApi, fetchCredentials, headers, body]
541
878
  );
542
- const toolsRef = (0, import_react3.useRef)(clientTools);
879
+ const toolsRef = (0, import_react4.useRef)(clientTools);
543
880
  toolsRef.current = clientTools;
544
- const chatRef = (0, import_react3.useRef)(null);
881
+ const chatRef = (0, import_react4.useRef)(null);
545
882
  const resolvedId = id ?? (conversationId ? `shogo-chat:${conversationId}` : DEFAULT_CHAT_ID);
546
- const chat = (0, import_react4.useChat)({
883
+ const chat = (0, import_react5.useChat)({
547
884
  id: resolvedId,
548
885
  transport,
549
886
  messages: initialMessages,
@@ -583,17 +920,17 @@ function useChatConversation(options = {}) {
583
920
  }
584
921
  });
585
922
  chatRef.current = chat;
586
- const sendMessage = (0, import_react3.useCallback)(
923
+ const sendMessage = (0, import_react4.useCallback)(
587
924
  async (text) => {
588
925
  if (!text.trim()) return;
589
926
  await chatRef.current?.sendMessage({ text });
590
927
  },
591
928
  []
592
929
  );
593
- const setMessages = (0, import_react3.useCallback)((messages) => {
930
+ const setMessages = (0, import_react4.useCallback)((messages) => {
594
931
  chatRef.current?.setMessages?.(messages);
595
932
  }, []);
596
- const appendAssistantMessage = (0, import_react3.useCallback)((text) => {
933
+ const appendAssistantMessage = (0, import_react4.useCallback)((text) => {
597
934
  const next = {
598
935
  id: syntheticId("synthetic-assistant"),
599
936
  role: "assistant",
@@ -604,7 +941,7 @@ function useChatConversation(options = {}) {
604
941
  const nextList = [...current.messages, next];
605
942
  current.setMessages?.(nextList);
606
943
  }, []);
607
- const appendUserMessage = (0, import_react3.useCallback)((text) => {
944
+ const appendUserMessage = (0, import_react4.useCallback)((text) => {
608
945
  const next = {
609
946
  id: syntheticId("synthetic-user"),
610
947
  role: "user",
@@ -637,14 +974,14 @@ function useShogoChat(opts = {}) {
637
974
  }
638
975
 
639
976
  // src/react/ShogoVoiceProvider.tsx
640
- var import_react5 = require("@elevenlabs/react");
977
+ var import_react6 = require("@elevenlabs/react");
641
978
  var import_jsx_runtime = require("react/jsx-runtime");
642
979
  function ShogoVoiceProvider(props) {
643
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react5.ConversationProvider, { children: props.children });
980
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react6.ConversationProvider, { children: props.children });
644
981
  }
645
982
 
646
983
  // src/react/OrganicSphere.tsx
647
- var import_react6 = require("react");
984
+ var import_react7 = require("react");
648
985
  var THREE = __toESM(require("three"), 1);
649
986
 
650
987
  // src/react/shaders/organicSphereShaders.ts
@@ -964,8 +1301,8 @@ function OrganicSphere({
964
1301
  className,
965
1302
  style
966
1303
  }) {
967
- const containerRef = (0, import_react6.useRef)(null);
968
- const resolvedConfig = (0, import_react6.useMemo)(() => {
1304
+ const containerRef = (0, import_react7.useRef)(null);
1305
+ const resolvedConfig = (0, import_react7.useMemo)(() => {
969
1306
  const base = resolveOrganicSphereConfig(configProp);
970
1307
  const overrides = {};
971
1308
  if (lightAColor !== void 0) overrides.lightAColor = lightAColor;
@@ -988,22 +1325,22 @@ function OrganicSphere({
988
1325
  subdivisions,
989
1326
  maxPixelRatio
990
1327
  ]);
991
- const configRef = (0, import_react6.useRef)(resolvedConfig);
992
- (0, import_react6.useEffect)(() => {
1328
+ const configRef = (0, import_react7.useRef)(resolvedConfig);
1329
+ (0, import_react7.useEffect)(() => {
993
1330
  configRef.current = resolvedConfig;
994
1331
  }, [resolvedConfig]);
995
- const getFrequencyDataRef = (0, import_react6.useRef)(getFrequencyData);
996
- const activeRef = (0, import_react6.useRef)(active);
997
- (0, import_react6.useEffect)(() => {
1332
+ const getFrequencyDataRef = (0, import_react7.useRef)(getFrequencyData);
1333
+ const activeRef = (0, import_react7.useRef)(active);
1334
+ (0, import_react7.useEffect)(() => {
998
1335
  getFrequencyDataRef.current = getFrequencyData;
999
1336
  }, [getFrequencyData]);
1000
- (0, import_react6.useEffect)(() => {
1337
+ (0, import_react7.useEffect)(() => {
1001
1338
  activeRef.current = active;
1002
1339
  }, [active]);
1003
1340
  const initSubdivisions = resolvedConfig.subdivisions;
1004
1341
  const initMaxPixelRatio = resolvedConfig.maxPixelRatio;
1005
1342
  const initBackgroundColor = resolvedConfig.backgroundColor;
1006
- (0, import_react6.useEffect)(() => {
1343
+ (0, import_react7.useEffect)(() => {
1007
1344
  const container = containerRef.current;
1008
1345
  if (!container) return;
1009
1346
  const cfg0 = configRef.current;
@@ -1213,7 +1550,7 @@ function OrganicSphere({
1213
1550
  }
1214
1551
 
1215
1552
  // src/react/OrganicParticles.tsx
1216
- var import_react7 = require("react");
1553
+ var import_react8 = require("react");
1217
1554
  var THREE2 = __toESM(require("three"), 1);
1218
1555
 
1219
1556
  // src/react/shaders/organicParticlesShaders.ts
@@ -1428,21 +1765,21 @@ function OrganicParticles({
1428
1765
  className,
1429
1766
  style
1430
1767
  }) {
1431
- const containerRef = (0, import_react7.useRef)(null);
1432
- const resolvedConfig = (0, import_react7.useMemo)(
1768
+ const containerRef = (0, import_react8.useRef)(null);
1769
+ const resolvedConfig = (0, import_react8.useMemo)(
1433
1770
  () => resolveOrganicParticlesConfig(configProp),
1434
1771
  [configProp]
1435
1772
  );
1436
- const configRef = (0, import_react7.useRef)(resolvedConfig);
1437
- (0, import_react7.useEffect)(() => {
1773
+ const configRef = (0, import_react8.useRef)(resolvedConfig);
1774
+ (0, import_react8.useEffect)(() => {
1438
1775
  configRef.current = resolvedConfig;
1439
1776
  }, [resolvedConfig]);
1440
- const getFrequencyDataRef = (0, import_react7.useRef)(getFrequencyData);
1441
- const activeRef = (0, import_react7.useRef)(active);
1442
- (0, import_react7.useEffect)(() => {
1777
+ const getFrequencyDataRef = (0, import_react8.useRef)(getFrequencyData);
1778
+ const activeRef = (0, import_react8.useRef)(active);
1779
+ (0, import_react8.useEffect)(() => {
1443
1780
  getFrequencyDataRef.current = getFrequencyData;
1444
1781
  }, [getFrequencyData]);
1445
- (0, import_react7.useEffect)(() => {
1782
+ (0, import_react8.useEffect)(() => {
1446
1783
  activeRef.current = active;
1447
1784
  }, [active]);
1448
1785
  const initCount = resolvedConfig.count;
@@ -1451,7 +1788,7 @@ function OrganicParticles({
1451
1788
  const initSeed = resolvedConfig.seed;
1452
1789
  const initMaxPixelRatio = resolvedConfig.maxPixelRatio;
1453
1790
  const initBackgroundColor = resolvedConfig.backgroundColor;
1454
- (0, import_react7.useEffect)(() => {
1791
+ (0, import_react8.useEffect)(() => {
1455
1792
  const container = containerRef.current;
1456
1793
  if (!container) return;
1457
1794
  const cfg0 = configRef.current;
@@ -1663,6 +2000,7 @@ function OrganicParticles({
1663
2000
  resolveOrganicParticlesConfig,
1664
2001
  resolveOrganicSphereConfig,
1665
2002
  useChatConversation,
2003
+ useLiveVoiceConversation,
1666
2004
  useShogoChat,
1667
2005
  useShogoVoice,
1668
2006
  useVoiceConversation