@agent-native/core 0.7.54 → 0.7.56

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 (60) hide show
  1. package/dist/a2a/artifact-response.d.ts +1 -0
  2. package/dist/a2a/artifact-response.d.ts.map +1 -1
  3. package/dist/a2a/artifact-response.js +111 -13
  4. package/dist/a2a/artifact-response.js.map +1 -1
  5. package/dist/a2a/task-store.d.ts +1 -0
  6. package/dist/a2a/task-store.d.ts.map +1 -1
  7. package/dist/a2a/task-store.js +15 -0
  8. package/dist/a2a/task-store.js.map +1 -1
  9. package/dist/cli/templates-meta.js +1 -1
  10. package/dist/cli/templates-meta.js.map +1 -1
  11. package/dist/client/AssistantChat.d.ts +15 -0
  12. package/dist/client/AssistantChat.d.ts.map +1 -1
  13. package/dist/client/AssistantChat.js +55 -52
  14. package/dist/client/AssistantChat.js.map +1 -1
  15. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  16. package/dist/client/MultiTabAssistantChat.js +0 -13
  17. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  18. package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
  19. package/dist/client/composer/TiptapComposer.js +59 -19
  20. package/dist/client/composer/TiptapComposer.js.map +1 -1
  21. package/dist/client/composer/useVoiceDictation.d.ts +8 -3
  22. package/dist/client/composer/useVoiceDictation.d.ts.map +1 -1
  23. package/dist/client/composer/useVoiceDictation.js +278 -22
  24. package/dist/client/composer/useVoiceDictation.js.map +1 -1
  25. package/dist/client/index.d.ts +1 -0
  26. package/dist/client/index.d.ts.map +1 -1
  27. package/dist/client/index.js +1 -0
  28. package/dist/client/index.js.map +1 -1
  29. package/dist/client/resources/ResourcesPanel.js +2 -2
  30. package/dist/client/resources/ResourcesPanel.js.map +1 -1
  31. package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
  32. package/dist/client/settings/SettingsPanel.js +7 -5
  33. package/dist/client/settings/SettingsPanel.js.map +1 -1
  34. package/dist/client/settings/VoiceTranscriptionSection.d.ts +4 -2
  35. package/dist/client/settings/VoiceTranscriptionSection.d.ts.map +1 -1
  36. package/dist/client/settings/VoiceTranscriptionSection.js +164 -60
  37. package/dist/client/settings/VoiceTranscriptionSection.js.map +1 -1
  38. package/dist/client/use-chat-models.d.ts +33 -0
  39. package/dist/client/use-chat-models.d.ts.map +1 -0
  40. package/dist/client/use-chat-models.js +183 -0
  41. package/dist/client/use-chat-models.js.map +1 -0
  42. package/dist/integrations/a2a-continuation-processor.js +29 -15
  43. package/dist/integrations/a2a-continuation-processor.js.map +1 -1
  44. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  45. package/dist/server/agent-chat-plugin.js +22 -1
  46. package/dist/server/agent-chat-plugin.js.map +1 -1
  47. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  48. package/dist/server/core-routes-plugin.js +6 -0
  49. package/dist/server/core-routes-plugin.js.map +1 -1
  50. package/dist/server/google-realtime-session.d.ts +14 -0
  51. package/dist/server/google-realtime-session.d.ts.map +1 -0
  52. package/dist/server/google-realtime-session.js +155 -0
  53. package/dist/server/google-realtime-session.js.map +1 -0
  54. package/dist/server/voice-providers-status.d.ts +7 -0
  55. package/dist/server/voice-providers-status.d.ts.map +1 -1
  56. package/dist/server/voice-providers-status.js +14 -1
  57. package/dist/server/voice-providers-status.js.map +1 -1
  58. package/docs/content/sharing.md +155 -0
  59. package/docs/content/template-clips.md +8 -5
  60. package/package.json +1 -1
@@ -2,12 +2,15 @@
2
2
  * Voice dictation hook for the agent composer.
3
3
  *
4
4
  * Wires voice providers behind a single state machine:
5
- * - "openai" / "builder" / "builder-gemini" / "gemini" / "groq"
5
+ * - "auto" / "openai" / "builder" / "builder-gemini" / "gemini" / "groq"
6
6
  * — MediaRecorder → POST /_agent-native/transcribe-voice
7
+ * - "google-realtime"
8
+ * — MediaRecorder chunks → POST /_agent-native/transcribe-stream/session
9
+ * → managed WebSocket → Google Speech-to-Text streaming
7
10
  * - "browser" — Web Speech API (low quality, offline capable)
8
11
  *
9
12
  * Provider preference lives in application_state under
10
- * `voice-transcription-prefs` (`{ provider: VoiceProvider, instructions?: string }`).
13
+ * `voice-transcription-prefs` (`{ transcriptionMode, provider, instructions }`).
11
14
  * The composer reads it on every start so settings changes take effect
12
15
  * immediately without unmounting the composer.
13
16
  *
@@ -19,28 +22,37 @@ import { agentNativePath } from "../api-path.js";
19
22
  const PREFS_KEY = "voice-transcription-prefs";
20
23
  const PREFS_URL = agentNativePath(`/_agent-native/application-state/${PREFS_KEY}`);
21
24
  const TRANSCRIBE_URL = agentNativePath("/_agent-native/transcribe-voice");
