@agent-native/core 0.12.21 → 0.12.22

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.
@@ -43,5 +43,6 @@ export interface VoiceDictationApi {
43
43
  cancel: () => void;
44
44
  dismissError: () => void;
45
45
  }
46
+ export declare function voiceDictationStartErrorMessage(error: unknown): string;
46
47
  export declare function useVoiceDictation(options: UseVoiceDictationOptions): VoiceDictationApi;
47
48
  //# sourceMappingURL=useVoiceDictation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useVoiceDictation.d.ts","sourceRoot":"","sources":["../../../src/client/composer/useVoiceDictation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAKH,MAAM,MAAM,aAAa,GACrB,MAAM,GACN,QAAQ,GACR,SAAS,GACT,iBAAiB,GACjB,gBAAgB,GAChB,SAAS,GACT,QAAQ,GACR,MAAM,CAAC;AAEX,MAAM,MAAM,iBAAiB,GAAG,YAAY,GAAG,iBAAiB,GAAG,OAAO,CAAC;AAE3E,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,aAAa,CAAC;IACxB,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAgDD,MAAM,MAAM,UAAU,GAClB,MAAM,GACN,UAAU,GACV,WAAW,GACX,cAAc,GACd,OAAO,CAAC;AAEZ,MAAM,WAAW,wBAAwB;IACvC,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,mGAAmG;IACnG,YAAY,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;CACjE;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,UAAU,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,QAAQ,EAAE,aAAa,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,YAAY,EAAE,MAAM,IAAI,CAAC;CAC1B;AAmED,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,wBAAwB,GAChC,iBAAiB,CAktBnB"}
1
+ {"version":3,"file":"useVoiceDictation.d.ts","sourceRoot":"","sources":["../../../src/client/composer/useVoiceDictation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAKH,MAAM,MAAM,aAAa,GACrB,MAAM,GACN,QAAQ,GACR,SAAS,GACT,iBAAiB,GACjB,gBAAgB,GAChB,SAAS,GACT,QAAQ,GACR,MAAM,CAAC;AAEX,MAAM,MAAM,iBAAiB,GAAG,YAAY,GAAG,iBAAiB,GAAG,OAAO,CAAC;AAE3E,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,aAAa,CAAC;IACxB,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAgDD,MAAM,MAAM,UAAU,GAClB,MAAM,GACN,UAAU,GACV,WAAW,GACX,cAAc,GACd,OAAO,CAAC;AAEZ,MAAM,WAAW,wBAAwB;IACvC,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,mGAAmG;IACnG,YAAY,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;CACjE;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,UAAU,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,QAAQ,EAAE,aAAa,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,YAAY,EAAE,MAAM,IAAI,CAAC;CAC1B;AAsFD,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAkCtE;AAeD,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,wBAAwB,GAChC,iBAAiB,CA0sBnB"}
@@ -110,6 +110,56 @@ function pickMimeType() {
110
110
  }
111
111
  return "audio/webm";
112
112
  }
