@absolutejs/voice 0.0.22-beta.586 → 0.0.22-beta.587

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.
@@ -847,6 +847,27 @@ var createInitialReconnectState = () => ({
847
847
  maxAttempts: 0,
848
848
  status: "idle"
849
849
  });
850
+ var appendSegmentText = (accumulated, next) => {
851
+ const nextText = next.trim().replace(/\s+/g, " ");
852
+ if (!nextText)
853
+ return accumulated;
854
+ if (!accumulated)
855
+ return nextText;
856
+ if (accumulated === nextText || accumulated.endsWith(nextText)) {
857
+ return accumulated;
858
+ }
859
+ if (nextText.includes(accumulated))
860
+ return nextText;
861
+ return `${accumulated} ${nextText}`;
862
+ };
863
+ var joinPartial = (finalized, interim) => {
864
+ const interimText = interim.trim().replace(/\s+/g, " ");
865
+ if (!finalized)
866
+ return interimText;
867
+ if (!interimText || finalized.endsWith(interimText))
868
+ return finalized;
869
+ return `${finalized} ${interimText}`;
870
+ };
850
871
  var createInitialState = () => ({
851
872
  assistantAudio: [],
852
873
  assistantStreamingText: "",
@@ -864,6 +885,7 @@ var createInitialState = () => ({
864
885
  });
865
886
  var createVoiceStreamStore = () => {
866
887
  let state = createInitialState();
888
+ let turnFinalText = "";
867
889
  const subscribers = new Set;
868
890
  const notify = () => {
869
891
  subscribers.forEach((subscriber) => subscriber());
@@ -949,19 +971,20 @@ var createVoiceStreamStore = () => {
949
971
  };
950
972
  break;
951
973
  case "final":
974
+ turnFinalText = appendSegmentText(turnFinalText, action.transcript.text);
952
975
  state = {
953
976
  ...state,
954
- partial: action.transcript.text,
955
- turns: state.turns.map((turn) => turn)
977
+ partial: turnFinalText
956
978
  };
957
979
  break;
958
980
  case "partial":
959
981
  state = {
960
982
  ...state,
961
- partial: action.transcript.text
983
+ partial: joinPartial(turnFinalText, action.transcript.text)
962
984
  };
963
985
  break;
964
986
  case "replay":
987
+ turnFinalText = action.partial;
965
988
  state = {
966
989
  ...state,
967
990
  assistantStreamingText: "",
@@ -995,6 +1018,7 @@ var createVoiceStreamStore = () => {
995
1018
  };
996
1019
  break;
997
1020
  case "turn":
1021
+ turnFinalText = "";
998
1022
  state = {
999
1023
  ...state,
1000
1024
  partial: "",
@@ -764,6 +764,27 @@ var createInitialReconnectState = () => ({
764
764
  maxAttempts: 0,
765
765
  status: "idle"
766
766
  });
767
+ var appendSegmentText = (accumulated, next) => {
768
+ const nextText = next.trim().replace(/\s+/g, " ");
769
+ if (!nextText)
770
+ return accumulated;
771
+ if (!accumulated)
772
+ return nextText;
773
+ if (accumulated === nextText || accumulated.endsWith(nextText)) {
774
+ return accumulated;
775
+ }
776
+ if (nextText.includes(accumulated))
777
+ return nextText;
778
+ return `${accumulated} ${nextText}`;
779
+ };
780
+ var joinPartial = (finalized, interim) => {
781
+ const interimText = interim.trim().replace(/\s+/g, " ");
782
+ if (!finalized)
783
+ return interimText;
784
+ if (!interimText || finalized.endsWith(interimText))
785
+ return finalized;
786
+ return `${finalized} ${interimText}`;
787
+ };
767
788
  var createInitialState = () => ({
768
789
  assistantAudio: [],
769
790
  assistantStreamingText: "",
@@ -781,6 +802,7 @@ var createInitialState = () => ({
781
802
  });
782
803
  var createVoiceStreamStore = () => {
783
804
  let state = createInitialState();
805
+ let turnFinalText = "";
784
806
  const subscribers = new Set;
785
807
  const notify = () => {
786
808
  subscribers.forEach((subscriber) => subscriber());
@@ -866,19 +888,20 @@ var createVoiceStreamStore = () => {
866
888
  };
867
889
  break;
868
890
  case "final":
891
+ turnFinalText = appendSegmentText(turnFinalText, action.transcript.text);
869
892
  state = {
870
893
  ...state,
871
- partial: action.transcript.text,
872
- turns: state.turns.map((turn) => turn)
894
+ partial: turnFinalText
873
895
  };
874
896
  break;
875
897
  case "partial":
876
898
  state = {
877
899
  ...state,
878
- partial: action.transcript.text
900
+ partial: joinPartial(turnFinalText, action.transcript.text)
879
901
  };
880
902
  break;
881
903
  case "replay":
904
+ turnFinalText = action.partial;
882
905
  state = {
883
906
  ...state,
884
907
  assistantStreamingText: "",
@@ -912,6 +935,7 @@ var createVoiceStreamStore = () => {
912
935
  };
913
936
  break;
914
937
  case "turn":
938
+ turnFinalText = "";
915
939
  state = {
916
940
  ...state,
917
941
  partial: "",
@@ -1151,6 +1151,27 @@ var createInitialReconnectState = () => ({
1151
1151
  maxAttempts: 0,
1152
1152
  status: "idle"
1153
1153
  });
1154
+ var appendSegmentText = (accumulated, next) => {
1155
+ const nextText = next.trim().replace(/\s+/g, " ");
1156
+ if (!nextText)
1157
+ return accumulated;
1158
+ if (!accumulated)
1159
+ return nextText;
1160
+ if (accumulated === nextText || accumulated.endsWith(nextText)) {
1161
+ return accumulated;
1162
+ }
1163
+ if (nextText.includes(accumulated))
1164
+ return nextText;
1165
+ return `${accumulated} ${nextText}`;
1166
+ };
1167
+ var joinPartial = (finalized, interim) => {
1168
+ const interimText = interim.trim().replace(/\s+/g, " ");
1169
+ if (!finalized)
1170
+ return interimText;
1171
+ if (!interimText || finalized.endsWith(interimText))
1172
+ return finalized;
1173
+ return `${finalized} ${interimText}`;
1174
+ };
1154
1175
  var createInitialState2 = () => ({
1155
1176
  assistantAudio: [],
1156
1177
  assistantStreamingText: "",
@@ -1168,6 +1189,7 @@ var createInitialState2 = () => ({
1168
1189
  });
1169
1190
  var createVoiceStreamStore = () => {
1170
1191
  let state = createInitialState2();
1192
+ let turnFinalText = "";
1171
1193
  const subscribers = new Set;
1172
1194
  const notify = () => {
1173
1195
  subscribers.forEach((subscriber) => subscriber());
@@ -1253,19 +1275,20 @@ var createVoiceStreamStore = () => {
1253
1275
  };
1254
1276
  break;
1255
1277
  case "final":
1278
+ turnFinalText = appendSegmentText(turnFinalText, action.transcript.text);
1256
1279
  state = {
1257
1280
  ...state,
1258
- partial: action.transcript.text,
1259
- turns: state.turns.map((turn) => turn)
1281
+ partial: turnFinalText
1260
1282
  };
1261
1283
  break;
1262
1284
  case "partial":
1263
1285
  state = {
1264
1286
  ...state,
1265
- partial: action.transcript.text
1287
+ partial: joinPartial(turnFinalText, action.transcript.text)
1266
1288
  };
1267
1289
  break;
1268
1290
  case "replay":
1291
+ turnFinalText = action.partial;
1269
1292
  state = {
1270
1293
  ...state,
1271
1294
  assistantStreamingText: "",
@@ -1299,6 +1322,7 @@ var createVoiceStreamStore = () => {
1299
1322
  };
1300
1323
  break;
1301
1324
  case "turn":
1325
+ turnFinalText = "";
1302
1326
  state = {
1303
1327
  ...state,
1304
1328
  partial: "",
@@ -761,6 +761,27 @@ var createInitialReconnectState = () => ({
761
761
  maxAttempts: 0,
762
762
  status: "idle"
763
763
  });
764
+ var appendSegmentText = (accumulated, next) => {
765
+ const nextText = next.trim().replace(/\s+/g, " ");
766
+ if (!nextText)
767
+ return accumulated;
768
+ if (!accumulated)
769
+ return nextText;
770
+ if (accumulated === nextText || accumulated.endsWith(nextText)) {
771
+ return accumulated;
772
+ }
773
+ if (nextText.includes(accumulated))
774
+ return nextText;
775
+ return `${accumulated} ${nextText}`;
776
+ };
777
+ var joinPartial = (finalized, interim) => {
778
+ const interimText = interim.trim().replace(/\s+/g, " ");
779
+ if (!finalized)
780
+ return interimText;
781
+ if (!interimText || finalized.endsWith(interimText))
782
+ return finalized;
783
+ return `${finalized} ${interimText}`;
784
+ };
764
785
  var createInitialState = () => ({
765
786
  assistantAudio: [],
766
787
  assistantStreamingText: "",
@@ -778,6 +799,7 @@ var createInitialState = () => ({
778
799
  });
779
800
  var createVoiceStreamStore = () => {
780
801
  let state = createInitialState();
802
+ let turnFinalText = "";
781
803
  const subscribers = new Set;
782
804
  const notify = () => {
783
805
  subscribers.forEach((subscriber) => subscriber());
@@ -863,19 +885,20 @@ var createVoiceStreamStore = () => {
863
885
  };
864
886
  break;
865
887
  case "final":
888
+ turnFinalText = appendSegmentText(turnFinalText, action.transcript.text);
866
889
  state = {
867
890
  ...state,
868
- partial: action.transcript.text,
869
- turns: state.turns.map((turn) => turn)
891
+ partial: turnFinalText
870
892
  };
871
893
  break;
872
894
  case "partial":
873
895
  state = {
874
896
  ...state,
875
- partial: action.transcript.text
897
+ partial: joinPartial(turnFinalText, action.transcript.text)
876
898
  };
877
899
  break;
878
900
  case "replay":
901
+ turnFinalText = action.partial;
879
902
  state = {
880
903
  ...state,
881
904
  assistantStreamingText: "",
@@ -909,6 +932,7 @@ var createVoiceStreamStore = () => {
909
932
  };
910
933
  break;
911
934
  case "turn":
935
+ turnFinalText = "";
912
936
  state = {
913
937
  ...state,
914
938
  partial: "",
@@ -1,10 +1,10 @@
1
- (()=>{var{defineProperty:Q,getOwnPropertyNames:Ic,getOwnPropertyDescriptor:Vc}=Object,Sc=Object.prototype.hasOwnProperty;function Rc(c){return this[c]}var yc=(c)=>{var g=(z??=new WeakMap).get(c),C;if(g)return g;if(g=Q({},"__esModule",{value:!0}),c&&typeof c==="object"||typeof c==="function"){for(var A of Ic(c))if(!Sc.call(g,A))Q(g,A,{get:Rc.bind(c,A),enumerable:!(C=Vc(c,A))||C.enumerable})}return z.set(c,g),g},z;var _c=(c)=>c;function Tc(c,g){this[c]=_c.bind(null,g)}var wc=(c,g)=>{for(var C in g)Q(c,C,{get:g[C],enumerable:!0,configurable:!0,set:Tc.bind(g,C)})};var Fc={};wc(Fc,{mount:()=>cc,default:()=>oc,VOICE_EMBED_VERSION:()=>gc});var hc=(c)=>{if(typeof c!=="string")return c;return document.querySelector(c)},Lc=(c,g,C,A)=>{let I=g??c.getAttribute("hx-get")??"";if(!I)return"";let R=new URL(I,window.location.origin);if(A)R.searchParams.set(C,A);else R.searchParams.delete(C);return`${R.pathname}${R.search}${R.hash}`},B=(c,g)=>{if(typeof window>"u"||typeof document>"u")return()=>{};let C=hc(g.element);if(!C)return()=>{};let A=g.eventName??"voice-refresh",I=g.sessionQueryParam??"sessionId",R=()=>{let T=window,w=Lc(C,g.route,I,c.sessionId);if(w)C.setAttribute("hx-get",w);T.htmx?.process?.(C),T.htmx?.trigger?.(C,A)},S=c.subscribe(R);return R(),()=>{S()}};var Uc=(c)=>Math.max(-1,Math.min(1,c)),$c=(c)=>{let g=new Int16Array(c.length);for(let C=0;C<c.length;C+=1){let A=Uc(c[C]??0);g[C]=A<0?A*32768:A*32767}return new Uint8Array(g.buffer)},nc=(c)=>{let g=c instanceof Uint8Array?c:new Uint8Array(c);if(g.byteLength<2)return 0;let C=new Int16Array(g.buffer,g.byteOffset,Math.floor(g.byteLength/2));if(C.length===0)return 0;let A=0;for(let I of C){let R=I/32768;A+=R*R}return Math.min(1,Math.max(0,Math.sqrt(A/C.length)*5.5))},Oc=(c,g,C)=>{if(g===C)return c;let A=g/C,I=Math.round(c.length/A),R=new Float32Array(I),S=0,T=0;while(S<R.length){let w=Math.round((S+1)*A),U=0,_=0;for(let L=T;L<w&&L<c.length;L+=1)U+=c[L]??0,_+=1;R[S]=_>0?U/_:0,S+=1,T=w}return R},j=(c)=>{let g=null,C=null,A=null,I=null;return{start:async()=>{if(!c.stream&&(typeof navigator>"u"||!navigator.mediaDevices?.getUserMedia))throw Error("Browser microphone capture requires navigator.mediaDevices.getUserMedia.");let T=(typeof window<"u"?window.AudioContext??window.webkitAudioContext:void 0)??AudioContext;if(!T)throw Error("Browser microphone capture requires AudioContext support.");if(I=c.stream??await navigator.mediaDevices.getUserMedia({audio:{autoGainControl:!0,channelCount:c.channelCount??1,echoCancellation:!0,noiseSuppression:!0}}),g=new T,g.state==="suspended")await g.resume();C=g.createMediaStreamSource(I),A=g.createScriptProcessor(4096,1,1),A.onaudioprocess=(w)=>{let U=w.inputBuffer.getChannelData(0),_=Oc(U,g?.sampleRate??48000,c.sampleRateHz??16000),L=$c(_);c.onLevel?.(nc(L)),c.onAudio(L)},C.connect(A),A.connect(g.destination)},stop:()=>{A?.disconnect(),C?.disconnect(),I?.getTracks().forEach((T)=>T.stop()),g?.close(),c.onLevel?.(0),g=null,I=null,A=null,C=null}}};var K=(c)=>{if(typeof c==="string"&&c.trim())return c;if(c instanceof Error&&c.message.trim())return c.message;if(c&&typeof c==="object"){let g=c;for(let C of["message","reason","description"]){let A=g[C];if(typeof A==="string"&&A.trim())return A}if("error"in g)return K(g.error);if("cause"in g)return K(g.cause);try{return JSON.stringify(c)}catch{}}return"Unexpected error"},d=(c)=>{switch(c.type){case"audio":return{chunk:Uint8Array.from(atob(c.chunkBase64),(g)=>g.charCodeAt(0)),format:c.format,receivedAt:c.receivedAt,turnId:c.turnId,type:"audio"};case"assistant":return{text:c.text,turnId:c.turnId,type:"assistant"};case"assistant_delta":return{delta:c.delta,turnId:c.turnId,type:"assistant_delta"};case"complete":return{sessionId:c.sessionId,type:"complete"};case"connection":return{reconnect:c.reconnect,type:"connection"};case"call_lifecycle":return{event:c.event,sessionId:c.sessionId,type:"call_lifecycle"};case"error":return{message:K(c.message),type:"error"};case"final":return{transcript:c.transcript,type:"final"};case"partial":return{transcript:c.transcript,type:"partial"};case"replay":return{assistantTexts:c.assistantTexts,call:c.call,partial:c.partial,scenarioId:c.scenarioId,sessionId:c.sessionId,sessionMetadata:c.sessionMetadata,status:c.status,turns:c.turns,type:"replay"};case"session":return{sessionId:c.sessionId,sessionMetadata:c.sessionMetadata,scenarioId:c.scenarioId,status:c.status,type:"session"};case"turn":return{turn:c.turn,type:"turn"};default:return null}};var tc=Math.PI*2;var N=(c,g,C,A)=>{c.push({code:C,message:A,severity:g})};var bc=(c)=>c.length===0?void 0:c.reduce((g,C)=>g+C,0)/c.length,J=(c)=>c.length===0?void 0:Math.max(...c);var n=(c,g)=>{let C=c[g];return typeof C==="number"&&Number.isFinite(C)?C:void 0},Y=(c,g)=>{let C=c[g];return typeof C==="boolean"?C:void 0},O=(c,g)=>{let C=c[g];return typeof C==="string"?C:void 0},q=(c)=>String(c.id??O(c,"ssrc")??n(c,"ssrc")??O(c,"trackIdentifier")??O(c,"mid")??"unknown"),k=(c)=>c===void 0?void 0:c*1000;var Dc=(c)=>{let g={};for(let[C,A]of Object.entries(c))if(A===null||typeof A==="boolean"||typeof A==="number"||typeof A==="string")g[C]=A;return g};var x=(c={})=>{let g=c.stats??[],C=[],A=g.filter((V)=>V.type==="inbound-rtp"&&O(V,"kind")!=="video"),I=g.filter((V)=>V.type==="outbound-rtp"&&O(V,"kind")!=="video"),R=g.filter((V)=>V.type==="candidate-pair"),S=g.filter((V)=>(V.type==="track"||V.type==="media-source")&&O(V,"kind")==="audio"),T=R.filter((V)=>Y(V,"selected")===!0||Y(V,"nominated")===!0||O(V,"state")==="succeeded").length,w=S.filter((V)=>O(V,"readyState")!=="ended"&&O(V,"trackState")!=="ended"&&Y(V,"ended")!==!0).length,U=S.filter((V)=>O(V,"readyState")==="ended"||O(V,"trackState")==="ended"||Y(V,"ended")===!0).length,_=A.reduce((V,$)=>V+(n($,"packetsReceived")??0),0),L=I.reduce((V,$)=>V+(n($,"packetsSent")??0),0),y=[...A,...I].reduce((V,$)=>V+Math.max(0,n($,"packetsLost")??0),0),b=_+y,h=b===0?0:y/b,E=A.reduce((V,$)=>V+(n($,"bytesReceived")??0),0),H=I.reduce((V,$)=>V+(n($,"bytesSent")??0),0),G=J(R.map((V)=>k(n(V,"currentRoundTripTime")??n(V,"roundTripTime"))).filter((V)=>V!==void 0)),M=J([...A,...I].map((V)=>k(n(V,"jitter"))).filter((V)=>V!==void 0)),X=J(A.map((V)=>{let $=n(V,"jitterBufferDelay"),D=n(V,"jitterBufferEmittedCount");return $!==void 0&&D!==void 0&&D>0?$/D*1000:void 0}).filter((V)=>V!==void 0)),P=S.map((V)=>n(V,"audioLevel")).filter((V)=>V!==void 0);if(c.requireConnectedCandidatePair&&R.length>0&&T===0)N(C,"error","media.webrtc_candidate_pair_missing","No active WebRTC candidate pair was observed.");if(c.requireLiveAudioTrack&&w===0)N(C,"error","media.webrtc_audio_track_missing","No live WebRTC audio track was observed.");if(c.maxPacketLossRatio!==void 0&&h>c.maxPacketLossRatio)N(C,"warning","media.webrtc_packet_loss",`Observed WebRTC packet loss ratio ${String(h)} above ${String(c.maxPacketLossRatio)}.`);if(c.maxRoundTripTimeMs!==void 0&&G!==void 0&&G>c.maxRoundTripTimeMs)N(C,"warning","media.webrtc_round_trip_time",`Observed WebRTC RTT ${String(G)}ms above ${String(c.maxRoundTripTimeMs)}ms.`);if(c.maxJitterMs!==void 0&&M!==void 0&&M>c.maxJitterMs)N(C,"warning","media.webrtc_jitter",`Observed WebRTC jitter ${String(M)}ms above ${String(c.maxJitterMs)}ms.`);return{activeCandidatePairs:T,audioLevelAverage:bc(P),bytesReceived:E,bytesSent:H,checkedAt:Date.now(),endedAudioTracks:U,inboundPackets:_,issues:C,jitterBufferDelayMs:X,jitterMs:M,liveAudioTracks:w,outboundPackets:L,packetLossRatio:h,packetsLost:y,roundTripTimeMs:G,status:C.some((V)=>V.severity==="error")?"fail":C.length>0?"warn":"pass",totalStats:g.length}},i=async(c)=>{return[...(await c.peerConnection.getStats(c.selector??null)).values()].map(Dc)};var f=(c={})=>{let g=c.stats??[],C=c.previousStats??[],A=[],I=new Map(C.map((y)=>[q(y),y])),S=g.filter((y)=>(y.type==="inbound-rtp"||y.type==="outbound-rtp")&&O(y,"kind")!=="video"&&O(y,"mediaType")!=="video").map((y)=>{let b=y.type==="outbound-rtp"?"outbound":"inbound",h=b==="outbound"?"packetsSent":"packetsReceived",E=b==="outbound"?"bytesSent":"bytesReceived",H=I.get(q(y)),G=n(y,h),M=H?n(H,h):void 0,X=n(y,E),P=H?n(H,E):void 0,V=y.timestamp!==void 0&&H?.timestamp!==void 0?y.timestamp-H.timestamp:void 0;return{bytesDelta:X!==void 0&&P!==void 0?X-P:void 0,currentPackets:G,direction:b,id:q(y),packetDelta:G!==void 0&&M!==void 0?G-M:void 0,previousPackets:M,timeDeltaMs:V}}),T=S.filter((y)=>y.direction==="inbound"),w=S.filter((y)=>y.direction==="outbound"),U=J(S.map((y)=>y.timeDeltaMs).filter((y)=>y!==void 0)),_=T.filter((y)=>c.maxInboundPacketStallMs!==void 0&&y.timeDeltaMs!==void 0&&y.timeDeltaMs>=c.maxInboundPacketStallMs&&y.packetDelta!==void 0&&y.packetDelta<=0).length,L=w.filter((y)=>c.maxOutboundPacketStallMs!==void 0&&y.timeDeltaMs!==void 0&&y.timeDeltaMs>=c.maxOutboundPacketStallMs&&y.packetDelta!==void 0&&y.packetDelta<=0).length;if(c.requireInboundAudio&&T.length===0)N(A,"error","media.webrtc_inbound_audio_missing","No inbound WebRTC audio RTP stream was observed.");if(c.requireOutboundAudio&&w.length===0)N(A,"error","media.webrtc_outbound_audio_missing","No outbound WebRTC audio RTP stream was observed.");if(c.maxGapMs!==void 0&&U!==void 0&&U>c.maxGapMs)N(A,"warning","media.webrtc_stream_gap",`Observed WebRTC stream sample gap ${String(U)}ms above ${String(c.maxGapMs)}ms.`);if(_>0)N(A,"error","media.webrtc_inbound_stalled",`${String(_)} inbound WebRTC audio stream(s) stopped receiving packets.`);if(L>0)N(A,"error","media.webrtc_outbound_stalled",`${String(L)} outbound WebRTC audio stream(s) stopped sending packets.`);return{checkedAt:Date.now(),inboundAudioStreams:T.length,issues:A,maxObservedGapMs:U,outboundAudioStreams:w.length,stalledInboundStreams:_,stalledOutboundStreams:L,status:A.some((y)=>y.severity==="error")?"fail":A.length>0?"warn":"pass",streams:S,totalStats:g.length}};var Hc="/api/voice/browser-media",Gc=5000,Mc=async(c)=>c.peerConnection??await c.getPeerConnection?.()??null,Nc=async(c,g)=>{let C=g.fetch??globalThis.fetch;if(!C)return;await C(g.path??Hc,{body:JSON.stringify(c),headers:{"Content-Type":"application/json"},keepalive:!0,method:"POST"})},F=(c)=>{let g=null,C=[],A=async()=>{let S=await Mc(c);if(!S)return;let T=await i({peerConnection:S}),w=x({...c,stats:T}),U=c.continuity===!1?void 0:f({...c.continuity,previousStats:C,stats:T}),_={at:Date.now(),continuity:U,report:w,scenarioId:c.getScenarioId?.()??null,sessionId:c.getSessionId?.()??null};return C=T,c.onReport?.(_),await Nc(_,c),_},I=()=>{A().catch((S)=>{c.onError?.(S)})},R=()=>{if(g)clearInterval(g),g=null};return{close:R,reportOnce:A,stop:R,start:()=>{if(g)return;I(),g=setInterval(I,c.intervalMs??Gc)}}};var W=()=>{},lc=()=>W,Wc={callControl:W,close:W,endTurn:W,send:W,sendAudio:W,simulateDisconnect:W,subscribe:lc,getReadyState:()=>3,getScenarioId:()=>"",getSessionId:()=>"",start:()=>{}},Ec=()=>crypto.randomUUID(),Xc=(c,g,C)=>{let{hostname:A,port:I,protocol:R}=window.location,S=R==="https:"?"wss:":"ws:",T=I?`:${I}`:"",w=new URL(`${S}//${A}${T}${c}`);if(w.searchParams.set("sessionId",g),C)w.searchParams.set("scenarioId",C);return w.toString()},Pc=(c)=>{if(!c||typeof c!=="object"||!("type"in c))return!1;switch(c.type){case"audio":case"assistant":case"call_lifecycle":case"complete":case"connection":case"error":case"final":case"partial":case"pong":case"replay":case"session":case"turn":return!0;default:return!1}},Yc=(c)=>{if(typeof c.data!=="string")return null;try{let g=JSON.parse(c.data);return Pc(g)?g:null}catch{return null}},o=(c,g={})=>{if(typeof window>"u")return Wc;let C=new Set,A=g.reconnect!==!1,I=g.maxReconnectAttempts??10,R=g.pingInterval??30000,S={isConnected:!1,pendingMessages:[],scenarioId:g.scenarioId??null,pingInterval:null,reconnectAttempts:0,reconnectTimeout:null,sessionId:g.sessionId??Ec(),ws:null},T=(V)=>{C.forEach(($)=>$(V))},w=()=>{if(S.pingInterval)clearInterval(S.pingInterval),S.pingInterval=null;if(S.reconnectTimeout)clearTimeout(S.reconnectTimeout),S.reconnectTimeout=null},U=()=>{if(S.ws?.readyState!==1)return;while(S.pendingMessages.length>0){let V=S.pendingMessages.shift();if(V!==void 0)S.ws.send(V)}},_=()=>{let V=Date.now()+500;S.reconnectAttempts+=1,T({reconnect:{attempts:S.reconnectAttempts,lastDisconnectAt:Date.now(),maxAttempts:I,nextAttemptAt:V,status:"reconnecting"},type:"connection"}),S.reconnectTimeout=setTimeout(()=>{if(S.reconnectAttempts>I){T({reconnect:{attempts:S.reconnectAttempts,maxAttempts:I,status:"exhausted"},type:"connection"});return}L()},500)},L=()=>{let V=new WebSocket(Xc(c,S.sessionId,S.scenarioId));V.binaryType="arraybuffer",V.onopen=()=>{let $=S.reconnectAttempts>0;if(S.isConnected=!0,U(),$)T({reconnect:{attempts:S.reconnectAttempts,lastResumedAt:Date.now(),maxAttempts:I,status:"resumed"},type:"connection"}),S.reconnectAttempts=0;C.forEach((D)=>D({scenarioId:S.scenarioId??void 0,sessionId:S.sessionId,status:"active",type:"session"})),S.pingInterval=setInterval(()=>{if(V.readyState===1)V.send(JSON.stringify({type:"ping"}))},R)},V.onmessage=($)=>{let D=Yc($);if(!D)return;if(D.type==="session")S.sessionId=D.sessionId,S.scenarioId=D.scenarioId??S.scenarioId;C.forEach((Cc)=>Cc(D))},V.onclose=($)=>{if(S.isConnected=!1,w(),A&&$.code!==1000&&S.reconnectAttempts<I)_();else if(A&&$.code!==1000)T({reconnect:{attempts:S.reconnectAttempts,lastDisconnectAt:Date.now(),maxAttempts:I,status:"exhausted"},type:"connection"})},S.ws=V},y=(V)=>{if(S.ws?.readyState===1){S.ws.send(V);return}S.pendingMessages.push(V)},b=(V)=>{y(JSON.stringify(V))},h=(V={})=>{if(V.sessionId)S.sessionId=V.sessionId;if(V.scenarioId)S.scenarioId=V.scenarioId;b({scenarioId:S.scenarioId??void 0,sessionId:S.sessionId,type:"start"})},E=(V)=>{y(V)},H=()=>{b({type:"end_turn"})},G=(V)=>{b({...V,type:"call_control"})},M=()=>{if(w(),S.ws)S.ws.close(1000),S.ws=null;S.isConnected=!1,C.clear()},X=()=>{if(S.ws?.readyState===1)S.ws.close(4000,"absolutejs-voice-reconnect-proof")},P=(V)=>{return C.add(V),()=>{C.delete(V)}};return L(),{callControl:G,close:M,endTurn:H,send:b,sendAudio:E,simulateDisconnect:X,start:h,subscribe:P,getReadyState:()=>S.ws?.readyState??3,getScenarioId:()=>S.scenarioId??"",getSessionId:()=>S.sessionId}};var Jc=()=>({attempts:0,maxAttempts:0,status:"idle"}),Zc=()=>({assistantAudio:[],assistantStreamingText:"",assistantTexts:[],call:null,error:null,isConnected:!1,partial:"",reconnect:Jc(),scenarioId:null,sessionId:null,sessionMetadata:null,status:"idle",turns:[]}),s=()=>{let c=Zc(),g=new Set,C=()=>{g.forEach((I)=>I())};return{dispatch:(I)=>{switch(I.type){case"audio":c={...c,assistantAudio:[...c.assistantAudio,{chunk:I.chunk,format:I.format,receivedAt:I.receivedAt,turnId:I.turnId}]};break;case"assistant":c={...c,assistantStreamingText:"",assistantTexts:[...c.assistantTexts,I.text]};break;case"assistant_delta":c={...c,assistantStreamingText:`${c.assistantStreamingText}${I.delta}`};break;case"complete":c={...c,sessionId:I.sessionId,status:"completed"};break;case"call_lifecycle":c={...c,call:{...c.call,disposition:I.event.type==="end"?I.event.disposition:c.call?.disposition,endedAt:I.event.type==="end"?I.event.at:c.call?.endedAt,events:[...c.call?.events??[],I.event],lastEventAt:I.event.at,startedAt:c.call?.startedAt??I.event.at},sessionId:I.sessionId};break;case"connected":c={...c,isConnected:!0,reconnect:c.reconnect.status==="reconnecting"?{...c.reconnect,lastResumedAt:Date.now(),nextAttemptAt:void 0,status:"resumed"}:c.reconnect};break;case"connection":c={...c,reconnect:I.reconnect};break;case"disconnected":c={...c,isConnected:!1};break;case"error":c={...c,error:I.message};break;case"final":c={...c,partial:I.transcript.text,turns:c.turns.map((R)=>R)};break;case"partial":c={...c,partial:I.transcript.text};break;case"replay":c={...c,assistantStreamingText:"",assistantTexts:[...I.assistantTexts],call:I.call??null,error:null,isConnected:I.status==="active",partial:I.partial,reconnect:c.reconnect.status==="reconnecting"?{...c.reconnect,lastResumedAt:Date.now(),nextAttemptAt:void 0,status:"resumed"}:c.reconnect,scenarioId:I.scenarioId??c.scenarioId,sessionId:I.sessionId,sessionMetadata:I.sessionMetadata??c.sessionMetadata,status:I.status,turns:[...I.turns]};break;case"session":c={...c,error:null,scenarioId:I.scenarioId??c.scenarioId,isConnected:I.status==="active",sessionId:I.sessionId,sessionMetadata:I.sessionMetadata??c.sessionMetadata,status:I.status};break;case"turn":c={...c,partial:"",turns:[...c.turns,I.turn]};break}C()},getServerSnapshot:()=>c,getSnapshot:()=>c,subscribe:(I)=>{return g.add(I),()=>{g.delete(I)}}}};var v=(c,g={})=>{let C=o(c,g),A=s(),I=g.browserMedia&&typeof window<"u"?F({...g.browserMedia,getScenarioId:()=>g.browserMedia?g.browserMedia.getScenarioId?.()??C.getScenarioId():C.getScenarioId(),getSessionId:()=>g.browserMedia?g.browserMedia.getSessionId?.()??C.getSessionId():C.getSessionId()}):null,R=new Set,S=(_)=>Promise.resolve().then(()=>{if(!_?.sessionId&&!_?.scenarioId)return;C.start(_),I?.start()}),T=()=>{R.forEach((_)=>_())},w=()=>{if(!g.reconnectReportPath||typeof fetch>"u")return;let _=A.getSnapshot(),L=JSON.stringify({at:Date.now(),reconnect:_.reconnect,scenarioId:_.scenarioId,sessionId:C.getSessionId(),turnIds:_.turns.map((y)=>y.id)});fetch(g.reconnectReportPath,{body:L,headers:{"Content-Type":"application/json"},keepalive:!0,method:"POST"}).catch(()=>{})},U=C.subscribe((_)=>{let L=d(_);if(L){if(A.dispatch(L),_.type==="connection")w();T()}});return{start:S,get assistantAudio(){return A.getSnapshot().assistantAudio},get assistantTexts(){return A.getSnapshot().assistantTexts},get assistantStreamingText(){return A.getSnapshot().assistantStreamingText},get call(){return A.getSnapshot().call},callControl(_){C.callControl(_)},close(){U(),I?.close(),C.close(),A.dispatch({type:"disconnected"}),T()},endTurn(){C.endTurn()},get error(){return A.getSnapshot().error},getServerSnapshot(){return A.getServerSnapshot()},getSnapshot(){return A.getSnapshot()},get isConnected(){return A.getSnapshot().isConnected},get partial(){return A.getSnapshot().partial},get reconnect(){return A.getSnapshot().reconnect},get scenarioId(){return A.getSnapshot().scenarioId},sendAudio(_){C.sendAudio(_)},get sessionId(){return C.getSessionId()},get sessionMetadata(){return A.getSnapshot().sessionMetadata},simulateDisconnect(){C.simulateDisconnect()},get status(){return A.getSnapshot().status},subscribe(_){return R.add(_),()=>{R.delete(_)}},get turns(){return A.getSnapshot().turns}}};var a=(c)=>{if(!c||c.enabled===!1)return;return{enabled:!0,maxGain:c.maxGain??3,noiseGateAttenuation:c.noiseGateAttenuation??0.15,noiseGateThreshold:c.noiseGateThreshold??0.006,targetLevel:c.targetLevel??0.08}};var Z=1200;var Qc={balanced:{qualityProfile:"general",semanticVetoMaxMs:0,semanticVetoRecheckMs:Z,silenceMs:1400,speechThreshold:0.012,transcriptStabilityMs:1000},fast:{qualityProfile:"general",semanticVetoMaxMs:0,semanticVetoRecheckMs:Z,silenceMs:700,speechThreshold:0.015,transcriptStabilityMs:450},"long-form":{qualityProfile:"general",semanticVetoMaxMs:0,semanticVetoRecheckMs:Z,silenceMs:2200,speechThreshold:0.01,transcriptStabilityMs:1500}},Kc={"accent-heavy":{silenceMs:1200,speechThreshold:0.01,transcriptStabilityMs:1200},general:{},"noisy-room":{silenceMs:2000,speechThreshold:0.02,transcriptStabilityMs:1600},"short-command":{silenceMs:500,speechThreshold:0.016,transcriptStabilityMs:420}},qc="fast",zc="general",r=(c)=>{let g=c?.profile??qc,C=c?.qualityProfile??zc,A=Qc[g],I=Kc[C];return{profile:g,qualityProfile:C,semanticVetoMaxMs:c?.semanticVetoMaxMs??A.semanticVetoMaxMs,semanticVetoRecheckMs:c?.semanticVetoRecheckMs??A.semanticVetoRecheckMs,silenceMs:c?.silenceMs??I.silenceMs??A.silenceMs,speechThreshold:c?.speechThreshold??I.speechThreshold??A.speechThreshold,transcriptStabilityMs:c?.transcriptStabilityMs??I.transcriptStabilityMs??A.transcriptStabilityMs}};var Bc={chat:{audioConditioning:{enabled:!0,maxGain:2.5,noiseGateAttenuation:0,noiseGateThreshold:0.004,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:10,pingInterval:30000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"balanced",qualityProfile:"short-command"}},default:{capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:10,pingInterval:30000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"fast",qualityProfile:"general"}},dictation:{audioConditioning:{enabled:!0,maxGain:2.25,noiseGateAttenuation:0.05,noiseGateThreshold:0.003,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:12,pingInterval:30000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"long-form",qualityProfile:"accent-heavy"}},"guided-intake":{audioConditioning:{enabled:!0,maxGain:2.5,noiseGateAttenuation:0,noiseGateThreshold:0.004,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:12,pingInterval:30000,reconnect:!0},sttLifecycle:"turn-scoped",turnDetection:{profile:"long-form",qualityProfile:"accent-heavy"}},"noisy-room":{audioConditioning:{enabled:!0,maxGain:3,noiseGateAttenuation:0.12,noiseGateThreshold:0.006,targetLevel:0.085},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:14,pingInterval:45000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"long-form",qualityProfile:"noisy-room",silenceMs:2100,speechThreshold:0.02,transcriptStabilityMs:1650}},"pstn-balanced":{audioConditioning:{enabled:!0,maxGain:2.8,noiseGateAttenuation:0.07,noiseGateThreshold:0.005,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:14,pingInterval:45000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"long-form",qualityProfile:"noisy-room",silenceMs:660,speechThreshold:0.012,transcriptStabilityMs:300}},"pstn-fast":{audioConditioning:{enabled:!0,maxGain:2.75,noiseGateAttenuation:0.06,noiseGateThreshold:0.005,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:14,pingInterval:45000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"long-form",qualityProfile:"noisy-room",silenceMs:620,speechThreshold:0.012,transcriptStabilityMs:280}},reliability:{audioConditioning:{enabled:!0,maxGain:2.9,noiseGateAttenuation:0.08,noiseGateThreshold:0.005,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:14,pingInterval:45000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"long-form",qualityProfile:"noisy-room"}}},t=(c="default")=>{let g=Bc[c];return{audioConditioning:a(g.audioConditioning),capture:{channelCount:g.capture?.channelCount??1,sampleRateHz:g.capture?.sampleRateHz??16000},connection:{...g.connection},name:c,sttLifecycle:g.sttLifecycle??"continuous",turnDetection:r(g.turnDetection)}};var jc=(c)=>({assistantAudio:[...c.assistantAudio],assistantStreamingText:c.assistantStreamingText,assistantTexts:[...c.assistantTexts],call:c.call,error:c.error,isConnected:c.isConnected,isRecording:!1,partial:c.partial,reconnect:c.reconnect,recordingError:null,sessionId:c.sessionId,sessionMetadata:c.sessionMetadata,scenarioId:c.scenarioId,status:c.status,turns:[...c.turns]}),e=(c,g={})=>{let C=t(g.preset),A=v(c,{...C.connection,...g.connection}),I=null,R=jc(A),S=new Set,T=()=>{for(let h of S)h()},w=()=>{if(R={...R,assistantAudio:[...A.assistantAudio],assistantStreamingText:A.assistantStreamingText,assistantTexts:[...A.assistantTexts],call:A.call,error:A.error,isConnected:A.isConnected,partial:A.partial,reconnect:A.reconnect,sessionId:A.sessionId,sessionMetadata:A.sessionMetadata,scenarioId:A.scenarioId,status:A.status,turns:[...A.turns]},g.autoStopOnComplete!==!1&&R.status==="completed"&&R.isRecording)I?.stop(),I=null,R={...R,isRecording:!1};T()},U=A.subscribe(w);w();let _=()=>{if(I)return I;return I=j({channelCount:g.capture?.channelCount??C.capture.channelCount,onLevel:g.capture?.onLevel,onAudio:(h)=>{if(g.capture?.onAudio){g.capture.onAudio(h,A.sendAudio);return}A.sendAudio(h)},sampleRateHz:g.capture?.sampleRateHz??C.capture.sampleRateHz,...g.capture?.stream?{stream:g.capture.stream}:{}}),I},L=()=>{I?.stop(),I=null,R={...R,isRecording:!1},T()},y=async()=>{if(R.isRecording)return;try{R={...R,recordingError:null},T(),await _().start(),R={...R,isRecording:!0},T()}catch(h){throw I=null,R={...R,isRecording:!1,recordingError:h instanceof Error?h.message:String(h)},T(),h}};return{close:()=>{U(),L(),A.close()},startRecording:y,stopRecording:L,get assistantAudio(){return R.assistantAudio},get assistantTexts(){return R.assistantTexts},get assistantStreamingText(){return R.assistantStreamingText},bindHTMX(h){return B(A,h)},get call(){return R.call},callControl:(h)=>A.callControl(h),endTurn:()=>A.endTurn(),get error(){return R.error},getServerSnapshot:()=>R,getSnapshot:()=>R,get isConnected(){return R.isConnected},get isRecording(){return R.isRecording},get partial(){return R.partial},get reconnect(){return R.reconnect},get recordingError(){return R.recordingError},get scenarioId(){return R.scenarioId},sendAudio:(h)=>A.sendAudio(h),get sessionId(){return R.sessionId},get sessionMetadata(){return R.sessionMetadata},simulateDisconnect:()=>A.simulateDisconnect(),get status(){return R.status},subscribe:(h)=>{return S.add(h),()=>{S.delete(h)}},toggleRecording:async()=>{if(R.isRecording){L();return}await y()},get turns(){return R.turns}}};var l=(c)=>String(c).replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;").replaceAll('"',"&quot;").replaceAll("'","&#39;");var m=(c)=>{if(!c.isConnected)return"idle";if(c.isPlaying)return"speaking";if(c.isRecording&&c.hasActivePartial)return"listening";if(c.isRecording)return"listening";if(c.lastTranscriptAt&&!c.lastAssistantAt)return"thinking";if(c.lastTranscriptAt&&c.lastAssistantAt&&c.lastTranscriptAt>c.lastAssistantAt)return"thinking";return"idle"};var dc={accent:"#3b82f6",background:"#0f172a",errorAccent:"#ef4444",fontFamily:'ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',foreground:"#f8fafc",radius:16},kc={callEnded:"Call ended",connecting:"Connecting…",endCall:"End call",idle:"Idle",listening:"Listening",mute:"Mute",speaking:"Speaking",startCall:"Start call",thinking:"Thinking",unmute:"Unmute"},xc=(c,g)=>{switch(c){case"listening":return g.listening;case"speaking":return g.speaking;case"thinking":return g.thinking;case"idle":return g.idle}},u=(c)=>{let g={...dc,...c.theme},C={...kc,...c.labels},A=c.state.assistantAudio.at(-1)?.receivedAt,I=c.state.turns.at(-1)?.committedAt,R=m({hasActivePartial:c.state.partial.length>0,isConnected:c.state.isConnected,isPlaying:!1,isRecording:c.state.isRecording,lastAssistantAt:A,lastTranscriptAt:I}),S=!c.state.isConnected&&c.state.status!=="idle"&&!c.state.error,T=c.state.error?"Error":S?C.connecting:c.state.status==="completed"?C.callEnded:xc(R,C);return{agentState:R,classes:{container:`absolute-voice-widget absolute-voice-widget--${R}`,dot:`absolute-voice-widget__dot${c.state.error?" absolute-voice-widget__dot--error":""}`},controls:{canEnd:c.state.isConnected,canMute:c.state.isRecording,canStart:!c.state.isRecording&&c.state.status!=="completed"},errorMessage:c.state.error??void 0,labels:C,partial:c.state.partial||void 0,statusLabel:T,theme:g,title:c.title??"Voice"}},ic=(c)=>typeof c==="number"?`${c}px`:c,p=(c)=>{let g=c.theme,C=`background:${g.background};border-radius:${ic(g.radius)};color:${g.foreground};font-family:${g.fontFamily};min-width:240px;padding:20px 22px;`,A=`background:${c.errorMessage?g.errorAccent:c.agentState==="idle"?"rgba(148,163,184,0.6)":g.accent};border-radius:50%;height:10px;width:10px;`,I=[];if(c.controls.canStart)I.push(`<button type="button" data-action="start" style="background:${g.accent};border:none;border-radius:12px;color:${g.foreground};cursor:pointer;font-size:14px;font-weight:500;padding:10px 14px;">${l(c.labels.startCall)}</button>`);if(c.controls.canMute)I.push(`<button type="button" data-action="mute" style="background:transparent;border:1px solid rgba(255,255,255,0.18);border-radius:12px;color:${g.foreground};cursor:pointer;font-size:14px;font-weight:500;padding:10px 14px;">${l(c.labels.mute)}</button>`);if(c.controls.canEnd)I.push(`<button type="button" data-action="end" style="background:${g.errorAccent};border:none;border-radius:12px;color:${g.foreground};cursor:pointer;font-size:14px;font-weight:500;padding:10px 14px;">${l(c.labels.endCall)}</button>`);return`<div role="region" aria-live="polite" data-agent-state="${c.agentState}" class="${l(c.classes.container)}" style="${C}">
1
+ (()=>{var{defineProperty:q,getOwnPropertyNames:Vc,getOwnPropertyDescriptor:Ic}=Object,Rc=Object.prototype.hasOwnProperty;function _c(c){return this[c]}var yc=(c)=>{var g=(z??=new WeakMap).get(c),C;if(g)return g;if(g=q({},"__esModule",{value:!0}),c&&typeof c==="object"||typeof c==="function"){for(var A of Vc(c))if(!Rc.call(g,A))q(g,A,{get:_c.bind(c,A),enumerable:!(C=Ic(c,A))||C.enumerable})}return z.set(c,g),g},z;var Sc=(c)=>c;function wc(c,g){this[c]=Sc.bind(null,g)}var Lc=(c,g)=>{for(var C in g)q(c,C,{get:g[C],enumerable:!0,configurable:!0,set:wc.bind(g,C)})};var vc={};Lc(vc,{mount:()=>cc,default:()=>sc,VOICE_EMBED_VERSION:()=>gc});var Uc=(c)=>{if(typeof c!=="string")return c;return document.querySelector(c)},Oc=(c,g,C,A)=>{let _=g??c.getAttribute("hx-get")??"";if(!_)return"";let V=new URL(_,window.location.origin);if(A)V.searchParams.set(C,A);else V.searchParams.delete(C);return`${V.pathname}${V.search}${V.hash}`},k=(c,g)=>{if(typeof window>"u"||typeof document>"u")return()=>{};let C=Uc(g.element);if(!C)return()=>{};let A=g.eventName??"voice-refresh",_=g.sessionQueryParam??"sessionId",V=()=>{let w=window,L=Oc(C,g.route,_,c.sessionId);if(L)C.setAttribute("hx-get",L);w.htmx?.process?.(C),w.htmx?.trigger?.(C,A)},R=c.subscribe(V);return V(),()=>{R()}};var $c=(c)=>Math.max(-1,Math.min(1,c)),hc=(c)=>{let g=new Int16Array(c.length);for(let C=0;C<c.length;C+=1){let A=$c(c[C]??0);g[C]=A<0?A*32768:A*32767}return new Uint8Array(g.buffer)},Dc=(c)=>{let g=c instanceof Uint8Array?c:new Uint8Array(c);if(g.byteLength<2)return 0;let C=new Int16Array(g.buffer,g.byteOffset,Math.floor(g.byteLength/2));if(C.length===0)return 0;let A=0;for(let _ of C){let V=_/32768;A+=V*V}return Math.min(1,Math.max(0,Math.sqrt(A/C.length)*5.5))},Tc=(c,g,C)=>{if(g===C)return c;let A=g/C,_=Math.round(c.length/A),V=new Float32Array(_),R=0,w=0;while(R<V.length){let L=Math.round((R+1)*A),$=0,S=0;for(let O=w;O<L&&O<c.length;O+=1)$+=c[O]??0,S+=1;V[R]=S>0?$/S:0,R+=1,w=L}return V},l=(c)=>{let g=null,C=null,A=null,_=null;return{start:async()=>{if(!c.stream&&(typeof navigator>"u"||!navigator.mediaDevices?.getUserMedia))throw Error("Browser microphone capture requires navigator.mediaDevices.getUserMedia.");let w=(typeof window<"u"?window.AudioContext??window.webkitAudioContext:void 0)??AudioContext;if(!w)throw Error("Browser microphone capture requires AudioContext support.");if(_=c.stream??await navigator.mediaDevices.getUserMedia({audio:{autoGainControl:!0,channelCount:c.channelCount??1,echoCancellation:!0,noiseSuppression:!0}}),g=new w,g.state==="suspended")await g.resume();C=g.createMediaStreamSource(_),A=g.createScriptProcessor(4096,1,1),A.onaudioprocess=(L)=>{let $=L.inputBuffer.getChannelData(0),S=Tc($,g?.sampleRate??48000,c.sampleRateHz??16000),O=hc(S);c.onLevel?.(Dc(O)),c.onAudio(O)},C.connect(A),A.connect(g.destination)},stop:()=>{A?.disconnect(),C?.disconnect(),_?.getTracks().forEach((w)=>w.stop()),g?.close(),c.onLevel?.(0),g=null,_=null,A=null,C=null}}};var B=(c)=>{if(typeof c==="string"&&c.trim())return c;if(c instanceof Error&&c.message.trim())return c.message;if(c&&typeof c==="object"){let g=c;for(let C of["message","reason","description"]){let A=g[C];if(typeof A==="string"&&A.trim())return A}if("error"in g)return B(g.error);if("cause"in g)return B(g.cause);try{return JSON.stringify(c)}catch{}}return"Unexpected error"},x=(c)=>{switch(c.type){case"audio":return{chunk:Uint8Array.from(atob(c.chunkBase64),(g)=>g.charCodeAt(0)),format:c.format,receivedAt:c.receivedAt,turnId:c.turnId,type:"audio"};case"assistant":return{text:c.text,turnId:c.turnId,type:"assistant"};case"assistant_delta":return{delta:c.delta,turnId:c.turnId,type:"assistant_delta"};case"complete":return{sessionId:c.sessionId,type:"complete"};case"connection":return{reconnect:c.reconnect,type:"connection"};case"call_lifecycle":return{event:c.event,sessionId:c.sessionId,type:"call_lifecycle"};case"error":return{message:B(c.message),type:"error"};case"final":return{transcript:c.transcript,type:"final"};case"partial":return{transcript:c.transcript,type:"partial"};case"replay":return{assistantTexts:c.assistantTexts,call:c.call,partial:c.partial,scenarioId:c.scenarioId,sessionId:c.sessionId,sessionMetadata:c.sessionMetadata,status:c.status,turns:c.turns,type:"replay"};case"session":return{sessionId:c.sessionId,sessionMetadata:c.sessionMetadata,scenarioId:c.scenarioId,status:c.status,type:"session"};case"turn":return{turn:c.turn,type:"turn"};default:return null}};var ec=Math.PI*2;var M=(c,g,C,A)=>{c.push({code:C,message:A,severity:g})};var Hc=(c)=>c.length===0?void 0:c.reduce((g,C)=>g+C,0)/c.length,Q=(c)=>c.length===0?void 0:Math.max(...c);var D=(c,g)=>{let C=c[g];return typeof C==="number"&&Number.isFinite(C)?C:void 0},Z=(c,g)=>{let C=c[g];return typeof C==="boolean"?C:void 0},T=(c,g)=>{let C=c[g];return typeof C==="string"?C:void 0},j=(c)=>String(c.id??T(c,"ssrc")??D(c,"ssrc")??T(c,"trackIdentifier")??T(c,"mid")??"unknown"),d=(c)=>c===void 0?void 0:c*1000;var Gc=(c)=>{let g={};for(let[C,A]of Object.entries(c))if(A===null||typeof A==="boolean"||typeof A==="number"||typeof A==="string")g[C]=A;return g};var f=(c={})=>{let g=c.stats??[],C=[],A=g.filter((I)=>I.type==="inbound-rtp"&&T(I,"kind")!=="video"),_=g.filter((I)=>I.type==="outbound-rtp"&&T(I,"kind")!=="video"),V=g.filter((I)=>I.type==="candidate-pair"),R=g.filter((I)=>(I.type==="track"||I.type==="media-source")&&T(I,"kind")==="audio"),w=V.filter((I)=>Z(I,"selected")===!0||Z(I,"nominated")===!0||T(I,"state")==="succeeded").length,L=R.filter((I)=>T(I,"readyState")!=="ended"&&T(I,"trackState")!=="ended"&&Z(I,"ended")!==!0).length,$=R.filter((I)=>T(I,"readyState")==="ended"||T(I,"trackState")==="ended"||Z(I,"ended")===!0).length,S=A.reduce((I,h)=>I+(D(h,"packetsReceived")??0),0),O=_.reduce((I,h)=>I+(D(h,"packetsSent")??0),0),y=[...A,..._].reduce((I,h)=>I+Math.max(0,D(h,"packetsLost")??0),0),H=S+y,U=H===0?0:y/H,J=A.reduce((I,h)=>I+(D(h,"bytesReceived")??0),0),N=_.reduce((I,h)=>I+(D(h,"bytesSent")??0),0),W=Q(V.map((I)=>d(D(I,"currentRoundTripTime")??D(I,"roundTripTime"))).filter((I)=>I!==void 0)),E=Q([...A,..._].map((I)=>d(D(I,"jitter"))).filter((I)=>I!==void 0)),P=Q(A.map((I)=>{let h=D(I,"jitterBufferDelay"),G=D(I,"jitterBufferEmittedCount");return h!==void 0&&G!==void 0&&G>0?h/G*1000:void 0}).filter((I)=>I!==void 0)),b=R.map((I)=>D(I,"audioLevel")).filter((I)=>I!==void 0);if(c.requireConnectedCandidatePair&&V.length>0&&w===0)M(C,"error","media.webrtc_candidate_pair_missing","No active WebRTC candidate pair was observed.");if(c.requireLiveAudioTrack&&L===0)M(C,"error","media.webrtc_audio_track_missing","No live WebRTC audio track was observed.");if(c.maxPacketLossRatio!==void 0&&U>c.maxPacketLossRatio)M(C,"warning","media.webrtc_packet_loss",`Observed WebRTC packet loss ratio ${String(U)} above ${String(c.maxPacketLossRatio)}.`);if(c.maxRoundTripTimeMs!==void 0&&W!==void 0&&W>c.maxRoundTripTimeMs)M(C,"warning","media.webrtc_round_trip_time",`Observed WebRTC RTT ${String(W)}ms above ${String(c.maxRoundTripTimeMs)}ms.`);if(c.maxJitterMs!==void 0&&E!==void 0&&E>c.maxJitterMs)M(C,"warning","media.webrtc_jitter",`Observed WebRTC jitter ${String(E)}ms above ${String(c.maxJitterMs)}ms.`);return{activeCandidatePairs:w,audioLevelAverage:Hc(b),bytesReceived:J,bytesSent:N,checkedAt:Date.now(),endedAudioTracks:$,inboundPackets:S,issues:C,jitterBufferDelayMs:P,jitterMs:E,liveAudioTracks:L,outboundPackets:O,packetLossRatio:U,packetsLost:y,roundTripTimeMs:W,status:C.some((I)=>I.severity==="error")?"fail":C.length>0?"warn":"pass",totalStats:g.length}},F=async(c)=>{return[...(await c.peerConnection.getStats(c.selector??null)).values()].map(Gc)};var n=(c={})=>{let g=c.stats??[],C=c.previousStats??[],A=[],_=new Map(C.map((y)=>[j(y),y])),R=g.filter((y)=>(y.type==="inbound-rtp"||y.type==="outbound-rtp")&&T(y,"kind")!=="video"&&T(y,"mediaType")!=="video").map((y)=>{let H=y.type==="outbound-rtp"?"outbound":"inbound",U=H==="outbound"?"packetsSent":"packetsReceived",J=H==="outbound"?"bytesSent":"bytesReceived",N=_.get(j(y)),W=D(y,U),E=N?D(N,U):void 0,P=D(y,J),b=N?D(N,J):void 0,I=y.timestamp!==void 0&&N?.timestamp!==void 0?y.timestamp-N.timestamp:void 0;return{bytesDelta:P!==void 0&&b!==void 0?P-b:void 0,currentPackets:W,direction:H,id:j(y),packetDelta:W!==void 0&&E!==void 0?W-E:void 0,previousPackets:E,timeDeltaMs:I}}),w=R.filter((y)=>y.direction==="inbound"),L=R.filter((y)=>y.direction==="outbound"),$=Q(R.map((y)=>y.timeDeltaMs).filter((y)=>y!==void 0)),S=w.filter((y)=>c.maxInboundPacketStallMs!==void 0&&y.timeDeltaMs!==void 0&&y.timeDeltaMs>=c.maxInboundPacketStallMs&&y.packetDelta!==void 0&&y.packetDelta<=0).length,O=L.filter((y)=>c.maxOutboundPacketStallMs!==void 0&&y.timeDeltaMs!==void 0&&y.timeDeltaMs>=c.maxOutboundPacketStallMs&&y.packetDelta!==void 0&&y.packetDelta<=0).length;if(c.requireInboundAudio&&w.length===0)M(A,"error","media.webrtc_inbound_audio_missing","No inbound WebRTC audio RTP stream was observed.");if(c.requireOutboundAudio&&L.length===0)M(A,"error","media.webrtc_outbound_audio_missing","No outbound WebRTC audio RTP stream was observed.");if(c.maxGapMs!==void 0&&$!==void 0&&$>c.maxGapMs)M(A,"warning","media.webrtc_stream_gap",`Observed WebRTC stream sample gap ${String($)}ms above ${String(c.maxGapMs)}ms.`);if(S>0)M(A,"error","media.webrtc_inbound_stalled",`${String(S)} inbound WebRTC audio stream(s) stopped receiving packets.`);if(O>0)M(A,"error","media.webrtc_outbound_stalled",`${String(O)} outbound WebRTC audio stream(s) stopped sending packets.`);return{checkedAt:Date.now(),inboundAudioStreams:w.length,issues:A,maxObservedGapMs:$,outboundAudioStreams:L.length,stalledInboundStreams:S,stalledOutboundStreams:O,status:A.some((y)=>y.severity==="error")?"fail":A.length>0?"warn":"pass",streams:R,totalStats:g.length}};var Nc="/api/voice/browser-media",Wc=5000,Ec=async(c)=>c.peerConnection??await c.getPeerConnection?.()??null,Mc=async(c,g)=>{let C=g.fetch??globalThis.fetch;if(!C)return;await C(g.path??Nc,{body:JSON.stringify(c),headers:{"Content-Type":"application/json"},keepalive:!0,method:"POST"})},o=(c)=>{let g=null,C=[],A=async()=>{let R=await Ec(c);if(!R)return;let w=await F({peerConnection:R}),L=f({...c,stats:w}),$=c.continuity===!1?void 0:n({...c.continuity,previousStats:C,stats:w}),S={at:Date.now(),continuity:$,report:L,scenarioId:c.getScenarioId?.()??null,sessionId:c.getSessionId?.()??null};return C=w,c.onReport?.(S),await Mc(S,c),S},_=()=>{A().catch((R)=>{c.onError?.(R)})},V=()=>{if(g)clearInterval(g),g=null};return{close:V,reportOnce:A,stop:V,start:()=>{if(g)return;_(),g=setInterval(_,c.intervalMs??Wc)}}};var Y=()=>{},Xc=()=>Y,Yc={callControl:Y,close:Y,endTurn:Y,send:Y,sendAudio:Y,simulateDisconnect:Y,subscribe:Xc,getReadyState:()=>3,getScenarioId:()=>"",getSessionId:()=>"",start:()=>{}},Jc=()=>crypto.randomUUID(),Pc=(c,g,C)=>{let{hostname:A,port:_,protocol:V}=window.location,R=V==="https:"?"wss:":"ws:",w=_?`:${_}`:"",L=new URL(`${R}//${A}${w}${c}`);if(L.searchParams.set("sessionId",g),C)L.searchParams.set("scenarioId",C);return L.toString()},bc=(c)=>{if(!c||typeof c!=="object"||!("type"in c))return!1;switch(c.type){case"audio":case"assistant":case"call_lifecycle":case"complete":case"connection":case"error":case"final":case"partial":case"pong":case"replay":case"session":case"turn":return!0;default:return!1}},Zc=(c)=>{if(typeof c.data!=="string")return null;try{let g=JSON.parse(c.data);return bc(g)?g:null}catch{return null}},i=(c,g={})=>{if(typeof window>"u")return Yc;let C=new Set,A=g.reconnect!==!1,_=g.maxReconnectAttempts??10,V=g.pingInterval??30000,R={isConnected:!1,pendingMessages:[],scenarioId:g.scenarioId??null,pingInterval:null,reconnectAttempts:0,reconnectTimeout:null,sessionId:g.sessionId??Jc(),ws:null},w=(I)=>{C.forEach((h)=>h(I))},L=()=>{if(R.pingInterval)clearInterval(R.pingInterval),R.pingInterval=null;if(R.reconnectTimeout)clearTimeout(R.reconnectTimeout),R.reconnectTimeout=null},$=()=>{if(R.ws?.readyState!==1)return;while(R.pendingMessages.length>0){let I=R.pendingMessages.shift();if(I!==void 0)R.ws.send(I)}},S=()=>{let I=Date.now()+500;R.reconnectAttempts+=1,w({reconnect:{attempts:R.reconnectAttempts,lastDisconnectAt:Date.now(),maxAttempts:_,nextAttemptAt:I,status:"reconnecting"},type:"connection"}),R.reconnectTimeout=setTimeout(()=>{if(R.reconnectAttempts>_){w({reconnect:{attempts:R.reconnectAttempts,maxAttempts:_,status:"exhausted"},type:"connection"});return}O()},500)},O=()=>{let I=new WebSocket(Pc(c,R.sessionId,R.scenarioId));I.binaryType="arraybuffer",I.onopen=()=>{let h=R.reconnectAttempts>0;if(R.isConnected=!0,$(),h)w({reconnect:{attempts:R.reconnectAttempts,lastResumedAt:Date.now(),maxAttempts:_,status:"resumed"},type:"connection"}),R.reconnectAttempts=0;C.forEach((G)=>G({scenarioId:R.scenarioId??void 0,sessionId:R.sessionId,status:"active",type:"session"})),R.pingInterval=setInterval(()=>{if(I.readyState===1)I.send(JSON.stringify({type:"ping"}))},V)},I.onmessage=(h)=>{let G=Zc(h);if(!G)return;if(G.type==="session")R.sessionId=G.sessionId,R.scenarioId=G.scenarioId??R.scenarioId;C.forEach((Cc)=>Cc(G))},I.onclose=(h)=>{if(R.isConnected=!1,L(),A&&h.code!==1000&&R.reconnectAttempts<_)S();else if(A&&h.code!==1000)w({reconnect:{attempts:R.reconnectAttempts,lastDisconnectAt:Date.now(),maxAttempts:_,status:"exhausted"},type:"connection"})},R.ws=I},y=(I)=>{if(R.ws?.readyState===1){R.ws.send(I);return}R.pendingMessages.push(I)},H=(I)=>{y(JSON.stringify(I))},U=(I={})=>{if(I.sessionId)R.sessionId=I.sessionId;if(I.scenarioId)R.scenarioId=I.scenarioId;H({scenarioId:R.scenarioId??void 0,sessionId:R.sessionId,type:"start"})},J=(I)=>{y(I)},N=()=>{H({type:"end_turn"})},W=(I)=>{H({...I,type:"call_control"})},E=()=>{if(L(),R.ws)R.ws.close(1000),R.ws=null;R.isConnected=!1,C.clear()},P=()=>{if(R.ws?.readyState===1)R.ws.close(4000,"absolutejs-voice-reconnect-proof")},b=(I)=>{return C.add(I),()=>{C.delete(I)}};return O(),{callControl:W,close:E,endTurn:N,send:H,sendAudio:J,simulateDisconnect:P,start:U,subscribe:b,getReadyState:()=>R.ws?.readyState??3,getScenarioId:()=>R.scenarioId??"",getSessionId:()=>R.sessionId}};var Qc=()=>({attempts:0,maxAttempts:0,status:"idle"}),Kc=(c,g)=>{let C=g.trim().replace(/\s+/g," ");if(!C)return c;if(!c)return C;if(c===C||c.endsWith(C))return c;if(C.includes(c))return C;return`${c} ${C}`},qc=(c,g)=>{let C=g.trim().replace(/\s+/g," ");if(!c)return C;if(!C||c.endsWith(C))return c;return`${c} ${C}`},Bc=()=>({assistantAudio:[],assistantStreamingText:"",assistantTexts:[],call:null,error:null,isConnected:!1,partial:"",reconnect:Qc(),scenarioId:null,sessionId:null,sessionMetadata:null,status:"idle",turns:[]}),v=()=>{let c=Bc(),g="",C=new Set,A=()=>{C.forEach((V)=>V())};return{dispatch:(V)=>{switch(V.type){case"audio":c={...c,assistantAudio:[...c.assistantAudio,{chunk:V.chunk,format:V.format,receivedAt:V.receivedAt,turnId:V.turnId}]};break;case"assistant":c={...c,assistantStreamingText:"",assistantTexts:[...c.assistantTexts,V.text]};break;case"assistant_delta":c={...c,assistantStreamingText:`${c.assistantStreamingText}${V.delta}`};break;case"complete":c={...c,sessionId:V.sessionId,status:"completed"};break;case"call_lifecycle":c={...c,call:{...c.call,disposition:V.event.type==="end"?V.event.disposition:c.call?.disposition,endedAt:V.event.type==="end"?V.event.at:c.call?.endedAt,events:[...c.call?.events??[],V.event],lastEventAt:V.event.at,startedAt:c.call?.startedAt??V.event.at},sessionId:V.sessionId};break;case"connected":c={...c,isConnected:!0,reconnect:c.reconnect.status==="reconnecting"?{...c.reconnect,lastResumedAt:Date.now(),nextAttemptAt:void 0,status:"resumed"}:c.reconnect};break;case"connection":c={...c,reconnect:V.reconnect};break;case"disconnected":c={...c,isConnected:!1};break;case"error":c={...c,error:V.message};break;case"final":g=Kc(g,V.transcript.text),c={...c,partial:g};break;case"partial":c={...c,partial:qc(g,V.transcript.text)};break;case"replay":g=V.partial,c={...c,assistantStreamingText:"",assistantTexts:[...V.assistantTexts],call:V.call??null,error:null,isConnected:V.status==="active",partial:V.partial,reconnect:c.reconnect.status==="reconnecting"?{...c.reconnect,lastResumedAt:Date.now(),nextAttemptAt:void 0,status:"resumed"}:c.reconnect,scenarioId:V.scenarioId??c.scenarioId,sessionId:V.sessionId,sessionMetadata:V.sessionMetadata??c.sessionMetadata,status:V.status,turns:[...V.turns]};break;case"session":c={...c,error:null,scenarioId:V.scenarioId??c.scenarioId,isConnected:V.status==="active",sessionId:V.sessionId,sessionMetadata:V.sessionMetadata??c.sessionMetadata,status:V.status};break;case"turn":g="",c={...c,partial:"",turns:[...c.turns,V.turn]};break}A()},getServerSnapshot:()=>c,getSnapshot:()=>c,subscribe:(V)=>{return C.add(V),()=>{C.delete(V)}}}};var s=(c,g={})=>{let C=i(c,g),A=v(),_=g.browserMedia&&typeof window<"u"?o({...g.browserMedia,getScenarioId:()=>g.browserMedia?g.browserMedia.getScenarioId?.()??C.getScenarioId():C.getScenarioId(),getSessionId:()=>g.browserMedia?g.browserMedia.getSessionId?.()??C.getSessionId():C.getSessionId()}):null,V=new Set,R=(S)=>Promise.resolve().then(()=>{if(!S?.sessionId&&!S?.scenarioId)return;C.start(S),_?.start()}),w=()=>{V.forEach((S)=>S())},L=()=>{if(!g.reconnectReportPath||typeof fetch>"u")return;let S=A.getSnapshot(),O=JSON.stringify({at:Date.now(),reconnect:S.reconnect,scenarioId:S.scenarioId,sessionId:C.getSessionId(),turnIds:S.turns.map((y)=>y.id)});fetch(g.reconnectReportPath,{body:O,headers:{"Content-Type":"application/json"},keepalive:!0,method:"POST"}).catch(()=>{})},$=C.subscribe((S)=>{let O=x(S);if(O){if(A.dispatch(O),S.type==="connection")L();w()}});return{start:R,get assistantAudio(){return A.getSnapshot().assistantAudio},get assistantTexts(){return A.getSnapshot().assistantTexts},get assistantStreamingText(){return A.getSnapshot().assistantStreamingText},get call(){return A.getSnapshot().call},callControl(S){C.callControl(S)},close(){$(),_?.close(),C.close(),A.dispatch({type:"disconnected"}),w()},endTurn(){C.endTurn()},get error(){return A.getSnapshot().error},getServerSnapshot(){return A.getServerSnapshot()},getSnapshot(){return A.getSnapshot()},get isConnected(){return A.getSnapshot().isConnected},get partial(){return A.getSnapshot().partial},get reconnect(){return A.getSnapshot().reconnect},get scenarioId(){return A.getSnapshot().scenarioId},sendAudio(S){C.sendAudio(S)},get sessionId(){return C.getSessionId()},get sessionMetadata(){return A.getSnapshot().sessionMetadata},simulateDisconnect(){C.simulateDisconnect()},get status(){return A.getSnapshot().status},subscribe(S){return V.add(S),()=>{V.delete(S)}},get turns(){return A.getSnapshot().turns}}};var m=(c)=>{if(!c||c.enabled===!1)return;return{enabled:!0,maxGain:c.maxGain??3,noiseGateAttenuation:c.noiseGateAttenuation??0.15,noiseGateThreshold:c.noiseGateThreshold??0.006,targetLevel:c.targetLevel??0.08}};var K=1200;var jc={balanced:{qualityProfile:"general",semanticVetoMaxMs:0,semanticVetoRecheckMs:K,silenceMs:1400,speechThreshold:0.012,transcriptStabilityMs:1000},fast:{qualityProfile:"general",semanticVetoMaxMs:0,semanticVetoRecheckMs:K,silenceMs:700,speechThreshold:0.015,transcriptStabilityMs:450},"long-form":{qualityProfile:"general",semanticVetoMaxMs:0,semanticVetoRecheckMs:K,silenceMs:2200,speechThreshold:0.01,transcriptStabilityMs:1500}},zc={"accent-heavy":{silenceMs:1200,speechThreshold:0.01,transcriptStabilityMs:1200},general:{},"noisy-room":{silenceMs:2000,speechThreshold:0.02,transcriptStabilityMs:1600},"short-command":{silenceMs:500,speechThreshold:0.016,transcriptStabilityMs:420}},kc="fast",lc="general",r=(c)=>{let g=c?.profile??kc,C=c?.qualityProfile??lc,A=jc[g],_=zc[C];return{profile:g,qualityProfile:C,semanticVetoMaxMs:c?.semanticVetoMaxMs??A.semanticVetoMaxMs,semanticVetoRecheckMs:c?.semanticVetoRecheckMs??A.semanticVetoRecheckMs,silenceMs:c?.silenceMs??_.silenceMs??A.silenceMs,speechThreshold:c?.speechThreshold??_.speechThreshold??A.speechThreshold,transcriptStabilityMs:c?.transcriptStabilityMs??_.transcriptStabilityMs??A.transcriptStabilityMs}};var xc={chat:{audioConditioning:{enabled:!0,maxGain:2.5,noiseGateAttenuation:0,noiseGateThreshold:0.004,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:10,pingInterval:30000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"balanced",qualityProfile:"short-command"}},default:{capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:10,pingInterval:30000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"fast",qualityProfile:"general"}},dictation:{audioConditioning:{enabled:!0,maxGain:2.25,noiseGateAttenuation:0.05,noiseGateThreshold:0.003,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:12,pingInterval:30000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"long-form",qualityProfile:"accent-heavy"}},"guided-intake":{audioConditioning:{enabled:!0,maxGain:2.5,noiseGateAttenuation:0,noiseGateThreshold:0.004,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:12,pingInterval:30000,reconnect:!0},sttLifecycle:"turn-scoped",turnDetection:{profile:"long-form",qualityProfile:"accent-heavy"}},"noisy-room":{audioConditioning:{enabled:!0,maxGain:3,noiseGateAttenuation:0.12,noiseGateThreshold:0.006,targetLevel:0.085},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:14,pingInterval:45000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"long-form",qualityProfile:"noisy-room",silenceMs:2100,speechThreshold:0.02,transcriptStabilityMs:1650}},"pstn-balanced":{audioConditioning:{enabled:!0,maxGain:2.8,noiseGateAttenuation:0.07,noiseGateThreshold:0.005,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:14,pingInterval:45000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"long-form",qualityProfile:"noisy-room",silenceMs:660,speechThreshold:0.012,transcriptStabilityMs:300}},"pstn-fast":{audioConditioning:{enabled:!0,maxGain:2.75,noiseGateAttenuation:0.06,noiseGateThreshold:0.005,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:14,pingInterval:45000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"long-form",qualityProfile:"noisy-room",silenceMs:620,speechThreshold:0.012,transcriptStabilityMs:280}},reliability:{audioConditioning:{enabled:!0,maxGain:2.9,noiseGateAttenuation:0.08,noiseGateThreshold:0.005,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:14,pingInterval:45000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"long-form",qualityProfile:"noisy-room"}}},a=(c="default")=>{let g=xc[c];return{audioConditioning:m(g.audioConditioning),capture:{channelCount:g.capture?.channelCount??1,sampleRateHz:g.capture?.sampleRateHz??16000},connection:{...g.connection},name:c,sttLifecycle:g.sttLifecycle??"continuous",turnDetection:r(g.turnDetection)}};var dc=(c)=>({assistantAudio:[...c.assistantAudio],assistantStreamingText:c.assistantStreamingText,assistantTexts:[...c.assistantTexts],call:c.call,error:c.error,isConnected:c.isConnected,isRecording:!1,partial:c.partial,reconnect:c.reconnect,recordingError:null,sessionId:c.sessionId,sessionMetadata:c.sessionMetadata,scenarioId:c.scenarioId,status:c.status,turns:[...c.turns]}),u=(c,g={})=>{let C=a(g.preset),A=s(c,{...C.connection,...g.connection}),_=null,V=dc(A),R=new Set,w=()=>{for(let U of R)U()},L=()=>{if(V={...V,assistantAudio:[...A.assistantAudio],assistantStreamingText:A.assistantStreamingText,assistantTexts:[...A.assistantTexts],call:A.call,error:A.error,isConnected:A.isConnected,partial:A.partial,reconnect:A.reconnect,sessionId:A.sessionId,sessionMetadata:A.sessionMetadata,scenarioId:A.scenarioId,status:A.status,turns:[...A.turns]},g.autoStopOnComplete!==!1&&V.status==="completed"&&V.isRecording)_?.stop(),_=null,V={...V,isRecording:!1};w()},$=A.subscribe(L);L();let S=()=>{if(_)return _;return _=l({channelCount:g.capture?.channelCount??C.capture.channelCount,onLevel:g.capture?.onLevel,onAudio:(U)=>{if(g.capture?.onAudio){g.capture.onAudio(U,A.sendAudio);return}A.sendAudio(U)},sampleRateHz:g.capture?.sampleRateHz??C.capture.sampleRateHz,...g.capture?.stream?{stream:g.capture.stream}:{}}),_},O=()=>{_?.stop(),_=null,V={...V,isRecording:!1},w()},y=async()=>{if(V.isRecording)return;try{V={...V,recordingError:null},w(),await S().start(),V={...V,isRecording:!0},w()}catch(U){throw _=null,V={...V,isRecording:!1,recordingError:U instanceof Error?U.message:String(U)},w(),U}};return{close:()=>{$(),O(),A.close()},startRecording:y,stopRecording:O,get assistantAudio(){return V.assistantAudio},get assistantTexts(){return V.assistantTexts},get assistantStreamingText(){return V.assistantStreamingText},bindHTMX(U){return k(A,U)},get call(){return V.call},callControl:(U)=>A.callControl(U),endTurn:()=>A.endTurn(),get error(){return V.error},getServerSnapshot:()=>V,getSnapshot:()=>V,get isConnected(){return V.isConnected},get isRecording(){return V.isRecording},get partial(){return V.partial},get reconnect(){return V.reconnect},get recordingError(){return V.recordingError},get scenarioId(){return V.scenarioId},sendAudio:(U)=>A.sendAudio(U),get sessionId(){return V.sessionId},get sessionMetadata(){return V.sessionMetadata},simulateDisconnect:()=>A.simulateDisconnect(),get status(){return V.status},subscribe:(U)=>{return R.add(U),()=>{R.delete(U)}},toggleRecording:async()=>{if(V.isRecording){O();return}await y()},get turns(){return V.turns}}};var X=(c)=>String(c).replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;").replaceAll('"',"&quot;").replaceAll("'","&#39;");var e=(c)=>{if(!c.isConnected)return"idle";if(c.isPlaying)return"speaking";if(c.isRecording&&c.hasActivePartial)return"listening";if(c.isRecording)return"listening";if(c.lastTranscriptAt&&!c.lastAssistantAt)return"thinking";if(c.lastTranscriptAt&&c.lastAssistantAt&&c.lastTranscriptAt>c.lastAssistantAt)return"thinking";return"idle"};var fc={accent:"#3b82f6",background:"#0f172a",errorAccent:"#ef4444",fontFamily:'ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',foreground:"#f8fafc",radius:16},Fc={callEnded:"Call ended",connecting:"Connecting…",endCall:"End call",idle:"Idle",listening:"Listening",mute:"Mute",speaking:"Speaking",startCall:"Start call",thinking:"Thinking",unmute:"Unmute"},nc=(c,g)=>{switch(c){case"listening":return g.listening;case"speaking":return g.speaking;case"thinking":return g.thinking;case"idle":return g.idle}},p=(c)=>{let g={...fc,...c.theme},C={...Fc,...c.labels},A=c.state.assistantAudio.at(-1)?.receivedAt,_=c.state.turns.at(-1)?.committedAt,V=e({hasActivePartial:c.state.partial.length>0,isConnected:c.state.isConnected,isPlaying:!1,isRecording:c.state.isRecording,lastAssistantAt:A,lastTranscriptAt:_}),R=!c.state.isConnected&&c.state.status!=="idle"&&!c.state.error,w=c.state.error?"Error":R?C.connecting:c.state.status==="completed"?C.callEnded:nc(V,C);return{agentState:V,classes:{container:`absolute-voice-widget absolute-voice-widget--${V}`,dot:`absolute-voice-widget__dot${c.state.error?" absolute-voice-widget__dot--error":""}`},controls:{canEnd:c.state.isConnected,canMute:c.state.isRecording,canStart:!c.state.isRecording&&c.state.status!=="completed"},errorMessage:c.state.error??void 0,labels:C,partial:c.state.partial||void 0,statusLabel:w,theme:g,title:c.title??"Voice"}},oc=(c)=>typeof c==="number"?`${c}px`:c,t=(c)=>{let g=c.theme,C=`background:${g.background};border-radius:${oc(g.radius)};color:${g.foreground};font-family:${g.fontFamily};min-width:240px;padding:20px 22px;`,A=`background:${c.errorMessage?g.errorAccent:c.agentState==="idle"?"rgba(148,163,184,0.6)":g.accent};border-radius:50%;height:10px;width:10px;`,_=[];if(c.controls.canStart)_.push(`<button type="button" data-action="start" style="background:${g.accent};border:none;border-radius:12px;color:${g.foreground};cursor:pointer;font-size:14px;font-weight:500;padding:10px 14px;">${X(c.labels.startCall)}</button>`);if(c.controls.canMute)_.push(`<button type="button" data-action="mute" style="background:transparent;border:1px solid rgba(255,255,255,0.18);border-radius:12px;color:${g.foreground};cursor:pointer;font-size:14px;font-weight:500;padding:10px 14px;">${X(c.labels.mute)}</button>`);if(c.controls.canEnd)_.push(`<button type="button" data-action="end" style="background:${g.errorAccent};border:none;border-radius:12px;color:${g.foreground};cursor:pointer;font-size:14px;font-weight:500;padding:10px 14px;">${X(c.labels.endCall)}</button>`);return`<div role="region" aria-live="polite" data-agent-state="${c.agentState}" class="${X(c.classes.container)}" style="${C}">
2
2
  <div style="align-items:center;display:flex;gap:10px;margin-bottom:12px;">
3
- <span aria-hidden="true" class="${l(c.classes.dot)}" style="${A}"></span>
4
- <strong style="font-size:15px;">${l(c.title)}</strong>
5
- <span style="font-size:13px;margin-left:auto;opacity:0.7;">${l(c.statusLabel)}</span>
3
+ <span aria-hidden="true" class="${X(c.classes.dot)}" style="${A}"></span>
4
+ <strong style="font-size:15px;">${X(c.title)}</strong>
5
+ <span style="font-size:13px;margin-left:auto;opacity:0.7;">${X(c.statusLabel)}</span>
6
6
  </div>
7
- ${c.partial?`<p style="font-size:13px;margin:8px 0 12px;opacity:0.85;word-break:break-word;">“${l(c.partial)}”</p>`:""}
8
- <div style="display:flex;gap:10px;">${I.join("")}</div>
9
- ${c.errorMessage?`<p style="color:${g.errorAccent};font-size:12px;margin-top:12px;">${l(c.errorMessage)}</p>`:""}
10
- </div>`};var fc=(c)=>{if(typeof c!=="string")return c;let g=document.querySelector(c);if(!g)throw Error(`AbsoluteVoice.mount: no element matches "${c}"`);return g},cc=(c,g={})=>{let C=fc(c),A=e(g.path??"/voice",g.controllerOptions),I=null,R=null,S=()=>{let w=u({...g.labels!==void 0?{labels:g.labels}:{},state:{assistantAudio:A.assistantAudio,error:A.error,isConnected:A.isConnected,isRecording:A.isRecording,partial:A.partial,status:A.status,turns:A.turns},...g.theme!==void 0?{theme:g.theme}:{},...g.title!==void 0?{title:g.title}:{}});C.innerHTML=p(w);for(let U of C.querySelectorAll("button[data-action]")){let{action:_}=U.dataset;U.addEventListener("click",()=>{if(_==="start")A.startRecording();else if(_==="mute")A.stopRecording();else if(_==="end")A.close()})}if(A.error&&A.error!==I)I=A.error,g.onError?.(A.error);if(A.status!==R)R=A.status,g.onStatusChange?.(A.status)},T=A.subscribe(S);if(S(),g.autoStart)A.startRecording();return{controller:A,async end(){await A.close()},mute(){A.stopRecording()},async start(){await A.startRecording()},unmount(){T(),A.close(),C.innerHTML=""}}},gc="0.0.22-beta.516",Ac={mount:cc,version:gc};if(typeof globalThis<"u")globalThis.AbsoluteVoice=Ac;var oc=Ac;})();
7
+ ${c.partial?`<p style="font-size:13px;margin:8px 0 12px;opacity:0.85;word-break:break-word;">“${X(c.partial)}”</p>`:""}
8
+ <div style="display:flex;gap:10px;">${_.join("")}</div>
9
+ ${c.errorMessage?`<p style="color:${g.errorAccent};font-size:12px;margin-top:12px;">${X(c.errorMessage)}</p>`:""}
10
+ </div>`};var ic=(c)=>{if(typeof c!=="string")return c;let g=document.querySelector(c);if(!g)throw Error(`AbsoluteVoice.mount: no element matches "${c}"`);return g},cc=(c,g={})=>{let C=ic(c),A=u(g.path??"/voice",g.controllerOptions),_=null,V=null,R=()=>{let L=p({...g.labels!==void 0?{labels:g.labels}:{},state:{assistantAudio:A.assistantAudio,error:A.error,isConnected:A.isConnected,isRecording:A.isRecording,partial:A.partial,status:A.status,turns:A.turns},...g.theme!==void 0?{theme:g.theme}:{},...g.title!==void 0?{title:g.title}:{}});C.innerHTML=t(L);for(let $ of C.querySelectorAll("button[data-action]")){let{action:S}=$.dataset;$.addEventListener("click",()=>{if(S==="start")A.startRecording();else if(S==="mute")A.stopRecording();else if(S==="end")A.close()})}if(A.error&&A.error!==_)_=A.error,g.onError?.(A.error);if(A.status!==V)V=A.status,g.onStatusChange?.(A.status)},w=A.subscribe(R);if(R(),g.autoStart)A.startRecording();return{controller:A,async end(){await A.close()},mute(){A.stopRecording()},async start(){await A.startRecording()},unmount(){w(),A.close(),C.innerHTML=""}}},gc="0.0.22-beta.516",Ac={mount:cc,version:gc};if(typeof globalThis<"u")globalThis.AbsoluteVoice=Ac;var sc=Ac;})();
@@ -11706,6 +11706,27 @@ var createInitialReconnectState = () => ({
11706
11706
  maxAttempts: 0,
11707
11707
  status: "idle"
11708
11708
  });
11709
+ var appendSegmentText = (accumulated, next) => {
11710
+ const nextText = next.trim().replace(/\s+/g, " ");
11711
+ if (!nextText)
11712
+ return accumulated;
11713
+ if (!accumulated)
11714
+ return nextText;
11715
+ if (accumulated === nextText || accumulated.endsWith(nextText)) {
11716
+ return accumulated;
11717
+ }
11718
+ if (nextText.includes(accumulated))
11719
+ return nextText;
11720
+ return `${accumulated} ${nextText}`;
11721
+ };
11722
+ var joinPartial = (finalized, interim) => {
11723
+ const interimText = interim.trim().replace(/\s+/g, " ");
11724
+ if (!finalized)
11725
+ return interimText;
11726
+ if (!interimText || finalized.endsWith(interimText))
11727
+ return finalized;
11728
+ return `${finalized} ${interimText}`;
11729
+ };
11709
11730
  var createInitialState = () => ({
11710
11731
  assistantAudio: [],
11711
11732
  assistantStreamingText: "",
@@ -11723,6 +11744,7 @@ var createInitialState = () => ({
11723
11744
  });
11724
11745
  var createVoiceStreamStore = () => {
11725
11746
  let state = createInitialState();
11747
+ let turnFinalText = "";
11726
11748
  const subscribers = new Set;
11727
11749
  const notify = () => {
11728
11750
  subscribers.forEach((subscriber) => subscriber());
@@ -11808,19 +11830,20 @@ var createVoiceStreamStore = () => {
11808
11830
  };
11809
11831
  break;
11810
11832
  case "final":
11833
+ turnFinalText = appendSegmentText(turnFinalText, action.transcript.text);
11811
11834
  state = {
11812
11835
  ...state,
11813
- partial: action.transcript.text,
11814
- turns: state.turns.map((turn) => turn)
11836
+ partial: turnFinalText
11815
11837
  };
11816
11838
  break;
11817
11839
  case "partial":
11818
11840
  state = {
11819
11841
  ...state,
11820
- partial: action.transcript.text
11842
+ partial: joinPartial(turnFinalText, action.transcript.text)
11821
11843
  };
11822
11844
  break;
11823
11845
  case "replay":
11846
+ turnFinalText = action.partial;
11824
11847
  state = {
11825
11848
  ...state,
11826
11849
  assistantStreamingText: "",
@@ -11854,6 +11877,7 @@ var createVoiceStreamStore = () => {
11854
11877
  };
11855
11878
  break;
11856
11879
  case "turn":
11880
+ turnFinalText = "";
11857
11881
  state = {
11858
11882
  ...state,
11859
11883
  partial: "",
@@ -1029,6 +1029,27 @@ var createInitialReconnectState = () => ({
1029
1029
  maxAttempts: 0,
1030
1030
  status: "idle"
1031
1031
  });
1032
+ var appendSegmentText = (accumulated, next) => {
1033
+ const nextText = next.trim().replace(/\s+/g, " ");
1034
+ if (!nextText)
1035
+ return accumulated;
1036
+ if (!accumulated)
1037
+ return nextText;
1038
+ if (accumulated === nextText || accumulated.endsWith(nextText)) {
1039
+ return accumulated;
1040
+ }
1041
+ if (nextText.includes(accumulated))
1042
+ return nextText;
1043
+ return `${accumulated} ${nextText}`;
1044
+ };
1045
+ var joinPartial = (finalized, interim) => {
1046
+ const interimText = interim.trim().replace(/\s+/g, " ");
1047
+ if (!finalized)
1048
+ return interimText;
1049
+ if (!interimText || finalized.endsWith(interimText))
1050
+ return finalized;
1051
+ return `${finalized} ${interimText}`;
1052
+ };
1032
1053
  var createInitialState = () => ({
1033
1054
  assistantAudio: [],
1034
1055
  assistantStreamingText: "",
@@ -1046,6 +1067,7 @@ var createInitialState = () => ({
1046
1067
  });
1047
1068
  var createVoiceStreamStore = () => {
1048
1069
  let state = createInitialState();
1070
+ let turnFinalText = "";
1049
1071
  const subscribers = new Set;
1050
1072
  const notify = () => {
1051
1073
  subscribers.forEach((subscriber) => subscriber());
@@ -1131,19 +1153,20 @@ var createVoiceStreamStore = () => {
1131
1153
  };
1132
1154
  break;
1133
1155
  case "final":
1156
+ turnFinalText = appendSegmentText(turnFinalText, action.transcript.text);
1134
1157
  state = {
1135
1158
  ...state,
1136
- partial: action.transcript.text,
1137
- turns: state.turns.map((turn) => turn)
1159
+ partial: turnFinalText
1138
1160
  };
1139
1161
  break;
1140
1162
  case "partial":
1141
1163
  state = {
1142
1164
  ...state,
1143
- partial: action.transcript.text
1165
+ partial: joinPartial(turnFinalText, action.transcript.text)
1144
1166
  };
1145
1167
  break;
1146
1168
  case "replay":
1169
+ turnFinalText = action.partial;
1147
1170
  state = {
1148
1171
  ...state,
1149
1172
  assistantStreamingText: "",
@@ -1177,6 +1200,7 @@ var createVoiceStreamStore = () => {
1177
1200
  };
1178
1201
  break;
1179
1202
  case "turn":
1203
+ turnFinalText = "";
1180
1204
  state = {
1181
1205
  ...state,
1182
1206
  partial: "",
@@ -2779,6 +2779,27 @@ var createInitialReconnectState = () => ({
2779
2779
  maxAttempts: 0,
2780
2780
  status: "idle"
2781
2781
  });
2782
+ var appendSegmentText = (accumulated, next) => {
2783
+ const nextText = next.trim().replace(/\s+/g, " ");
2784
+ if (!nextText)
2785
+ return accumulated;
2786
+ if (!accumulated)
2787
+ return nextText;
2788
+ if (accumulated === nextText || accumulated.endsWith(nextText)) {
2789
+ return accumulated;
2790
+ }
2791
+ if (nextText.includes(accumulated))
2792
+ return nextText;
2793
+ return `${accumulated} ${nextText}`;
2794
+ };
2795
+ var joinPartial = (finalized, interim) => {
2796
+ const interimText = interim.trim().replace(/\s+/g, " ");
2797
+ if (!finalized)
2798
+ return interimText;
2799
+ if (!interimText || finalized.endsWith(interimText))
2800
+ return finalized;
2801
+ return `${finalized} ${interimText}`;
2802
+ };
2782
2803
  var createInitialState2 = () => ({
2783
2804
  assistantAudio: [],
2784
2805
  assistantStreamingText: "",
@@ -2796,6 +2817,7 @@ var createInitialState2 = () => ({
2796
2817
  });
2797
2818
  var createVoiceStreamStore = () => {
2798
2819
  let state = createInitialState2();
2820
+ let turnFinalText = "";
2799
2821
  const subscribers = new Set;
2800
2822
  const notify = () => {
2801
2823
  subscribers.forEach((subscriber) => subscriber());
@@ -2881,19 +2903,20 @@ var createVoiceStreamStore = () => {
2881
2903
  };
2882
2904
  break;
2883
2905
  case "final":
2906
+ turnFinalText = appendSegmentText(turnFinalText, action.transcript.text);
2884
2907
  state = {
2885
2908
  ...state,
2886
- partial: action.transcript.text,
2887
- turns: state.turns.map((turn) => turn)
2909
+ partial: turnFinalText
2888
2910
  };
2889
2911
  break;
2890
2912
  case "partial":
2891
2913
  state = {
2892
2914
  ...state,
2893
- partial: action.transcript.text
2915
+ partial: joinPartial(turnFinalText, action.transcript.text)
2894
2916
  };
2895
2917
  break;
2896
2918
  case "replay":
2919
+ turnFinalText = action.partial;
2897
2920
  state = {
2898
2921
  ...state,
2899
2922
  assistantStreamingText: "",
@@ -2927,6 +2950,7 @@ var createVoiceStreamStore = () => {
2927
2950
  };
2928
2951
  break;
2929
2952
  case "turn":
2953
+ turnFinalText = "";
2930
2954
  state = {
2931
2955
  ...state,
2932
2956
  partial: "",
package/dist/vue/index.js CHANGED
@@ -11102,6 +11102,27 @@ var createInitialReconnectState = () => ({
11102
11102
  maxAttempts: 0,
11103
11103
  status: "idle"
11104
11104
  });
11105
+ var appendSegmentText = (accumulated, next) => {
11106
+ const nextText = next.trim().replace(/\s+/g, " ");
11107
+ if (!nextText)
11108
+ return accumulated;
11109
+ if (!accumulated)
11110
+ return nextText;
11111
+ if (accumulated === nextText || accumulated.endsWith(nextText)) {
11112
+ return accumulated;
11113
+ }
11114
+ if (nextText.includes(accumulated))
11115
+ return nextText;
11116
+ return `${accumulated} ${nextText}`;
11117
+ };
11118
+ var joinPartial = (finalized, interim) => {
11119
+ const interimText = interim.trim().replace(/\s+/g, " ");
11120
+ if (!finalized)
11121
+ return interimText;
11122
+ if (!interimText || finalized.endsWith(interimText))
11123
+ return finalized;
11124
+ return `${finalized} ${interimText}`;
11125
+ };
11105
11126
  var createInitialState = () => ({
11106
11127
  assistantAudio: [],
11107
11128
  assistantStreamingText: "",
@@ -11119,6 +11140,7 @@ var createInitialState = () => ({
11119
11140
  });
11120
11141
  var createVoiceStreamStore = () => {
11121
11142
  let state = createInitialState();
11143
+ let turnFinalText = "";
11122
11144
  const subscribers = new Set;
11123
11145
  const notify = () => {
11124
11146
  subscribers.forEach((subscriber) => subscriber());
@@ -11204,19 +11226,20 @@ var createVoiceStreamStore = () => {
11204
11226
  };
11205
11227
  break;
11206
11228
  case "final":
11229
+ turnFinalText = appendSegmentText(turnFinalText, action.transcript.text);
11207
11230
  state = {
11208
11231
  ...state,
11209
- partial: action.transcript.text,
11210
- turns: state.turns.map((turn) => turn)
11232
+ partial: turnFinalText
11211
11233
  };
11212
11234
  break;
11213
11235
  case "partial":
11214
11236
  state = {
11215
11237
  ...state,
11216
- partial: action.transcript.text
11238
+ partial: joinPartial(turnFinalText, action.transcript.text)
11217
11239
  };
11218
11240
  break;
11219
11241
  case "replay":
11242
+ turnFinalText = action.partial;
11220
11243
  state = {
11221
11244
  ...state,
11222
11245
  assistantStreamingText: "",
@@ -11250,6 +11273,7 @@ var createVoiceStreamStore = () => {
11250
11273
  };
11251
11274
  break;
11252
11275
  case "turn":
11276
+ turnFinalText = "";
11253
11277
  state = {
11254
11278
  ...state,
11255
11279
  partial: "",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.586",
3
+ "version": "0.0.22-beta.587",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",