@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.
- package/dist/angular/index.js +27 -3
- package/dist/client/htmxBootstrap.js +27 -3
- package/dist/client/index.js +27 -3
- package/dist/embed/index.js +27 -3
- package/dist/embed/voice-widget.js +8 -8
- package/dist/react/index.js +27 -3
- package/dist/svelte/index.js +27 -3
- package/dist/testing/index.js +27 -3
- package/dist/vue/index.js +27 -3
- package/package.json +1 -1
package/dist/angular/index.js
CHANGED
|
@@ -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:
|
|
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:
|
|
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: "",
|
package/dist/client/index.js
CHANGED
|
@@ -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:
|
|
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: "",
|
package/dist/embed/index.js
CHANGED
|
@@ -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:
|
|
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("&","&").replaceAll("<","<").replaceAll(">",">").replaceAll('"',""").replaceAll("'","'");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("&","&").replaceAll("<","<").replaceAll(">",">").replaceAll('"',""").replaceAll("'","'");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="${
|
|
4
|
-
<strong style="font-size:15px;">${
|
|
5
|
-
<span style="font-size:13px;margin-left:auto;opacity:0.7;">${
|
|
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;">“${
|
|
8
|
-
<div style="display:flex;gap:10px;">${
|
|
9
|
-
${c.errorMessage?`<p style="color:${g.errorAccent};font-size:12px;margin-top:12px;">${
|
|
10
|
-
</div>`};var
|
|
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;})();
|
package/dist/react/index.js
CHANGED
|
@@ -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:
|
|
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: "",
|
package/dist/svelte/index.js
CHANGED
|
@@ -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:
|
|
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: "",
|
package/dist/testing/index.js
CHANGED
|
@@ -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:
|
|
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:
|
|
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: "",
|