113
+ function microphoneBlockedByPermissionsPolicy() {
114
+ if (typeof document === "undefined")
115
+ return false;
116
+ const doc = document;
117
+ const policy = doc.permissionsPolicy ?? doc.featurePolicy ?? null;
118
+ if (!policy?.allowsFeature)
119
+ return false;
120
+ try {
121
+ return !policy.allowsFeature("microphone");
122
+ }
123
+ catch {
124
+ return false;
125
+ }
126
+ }
127
+ export function voiceDictationStartErrorMessage(error) {
128
+ const name = typeof error?.name === "string"
129
+ ? error.name
130
+ : "";
131
+ const message = typeof error?.message === "string"
132
+ ? error.message
133
+ : "";
134
+ if (microphoneBlockedByPermissionsPolicy() ||
135
+ /permissions[- ]policy|feature policy/i.test(message)) {
136
+ return "This app is blocking microphone access through its browser permissions policy. Reload the app, or open it directly in a browser tab.";
137
+ }
138
+ if (name === "NotAllowedError" ||
139
+ name === "SecurityError" ||
140
+ /permission|denied|not allowed/i.test(message)) {
141
+ return "Microphone access is blocked. Click the site controls icon in the address bar, set Microphone to Allow for this app, then try again.";
142
+ }
143
+ if (name === "NotFoundError" || name === "DevicesNotFoundError") {
144
+ return "No microphone was found. Plug one in or choose a different input, then try again.";
145
+ }
146
+ if (name === "NotReadableError" || name === "TrackStartError") {
147
+ return "Your microphone is busy in another app. Close the other app or choose a different input, then try again.";
148
+ }
149
+ return message || "Could not start recording";
150
+ }
151
+ function voiceDictationSpeechErrorMessage(error) {
152
+ if (error === "not-allowed" || error === "service-not-allowed") {
153
+ return voiceDictationStartErrorMessage({
154
+ name: "NotAllowedError",
155
+ message: error,
156
+ });
157
+ }
158
+ if (error === "audio-capture") {
159
+ return "No microphone was found. Plug one in or choose a different input, then try again.";
160
+ }
161
+ return `Speech recognition error: ${error ?? "unknown"}`;
162
+ }
113
163
  export function useVoiceDictation(options) {
114
164
  const { onTranscript, onError, onLiveUpdate } = options;
115
165
  const onTranscriptRef = useRef(onTranscript);
@@ -436,9 +486,7 @@ export function useVoiceDictation(options) {
436
486
  recognition.onerror = (event) => {
437
487
  if (event?.error === "no-speech" || event?.error === "aborted")
438
488
  return;
439
- failWith(event?.error === "not-allowed"
440
- ? "Microphone permission denied. Enable it in your browser settings."
441
- : `Speech recognition error: ${event?.error ?? "unknown"}`);
489
+ failWith(voiceDictationSpeechErrorMessage(event?.error));
442
490
  };
443
491
  recognition.onend = () => {
444
492
  const text = speechTranscriptRef.current.trim();
@@ -690,10 +738,7 @@ export function useVoiceDictation(options) {
690
738
  setState("idle");
691
739
  return;
692
740
  }
693
- const message = err?.name === "NotAllowedError"
694
- ? "Microphone permission denied. Enable it in your browser settings."
695
- : (err?.message ?? "Could not start recording");
696
- failWith(message);
741
+ failWith(voiceDictationStartErrorMessage(err));
697
742
  }
698
743
  }, [
699
744
  state,
@@ -1 +1 @@
1
- {"version":3,"file":"useVoiceDictation.js","sourceRoot":"","sources":["../../../src/client/composer/useVoiceDictation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAoBjD,MAAM,SAAS,GAAG,2BAA2B,CAAC;AAC9C,MAAM,SAAS,GAAG,eAAe,CAC/B,oCAAoC,SAAS,EAAE,CAChD,CAAC;AACF,MAAM,cAAc,GAAG,eAAe,CAAC,iCAAiC,CAAC,CAAC;AAC1E,MAAM,2BAA2B,GAAG,eAAe,CACjD,0CAA0C,CAC3C,CAAC;AACF,MAAM,2BAA2B,GAAG,oBAAoB,CAAC;AACzD,SAAS,eAAe,CAAC,KAAc;IACrC,OAAO,CACL,KAAK,KAAK,MAAM;QAChB,KAAK,KAAK,QAAQ;QAClB,KAAK,KAAK,SAAS;QACnB,KAAK,KAAK,iBAAiB;QAC3B,KAAK,KAAK,gBAAgB;QAC1B,KAAK,KAAK,SAAS;QACnB,KAAK,KAAK,QAAQ;QAClB,KAAK,KAAK,MAAM,CACjB,CAAC;AACJ,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAc;IACzC,OAAO,CACL,KAAK,KAAK,YAAY,IAAI,KAAK,KAAK,iBAAiB,IAAI,KAAK,KAAK,OAAO,CAC3E,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,eAAe;IAC5B,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,wBAAwB,CAC/B,IAAmC,EACnC,QAA8B;IAE9B,IAAI,IAAI,KAAK,YAAY;QAAE,OAAO,SAAS,CAAC;IAC5C,IAAI,IAAI,KAAK,iBAAiB;QAAE,OAAO,iBAAiB,CAAC;IACzD,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QACrB,IAAI,CAAC,QAAQ,IAAI,QAAQ,KAAK,SAAS;YAAE,OAAO,MAAM,CAAC;QACvD,OAAO,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAAC;IAC9D,CAAC;IACD,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC3B,OAAO,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAAC;AAC9D,CAAC;AA6BD,KAAK,UAAU,cAAc;IAC3B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,SAAS,CAAC,CAAC;QACnC,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,EAAE,EAAE,CAAC;QAC1D,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAGtB,CAAC;QACT,MAAM,KAAK,GACR,IAAsC,EAAE,KAAK;YAC7C,IAA0B,CAAC;QAC9B,MAAM,IAAI,GAAG,mBAAmB,CAAC,KAAK,EAAE,iBAAiB,CAAC;YACxD,CAAC,CAAC,KAAK,CAAC,iBAAiB;YACzB,CAAC,CAAC,SAAS,CAAC;QACd,MAAM,CAAC,GACJ,IAA0B,EAAE,QAAQ;YACpC,IAAsC,EAAE,KAAK,EAAE,QAAQ,CAAC;QAC3D,MAAM,YAAY,GACf,IAA0B,EAAE,YAAY;YACxC,IAAsC,EAAE,KAAK,EAAE,YAAY,CAAC;QAC/D,MAAM,QAAQ,GAAG,wBAAwB,CACvC,IAAI,EACJ,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAC9B,CAAC;QACF,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO;gBACL,iBAAiB,EAAE,IAAI;gBACvB,QAAQ;gBACR,YAAY,EACV,OAAO,YAAY,KAAK,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS;aACrE,CAAC;QACJ,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,kBAAkB;IACpB,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,EAAE,EAAE,CAAC;AAC/C,CAAC;AAED,SAAS,wBAAwB;IAC/B,IAAI,OAAO,MAAM,KAAK,WAAW;QAAE,OAAO,IAAI,CAAC;IAC/C,OAAO,CACJ,MAAc,CAAC,iBAAiB;QAChC,MAAc,CAAC,uBAAuB;QACvC,IAAI,CACL,CAAC;AACJ,CAAC;AAED,SAAS,YAAY;IACnB,IAAI,OAAO,aAAa,KAAK,WAAW;QAAE,OAAO,YAAY,CAAC;IAC9D,MAAM,UAAU,GAAG;QACjB,wBAAwB;QACxB,YAAY;QACZ,WAAW;QACX,uBAAuB;KACxB,CAAC;IACF,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,IAAI,CAAC;YACH,IAAI,aAAa,CAAC,eAAe,CAAC,IAAI,CAAC;gBAAE,OAAO,IAAI,CAAC;QACvD,CAAC;QAAC,MAAM,CAAC;YACP,YAAY;QACd,CAAC;IACH,CAAC;IACD,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,OAAiC;IAEjC,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC;IACxD,MAAM,eAAe,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;IAC7C,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IACnC,MAAM,eAAe,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;IAC7C,eAAe,CAAC,OAAO,GAAG,YAAY,CAAC;IACvC,UAAU,CAAC,OAAO,GAAG,OAAO,CAAC;IAC7B,eAAe,CAAC,OAAO,GAAG,YAAY,CAAC;IAEvC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAa,MAAM,CAAC,CAAC;IACvD,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IAC9C,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IAChD,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IACtE,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAgB,MAAM,CAAC,CAAC;IAEhE,gDAAgD;IAChD,MAAM,cAAc,GAAG,MAAM,CAAqB,IAAI,CAAC,CAAC;IACxD,MAAM,gBAAgB,GAAG,MAAM,CAAuB,IAAI,CAAC,CAAC;IAC5D,MAAM,SAAS,GAAG,MAAM,CAAS,EAAE,CAAC,CAAC;IACrC,MAAM,eAAe,GAAG,MAAM,CAAsB,IAAI,CAAC,CAAC;IAC1D,MAAM,WAAW,GAAG,MAAM,CAAsB,IAAI,CAAC,CAAC;IACtD,MAAM,MAAM,GAAG,MAAM,CAAgB,IAAI,CAAC,CAAC;IAC3C,MAAM,QAAQ,GAAG,MAAM,CAAwC,IAAI,CAAC,CAAC;IACrE,MAAM,YAAY,GAAG,MAAM,CAAS,CAAC,CAAC,CAAC;IACvC,MAAM,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IACnC,MAAM,SAAS,GAAG,MAAM,CAAM,IAAI,CAAC,CAAC;IACpC,MAAM,mBAAmB,GAAG,MAAM,CAAS,EAAE,CAAC,CAAC;IAC/C,MAAM,iBAAiB,GAAG,MAAM,CAAgB,SAAS,CAAC,CAAC;IAC3D,oGAAoG;IACpG,MAAM,aAAa,GAAG,MAAM,CAAM,IAAI,CAAC,CAAC;IACxC,MAAM,WAAW,GAAG,MAAM,CAAS,EAAE,CAAC,CAAC;IACvC,MAAM,iBAAiB,GAAG,MAAM,CAAmB,IAAI,CAAC,CAAC;IACzD,MAAM,gBAAgB,GAAG,MAAM,CAAS,EAAE,CAAC,CAAC;IAC5C,MAAM,kBAAkB,GAAG,MAAM,CAAS,EAAE,CAAC,CAAC;IAC9C,MAAM,sBAAsB,GAAG,MAAM,CAAgB,IAAI,CAAC,CAAC;IAE3D,MAAM,sBAAsB,GAC1B,OAAO,MAAM,KAAK,WAAW;QAC7B,OAAO,SAAS,KAAK,WAAW;QAChC,CAAC,CAAC,SAAS,CAAC,YAAY,EAAE,YAAY;QACtC,OAAQ,MAAc,CAAC,aAAa,KAAK,WAAW,CAAC;IACvD,MAAM,eAAe,GAAG,CAAC,CAAC,wBAAwB,EAAE,CAAC;IACrD,MAAM,SAAS,GAAG,sBAAsB,IAAI,eAAe,CAAC;IAE5D,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE;QAChC,IAAI,MAAM,CAAC,OAAO,IAAI,IAAI,EAAE,CAAC;YAC3B,oBAAoB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACrC,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;QACxB,CAAC;QACD,IAAI,QAAQ,CAAC,OAAO,IAAI,IAAI,EAAE,CAAC;YAC7B,aAAa,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YAChC,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAC;QAC1B,CAAC;QACD,IAAI,cAAc,CAAC,OAAO,EAAE,CAAC;YAC3B,KAAK,MAAM,KAAK,IAAI,cAAc,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;gBACvD,KAAK,CAAC,IAAI,EAAE,CAAC;YACf,CAAC;YACD,cAAc,CAAC,OAAO,GAAG,IAAI,CAAC;QAChC,CAAC;QACD,IAAI,eAAe,CAAC,OAAO,EAAE,CAAC;YAC5B,eAAe,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YAChD,eAAe,CAAC,OAAO,GAAG,IAAI,CAAC;QACjC,CAAC;QACD,IAAI,SAAS,CAAC,OAAO,EAAE,CAAC;YACtB,qEAAqE;YACrE,sEAAsE;YACtE,sEAAsE;YACtE,8DAA8D;YAC9D,IAAI,CAAC;gBACH,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;YAC9B,CAAC;YAAC,MAAM,CAAC;gBACP,YAAY;YACd,CAAC;QACH,CAAC;QACD,IAAI,aAAa,CAAC,OAAO,EAAE,CAAC;YAC1B,IAAI,CAAC;gBACH,aAAa,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;YAClC,CAAC;YAAC,MAAM,CAAC;gBACP,YAAY;YACd,CAAC;YACD,aAAa,CAAC,OAAO,GAAG,IAAI,CAAC;QAC/B,CAAC;QACD,IAAI,iBAAiB,CAAC,OAAO,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC;YACzC,iBAAiB,CAAC,OAAO,GAAG,IAAI,CAAC;YACjC,IAAI,CAAC;gBACH,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,CAAC;YAAC,MAAM,CAAC;gBACP,YAAY;YACd,CAAC;QACH,CAAC;QACD,IAAI,sBAAsB,CAAC,OAAO,EAAE,CAAC;YACnC,YAAY,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;YAC7C,sBAAsB,CAAC,OAAO,GAAG,IAAI,CAAC;QACxC,CAAC;QACD,WAAW,CAAC,OAAO,GAAG,IAAI,CAAC;QAC3B,gBAAgB,CAAC,OAAO,GAAG,IAAI,CAAC;QAChC,SAAS,CAAC,OAAO,GAAG,EAAE,CAAC;QACvB,SAAS,CAAC,OAAO,GAAG,IAAI,CAAC;QACzB,mBAAmB,CAAC,OAAO,GAAG,EAAE,CAAC;QACjC,WAAW,CAAC,OAAO,GAAG,EAAE,CAAC;QACzB,gBAAgB,CAAC,OAAO,GAAG,EAAE,CAAC;QAC9B,kBAAkB,CAAC,OAAO,GAAG,EAAE,CAAC;QAChC,YAAY,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,SAAS,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEtC,MAAM,QAAQ,GAAG,WAAW,CAC1B,CAAC,OAAe,EAAE,EAAE;QAClB,eAAe,CAAC,OAAO,CAAC,CAAC;QACzB,QAAQ,CAAC,OAAO,CAAC,CAAC;QAClB,UAAU,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC;QAC9B,QAAQ,EAAE,CAAC;IACb,CAAC,EACD,CAAC,QAAQ,CAAC,CACX,CAAC;IAEF,MAAM,UAAU,GAAG,WAAW,CAAC,CAAC,MAAmB,EAAE,EAAE;QACrD,IAAI,CAAC;YACH,MAAM,SAAS,GACb,OAAO,MAAM,KAAK,WAAW;gBAC3B,CAAC,CAAC,MAAM,CAAC,YAAY,IAAK,MAAc,CAAC,kBAAkB,IAAI,IAAI;gBACnE,CAAC,CAAC,IAAI,CAAC;YACX,IAAI,CAAC,SAAS;gBAAE,OAAO;YACvB,MAAM,GAAG,GAAiB,IAAI,SAAS,EAAE,CAAC;YAC1C,MAAM,MAAM,GAAG,GAAG,CAAC,uBAAuB,CAAC,MAAM,CAAC,CAAC;YACnD,MAAM,QAAQ,GAAG,GAAG,CAAC,cAAc,EAAE,CAAC;YACtC,QAAQ,CAAC,OAAO,GAAG,GAAG,CAAC;YACvB,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YACzB,eAAe,CAAC,OAAO,GAAG,GAAG,CAAC;YAC9B,WAAW,CAAC,OAAO,GAAG,QAAQ,CAAC;YAE/B,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC;YAC1D,MAAM,IAAI,GAAG,GAAG,EAAE;gBAChB,IAAI,CAAC,WAAW,CAAC,OAAO;oBAAE,OAAO;gBACjC,WAAW,CAAC,OAAO,CAAC,qBAAqB,CAAC,MAAM,CAAC,CAAC;gBAClD,IAAI,UAAU,GAAG,CAAC,CAAC;gBACnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oBACvC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC;oBAClC,UAAU,IAAI,CAAC,GAAG,CAAC,CAAC;gBACtB,CAAC;gBACD,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;gBAClD,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC;gBACrC,MAAM,CAAC,OAAO,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC;YAC/C,CAAC,CAAC;YACF,MAAM,CAAC,OAAO,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC;QAC/C,CAAC;QAAC,MAAM,CAAC;YACP,6BAA6B;QAC/B,CAAC;IACH,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,EAAE;QAClC,YAAY,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAClC,aAAa,CAAC,CAAC,CAAC,CAAC;QACjB,QAAQ,CAAC,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE;YAClC,aAAa,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;QACnD,CAAC,EAAE,GAAG,CAAC,CAAC;IACV,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,WAAW,GAAG,WAAW,CAC7B,KAAK,EAAE,YAA2B,EAAE,YAAqB,EAAE,EAAE;QAC3D,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,YAAY,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1E,wEAAwE;QACxE,mEAAmE;QACnE,IAAI,YAAY,CAAC,OAAO,EAAE,CAAC;YACzB,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,SAAS,EAAE;gBAAE,KAAK,CAAC,IAAI,EAAE,CAAC;YACrD,YAAY,CAAC,OAAO,GAAG,KAAK,CAAC;YAC7B,QAAQ,CAAC,MAAM,CAAC,CAAC;YACjB,OAAO;QACT,CAAC;QACD,cAAc,CAAC,OAAO,GAAG,MAAM,CAAC;QAChC,MAAM,QAAQ,GAAG,YAAY,EAAE,CAAC;QAChC,MAAM,QAAQ,GAAG,IAAI,aAAa,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;QACzD,gBAAgB,CAAC,OAAO,GAAG,QAAQ,CAAC;QACpC,SAAS,CAAC,OAAO,GAAG,EAAE,CAAC;QAEvB,QAAQ,CAAC,eAAe,GAAG,CAAC,CAAC,EAAE,EAAE;YAC/B,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC;gBAAE,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAChE,CAAC,CAAC;QACF,QAAQ,CAAC,MAAM,GAAG,KAAK,IAAI,EAAE;YAC3B,MAAM,WAAW,GAAG,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YAC9C,MAAM,SAAS,GAAG,QAAQ,CAAC,QAAQ,IAAI,QAAQ,CAAC;YAChD,MAAM,YAAY,GAAG,WAAW,CAAC,OAAO,CAAC;YACzC,QAAQ,EAAE,CAAC;YACX,IAAI,YAAY,CAAC,OAAO,EAAE,CAAC;gBACzB,YAAY,CAAC,OAAO,GAAG,KAAK,CAAC;gBAC7B,QAAQ,CAAC,MAAM,CAAC,CAAC;gBACjB,OAAO;YACT,CAAC;YACD,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC7B,IAAI,YAAY;oBAAE,eAAe,CAAC,OAAO,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,CAAC;gBACjE,QAAQ,CAAC,MAAM,CAAC,CAAC;gBACjB,OAAO;YACT,CAAC;YACD,QAAQ,CAAC,cAAc,CAAC,CAAC;YACzB,IAAI,CAAC;gBACH,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;gBAC7D,MAAM,IAAI,GAAG,IAAI,QAAQ,EAAE,CAAC;gBAC5B,IAAI,CAAC,MAAM,CACT,OAAO,EACP,SAAS,EACT,SAAS,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,MAAM,EAAE,CAC7C,CAAC;gBACF,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;gBACtC,IAAI,YAAY,EAAE,IAAI,EAAE,EAAE,CAAC;oBACzB,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,YAAY,CAAC,IAAI,EAAE,CAAC,CAAC;gBACnD,CAAC;gBACD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,cAAc,EAAE;oBACtC,MAAM,EAAE,MAAM;oBACd,IAAI,EAAE,IAAI;iBACX,CAAC,CAAC;gBACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;oBACZ,MAAM,IAAI,GAAG,MAAM,GAAG;yBACnB,IAAI,EAAE;yBACN,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC;oBAClD,MAAM,IAAI,KAAK,CACb,IAAI,CAAC,KAAK,IAAI,yBAAyB,GAAG,CAAC,MAAM,GAAG,CACrD,CAAC;gBACJ,CAAC;gBACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAsB,CAAC;gBACrD,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBACtC,IAAI,IAAI,EAAE,CAAC;oBACT,eAAe,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC;gBAClC,CAAC;qBAAM,IAAI,YAAY,EAAE,CAAC;oBACxB,eAAe,CAAC,OAAO,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,CAAC;gBACjD,CAAC;gBACD,QAAQ,CAAC,MAAM,CAAC,CAAC;YACnB,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,YAAY,EAAE,CAAC;oBACjB,eAAe,CAAC,OAAO,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,CAAC;oBAC/C,QAAQ,CAAC,MAAM,CAAC,CAAC;gBACnB,CAAC;qBAAM,CAAC;oBACN,QAAQ,CACL,GAAa,EAAE,OAAO;wBACrB,4EAA4E,CAC/E,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC,CAAC;QAEF,UAAU,CAAC,MAAM,CAAC,CAAC;QACnB,UAAU,EAAE,CAAC;QACb,QAAQ,CAAC,WAAW,CAAC,CAAC;QACtB,QAAQ,CAAC,KAAK,EAAE,CAAC;QAEjB,+DAA+D;QAC/D,kEAAkE;QAClE,4EAA4E;QAC5E,MAAM,UAAU,GAAG,wBAAwB,EAAE,CAAC;QAC9C,IAAI,UAAU,EAAE,CAAC;YACf,MAAM,UAAU,GAAG,IAAI,UAAU,EAAE,CAAC;YACpC,UAAU,CAAC,UAAU,GAAG,IAAI,CAAC;YAC7B,UAAU,CAAC,cAAc,GAAG,IAAI,CAAC;YACjC,UAAU,CAAC,IAAI;gBACb,CAAC,OAAO,SAAS,KAAK,WAAW,IAAI,SAAS,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC;YACtE,aAAa,CAAC,OAAO,GAAG,UAAU,CAAC;YACnC,WAAW,CAAC,OAAO,GAAG,EAAE,CAAC;YAEzB,UAAU,CAAC,QAAQ,GAAG,CAAC,KAAU,EAAE,EAAE;gBACnC,IAAI,OAAO,GAAG,EAAE,CAAC;gBACjB,KAAK,IAAI,CAAC,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oBAC9D,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;oBAChC,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,UAAU,IAAI,EAAE,CAAC;oBACzC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;wBACnB,WAAW,CAAC,OAAO,IAAI,IAAI,CAAC;oBAC9B,CAAC;yBAAM,CAAC;wBACN,OAAO,IAAI,IAAI,CAAC;oBAClB,CAAC;gBACH,CAAC;gBACD,eAAe,CAAC,OAAO,EAAE,CAAC,WAAW,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC1D,CAAC,CAAC;YAEF,UAAU,CAAC,KAAK,GAAG,GAAG,EAAE;gBACtB,IAAI,aAAa,CAAC,OAAO,KAAK,UAAU,EAAE,CAAC;oBACzC,IAAI,CAAC;wBACH,UAAU,CAAC,KAAK,EAAE,CAAC;oBACrB,CAAC;oBAAC,MAAM,CAAC;wBACP,YAAY;oBACd,CAAC;gBACH,CAAC;YACH,CAAC,CAAC;YAEF,UAAU,CAAC,OAAO,GAAG,GAAG,EAAE,GAAE,CAAC,CAAC;YAE9B,IAAI,CAAC;gBACH,UAAU,CAAC,KAAK,EAAE,CAAC;YACrB,CAAC;YAAC,MAAM,CAAC;gBACP,kDAAkD;YACpD,CAAC;QACH,CAAC;IACH,CAAC,EACD,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAC7C,CAAC;IAEF,MAAM,YAAY,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QAC1C,MAAM,IAAI,GAAG,wBAAwB,EAAE,CAAC;QACxC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CACb,+GAA+G,CAChH,CAAC;QACJ,CAAC;QACD,yEAAyE;QACzE,uEAAuE;QACvE,mCAAmC;QACnC,IAAI,MAAM,GAAuB,IAAI,CAAC;QACtC,IAAI,CAAC;YACH,MAAM,GAAG,MAAM,SAAS,CAAC,YAAY,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACpE,cAAc,CAAC,OAAO,GAAG,MAAM,CAAC;YAChC,UAAU,CAAC,MAAM,CAAC,CAAC;QACrB,CAAC;QAAC,MAAM,CAAC;YACP,iEAAiE;QACnE,CAAC;QAED,IAAI,YAAY,CAAC,OAAO,EAAE,CAAC;YACzB,IAAI,MAAM;gBAAE,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,SAAS,EAAE;oBAAE,KAAK,CAAC,IAAI,EAAE,CAAC;YACjE,cAAc,CAAC,OAAO,GAAG,IAAI,CAAC;YAC9B,YAAY,CAAC,OAAO,GAAG,KAAK,CAAC;YAC7B,QAAQ,CAAC,MAAM,CAAC,CAAC;YACjB,OAAO;QACT,CAAC;QAED,MAAM,WAAW,GAAG,IAAI,IAAI,EAAE,CAAC;QAC/B,WAAW,CAAC,UAAU,GAAG,IAAI,CAAC;QAC9B,WAAW,CAAC,cAAc,GAAG,IAAI,CAAC;QAClC,WAAW,CAAC,IAAI;YACd,CAAC,OAAO,SAAS,KAAK,WAAW,IAAI,SAAS,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC;QACtE,SAAS,CAAC,OAAO,GAAG,WAAW,CAAC;QAChC,mBAAmB,CAAC,OAAO,GAAG,EAAE,CAAC;QAEjC,WAAW,CAAC,QAAQ,GAAG,CAAC,KAAU,EAAE,EAAE;YACpC,IAAI,OAAO,GAAG,EAAE,CAAC;YACjB,KAAK,IAAI,CAAC,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC9D,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;gBAChC,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,UAAU,IAAI,EAAE,CAAC;gBACzC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;oBACnB,mBAAmB,CAAC,OAAO,IAAI,IAAI,CAAC;gBACtC,CAAC;qBAAM,CAAC;oBACN,OAAO,IAAI,IAAI,CAAC;gBAClB,CAAC;YACH,CAAC;YACD,eAAe,CAAC,OAAO,EAAE,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAClE,CAAC,CAAC;QACF,WAAW,CAAC,OAAO,GAAG,CAAC,KAAU,EAAE,EAAE;YACnC,IAAI,KAAK,EAAE,KAAK,KAAK,WAAW,IAAI,KAAK,EAAE,KAAK,KAAK,SAAS;gBAAE,OAAO;YACvE,QAAQ,CACN,KAAK,EAAE,KAAK,KAAK,aAAa;gBAC5B,CAAC,CAAC,mEAAmE;gBACrE,CAAC,CAAC,6BAA6B,KAAK,EAAE,KAAK,IAAI,SAAS,EAAE,CAC7D,CAAC;QACJ,CAAC,CAAC;QACF,WAAW,CAAC,KAAK,GAAG,GAAG,EAAE;YACvB,MAAM,IAAI,GAAG,mBAAmB,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAChD,MAAM,YAAY,GAAG,YAAY,CAAC,OAAO,CAAC;YAC1C,YAAY,CAAC,OAAO,GAAG,KAAK,CAAC;YAC7B,QAAQ,EAAE,CAAC;YACX,IAAI,CAAC,YAAY,IAAI,IAAI;gBAAE,eAAe,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC;YAC3D,QAAQ,CAAC,MAAM,CAAC,CAAC;QACnB,CAAC,CAAC;QAEF,UAAU,EAAE,CAAC;QACb,QAAQ,CAAC,WAAW,CAAC,CAAC;QACtB,WAAW,CAAC,KAAK,EAAE,CAAC;IACtB,CAAC,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;IAEjD,MAAM,mBAAmB,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QACjD,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,YAAY,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1E,IAAI,YAAY,CAAC,OAAO,EAAE,CAAC;YACzB,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,SAAS,EAAE;gBAAE,KAAK,CAAC,IAAI,EAAE,CAAC;YACrD,YAAY,CAAC,OAAO,GAAG,KAAK,CAAC;YAC7B,QAAQ,CAAC,MAAM,CAAC,CAAC;YACjB,OAAO;QACT,CAAC;QAED,MAAM,UAAU,GAAG,MAAM,KAAK,CAAC,2BAA2B,EAAE;YAC1D,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,QAAQ,EACN,CAAC,OAAO,SAAS,KAAK,WAAW,IAAI,SAAS,CAAC,QAAQ,CAAC,IAAI,OAAO;aACtE,CAAC;SACH,CAAC,CAAC;QACH,MAAM,WAAW,GAAG,CAAC,MAAM,UAAU;aAClC,IAAI,EAAE;aACN,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAKvD,CAAC;QACF,IACE,CAAC,UAAU,CAAC,EAAE;YACd,CAAC,WAAW,CAAC,YAAY;YACzB,CAAC,WAAW,CAAC,YAAY,EACzB,CAAC;YACD,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,SAAS,EAAE;gBAAE,KAAK,CAAC,IAAI,EAAE,CAAC;YACrD,MAAM,IAAI,KAAK,CACb,WAAW,CAAC,KAAK;gBACf,kDAAkD,UAAU,CAAC,MAAM,GAAG,CACzE,CAAC;QACJ,CAAC;QACD,IAAI,YAAY,CAAC,OAAO,EAAE,CAAC;YACzB,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,SAAS,EAAE;gBAAE,KAAK,CAAC,IAAI,EAAE,CAAC;YACrD,YAAY,CAAC,OAAO,GAAG,KAAK,CAAC;YAC7B,QAAQ,CAAC,MAAM,CAAC,CAAC;YACjB,OAAO;QACT,CAAC;QAED,cAAc,CAAC,OAAO,GAAG,MAAM,CAAC;QAChC,MAAM,QAAQ,GAAG,YAAY,EAAE,CAAC;QAChC,MAAM,QAAQ,GAAG,IAAI,aAAa,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;QACzD,gBAAgB,CAAC,OAAO,GAAG,QAAQ,CAAC;QACpC,gBAAgB,CAAC,OAAO,GAAG,EAAE,CAAC;QAC9B,kBAAkB,CAAC,OAAO,GAAG,EAAE,CAAC;QAEhC,IAAI,SAAS,GAAG,KAAK,CAAC;QACtB,IAAI,eAAe,GAAG,KAAK,CAAC;QAC5B,MAAM,MAAM,GAAG,CAAC,YAAqB,EAAE,EAAE;YACvC,IAAI,SAAS;gBAAE,OAAO;YACtB,SAAS,GAAG,IAAI,CAAC;YACjB,MAAM,SAAS,GAAG,gBAAgB,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAClD,MAAM,WAAW,GAAG,kBAAkB,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YACtD,MAAM,IAAI,GAAG,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;YACvE,QAAQ,EAAE,CAAC;YACX,IAAI,YAAY,CAAC,OAAO,EAAE,CAAC;gBACzB,YAAY,CAAC,OAAO,GAAG,KAAK,CAAC;gBAC7B,QAAQ,CAAC,MAAM,CAAC,CAAC;gBACjB,OAAO;YACT,CAAC;YACD,IAAI,IAAI,EAAE,CAAC;gBACT,eAAe,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC;gBAChC,QAAQ,CAAC,MAAM,CAAC,CAAC;gBACjB,OAAO;YACT,CAAC;YACD,IAAI,YAAY,EAAE,CAAC;gBACjB,QAAQ,CAAC,YAAY,CAAC,CAAC;gBACvB,OAAO;YACT,CAAC;YACD,QAAQ,CAAC,MAAM,CAAC,CAAC;QACnB,CAAC,CAAC;QAEF,QAAQ,CAAC,eAAe,GAAG,KAAK,EAAE,KAAK,EAAE,EAAE;YACzC,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC;gBAAE,OAAO;YACjD,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC;YACzC,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS,CAAC,IAAI;gBAAE,OAAO;YAC5D,IAAI,CAAC;gBACH,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;YAC9C,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,CAAE,GAAa,EAAE,OAAO,IAAI,8BAA8B,CAAC,CAAC;YACpE,CAAC;QACH,CAAC,CAAC;QAEF,QAAQ,CAAC,MAAM,GAAG,GAAG,EAAE;YACrB,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC;YACzC,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS,CAAC,IAAI,EAAE,CAAC;gBACpD,MAAM,EAAE,CAAC;gBACT,OAAO;YACT,CAAC;YACD,QAAQ,CAAC,cAAc,CAAC,CAAC;YACzB,IAAI,CAAC;gBACH,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;YAChD,CAAC;YAAC,MAAM,CAAC;gBACP,MAAM,EAAE,CAAC;gBACT,OAAO;YACT,CAAC;YACD,sBAAsB,CAAC,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE;gBACtD,MAAM,YAAY,GAAG,iBAAiB,CAAC,OAAO,CAAC;gBAC/C,IAAI,YAAY,EAAE,UAAU,KAAK,SAAS,CAAC,IAAI,EAAE,CAAC;oBAChD,IAAI,CAAC;wBACH,YAAY,CAAC,KAAK,EAAE,CAAC;oBACvB,CAAC;oBAAC,MAAM,CAAC;wBACP,MAAM,EAAE,CAAC;oBACX,CAAC;oBACD,OAAO;gBACT,CAAC;gBACD,MAAM,EAAE,CAAC;YACX,CAAC,EAAE,KAAK,CAAC,CAAC;QACZ,CAAC,CAAC;QAEF,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,WAAW,CAAC,YAAY,EAAE;YACrD,WAAW,CAAC,iBAAiB,IAAI,2BAA2B;YAC5D,WAAW,CAAC,YAAY;SACzB,CAAC,CAAC;QACH,MAAM,CAAC,UAAU,GAAG,aAAa,CAAC;QAClC,iBAAiB,CAAC,OAAO,GAAG,MAAM,CAAC;QAEnC,MAAM,CAAC,SAAS,GAAG,CAAC,KAAK,EAAE,EAAE;YAC3B,IAAI,YAAY,CAAC,OAAO,EAAE,CAAC;gBACzB,MAAM,EAAE,CAAC;gBACT,OAAO;YACT,CAAC;YACD,MAAM,GAAG,GACP,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ;gBAC5B,CAAC,CAAC,KAAK,CAAC,IAAI;gBACZ,CAAC,CAAC,KAAK,CAAC,IAAI,YAAY,IAAI;oBAC1B,CAAC,CAAC,IAAI;oBACN,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC7C,IAAI,CAAC,GAAG;gBAAE,OAAO;YACjB,IAAI,OAMS,CAAC;YACd,IAAI,CAAC;gBACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC5B,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO;YACT,CAAC;YACD,IAAI,CAAC,OAAO,EAAE,IAAI;gBAAE,OAAO;YAC3B,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC7B,IAAI,CAAC,eAAe,EAAE,CAAC;oBACrB,eAAe,GAAG,IAAI,CAAC;oBACvB,UAAU,CAAC,MAAM,CAAC,CAAC;oBACnB,UAAU,EAAE,CAAC;oBACb,QAAQ,CAAC,WAAW,CAAC,CAAC;oBACtB,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBACtB,CAAC;gBACD,OAAO;YACT,CAAC;YACD,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC/B,kBAAkB,CAAC,OAAO,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBACzD,eAAe,CAAC,OAAO,EAAE,CACvB,gBAAgB,CAAC,OAAO,EACxB,kBAAkB,CAAC,OAAO,CAC3B,CAAC;gBACF,OAAO;YACT,CAAC;YACD,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC7B,MAAM,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBACzC,IAAI,IAAI,EAAE,CAAC;oBACT,gBAAgB,CAAC,OAAO,GAAG,CAAC,gBAAgB,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,IAAI,CAAC;yBAC/D,MAAM,CAAC,OAAO,CAAC;yBACf,IAAI,CAAC,GAAG,CAAC,CAAC;gBACf,CAAC;gBACD,kBAAkB,CAAC,OAAO,GAAG,EAAE,CAAC;gBAChC,eAAe,CAAC,OAAO,EAAE,CAAC,gBAAgB,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;gBACxD,OAAO;YACT,CAAC;YACD,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC7B,MAAM,CAAC,OAAO,CAAC,KAAK,IAAI,sCAAsC,CAAC,CAAC;gBAChE,OAAO;YACT,CAAC;YACD,IAAI,OAAO,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;gBAC3B,MAAM,EAAE,CAAC;YACX,CAAC;QACH,CAAC,CAAC;QAEF,MAAM,CAAC,OAAO,GAAG,GAAG,EAAE;YACpB,MAAM,CAAC,iDAAiD,CAAC,CAAC;QAC5D,CAAC,CAAC;QAEF,MAAM,CAAC,OAAO,GAAG,GAAG,EAAE;YACpB,MAAM,EAAE,CAAC;QACX,CAAC,CAAC;QAEF,MAAM,CAAC,MAAM,GAAG,GAAG,EAAE;YACnB,IAAI,YAAY,CAAC,OAAO,EAAE,CAAC;gBACzB,MAAM,EAAE,CAAC;gBACT,OAAO;YACT,CAAC;YACD,IAAI,CAAC;gBACH,MAAM,CAAC,IAAI,CACT,IAAI,CAAC,SAAS,CAAC;oBACb,IAAI,EAAE,OAAO;oBACb,QAAQ,EACN,CAAC,OAAO,SAAS,KAAK,WAAW,IAAI,SAAS,CAAC,QAAQ,CAAC;wBACxD,OAAO;oBACT,cAAc,EAAE,IAAI;oBACpB,QAAQ;iBACT,CAAC,CACH,CAAC;YACJ,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,CAAE,GAAa,EAAE,OAAO,IAAI,iCAAiC,CAAC,CAAC;YACvE,CAAC;QACH,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;IAEjD,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QACnC,IAAI,KAAK,KAAK,WAAW,IAAI,KAAK,KAAK,UAAU;YAAE,OAAO;QAC1D,eAAe,CAAC,IAAI,CAAC,CAAC;QACtB,QAAQ,CAAC,UAAU,CAAC,CAAC;QACrB,YAAY,CAAC,OAAO,GAAG,KAAK,CAAC;QAE7B,MAAM,KAAK,GAAG,MAAM,cAAc,EAAE,CAAC;QACrC,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC;QAC5B,WAAW,CAAC,IAAI,CAAC,CAAC;QAElB,iEAAiE;QACjE,8DAA8D;QAC9D,yDAAyD;QACzD,MAAM,gBAAgB,GACpB,IAAI,KAAK,MAAM;YACf,IAAI,KAAK,SAAS;YAClB,IAAI,KAAK,gBAAgB;YACzB,IAAI,KAAK,QAAQ;YACjB,IAAI,KAAK,MAAM;YACb,CAAC,CAAC,QAAQ;YACV,CAAC,CAAC,IAAI,CAAC;QACX,iBAAiB,CAAC,OAAO,GAAG,gBAAgB,CAAC;QAE7C,IAAI,CAAC;YACH,IAAI,gBAAgB,KAAK,QAAQ,EAAE,CAAC;gBAClC,IAAI,CAAC,sBAAsB,EAAE,CAAC;oBAC5B,MAAM,IAAI,KAAK,CACb,2GAA2G,CAC5G,CAAC;gBACJ,CAAC;gBACD,MAAM,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;YAC9C,CAAC;iBAAM,IAAI,gBAAgB,KAAK,iBAAiB,EAAE,CAAC;gBAClD,IAAI,CAAC,sBAAsB,EAAE,CAAC;oBAC5B,MAAM,IAAI,KAAK,CACb,6FAA6F,CAC9F,CAAC;gBACJ,CAAC;gBACD,MAAM,mBAAmB,EAAE,CAAC;YAC9B,CAAC;iBAAM,CAAC;gBACN,MAAM,YAAY,EAAE,CAAC;YACvB,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,YAAY,CAAC,OAAO,EAAE,CAAC;gBACzB,YAAY,CAAC,OAAO,GAAG,KAAK,CAAC;gBAC7B,QAAQ,EAAE,CAAC;gBACX,QAAQ,CAAC,MAAM,CAAC,CAAC;gBACjB,OAAO;YACT,CAAC;YACD,MAAM,OAAO,GACV,GAAa,EAAE,IAAI,KAAK,iBAAiB;gBACxC,CAAC,CAAC,mEAAmE;gBACrE,CAAC,CAAC,CAAE,GAAa,EAAE,OAAO,IAAI,2BAA2B,CAAC,CAAC;YAC/D,QAAQ,CAAC,OAAO,CAAC,CAAC;QACpB,CAAC;IACH,CAAC,EAAE;QACD,KAAK;QACL,sBAAsB;QACtB,WAAW;QACX,mBAAmB;QACnB,YAAY;QACZ,QAAQ;KACT,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,EAAE;QAC5B,IAAI,KAAK,KAAK,WAAW;YAAE,OAAO;QAClC,YAAY,CAAC,OAAO,GAAG,KAAK,CAAC;QAC7B,IACE,CAAC,iBAAiB,CAAC,OAAO,KAAK,QAAQ;YACrC,iBAAiB,CAAC,OAAO,KAAK,iBAAiB,CAAC;YAClD,gBAAgB,CAAC,OAAO,EACxB,CAAC;YACD,IAAI,CAAC;gBACH,gBAAgB,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAClC,CAAC;YAAC,MAAM,CAAC;gBACP,QAAQ,EAAE,CAAC;gBACX,QAAQ,CAAC,MAAM,CAAC,CAAC;YACnB,CAAC;QACH,CAAC;aAAM,IAAI,SAAS,CAAC,OAAO,EAAE,CAAC;YAC7B,IAAI,CAAC;gBACH,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAC3B,CAAC;YAAC,MAAM,CAAC;gBACP,QAAQ,EAAE,CAAC;gBACX,QAAQ,CAAC,MAAM,CAAC,CAAC;YACnB,CAAC;QACH,CAAC;aAAM,CAAC;YACN,QAAQ,EAAE,CAAC;YACX,QAAQ,CAAC,MAAM,CAAC,CAAC;QACnB,CAAC;IACH,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;IAEtB,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,EAAE;QAC9B,IAAI,KAAK,KAAK,WAAW,IAAI,KAAK,KAAK,UAAU;YAAE,OAAO;QAC1D,YAAY,CAAC,OAAO,GAAG,IAAI,CAAC;QAC5B,IACE,CAAC,iBAAiB,CAAC,OAAO,KAAK,QAAQ;YACrC,iBAAiB,CAAC,OAAO,KAAK,iBAAiB,CAAC;YAClD,gBAAgB,CAAC,OAAO,EACxB,CAAC;YACD,IAAI,CAAC;gBACH,gBAAgB,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAClC,CAAC;YAAC,MAAM,CAAC;gBACP,YAAY;YACd,CAAC;QACH,CAAC;aAAM,IAAI,SAAS,CAAC,OAAO,EAAE,CAAC;YAC7B,IAAI,CAAC;gBACH,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;YAC9B,CAAC;YAAC,MAAM,CAAC;gBACP,YAAY;YACd,CAAC;QACH,CAAC;QACD,QAAQ,EAAE,CAAC;QACX,QAAQ,CAAC,MAAM,CAAC,CAAC;IACnB,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;IAEtB,6EAA6E;IAC7E,6EAA6E;IAC7E,0EAA0E;IAC1E,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,KAAK,KAAK,OAAO;YAAE,OAAO;QAC9B,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,EAAE;YAC7B,eAAe,CAAC,IAAI,CAAC,CAAC;YACtB,QAAQ,CAAC,MAAM,CAAC,CAAC;QACnB,CAAC,EAAE,IAAI,CAAC,CAAC;QACT,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;IACpC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAEZ,MAAM,YAAY,GAAG,WAAW,CAAC,GAAG,EAAE;QACpC,eAAe,CAAC,IAAI,CAAC,CAAC;QACtB,IAAI,KAAK,KAAK,OAAO;YAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC1C,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAEZ,OAAO;QACL,KAAK;QACL,SAAS;QACT,UAAU;QACV,YAAY;QACZ,QAAQ;QACR,SAAS;QACT,KAAK;QACL,IAAI;QACJ,MAAM;QACN,YAAY;KACb,CAAC;AACJ,CAAC","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 dismissError: () => 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 // Auto-dismiss error after 8s so a stale \"permission denied\" message doesn't\n // sit forever after the user fixes the underlying permission. Manual dismiss\n // (via dismissError) and click-to-retry both also clear the error sooner.\n useEffect(() => {\n if (state !== \"error\") return;\n const handle = setTimeout(() => {\n setErrorMessage(null);\n setState(\"idle\");\n }, 8000);\n return () => clearTimeout(handle);\n }, [state]);\n\n const dismissError = useCallback(() => {\n setErrorMessage(null);\n if (state === \"error\") setState(\"idle\");\n }, [state]);\n\n return {\n state,\n amplitude,\n durationMs,\n errorMessage,\n provider,\n supported,\n start,\n stop,\n cancel,\n dismissError,\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 dismissError: () => 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\ntype BrowserDocumentPolicy = {\n allowsFeature: (feature: string) => boolean;\n};\n\nfunction microphoneBlockedByPermissionsPolicy(): boolean {\n if (typeof document === \"undefined\") return false;\n const doc = document as Document & {\n permissionsPolicy?: BrowserDocumentPolicy;\n featurePolicy?: BrowserDocumentPolicy;\n };\n const policy = doc.permissionsPolicy ?? doc.featurePolicy ?? null;\n if (!policy?.allowsFeature) return false;\n try {\n return !policy.allowsFeature(\"microphone\");\n } catch {\n return false;\n }\n}\n\nexport function voiceDictationStartErrorMessage(error: unknown): string {\n const name =\n typeof (error as { name?: unknown } | null)?.name === \"string\"\n ? (error as { name: string }).name\n : \"\";\n const message =\n typeof (error as { message?: unknown } | null)?.message === \"string\"\n ? (error as { message: string }).message\n : \"\";\n\n if (\n microphoneBlockedByPermissionsPolicy() ||\n /permissions[- ]policy|feature policy/i.test(message)\n ) {\n return \"This app is blocking microphone access through its browser permissions policy. Reload the app, or open it directly in a browser tab.\";\n }\n\n if (\n name === \"NotAllowedError\" ||\n name === \"SecurityError\" ||\n /permission|denied|not allowed/i.test(message)\n ) {\n return \"Microphone access is blocked. Click the site controls icon in the address bar, set Microphone to Allow for this app, then try again.\";\n }\n\n if (name === \"NotFoundError\" || name === \"DevicesNotFoundError\") {\n return \"No microphone was found. Plug one in or choose a different input, then try again.\";\n }\n\n if (name === \"NotReadableError\" || name === \"TrackStartError\") {\n return \"Your microphone is busy in another app. Close the other app or choose a different input, then try again.\";\n }\n\n return message || \"Could not start recording\";\n}\n\nfunction voiceDictationSpeechErrorMessage(error: string | undefined): string {\n if (error === \"not-allowed\" || error === \"service-not-allowed\") {\n return voiceDictationStartErrorMessage({\n name: \"NotAllowedError\",\n message: error,\n });\n }\n if (error === \"audio-capture\") {\n return \"No microphone was found. Plug one in or choose a different input, then try again.\";\n }\n return `Speech recognition error: ${error ?? \"unknown\"}`;\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(voiceDictationSpeechErrorMessage(event?.error));\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 failWith(voiceDictationStartErrorMessage(err));\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 // Auto-dismiss error after 8s so a stale \"permission denied\" message doesn't\n // sit forever after the user fixes the underlying permission. Manual dismiss\n // (via dismissError) and click-to-retry both also clear the error sooner.\n useEffect(() => {\n if (state !== \"error\") return;\n const handle = setTimeout(() => {\n setErrorMessage(null);\n setState(\"idle\");\n }, 8000);\n return () => clearTimeout(handle);\n }, [state]);\n\n const dismissError = useCallback(() => {\n setErrorMessage(null);\n if (state === \"error\") setState(\"idle\");\n }, [state]);\n\n return {\n state,\n amplitude,\n durationMs,\n errorMessage,\n provider,\n supported,\n start,\n stop,\n cancel,\n dismissError,\n };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"agent-chat-plugin.d.ts","sourceRoot":"","sources":["../../src/server/agent-chat-plugin.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agent-chat-plugin.d.ts","sourceRoot":"","sources":["../../src/server/agent-chat-plugin.ts"],"names":[],"mappings":"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"}
@@ -2618,11 +2618,28 @@ export function createAgentChatPlugin(options) {
2618
2618
  resolveOrgId: options?.resolveOrgId,
2619
2619
  });
2620
2620
  }
2621
+ const preRunGitStatusByThread = new Map();
2622
+ async function recordPreRunGitStatus(threadId) {
2623
+ if (!isDevMode())
2624
+ return;
2625
+ try {
2626
+ const { getUncommittedStatus, isGitRepo } = await import("../checkpoints/service.js");
2627
+ const cwd = process.cwd();
2628
+ preRunGitStatusByThread.set(threadId, isGitRepo(cwd) ? getUncommittedStatus(cwd) : null);
2629
+ }
2630
+ catch {
2631
+ preRunGitStatusByThread.set(threadId, null);
2632
+ }
2633
+ }
2621
2634
  // Callback to persist agent response when run finishes (even if client disconnected).
2622
2635
  // Reconstructs the assistant message from buffered events and appends to thread_data.
2623
2636
  const onRunComplete = async (run, threadId) => {
2624
- if (!threadId)
2637
+ const runThreadId = String(run?.threadId ?? threadId ?? "");
2638
+ if (!threadId) {
2639
+ if (runThreadId)
2640
+ preRunGitStatusByThread.delete(runThreadId);
2625
2641
  return;
2642
+ }
2626
2643
  // Serialize the read-modify-write against the same thread's other
2627
2644
  // `thread_data` writers (setThreadQueuedMessages, setThreadEngineMeta,
2628
2645
  // the frontend-triggered saves below). Without the lock, a concurrent
@@ -2707,9 +2724,21 @@ export function createAgentChatPlugin(options) {
2707
2724
  // Auto-checkpoint in dev mode after file-modifying agent turns
2708
2725
  if (isDevMode()) {
2709
2726
  try {
2710
- const { createCheckpoint: gitCheckpoint, isGitRepo, hasUncommittedChanges, getChangedFileNames, } = await import("../checkpoints/service.js");
2727
+ const { createCheckpoint: gitCheckpoint, isGitRepo, hasUncommittedChanges, getChangedFileNames, getUncommittedStatus, } = await import("../checkpoints/service.js");
2711
2728
  const cwd = process.cwd();
2712
- if (isGitRepo(cwd) && hasUncommittedChanges(cwd)) {
2729
+ const preRunStatus = runThreadId
2730
+ ? preRunGitStatusByThread.get(runThreadId)
2731
+ : undefined;
2732
+ if (runThreadId)
2733
+ preRunGitStatusByThread.delete(runThreadId);
2734
+ // Only auto-commit checkpoints for changes produced by this run.
2735
+ // If the tree was already dirty, a checkpoint commit would sweep
2736
+ // up the user's unrelated work when a reconnect/refresh finishes.
2737
+ const postRunStatus = getUncommittedStatus(cwd);
2738
+ if (preRunStatus === "" &&
2739
+ postRunStatus?.trim() &&
2740
+ isGitRepo(cwd) &&
2741
+ hasUncommittedChanges(cwd)) {
2713
2742
  let summary = "";
2714
2743
  // Try to extract the first sentence of the assistant's text response
2715
2744
  let assistantText = "";
@@ -2928,7 +2957,8 @@ export function createAgentChatPlugin(options) {
2928
2957
  runCtx.model = model;
2929
2958
  }
2930
2959
  },
2931
- onRunStart: (send, threadId) => {
2960
+ onRunStart: async (send, threadId) => {
2961
+ await recordPreRunGitStatus(threadId);
2932
2962
  _runSendByThread.set(threadId, send);
2933
2963
  const runCtx = ensureRequestRunContext();
2934
2964
  if (runCtx)
@@ -2963,7 +2993,8 @@ export function createAgentChatPlugin(options) {
2963
2993
  runCtx.model = model;
2964
2994
  }
2965
2995
  },
2966
- onRunStart: (send, threadId) => {
2996
+ onRunStart: async (send, threadId) => {
2997
+ await recordPreRunGitStatus(threadId);
2967
2998
  _runSendByThread.set(threadId, send);
2968
2999
  const runCtx = ensureRequestRunContext();
2969
3000
  if (runCtx)
@@ -3046,7 +3077,8 @@ export function createAgentChatPlugin(options) {
3046
3077
  runCtx.model = model;
3047
3078
  }
3048
3079
  },
3049
- onRunStart: (send, threadId) => {
3080
+ onRunStart: async (send, threadId) => {
3081
+ await recordPreRunGitStatus(threadId);
3050
3082
  _runSendByThread.set(threadId, send);
3051
3083
  const runCtx = ensureRequestRunContext();
3052
3084
  if (runCtx)