22
- const PROVIDER_STATUS_URL = agentNativePath("/_agent-native/voice-providers/status");
25
+ const GOOGLE_REALTIME_SESSION_URL = agentNativePath("/_agent-native/transcribe-stream/session");
26
+ const GOOGLE_REALTIME_WS_PROTOCOL = "google-realtime.v1";
23
27
  function isVoiceProvider(value) {
24
- return (value === "openai" ||
28
+ return (value === "auto" ||
29
+ value === "openai" ||
25
30
  value === "browser" ||
31
+ value === "google-realtime" ||
26
32
  value === "builder-gemini" ||
27
33
  value === "builder" ||
28
34
  value === "gemini" ||
29
35
  value === "groq");
30
36
  }
37
+ function isTranscriptionMode(value) {
38
+ return (value === "mac-native" || value === "google-realtime" || value === "batch");
39
+ }
31
40
  async function defaultProvider() {
32
- try {
33
- const res = await fetch(PROVIDER_STATUS_URL);
34
- if (!res.ok)
35
- return "browser";
36
- const status = (await res.json());
37
- if (status?.builder)
38
- return "builder-gemini";
39
- }
40
- catch {
41
- /* fall through */
41
+ return "auto";
42
+ }
43
+ function normalizeProviderForMode(mode, provider) {
44
+ if (mode === "mac-native")
45
+ return "browser";
46
+ if (mode === "google-realtime")
47
+ return "google-realtime";
48
+ if (mode === "batch") {
49
+ if (!provider || provider === "browser")
50
+ return "auto";
51
+ return provider === "builder" ? "builder-gemini" : provider;
42
52
  }
43
- return "browser";
53
+ if (!provider)
54
+ return null;
55
+ return provider === "builder" ? "builder-gemini" : provider;
44
56
  }
45
57
  async function readVoicePrefs() {
46
58
  try {
@@ -48,13 +60,20 @@ async function readVoicePrefs() {
48
60
  if (!res.ok)
49
61
  return { provider: await defaultProvider() };
50
62
  const body = (await res.json());
63
+ const value = body?.value ??
64
+ body;
65
+ const mode = isTranscriptionMode(value?.transcriptionMode)
66
+ ? value.transcriptionMode
67
+ : undefined;
51
68
  const p = body?.provider ??
52
69
  body?.value?.provider;
53
70
  const instructions = body?.instructions ??
54
71
  body?.value?.instructions;
55
- if (isVoiceProvider(p)) {
72
+ const provider = normalizeProviderForMode(mode, isVoiceProvider(p) ? p : null);
73
+ if (provider) {
56
74
  return {
57
- provider: p === "builder" ? "builder-gemini" : p,
75
+ transcriptionMode: mode,
76
+ provider,
58
77
  instructions: typeof instructions === "string" ? instructions.trim() : undefined,
59
78
  };
60
79
  }
@@ -103,7 +122,7 @@ export function useVoiceDictation(options) {
103
122
  const [amplitude, setAmplitude] = useState(0);
104
123
  const [durationMs, setDurationMs] = useState(0);
105
124
  const [errorMessage, setErrorMessage] = useState(null);
106
- const [provider, setProvider] = useState("browser");
125
+ const [provider, setProvider] = useState("auto");
107
126
  // Keep refs for teardown / cross-branch access.
108
127
  const mediaStreamRef = useRef(null);
109
128
  const mediaRecorderRef = useRef(null);
@@ -120,6 +139,10 @@ export function useVoiceDictation(options) {
120
139
  // Parallel live recognition for OpenAI mode (provides instant preview while MediaRecorder captures)
121
140
  const liveSpeechRef = useRef(null);
122
141
  const liveTextRef = useRef("");
142
+ const realtimeSocketRef = useRef(null);
143
+ const realtimeFinalRef = useRef("");
144
+ const realtimeInterimRef = useRef("");
145
+ const realtimeStopTimeoutRef = useRef(null);
123
146
  const mediaRecorderSupported = typeof window !== "undefined" &&
124
147
  typeof navigator !== "undefined" &&
125
148
  !!navigator.mediaDevices?.getUserMedia &&
@@ -166,12 +189,28 @@ export function useVoiceDictation(options) {
166
189
  }
167
190
  liveSpeechRef.current = null;
168
191
  }
192
+ if (realtimeSocketRef.current) {
193
+ const socket = realtimeSocketRef.current;
194
+ realtimeSocketRef.current = null;
195
+ try {
196
+ socket.close();
197
+ }
198
+ catch {
199
+ /* ignore */
200
+ }
201
+ }
202
+ if (realtimeStopTimeoutRef.current) {
203
+ clearTimeout(realtimeStopTimeoutRef.current);
204
+ realtimeStopTimeoutRef.current = null;
205
+ }
169
206
  analyserRef.current = null;
170
207
  mediaRecorderRef.current = null;
171
208
  chunksRef.current = [];
172
209
  speechRef.current = null;
173
210
  speechTranscriptRef.current = "";
174
211
  liveTextRef.current = "";
212
+ realtimeFinalRef.current = "";
213
+ realtimeInterimRef.current = "";
175
214
  setAmplitude(0);
176
215
  }, []);
177
216
  useEffect(() => teardown, [teardown]);
@@ -414,6 +453,199 @@ export function useVoiceDictation(options) {
414
453
  setState("recording");
415
454
  recognition.start();
416
455
  }, [startMeter, startTimer, teardown, failWith]);
456
+ const startGoogleRealtime = useCallback(async () => {
457
+ const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
458
+ if (cancelledRef.current) {
459
+ for (const track of stream.getTracks())
460
+ track.stop();
461
+ cancelledRef.current = false;
462
+ setState("idle");
463
+ return;
464
+ }
465
+ const sessionRes = await fetch(GOOGLE_REALTIME_SESSION_URL, {
466
+ method: "POST",
467
+ headers: { "Content-Type": "application/json" },
468
+ body: JSON.stringify({
469
+ language: (typeof navigator !== "undefined" && navigator.language) || "en-US",
470
+ }),
471
+ });
472
+ const sessionBody = (await sessionRes
473
+ .json()
474
+ .catch(() => ({ error: `HTTP ${sessionRes.status}` })));
475
+ if (!sessionRes.ok ||
476
+ !sessionBody.websocketUrl ||
477
+ !sessionBody.sessionToken) {
478
+ for (const track of stream.getTracks())
479
+ track.stop();
480
+ throw new Error(sessionBody.error ||
481
+ `Could not start Google realtime transcription (${sessionRes.status})`);
482
+ }
483
+ if (cancelledRef.current) {
484
+ for (const track of stream.getTracks())
485
+ track.stop();
486
+ cancelledRef.current = false;
487
+ setState("idle");
488
+ return;
489
+ }
490
+ mediaStreamRef.current = stream;
491
+ const mimeType = pickMimeType();
492
+ const recorder = new MediaRecorder(stream, { mimeType });
493
+ mediaRecorderRef.current = recorder;
494
+ realtimeFinalRef.current = "";
495
+ realtimeInterimRef.current = "";
496
+ let finalized = false;
497
+ let recorderStarted = false;
498
+ const finish = (errorMessage) => {
499
+ if (finalized)
500
+ return;
501
+ finalized = true;
502
+ const finalText = realtimeFinalRef.current.trim();
503
+ const interimText = realtimeInterimRef.current.trim();
504
+ const text = [finalText, interimText].filter(Boolean).join(" ").trim();
505
+ teardown();
506
+ if (cancelledRef.current) {
507
+ cancelledRef.current = false;
508
+ setState("idle");
509
+ return;
510
+ }
511
+ if (text) {
512
+ onTranscriptRef.current?.(text);
513
+ setState("idle");
514
+ return;
515
+ }
516
+ if (errorMessage) {
517
+ failWith(errorMessage);
518
+ return;
519
+ }
520
+ setState("idle");
521
+ };
522
+ recorder.ondataavailable = async (event) => {
523
+ if (!event.data || event.data.size === 0)
524
+ return;
525
+ const socket = realtimeSocketRef.current;
526
+ if (!socket || socket.readyState !== WebSocket.OPEN)
527
+ return;
528
+ try {
529
+ socket.send(await event.data.arrayBuffer());
530
+ }
531
+ catch (err) {
532
+ finish(err?.message ?? "Realtime audio upload failed");
533
+ }
534
+ };
535
+ recorder.onstop = () => {
536
+ const socket = realtimeSocketRef.current;
537
+ if (!socket || socket.readyState !== WebSocket.OPEN) {
538
+ finish();
539
+ return;
540
+ }
541
+ setState("transcribing");
542
+ try {
543
+ socket.send(JSON.stringify({ type: "stop" }));
544
+ }
545
+ catch {
546
+ finish();
547
+ return;
548
+ }
549
+ realtimeStopTimeoutRef.current = window.setTimeout(() => {
550
+ const activeSocket = realtimeSocketRef.current;
551
+ if (activeSocket?.readyState === WebSocket.OPEN) {
552
+ try {
553
+ activeSocket.close();
554
+ }
555
+ catch {
556
+ finish();
557
+ }
558
+ return;
559
+ }
560
+ finish();
561
+ }, 10000);
562
+ };
563
+ const socket = new WebSocket(sessionBody.websocketUrl, [
564
+ sessionBody.websocketProtocol || GOOGLE_REALTIME_WS_PROTOCOL,
565
+ sessionBody.sessionToken,
566
+ ]);
567
+ socket.binaryType = "arraybuffer";
568
+ realtimeSocketRef.current = socket;
569
+ socket.onmessage = (event) => {
570
+ if (cancelledRef.current) {
571
+ finish();
572
+ return;
573
+ }
574
+ const raw = typeof event.data === "string"
575
+ ? event.data
576
+ : event.data instanceof Blob
577
+ ? null
578
+ : new TextDecoder().decode(event.data);
579
+ if (!raw)
580
+ return;
581
+ let message;
582
+ try {
583
+ message = JSON.parse(raw);
584
+ }
585
+ catch {
586
+ return;
587
+ }
588
+ if (!message?.type)
589
+ return;
590
+ if (message.type === "ready") {
591
+ if (!recorderStarted) {
592
+ recorderStarted = true;
593
+ startMeter(stream);
594
+ startTimer();
595
+ setState("recording");
596
+ recorder.start(100);
597
+ }
598
+ return;
599
+ }
600
+ if (message.type === "partial") {
601
+ realtimeInterimRef.current = (message.text ?? "").trim();
602
+ onLiveUpdateRef.current?.(realtimeFinalRef.current, realtimeInterimRef.current);
603
+ return;
604
+ }
605
+ if (message.type === "final") {
606
+ const next = (message.text ?? "").trim();
607
+ if (next) {
608
+ realtimeFinalRef.current = [realtimeFinalRef.current.trim(), next]
609
+ .filter(Boolean)
610
+ .join(" ");
611
+ }
612
+ realtimeInterimRef.current = "";
613
+ onLiveUpdateRef.current?.(realtimeFinalRef.current, "");
614
+ return;
615
+ }
616
+ if (message.type === "error") {
617
+ finish(message.error || "Google realtime transcription failed");
618
+ return;
619
+ }
620
+ if (message.type === "end") {
621
+ finish();
622
+ }
623
+ };
624
+ socket.onerror = () => {
625
+ finish("Google realtime transcription connection failed");
626
+ };
627
+ socket.onclose = () => {
628
+ finish();
629
+ };
630
+ socket.onopen = () => {
631
+ if (cancelledRef.current) {
632
+ finish();
633
+ return;
634
+ }
635
+ try {
636
+ socket.send(JSON.stringify({
637
+ type: "start",
638
+ language: (typeof navigator !== "undefined" && navigator.language) ||
639
+ "en-US",
640
+ interimResults: true,
641
+ mimeType,
642
+ }));
643
+ }
644
+ catch (err) {
645
+ finish(err?.message ?? "Could not start realtime stream");
646
+ }
647
+ };
648
+ }, [startMeter, startTimer, teardown, failWith]);
417
649
  const start = useCallback(async () => {
418
650
  if (state === "recording" || state === "starting")
419
651
  return;
@@ -426,7 +658,8 @@ export function useVoiceDictation(options) {
426
658
  // Server providers all use the same client-side flow as "openai"
427
659
  // (MediaRecorder -> POST to /_agent-native/transcribe-voice).
428
660
  // The server route handles routing to the right backend.
429
- const resolvedProvider = pref === "builder" ||
661
+ const resolvedProvider = pref === "auto" ||
662
+ pref === "builder" ||
430
663
  pref === "builder-gemini" ||
431
664
  pref === "gemini" ||
432
665
  pref === "groq"
@@ -440,22 +673,43 @@ export function useVoiceDictation(options) {
440
673
  }
441
674
  await startOpenAi(pref, prefs.instructions);
442
675
  }
676
+ else if (resolvedProvider === "google-realtime") {
677
+ if (!mediaRecorderSupported) {
678
+ throw new Error("Your browser doesn't support audio recording, so Google realtime transcription can't start.");
679
+ }
680
+ await startGoogleRealtime();
681
+ }
443
682
  else {
444
683
  await startBrowser();
445
684
  }
446
685
  }
447
686
  catch (err) {
687
+ if (cancelledRef.current) {
688
+ cancelledRef.current = false;
689
+ teardown();
690
+ setState("idle");
691
+ return;
692
+ }
448
693
  const message = err?.name === "NotAllowedError"
449
694
  ? "Microphone permission denied. Enable it in your browser settings."
450
695
  : (err?.message ?? "Could not start recording");
451
696
  failWith(message);
452
697
  }
453
- }, [state, mediaRecorderSupported, startOpenAi, startBrowser, failWith]);
698
+ }, [
699
+ state,
700
+ mediaRecorderSupported,
701
+ startOpenAi,
702
+ startGoogleRealtime,
703
+ startBrowser,
704
+ failWith,
705
+ ]);
454
706
  const stop = useCallback(() => {
455
707
  if (state !== "recording")
456
708
  return;
457
709
  cancelledRef.current = false;
458
- if (activeProviderRef.current === "openai" && mediaRecorderRef.current) {
710
+ if ((activeProviderRef.current === "openai" ||
711
+ activeProviderRef.current === "google-realtime") &&
712
+ mediaRecorderRef.current) {
459
713
  try {
460
714
  mediaRecorderRef.current.stop();
461
715
  }
@@ -482,7 +736,9 @@ export function useVoiceDictation(options) {
482
736
  if (state !== "recording" && state !== "starting")
483
737
  return;
484
738
  cancelledRef.current = true;
485
- if (activeProviderRef.current === "openai" && mediaRecorderRef.current) {
739
+ if ((activeProviderRef.current === "openai" ||
740
+ activeProviderRef.current === "google-realtime") &&
741
+ mediaRecorderRef.current) {
486
742
  try {
487
743
  mediaRecorderRef.current.stop();
488
744
  }
@@ -1 +1 @@
1
- {"version":3,"file":"useVoiceDictation.js","sourceRoot":"","sources":["../../../src/client/composer/useVoiceDictation.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Voice dictation hook for the agent composer.\n *\n * Wires voice providers behind a single state machine:\n * - \"openai\" / \"builder\" / \"builder-gemini\" / \"gemini\" / \"groq\"\n * — MediaRecorder → POST /_agent-native/transcribe-voice\n * - \"browser\" — Web Speech API (low quality, offline capable)\n *\n * Provider preference lives in application_state under\n * `voice-transcription-prefs` (`{ provider: VoiceProvider, instructions?: string }`).\n * The composer reads it on every start so settings changes take effect\n * immediately without unmounting the composer.\n *\n * The hook exposes amplitude (0..1) and duration (ms) so the composer can\n * render the Lovable-style live waveform + MM:SS timer.\n */\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { agentNativePath } from \"../api-path.js\";\n\nexport type VoiceProvider =\n | \"openai\"\n | \"browser\"\n | \"builder-gemini\"\n | \"builder\"\n | \"gemini\"\n | \"groq\";\n\nexport interface VoicePrefs {\n provider: VoiceProvider;\n instructions?: string;\n}\n\nconst PREFS_KEY = \"voice-transcription-prefs\";\nconst PREFS_URL = agentNativePath(\n `/_agent-native/application-state/${PREFS_KEY}`,\n);\nconst TRANSCRIBE_URL = agentNativePath(\"/_agent-native/transcribe-voice\");\nconst PROVIDER_STATUS_URL = agentNativePath(\n \"/_agent-native/voice-providers/status\",\n);\n\ninterface ProviderStatus {\n builder?: boolean;\n}\n\nfunction isVoiceProvider(value: unknown): value is VoiceProvider {\n return (\n value === \"openai\" ||\n value === \"browser\" ||\n value === \"builder-gemini\" ||\n value === \"builder\" ||\n value === \"gemini\" ||\n value === \"groq\"\n );\n}\n\nasync function defaultProvider(): Promise<VoiceProvider> {\n try {\n const res = await fetch(PROVIDER_STATUS_URL);\n if (!res.ok) return \"browser\";\n const status = (await res.json()) as ProviderStatus | null;\n if (status?.builder) return \"builder-gemini\";\n } catch {\n /* fall through */\n }\n return \"browser\";\n}\n\nexport type VoiceState =\n | \"idle\"\n | \"starting\"\n | \"recording\"\n | \"transcribing\"\n | \"error\";\n\nexport interface UseVoiceDictationOptions {\n onTranscript: (text: string) => void;\n onError?: (message: string) => void;\n /** Called with (accumulatedFinalText, currentInterimText) as speech is recognized in real time. */\n onLiveUpdate?: (finalText: string, interimText: string) => void;\n}\n\nexport interface VoiceDictationApi {\n state: VoiceState;\n amplitude: number;\n durationMs: number;\n errorMessage: string | null;\n provider: VoiceProvider;\n supported: boolean;\n start: () => Promise<void>;\n stop: () => void;\n cancel: () => void;\n}\n\nasync function readVoicePrefs(): Promise<VoicePrefs> {\n try {\n const res = await fetch(PREFS_URL);\n if (!res.ok) return { provider: await defaultProvider() };\n const body = (await res.json()) as\n | VoicePrefs\n | { value?: VoicePrefs }\n | null;\n const p =\n (body as VoicePrefs | null)?.provider ??\n (body as { value?: VoicePrefs } | null)?.value?.provider;\n const instructions =\n (body as VoicePrefs | null)?.instructions ??\n (body as { value?: VoicePrefs } | null)?.value?.instructions;\n if (isVoiceProvider(p)) {\n return {\n provider: p === \"builder\" ? \"builder-gemini\" : p,\n instructions:\n typeof instructions === \"string\" ? instructions.trim() : undefined,\n };\n }\n } catch {\n /* fall through */\n }\n return { provider: await defaultProvider() };\n}\n\nfunction getSpeechRecognitionCtor(): any {\n if (typeof window === \"undefined\") return null;\n return (\n (window as any).SpeechRecognition ||\n (window as any).webkitSpeechRecognition ||\n null\n );\n}\n\nfunction pickMimeType(): string {\n if (typeof MediaRecorder === \"undefined\") return \"audio/webm\";\n const candidates = [\n \"audio/webm;codecs=opus\",\n \"audio/webm\",\n \"audio/mp4\",\n \"audio/ogg;codecs=opus\",\n ];\n for (const mime of candidates) {\n try {\n if (MediaRecorder.isTypeSupported(mime)) return mime;\n } catch {\n /* ignore */\n }\n }\n return \"audio/webm\";\n}\n\nexport function useVoiceDictation(\n options: UseVoiceDictationOptions,\n): VoiceDictationApi {\n const { onTranscript, onError, onLiveUpdate } = options;\n const onTranscriptRef = useRef(onTranscript);\n const onErrorRef = useRef(onError);\n const onLiveUpdateRef = useRef(onLiveUpdate);\n onTranscriptRef.current = onTranscript;\n onErrorRef.current = onError;\n onLiveUpdateRef.current = onLiveUpdate;\n\n const [state, setState] = useState<VoiceState>(\"idle\");\n const [amplitude, setAmplitude] = useState(0);\n const [durationMs, setDurationMs] = useState(0);\n const [errorMessage, setErrorMessage] = useState<string | null>(null);\n const [provider, setProvider] = useState<VoiceProvider>(\"browser\");\n\n // Keep refs for teardown / cross-branch access.\n const mediaStreamRef = useRef<MediaStream | null>(null);\n const mediaRecorderRef = useRef<MediaRecorder | null>(null);\n const chunksRef = useRef<Blob[]>([]);\n const audioContextRef = useRef<AudioContext | null>(null);\n const analyserRef = useRef<AnalyserNode | null>(null);\n const rafRef = useRef<number | null>(null);\n const timerRef = useRef<ReturnType<typeof setInterval> | null>(null);\n const startedAtRef = useRef<number>(0);\n const cancelledRef = useRef(false);\n const speechRef = useRef<any>(null);\n const speechTranscriptRef = useRef<string>(\"\");\n const activeProviderRef = useRef<VoiceProvider>(\"browser\");\n // Parallel live recognition for OpenAI mode (provides instant preview while MediaRecorder captures)\n const liveSpeechRef = useRef<any>(null);\n const liveTextRef = useRef<string>(\"\");\n\n const mediaRecorderSupported =\n typeof window !== \"undefined\" &&\n typeof navigator !== \"undefined\" &&\n !!navigator.mediaDevices?.getUserMedia &&\n typeof (window as any).MediaRecorder !== \"undefined\";\n const speechSupported = !!getSpeechRecognitionCtor();\n const supported = mediaRecorderSupported || speechSupported;\n\n const teardown = useCallback(() => {\n if (rafRef.current != null) {\n cancelAnimationFrame(rafRef.current);\n rafRef.current = null;\n }\n if (timerRef.current != null) {\n clearInterval(timerRef.current);\n timerRef.current = null;\n }\n if (mediaStreamRef.current) {\n for (const track of mediaStreamRef.current.getTracks()) {\n track.stop();\n }\n mediaStreamRef.current = null;\n }\n if (audioContextRef.current) {\n audioContextRef.current.close().catch(() => {});\n audioContextRef.current = null;\n }\n if (speechRef.current) {\n // Stop the Web Speech session before dropping the ref so the browser\n // releases the mic and stops dispatching onresult events into a stale\n // closure. abort() is fire-and-forget (no final result); stop() would\n // deliver remaining partials but we've already cleared state.\n try {\n speechRef.current.abort?.();\n } catch {\n /* ignore */\n }\n }\n if (liveSpeechRef.current) {\n try {\n liveSpeechRef.current.abort?.();\n } catch {\n /* ignore */\n }\n liveSpeechRef.current = null;\n }\n analyserRef.current = null;\n mediaRecorderRef.current = null;\n chunksRef.current = [];\n speechRef.current = null;\n speechTranscriptRef.current = \"\";\n liveTextRef.current = \"\";\n setAmplitude(0);\n }, []);\n\n useEffect(() => teardown, [teardown]);\n\n const failWith = useCallback(\n (message: string) => {\n setErrorMessage(message);\n setState(\"error\");\n onErrorRef.current?.(message);\n teardown();\n },\n [teardown],\n );\n\n const startMeter = useCallback((stream: MediaStream) => {\n try {\n const AudioCtor =\n typeof window !== \"undefined\"\n ? window.AudioContext || (window as any).webkitAudioContext || null\n : null;\n if (!AudioCtor) return;\n const ctx: AudioContext = new AudioCtor();\n const source = ctx.createMediaStreamSource(stream);\n const analyser = ctx.createAnalyser();\n analyser.fftSize = 512;\n source.connect(analyser);\n audioContextRef.current = ctx;\n analyserRef.current = analyser;\n\n const buffer = new Uint8Array(analyser.frequencyBinCount);\n const tick = () => {\n if (!analyserRef.current) return;\n analyserRef.current.getByteTimeDomainData(buffer);\n let sumSquares = 0;\n for (let i = 0; i < buffer.length; i++) {\n const n = (buffer[i] - 128) / 128;\n sumSquares += n * n;\n }\n const rms = Math.sqrt(sumSquares / buffer.length);\n setAmplitude(Math.min(1, rms * 2.5));\n rafRef.current = requestAnimationFrame(tick);\n };\n rafRef.current = requestAnimationFrame(tick);\n } catch {\n /* analyser is best-effort */\n }\n }, []);\n\n const startTimer = useCallback(() => {\n startedAtRef.current = Date.now();\n setDurationMs(0);\n timerRef.current = setInterval(() => {\n setDurationMs(Date.now() - startedAtRef.current);\n }, 100);\n }, []);\n\n const startOpenAi = useCallback(\n async (providerPref: VoiceProvider, instructions?: string) => {\n const stream = await navigator.mediaDevices.getUserMedia({ audio: true });\n // User may have pressed Escape (cancel) while the permission prompt was\n // open. If so, stop the stream and bail before we start recording.\n if (cancelledRef.current) {\n for (const track of stream.getTracks()) track.stop();\n cancelledRef.current = false;\n setState(\"idle\");\n return;\n }\n mediaStreamRef.current = stream;\n const mimeType = pickMimeType();\n const recorder = new MediaRecorder(stream, { mimeType });\n mediaRecorderRef.current = recorder;\n chunksRef.current = [];\n\n recorder.ondataavailable = (e) => {\n if (e.data && e.data.size > 0) chunksRef.current.push(e.data);\n };\n recorder.onstop = async () => {\n const localChunks = chunksRef.current.slice();\n const localMime = recorder.mimeType || mimeType;\n const liveSnapshot = liveTextRef.current;\n teardown();\n if (cancelledRef.current) {\n cancelledRef.current = false;\n setState(\"idle\");\n return;\n }\n if (localChunks.length === 0) {\n if (liveSnapshot) onTranscriptRef.current?.(liveSnapshot.trim());\n setState(\"idle\");\n return;\n }\n setState(\"transcribing\");\n try {\n const audioBlob = new Blob(localChunks, { type: localMime });\n const form = new FormData();\n form.append(\n \"audio\",\n audioBlob,\n `voice.${localMime.split(\"/\")[1] ?? \"webm\"}`,\n );\n form.append(\"provider\", providerPref);\n if (instructions?.trim()) {\n form.append(\"instructions\", instructions.trim());\n }\n const res = await fetch(TRANSCRIBE_URL, {\n method: \"POST\",\n body: form,\n });\n if (!res.ok) {\n const body = await res\n .json()\n .catch(() => ({ error: `HTTP ${res.status}` }));\n throw new Error(\n body.error || `Transcription failed (${res.status})`,\n );\n }\n const data = (await res.json()) as { text?: string };\n const text = (data.text ?? \"\").trim();\n if (text) {\n onTranscriptRef.current?.(text);\n } else if (liveSnapshot) {\n onTranscriptRef.current?.(liveSnapshot.trim());\n }\n setState(\"idle\");\n } catch (err) {\n if (liveSnapshot) {\n onTranscriptRef.current?.(liveSnapshot.trim());\n setState(\"idle\");\n } else {\n failWith(\n (err as Error)?.message ??\n \"Transcription failed. Check your voice transcription provider in settings.\",\n );\n }\n }\n };\n\n startMeter(stream);\n startTimer();\n setState(\"recording\");\n recorder.start();\n\n // Start parallel Web Speech recognition for live preview text.\n // This runs alongside MediaRecorder so the user sees words appear\n // immediately while the server provider processes the full recording later.\n const SpeechCtor = getSpeechRecognitionCtor();\n if (SpeechCtor) {\n const liveSpeech = new SpeechCtor();\n liveSpeech.continuous = true;\n liveSpeech.interimResults = true;\n liveSpeech.lang =\n (typeof navigator !== \"undefined\" && navigator.language) || \"en-US\";\n liveSpeechRef.current = liveSpeech;\n liveTextRef.current = \"\";\n\n liveSpeech.onresult = (event: any) => {\n let interim = \"\";\n for (let i = event.resultIndex; i < event.results.length; i++) {\n const result = event.results[i];\n const text = result[0]?.transcript ?? \"\";\n if (result.isFinal) {\n liveTextRef.current += text;\n } else {\n interim += text;\n }\n }\n onLiveUpdateRef.current?.(liveTextRef.current, interim);\n };\n\n liveSpeech.onend = () => {\n if (liveSpeechRef.current === liveSpeech) {\n try {\n liveSpeech.start();\n } catch {\n /* ignore */\n }\n }\n };\n\n liveSpeech.onerror = () => {};\n\n try {\n liveSpeech.start();\n } catch {\n /* best effort — live preview just won't appear */\n }\n }\n },\n [startMeter, startTimer, teardown, failWith],\n );\n\n const startBrowser = useCallback(async () => {\n const Ctor = getSpeechRecognitionCtor();\n if (!Ctor) {\n throw new Error(\n \"Your browser doesn't support speech recognition. Add an OpenAI API key in settings for Whisper transcription.\",\n );\n }\n // Still request mic to drive the amplitude meter, so the UI doesn't look\n // dead while the user talks. SpeechRecognition manages its own capture\n // under the hood in most browsers.\n let stream: MediaStream | null = null;\n try {\n stream = await navigator.mediaDevices.getUserMedia({ audio: true });\n mediaStreamRef.current = stream;\n startMeter(stream);\n } catch {\n /* non-fatal — recognition can still work without our analyser */\n }\n\n if (cancelledRef.current) {\n if (stream) for (const track of stream.getTracks()) track.stop();\n mediaStreamRef.current = null;\n cancelledRef.current = false;\n setState(\"idle\");\n return;\n }\n\n const recognition = new Ctor();\n recognition.continuous = true;\n recognition.interimResults = true;\n recognition.lang =\n (typeof navigator !== \"undefined\" && navigator.language) || \"en-US\";\n speechRef.current = recognition;\n speechTranscriptRef.current = \"\";\n\n recognition.onresult = (event: any) => {\n let interim = \"\";\n for (let i = event.resultIndex; i < event.results.length; i++) {\n const result = event.results[i];\n const text = result[0]?.transcript ?? \"\";\n if (result.isFinal) {\n speechTranscriptRef.current += text;\n } else {\n interim += text;\n }\n }\n onLiveUpdateRef.current?.(speechTranscriptRef.current, interim);\n };\n recognition.onerror = (event: any) => {\n if (event?.error === \"no-speech\" || event?.error === \"aborted\") return;\n failWith(\n event?.error === \"not-allowed\"\n ? \"Microphone permission denied. Enable it in your browser settings.\"\n : `Speech recognition error: ${event?.error ?? \"unknown\"}`,\n );\n };\n recognition.onend = () => {\n const text = speechTranscriptRef.current.trim();\n const wasCancelled = cancelledRef.current;\n cancelledRef.current = false;\n teardown();\n if (!wasCancelled && text) onTranscriptRef.current?.(text);\n setState(\"idle\");\n };\n\n startTimer();\n setState(\"recording\");\n recognition.start();\n }, [startMeter, startTimer, teardown, failWith]);\n\n const start = useCallback(async () => {\n if (state === \"recording\" || state === \"starting\") return;\n setErrorMessage(null);\n setState(\"starting\");\n cancelledRef.current = false;\n\n const prefs = await readVoicePrefs();\n const pref = prefs.provider;\n setProvider(pref);\n\n // Server providers all use the same client-side flow as \"openai\"\n // (MediaRecorder -> POST to /_agent-native/transcribe-voice).\n // The server route handles routing to the right backend.\n const resolvedProvider: VoiceProvider =\n pref === \"builder\" ||\n pref === \"builder-gemini\" ||\n pref === \"gemini\" ||\n pref === \"groq\"\n ? \"openai\"\n : pref;\n activeProviderRef.current = resolvedProvider;\n\n try {\n if (resolvedProvider === \"openai\") {\n if (!mediaRecorderSupported) {\n throw new Error(\n \"Your browser doesn't support audio recording. Use the browser provider in Settings → Voice Transcription.\",\n );\n }\n await startOpenAi(pref, prefs.instructions);\n } else {\n await startBrowser();\n }\n } catch (err) {\n const message =\n (err as Error)?.name === \"NotAllowedError\"\n ? \"Microphone permission denied. Enable it in your browser settings.\"\n : ((err as Error)?.message ?? \"Could not start recording\");\n failWith(message);\n }\n }, [state, mediaRecorderSupported, startOpenAi, startBrowser, failWith]);\n\n const stop = useCallback(() => {\n if (state !== \"recording\") return;\n cancelledRef.current = false;\n if (activeProviderRef.current === \"openai\" && mediaRecorderRef.current) {\n try {\n mediaRecorderRef.current.stop();\n } catch {\n teardown();\n setState(\"idle\");\n }\n } else if (speechRef.current) {\n try {\n speechRef.current.stop();\n } catch {\n teardown();\n setState(\"idle\");\n }\n } else {\n teardown();\n setState(\"idle\");\n }\n }, [state, teardown]);\n\n const cancel = useCallback(() => {\n if (state !== \"recording\" && state !== \"starting\") return;\n cancelledRef.current = true;\n if (activeProviderRef.current === \"openai\" && mediaRecorderRef.current) {\n try {\n mediaRecorderRef.current.stop();\n } catch {\n /* ignore */\n }\n } else if (speechRef.current) {\n try {\n speechRef.current.abort?.();\n } catch {\n /* ignore */\n }\n }\n teardown();\n setState(\"idle\");\n }, [state, teardown]);\n\n return {\n state,\n amplitude,\n durationMs,\n errorMessage,\n provider,\n supported,\n start,\n stop,\n cancel,\n };\n}\n"]}
1
+ {"version":3,"file":"useVoiceDictation.js","sourceRoot":"","sources":["../../../src/client/composer/useVoiceDictation.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Voice dictation hook for the agent composer.\n *\n * Wires voice providers behind a single state machine:\n * - \"auto\" / \"openai\" / \"builder\" / \"builder-gemini\" / \"gemini\" / \"groq\"\n * — MediaRecorder → POST /_agent-native/transcribe-voice\n * - \"google-realtime\"\n * — MediaRecorder chunks → POST /_agent-native/transcribe-stream/session\n * → managed WebSocket → Google Speech-to-Text streaming\n * - \"browser\" — Web Speech API (low quality, offline capable)\n *\n * Provider preference lives in application_state under\n * `voice-transcription-prefs` (`{ transcriptionMode, provider, instructions }`).\n * The composer reads it on every start so settings changes take effect\n * immediately without unmounting the composer.\n *\n * The hook exposes amplitude (0..1) and duration (ms) so the composer can\n * render the Lovable-style live waveform + MM:SS timer.\n */\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { agentNativePath } from \"../api-path.js\";\n\nexport type VoiceProvider =\n | \"auto\"\n | \"openai\"\n | \"browser\"\n | \"google-realtime\"\n | \"builder-gemini\"\n | \"builder\"\n | \"gemini\"\n | \"groq\";\n\nexport type TranscriptionMode = \"mac-native\" | \"google-realtime\" | \"batch\";\n\nexport interface VoicePrefs {\n provider: VoiceProvider;\n transcriptionMode?: TranscriptionMode;\n instructions?: string;\n}\n\nconst PREFS_KEY = \"voice-transcription-prefs\";\nconst PREFS_URL = agentNativePath(\n `/_agent-native/application-state/${PREFS_KEY}`,\n);\nconst TRANSCRIBE_URL = agentNativePath(\"/_agent-native/transcribe-voice\");\nconst GOOGLE_REALTIME_SESSION_URL = agentNativePath(\n \"/_agent-native/transcribe-stream/session\",\n);\nconst GOOGLE_REALTIME_WS_PROTOCOL = \"google-realtime.v1\";\nfunction isVoiceProvider(value: unknown): value is VoiceProvider {\n return (\n value === \"auto\" ||\n value === \"openai\" ||\n value === \"browser\" ||\n value === \"google-realtime\" ||\n value === \"builder-gemini\" ||\n value === \"builder\" ||\n value === \"gemini\" ||\n value === \"groq\"\n );\n}\n\nfunction isTranscriptionMode(value: unknown): value is TranscriptionMode {\n return (\n value === \"mac-native\" || value === \"google-realtime\" || value === \"batch\"\n );\n}\n\nasync function defaultProvider(): Promise<VoiceProvider> {\n return \"auto\";\n}\n\nfunction normalizeProviderForMode(\n mode: TranscriptionMode | undefined,\n provider: VoiceProvider | null,\n): VoiceProvider | null {\n if (mode === \"mac-native\") return \"browser\";\n if (mode === \"google-realtime\") return \"google-realtime\";\n if (mode === \"batch\") {\n if (!provider || provider === \"browser\") return \"auto\";\n return provider === \"builder\" ? \"builder-gemini\" : provider;\n }\n if (!provider) return null;\n return provider === \"builder\" ? \"builder-gemini\" : provider;\n}\n\nexport type VoiceState =\n | \"idle\"\n | \"starting\"\n | \"recording\"\n | \"transcribing\"\n | \"error\";\n\nexport interface UseVoiceDictationOptions {\n onTranscript: (text: string) => void;\n onError?: (message: string) => void;\n /** Called with (accumulatedFinalText, currentInterimText) as speech is recognized in real time. */\n onLiveUpdate?: (finalText: string, interimText: string) => void;\n}\n\nexport interface VoiceDictationApi {\n state: VoiceState;\n amplitude: number;\n durationMs: number;\n errorMessage: string | null;\n provider: VoiceProvider;\n supported: boolean;\n start: () => Promise<void>;\n stop: () => void;\n cancel: () => void;\n}\n\nasync function readVoicePrefs(): Promise<VoicePrefs> {\n try {\n const res = await fetch(PREFS_URL);\n if (!res.ok) return { provider: await defaultProvider() };\n const body = (await res.json()) as\n | VoicePrefs\n | { value?: VoicePrefs }\n | null;\n const value =\n (body as { value?: VoicePrefs } | null)?.value ??\n (body as VoicePrefs | null);\n const mode = isTranscriptionMode(value?.transcriptionMode)\n ? value.transcriptionMode\n : undefined;\n const p =\n (body as VoicePrefs | null)?.provider ??\n (body as { value?: VoicePrefs } | null)?.value?.provider;\n const instructions =\n (body as VoicePrefs | null)?.instructions ??\n (body as { value?: VoicePrefs } | null)?.value?.instructions;\n const provider = normalizeProviderForMode(\n mode,\n isVoiceProvider(p) ? p : null,\n );\n if (provider) {\n return {\n transcriptionMode: mode,\n provider,\n instructions:\n typeof instructions === \"string\" ? instructions.trim() : undefined,\n };\n }\n } catch {\n /* fall through */\n }\n return { provider: await defaultProvider() };\n}\n\nfunction getSpeechRecognitionCtor(): any {\n if (typeof window === \"undefined\") return null;\n return (\n (window as any).SpeechRecognition ||\n (window as any).webkitSpeechRecognition ||\n null\n );\n}\n\nfunction pickMimeType(): string {\n if (typeof MediaRecorder === \"undefined\") return \"audio/webm\";\n const candidates = [\n \"audio/webm;codecs=opus\",\n \"audio/webm\",\n \"audio/mp4\",\n \"audio/ogg;codecs=opus\",\n ];\n for (const mime of candidates) {\n try {\n if (MediaRecorder.isTypeSupported(mime)) return mime;\n } catch {\n /* ignore */\n }\n }\n return \"audio/webm\";\n}\n\nexport function useVoiceDictation(\n options: UseVoiceDictationOptions,\n): VoiceDictationApi {\n const { onTranscript, onError, onLiveUpdate } = options;\n const onTranscriptRef = useRef(onTranscript);\n const onErrorRef = useRef(onError);\n const onLiveUpdateRef = useRef(onLiveUpdate);\n onTranscriptRef.current = onTranscript;\n onErrorRef.current = onError;\n onLiveUpdateRef.current = onLiveUpdate;\n\n const [state, setState] = useState<VoiceState>(\"idle\");\n const [amplitude, setAmplitude] = useState(0);\n const [durationMs, setDurationMs] = useState(0);\n const [errorMessage, setErrorMessage] = useState<string | null>(null);\n const [provider, setProvider] = useState<VoiceProvider>(\"auto\");\n\n // Keep refs for teardown / cross-branch access.\n const mediaStreamRef = useRef<MediaStream | null>(null);\n const mediaRecorderRef = useRef<MediaRecorder | null>(null);\n const chunksRef = useRef<Blob[]>([]);\n const audioContextRef = useRef<AudioContext | null>(null);\n const analyserRef = useRef<AnalyserNode | null>(null);\n const rafRef = useRef<number | null>(null);\n const timerRef = useRef<ReturnType<typeof setInterval> | null>(null);\n const startedAtRef = useRef<number>(0);\n const cancelledRef = useRef(false);\n const speechRef = useRef<any>(null);\n const speechTranscriptRef = useRef<string>(\"\");\n const activeProviderRef = useRef<VoiceProvider>(\"browser\");\n // Parallel live recognition for OpenAI mode (provides instant preview while MediaRecorder captures)\n const liveSpeechRef = useRef<any>(null);\n const liveTextRef = useRef<string>(\"\");\n const realtimeSocketRef = useRef<WebSocket | null>(null);\n const realtimeFinalRef = useRef<string>(\"\");\n const realtimeInterimRef = useRef<string>(\"\");\n const realtimeStopTimeoutRef = useRef<number | null>(null);\n\n const mediaRecorderSupported =\n typeof window !== \"undefined\" &&\n typeof navigator !== \"undefined\" &&\n !!navigator.mediaDevices?.getUserMedia &&\n typeof (window as any).MediaRecorder !== \"undefined\";\n const speechSupported = !!getSpeechRecognitionCtor();\n const supported = mediaRecorderSupported || speechSupported;\n\n const teardown = useCallback(() => {\n if (rafRef.current != null) {\n cancelAnimationFrame(rafRef.current);\n rafRef.current = null;\n }\n if (timerRef.current != null) {\n clearInterval(timerRef.current);\n timerRef.current = null;\n }\n if (mediaStreamRef.current) {\n for (const track of mediaStreamRef.current.getTracks()) {\n track.stop();\n }\n mediaStreamRef.current = null;\n }\n if (audioContextRef.current) {\n audioContextRef.current.close().catch(() => {});\n audioContextRef.current = null;\n }\n if (speechRef.current) {\n // Stop the Web Speech session before dropping the ref so the browser\n // releases the mic and stops dispatching onresult events into a stale\n // closure. abort() is fire-and-forget (no final result); stop() would\n // deliver remaining partials but we've already cleared state.\n try {\n speechRef.current.abort?.();\n } catch {\n /* ignore */\n }\n }\n if (liveSpeechRef.current) {\n try {\n liveSpeechRef.current.abort?.();\n } catch {\n /* ignore */\n }\n liveSpeechRef.current = null;\n }\n if (realtimeSocketRef.current) {\n const socket = realtimeSocketRef.current;\n realtimeSocketRef.current = null;\n try {\n socket.close();\n } catch {\n /* ignore */\n }\n }\n if (realtimeStopTimeoutRef.current) {\n clearTimeout(realtimeStopTimeoutRef.current);\n realtimeStopTimeoutRef.current = null;\n }\n analyserRef.current = null;\n mediaRecorderRef.current = null;\n chunksRef.current = [];\n speechRef.current = null;\n speechTranscriptRef.current = \"\";\n liveTextRef.current = \"\";\n realtimeFinalRef.current = \"\";\n realtimeInterimRef.current = \"\";\n setAmplitude(0);\n }, []);\n\n useEffect(() => teardown, [teardown]);\n\n const failWith = useCallback(\n (message: string) => {\n setErrorMessage(message);\n setState(\"error\");\n onErrorRef.current?.(message);\n teardown();\n },\n [teardown],\n );\n\n const startMeter = useCallback((stream: MediaStream) => {\n try {\n const AudioCtor =\n typeof window !== \"undefined\"\n ? window.AudioContext || (window as any).webkitAudioContext || null\n : null;\n if (!AudioCtor) return;\n const ctx: AudioContext = new AudioCtor();\n const source = ctx.createMediaStreamSource(stream);\n const analyser = ctx.createAnalyser();\n analyser.fftSize = 512;\n source.connect(analyser);\n audioContextRef.current = ctx;\n analyserRef.current = analyser;\n\n const buffer = new Uint8Array(analyser.frequencyBinCount);\n const tick = () => {\n if (!analyserRef.current) return;\n analyserRef.current.getByteTimeDomainData(buffer);\n let sumSquares = 0;\n for (let i = 0; i < buffer.length; i++) {\n const n = (buffer[i] - 128) / 128;\n sumSquares += n * n;\n }\n const rms = Math.sqrt(sumSquares / buffer.length);\n setAmplitude(Math.min(1, rms * 2.5));\n rafRef.current = requestAnimationFrame(tick);\n };\n rafRef.current = requestAnimationFrame(tick);\n } catch {\n /* analyser is best-effort */\n }\n }, []);\n\n const startTimer = useCallback(() => {\n startedAtRef.current = Date.now();\n setDurationMs(0);\n timerRef.current = setInterval(() => {\n setDurationMs(Date.now() - startedAtRef.current);\n }, 100);\n }, []);\n\n const startOpenAi = useCallback(\n async (providerPref: VoiceProvider, instructions?: string) => {\n const stream = await navigator.mediaDevices.getUserMedia({ audio: true });\n // User may have pressed Escape (cancel) while the permission prompt was\n // open. If so, stop the stream and bail before we start recording.\n if (cancelledRef.current) {\n for (const track of stream.getTracks()) track.stop();\n cancelledRef.current = false;\n setState(\"idle\");\n return;\n }\n mediaStreamRef.current = stream;\n const mimeType = pickMimeType();\n const recorder = new MediaRecorder(stream, { mimeType });\n mediaRecorderRef.current = recorder;\n chunksRef.current = [];\n\n recorder.ondataavailable = (e) => {\n if (e.data && e.data.size > 0) chunksRef.current.push(e.data);\n };\n recorder.onstop = async () => {\n const localChunks = chunksRef.current.slice();\n const localMime = recorder.mimeType || mimeType;\n const liveSnapshot = liveTextRef.current;\n teardown();\n if (cancelledRef.current) {\n cancelledRef.current = false;\n setState(\"idle\");\n return;\n }\n if (localChunks.length === 0) {\n if (liveSnapshot) onTranscriptRef.current?.(liveSnapshot.trim());\n setState(\"idle\");\n return;\n }\n setState(\"transcribing\");\n try {\n const audioBlob = new Blob(localChunks, { type: localMime });\n const form = new FormData();\n form.append(\n \"audio\",\n audioBlob,\n `voice.${localMime.split(\"/\")[1] ?? \"webm\"}`,\n );\n form.append(\"provider\", providerPref);\n if (instructions?.trim()) {\n form.append(\"instructions\", instructions.trim());\n }\n const res = await fetch(TRANSCRIBE_URL, {\n method: \"POST\",\n body: form,\n });\n if (!res.ok) {\n const body = await res\n .json()\n .catch(() => ({ error: `HTTP ${res.status}` }));\n throw new Error(\n body.error || `Transcription failed (${res.status})`,\n );\n }\n const data = (await res.json()) as { text?: string };\n const text = (data.text ?? \"\").trim();\n if (text) {\n onTranscriptRef.current?.(text);\n } else if (liveSnapshot) {\n onTranscriptRef.current?.(liveSnapshot.trim());\n }\n setState(\"idle\");\n } catch (err) {\n if (liveSnapshot) {\n onTranscriptRef.current?.(liveSnapshot.trim());\n setState(\"idle\");\n } else {\n failWith(\n (err as Error)?.message ??\n \"Transcription failed. Check your voice transcription provider in settings.\",\n );\n }\n }\n };\n\n startMeter(stream);\n startTimer();\n setState(\"recording\");\n recorder.start();\n\n // Start parallel Web Speech recognition for live preview text.\n // This runs alongside MediaRecorder so the user sees words appear\n // immediately while the server provider processes the full recording later.\n const SpeechCtor = getSpeechRecognitionCtor();\n if (SpeechCtor) {\n const liveSpeech = new SpeechCtor();\n liveSpeech.continuous = true;\n liveSpeech.interimResults = true;\n liveSpeech.lang =\n (typeof navigator !== \"undefined\" && navigator.language) || \"en-US\";\n liveSpeechRef.current = liveSpeech;\n liveTextRef.current = \"\";\n\n liveSpeech.onresult = (event: any) => {\n let interim = \"\";\n for (let i = event.resultIndex; i < event.results.length; i++) {\n const result = event.results[i];\n const text = result[0]?.transcript ?? \"\";\n if (result.isFinal) {\n liveTextRef.current += text;\n } else {\n interim += text;\n }\n }\n onLiveUpdateRef.current?.(liveTextRef.current, interim);\n };\n\n liveSpeech.onend = () => {\n if (liveSpeechRef.current === liveSpeech) {\n try {\n liveSpeech.start();\n } catch {\n /* ignore */\n }\n }\n };\n\n liveSpeech.onerror = () => {};\n\n try {\n liveSpeech.start();\n } catch {\n /* best effort — live preview just won't appear */\n }\n }\n },\n [startMeter, startTimer, teardown, failWith],\n );\n\n const startBrowser = useCallback(async () => {\n const Ctor = getSpeechRecognitionCtor();\n if (!Ctor) {\n throw new Error(\n \"Your browser doesn't support speech recognition. Add an OpenAI API key in settings for Whisper transcription.\",\n );\n }\n // Still request mic to drive the amplitude meter, so the UI doesn't look\n // dead while the user talks. SpeechRecognition manages its own capture\n // under the hood in most browsers.\n let stream: MediaStream | null = null;\n try {\n stream = await navigator.mediaDevices.getUserMedia({ audio: true });\n mediaStreamRef.current = stream;\n startMeter(stream);\n } catch {\n /* non-fatal — recognition can still work without our analyser */\n }\n\n if (cancelledRef.current) {\n if (stream) for (const track of stream.getTracks()) track.stop();\n mediaStreamRef.current = null;\n cancelledRef.current = false;\n setState(\"idle\");\n return;\n }\n\n const recognition = new Ctor();\n recognition.continuous = true;\n recognition.interimResults = true;\n recognition.lang =\n (typeof navigator !== \"undefined\" && navigator.language) || \"en-US\";\n speechRef.current = recognition;\n speechTranscriptRef.current = \"\";\n\n recognition.onresult = (event: any) => {\n let interim = \"\";\n for (let i = event.resultIndex; i < event.results.length; i++) {\n const result = event.results[i];\n const text = result[0]?.transcript ?? \"\";\n if (result.isFinal) {\n speechTranscriptRef.current += text;\n } else {\n interim += text;\n }\n }\n onLiveUpdateRef.current?.(speechTranscriptRef.current, interim);\n };\n recognition.onerror = (event: any) => {\n if (event?.error === \"no-speech\" || event?.error === \"aborted\") return;\n failWith(\n event?.error === \"not-allowed\"\n ? \"Microphone permission denied. Enable it in your browser settings.\"\n : `Speech recognition error: ${event?.error ?? \"unknown\"}`,\n );\n };\n recognition.onend = () => {\n const text = speechTranscriptRef.current.trim();\n const wasCancelled = cancelledRef.current;\n cancelledRef.current = false;\n teardown();\n if (!wasCancelled && text) onTranscriptRef.current?.(text);\n setState(\"idle\");\n };\n\n startTimer();\n setState(\"recording\");\n recognition.start();\n }, [startMeter, startTimer, teardown, failWith]);\n\n const startGoogleRealtime = useCallback(async () => {\n const stream = await navigator.mediaDevices.getUserMedia({ audio: true });\n if (cancelledRef.current) {\n for (const track of stream.getTracks()) track.stop();\n cancelledRef.current = false;\n setState(\"idle\");\n return;\n }\n\n const sessionRes = await fetch(GOOGLE_REALTIME_SESSION_URL, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n language:\n (typeof navigator !== \"undefined\" && navigator.language) || \"en-US\",\n }),\n });\n const sessionBody = (await sessionRes\n .json()\n .catch(() => ({ error: `HTTP ${sessionRes.status}` }))) as {\n websocketUrl?: string;\n websocketProtocol?: string;\n sessionToken?: string;\n error?: string;\n };\n if (\n !sessionRes.ok ||\n !sessionBody.websocketUrl ||\n !sessionBody.sessionToken\n ) {\n for (const track of stream.getTracks()) track.stop();\n throw new Error(\n sessionBody.error ||\n `Could not start Google realtime transcription (${sessionRes.status})`,\n );\n }\n if (cancelledRef.current) {\n for (const track of stream.getTracks()) track.stop();\n cancelledRef.current = false;\n setState(\"idle\");\n return;\n }\n\n mediaStreamRef.current = stream;\n const mimeType = pickMimeType();\n const recorder = new MediaRecorder(stream, { mimeType });\n mediaRecorderRef.current = recorder;\n realtimeFinalRef.current = \"\";\n realtimeInterimRef.current = \"\";\n\n let finalized = false;\n let recorderStarted = false;\n const finish = (errorMessage?: string) => {\n if (finalized) return;\n finalized = true;\n const finalText = realtimeFinalRef.current.trim();\n const interimText = realtimeInterimRef.current.trim();\n const text = [finalText, interimText].filter(Boolean).join(\" \").trim();\n teardown();\n if (cancelledRef.current) {\n cancelledRef.current = false;\n setState(\"idle\");\n return;\n }\n if (text) {\n onTranscriptRef.current?.(text);\n setState(\"idle\");\n return;\n }\n if (errorMessage) {\n failWith(errorMessage);\n return;\n }\n setState(\"idle\");\n };\n\n recorder.ondataavailable = async (event) => {\n if (!event.data || event.data.size === 0) return;\n const socket = realtimeSocketRef.current;\n if (!socket || socket.readyState !== WebSocket.OPEN) return;\n try {\n socket.send(await event.data.arrayBuffer());\n } catch (err) {\n finish((err as Error)?.message ?? \"Realtime audio upload failed\");\n }\n };\n\n recorder.onstop = () => {\n const socket = realtimeSocketRef.current;\n if (!socket || socket.readyState !== WebSocket.OPEN) {\n finish();\n return;\n }\n setState(\"transcribing\");\n try {\n socket.send(JSON.stringify({ type: \"stop\" }));\n } catch {\n finish();\n return;\n }\n realtimeStopTimeoutRef.current = window.setTimeout(() => {\n const activeSocket = realtimeSocketRef.current;\n if (activeSocket?.readyState === WebSocket.OPEN) {\n try {\n activeSocket.close();\n } catch {\n finish();\n }\n return;\n }\n finish();\n }, 10000);\n };\n\n const socket = new WebSocket(sessionBody.websocketUrl, [\n sessionBody.websocketProtocol || GOOGLE_REALTIME_WS_PROTOCOL,\n sessionBody.sessionToken,\n ]);\n socket.binaryType = \"arraybuffer\";\n realtimeSocketRef.current = socket;\n\n socket.onmessage = (event) => {\n if (cancelledRef.current) {\n finish();\n return;\n }\n const raw =\n typeof event.data === \"string\"\n ? event.data\n : event.data instanceof Blob\n ? null\n : new TextDecoder().decode(event.data);\n if (!raw) return;\n let message:\n | {\n type?: string;\n text?: string;\n error?: string;\n }\n | undefined;\n try {\n message = JSON.parse(raw);\n } catch {\n return;\n }\n if (!message?.type) return;\n if (message.type === \"ready\") {\n if (!recorderStarted) {\n recorderStarted = true;\n startMeter(stream);\n startTimer();\n setState(\"recording\");\n recorder.start(100);\n }\n return;\n }\n if (message.type === \"partial\") {\n realtimeInterimRef.current = (message.text ?? \"\").trim();\n onLiveUpdateRef.current?.(\n realtimeFinalRef.current,\n realtimeInterimRef.current,\n );\n return;\n }\n if (message.type === \"final\") {\n const next = (message.text ?? \"\").trim();\n if (next) {\n realtimeFinalRef.current = [realtimeFinalRef.current.trim(), next]\n .filter(Boolean)\n .join(\" \");\n }\n realtimeInterimRef.current = \"\";\n onLiveUpdateRef.current?.(realtimeFinalRef.current, \"\");\n return;\n }\n if (message.type === \"error\") {\n finish(message.error || \"Google realtime transcription failed\");\n return;\n }\n if (message.type === \"end\") {\n finish();\n }\n };\n\n socket.onerror = () => {\n finish(\"Google realtime transcription connection failed\");\n };\n\n socket.onclose = () => {\n finish();\n };\n\n socket.onopen = () => {\n if (cancelledRef.current) {\n finish();\n return;\n }\n try {\n socket.send(\n JSON.stringify({\n type: \"start\",\n language:\n (typeof navigator !== \"undefined\" && navigator.language) ||\n \"en-US\",\n interimResults: true,\n mimeType,\n }),\n );\n } catch (err) {\n finish((err as Error)?.message ?? \"Could not start realtime stream\");\n }\n };\n }, [startMeter, startTimer, teardown, failWith]);\n\n const start = useCallback(async () => {\n if (state === \"recording\" || state === \"starting\") return;\n setErrorMessage(null);\n setState(\"starting\");\n cancelledRef.current = false;\n\n const prefs = await readVoicePrefs();\n const pref = prefs.provider;\n setProvider(pref);\n\n // Server providers all use the same client-side flow as \"openai\"\n // (MediaRecorder -> POST to /_agent-native/transcribe-voice).\n // The server route handles routing to the right backend.\n const resolvedProvider: VoiceProvider =\n pref === \"auto\" ||\n pref === \"builder\" ||\n pref === \"builder-gemini\" ||\n pref === \"gemini\" ||\n pref === \"groq\"\n ? \"openai\"\n : pref;\n activeProviderRef.current = resolvedProvider;\n\n try {\n if (resolvedProvider === \"openai\") {\n if (!mediaRecorderSupported) {\n throw new Error(\n \"Your browser doesn't support audio recording. Use the browser provider in Settings → Voice Transcription.\",\n );\n }\n await startOpenAi(pref, prefs.instructions);\n } else if (resolvedProvider === \"google-realtime\") {\n if (!mediaRecorderSupported) {\n throw new Error(\n \"Your browser doesn't support audio recording, so Google realtime transcription can't start.\",\n );\n }\n await startGoogleRealtime();\n } else {\n await startBrowser();\n }\n } catch (err) {\n if (cancelledRef.current) {\n cancelledRef.current = false;\n teardown();\n setState(\"idle\");\n return;\n }\n const message =\n (err as Error)?.name === \"NotAllowedError\"\n ? \"Microphone permission denied. Enable it in your browser settings.\"\n : ((err as Error)?.message ?? \"Could not start recording\");\n failWith(message);\n }\n }, [\n state,\n mediaRecorderSupported,\n startOpenAi,\n startGoogleRealtime,\n startBrowser,\n failWith,\n ]);\n\n const stop = useCallback(() => {\n if (state !== \"recording\") return;\n cancelledRef.current = false;\n if (\n (activeProviderRef.current === \"openai\" ||\n activeProviderRef.current === \"google-realtime\") &&\n mediaRecorderRef.current\n ) {\n try {\n mediaRecorderRef.current.stop();\n } catch {\n teardown();\n setState(\"idle\");\n }\n } else if (speechRef.current) {\n try {\n speechRef.current.stop();\n } catch {\n teardown();\n setState(\"idle\");\n }\n } else {\n teardown();\n setState(\"idle\");\n }\n }, [state, teardown]);\n\n const cancel = useCallback(() => {\n if (state !== \"recording\" && state !== \"starting\") return;\n cancelledRef.current = true;\n if (\n (activeProviderRef.current === \"openai\" ||\n activeProviderRef.current === \"google-realtime\") &&\n mediaRecorderRef.current\n ) {\n try {\n mediaRecorderRef.current.stop();\n } catch {\n /* ignore */\n }\n } else if (speechRef.current) {\n try {\n speechRef.current.abort?.();\n } catch {\n /* ignore */\n }\n }\n teardown();\n setState(\"idle\");\n }, [state, teardown]);\n\n return {\n state,\n amplitude,\n durationMs,\n errorMessage,\n provider,\n supported,\n start,\n stop,\n cancel,\n };\n}\n"]}
@@ -4,6 +4,7 @@ export { useAgentChatGenerating } from "./use-agent-chat.js";
4
4
  export { useDevMode } from "./use-dev-mode.js";
5
5
  export { agentNativePath, appApiPath, appBasePath, appPath, } from "./api-path.js";
6
6
  export { useSendToAgentChat } from "./use-send-to-agent-chat.js";
7
+ export { useChatModels, type UseChatModelsResult, type EngineModelGroup, } from "./use-chat-models.js";
7
8
  export { CodeRequiredDialog, type CodeRequiredDialogProps, } from "./components/CodeRequiredDialog.js";
8
9
  export { CodeAgentIndicator, type CodeAgentIndicatorProps, } from "./components/CodeAgentIndicator.js";
9
10
  export { useDbSync, useFileWatcher, useScreenRefreshKey, } from "./use-db-sync.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"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"}