@absolutejs/voice 0.0.22-beta.565 → 0.0.22-beta.567
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 +30 -0
- package/dist/angular/voice-controller.service.d.ts +1 -0
- package/dist/angular/voice-stream.service.d.ts +1 -0
- package/dist/client/actions.d.ts +33 -1
- package/dist/client/htmxBootstrap.js +42 -3
- package/dist/client/index.js +42 -3
- package/dist/core/types.d.ts +17 -1
- package/dist/embed/index.js +24 -0
- package/dist/embed/voice-widget.js +7 -7
- package/dist/index.js +1 -0
- package/dist/react/index.js +24 -0
- package/dist/react/useVoiceController.d.ts +1 -0
- package/dist/react/useVoiceStream.d.ts +1 -0
- package/dist/svelte/index.js +24 -0
- package/dist/testing/index.js +43 -3
- package/dist/vue/index.js +30 -0
- package/dist/vue/useVoiceController.d.ts +1 -0
- package/dist/vue/useVoiceStream.d.ts +1 -0
- package/package.json +1 -1
package/dist/embed/index.js
CHANGED
|
@@ -181,8 +181,15 @@ var serverMessageToAction = (message) => {
|
|
|
181
181
|
case "assistant":
|
|
182
182
|
return {
|
|
183
183
|
text: message.text,
|
|
184
|
+
turnId: message.turnId,
|
|
184
185
|
type: "assistant"
|
|
185
186
|
};
|
|
187
|
+
case "assistant_delta":
|
|
188
|
+
return {
|
|
189
|
+
delta: message.delta,
|
|
190
|
+
turnId: message.turnId,
|
|
191
|
+
type: "assistant_delta"
|
|
192
|
+
};
|
|
186
193
|
case "complete":
|
|
187
194
|
return {
|
|
188
195
|
sessionId: message.sessionId,
|
|
@@ -750,6 +757,7 @@ var createInitialReconnectState = () => ({
|
|
|
750
757
|
});
|
|
751
758
|
var createInitialState = () => ({
|
|
752
759
|
assistantAudio: [],
|
|
760
|
+
assistantStreamingText: "",
|
|
753
761
|
assistantTexts: [],
|
|
754
762
|
call: null,
|
|
755
763
|
error: null,
|
|
@@ -787,9 +795,16 @@ var createVoiceStreamStore = () => {
|
|
|
787
795
|
case "assistant":
|
|
788
796
|
state = {
|
|
789
797
|
...state,
|
|
798
|
+
assistantStreamingText: "",
|
|
790
799
|
assistantTexts: [...state.assistantTexts, action.text]
|
|
791
800
|
};
|
|
792
801
|
break;
|
|
802
|
+
case "assistant_delta":
|
|
803
|
+
state = {
|
|
804
|
+
...state,
|
|
805
|
+
assistantStreamingText: `${state.assistantStreamingText}${action.delta}`
|
|
806
|
+
};
|
|
807
|
+
break;
|
|
793
808
|
case "complete":
|
|
794
809
|
state = {
|
|
795
810
|
...state,
|
|
@@ -857,6 +872,7 @@ var createVoiceStreamStore = () => {
|
|
|
857
872
|
case "replay":
|
|
858
873
|
state = {
|
|
859
874
|
...state,
|
|
875
|
+
assistantStreamingText: "",
|
|
860
876
|
assistantTexts: [...action.assistantTexts],
|
|
861
877
|
call: action.call ?? null,
|
|
862
878
|
error: null,
|
|
@@ -968,6 +984,9 @@ var createVoiceStream = (path, options = {}) => {
|
|
|
968
984
|
get assistantTexts() {
|
|
969
985
|
return store.getSnapshot().assistantTexts;
|
|
970
986
|
},
|
|
987
|
+
get assistantStreamingText() {
|
|
988
|
+
return store.getSnapshot().assistantStreamingText;
|
|
989
|
+
},
|
|
971
990
|
get call() {
|
|
972
991
|
return store.getSnapshot().call;
|
|
973
992
|
},
|
|
@@ -1314,6 +1333,7 @@ var resolveVoiceRuntimePreset = (name = "default") => {
|
|
|
1314
1333
|
// src/client/controller.ts
|
|
1315
1334
|
var createInitialState2 = (stream) => ({
|
|
1316
1335
|
assistantAudio: [...stream.assistantAudio],
|
|
1336
|
+
assistantStreamingText: stream.assistantStreamingText,
|
|
1317
1337
|
assistantTexts: [...stream.assistantTexts],
|
|
1318
1338
|
call: stream.call,
|
|
1319
1339
|
error: stream.error,
|
|
@@ -1346,6 +1366,7 @@ var createVoiceController = (path, options = {}) => {
|
|
|
1346
1366
|
state = {
|
|
1347
1367
|
...state,
|
|
1348
1368
|
assistantAudio: [...stream.assistantAudio],
|
|
1369
|
+
assistantStreamingText: stream.assistantStreamingText,
|
|
1349
1370
|
assistantTexts: [...stream.assistantTexts],
|
|
1350
1371
|
call: stream.call,
|
|
1351
1372
|
error: stream.error,
|
|
@@ -1439,6 +1460,9 @@ var createVoiceController = (path, options = {}) => {
|
|
|
1439
1460
|
get assistantTexts() {
|
|
1440
1461
|
return state.assistantTexts;
|
|
1441
1462
|
},
|
|
1463
|
+
get assistantStreamingText() {
|
|
1464
|
+
return state.assistantStreamingText;
|
|
1465
|
+
},
|
|
1442
1466
|
bindHTMX(bindingOptions) {
|
|
1443
1467
|
return bindVoiceHTMX(stream, bindingOptions);
|
|
1444
1468
|
},
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
(()=>{var{defineProperty:H,getOwnPropertyNames:oc,getOwnPropertyDescriptor:lc}=Object,Ac=Object.prototype.hasOwnProperty;function Cc(c){return this[c]}var ic=(c)=>{var n=(Y??=new WeakMap).get(c),o;if(n)return n;if(n=H({},"__esModule",{value:!0}),c&&typeof c==="object"||typeof c==="function"){for(var g of oc(c))if(!Ac.call(n,g))H(n,g,{get:Cc.bind(c,g),enumerable:!(o=lc(c,g))||o.enumerable})}return Y.set(c,n),n},Y;var yc=(c)=>c;function Tc(c,n){this[c]=yc.bind(null,n)}var Vc=(c,n)=>{for(var o in n)H(c,o,{get:n[o],enumerable:!0,configurable:!0,set:Tc.bind(n,o)})};var Bc={};Vc(Bc,{mount:()=>p,default:()=>Kc,VOICE_EMBED_VERSION:()=>cc});var Ic=(c)=>{if(typeof c!=="string")return c;return document.querySelector(c)},Rc=(c,n,o,g)=>{let l=n??c.getAttribute("hx-get")??"";if(!l)return"";let i=new URL(l,window.location.origin);if(g)i.searchParams.set(o,g);else i.searchParams.delete(o);return`${i.pathname}${i.search}${i.hash}`},Q=(c,n)=>{if(typeof window>"u"||typeof document>"u")return()=>{};let o=Ic(n.element);if(!o)return()=>{};let g=n.eventName??"voice-refresh",l=n.sessionQueryParam??"sessionId",i=()=>{let V=window,I=Rc(o,n.route,l,c.sessionId);if(I)o.setAttribute("hx-get",I);V.htmx?.process?.(o),V.htmx?.trigger?.(o,g)},C=c.subscribe(i);return i(),()=>{C()}};var hc=(c)=>Math.max(-1,Math.min(1,c)),Sc=(c)=>{let n=new Int16Array(c.length);for(let o=0;o<c.length;o+=1){let g=hc(c[o]??0);n[o]=g<0?g*32768:g*32767}return new Uint8Array(n.buffer)},dc=(c)=>{let n=c instanceof Uint8Array?c:new Uint8Array(c);if(n.byteLength<2)return 0;let o=new Int16Array(n.buffer,n.byteOffset,Math.floor(n.byteLength/2));if(o.length===0)return 0;let g=0;for(let l of o){let i=l/32768;g+=i*i}return Math.min(1,Math.max(0,Math.sqrt(g/o.length)*5.5))},_c=(c,n,o)=>{if(n===o)return c;let g=n/o,l=Math.round(c.length/g),i=new Float32Array(l),C=0,V=0;while(C<i.length){let I=Math.round((C+1)*g),S=0,T=0;for(let h=V;h<I&&h<c.length;h+=1)S+=c[h]??0,T+=1;i[C]=T>0?S/T:0,C+=1,V=I}return i},J=(c)=>{let n=null,o=null,g=null,l=null;return{start:async()=>{if(typeof navigator>"u"||!navigator.mediaDevices?.getUserMedia)throw Error("Browser microphone capture requires navigator.mediaDevices.getUserMedia.");let V=(typeof window<"u"?window.AudioContext??window.webkitAudioContext:void 0)??AudioContext;if(!V)throw Error("Browser microphone capture requires AudioContext support.");l=await navigator.mediaDevices.getUserMedia({audio:{channelCount:c.channelCount??1}}),n=new V,o=n.createMediaStreamSource(l),g=n.createScriptProcessor(4096,1,1),g.onaudioprocess=(I)=>{let S=I.inputBuffer.getChannelData(0),T=_c(S,n?.sampleRate??48000,c.sampleRateHz??16000),h=Sc(T);c.onLevel?.(dc(h)),c.onAudio(h)},o.connect(g),g.connect(n.destination)},stop:()=>{g?.disconnect(),o?.disconnect(),l?.getTracks().forEach((V)=>V.stop()),n?.close(),c.onLevel?.(0),n=null,l=null,g=null,o=null}}};var G=(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 n=c;for(let o of["message","reason","description"]){let g=n[o];if(typeof g==="string"&&g.trim())return g}if("error"in n)return G(n.error);if("cause"in n)return G(n.cause);try{return JSON.stringify(c)}catch{}}return"Unexpected error"},q=(c)=>{switch(c.type){case"audio":return{chunk:Uint8Array.from(atob(c.chunkBase64),(n)=>n.charCodeAt(0)),format:c.format,receivedAt:c.receivedAt,turnId:c.turnId,type:"audio"};case"assistant":return{text:c.text,type:"assistant"};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:G(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 D=(c,n,o,g)=>{c.push({code:o,message:g,severity:n})};var wc=(c)=>c.length===0?void 0:c.reduce((n,o)=>n+o,0)/c.length,$=(c)=>c.length===0?void 0:Math.max(...c);var _=(c,n)=>{let o=c[n];return typeof o==="number"&&Number.isFinite(o)?o:void 0},N=(c,n)=>{let o=c[n];return typeof o==="boolean"?o:void 0},w=(c,n)=>{let o=c[n];return typeof o==="string"?o:void 0},X=(c)=>String(c.id??w(c,"ssrc")??_(c,"ssrc")??w(c,"trackIdentifier")??w(c,"mid")??"unknown"),Z=(c)=>c===void 0?void 0:c*1000;var Lc=(c)=>{let n={};for(let[o,g]of Object.entries(c))if(g===null||typeof g==="boolean"||typeof g==="number"||typeof g==="string")n[o]=g;return n};var z=(c={})=>{let n=c.stats??[],o=[],g=n.filter((A)=>A.type==="inbound-rtp"&&w(A,"kind")!=="video"),l=n.filter((A)=>A.type==="outbound-rtp"&&w(A,"kind")!=="video"),i=n.filter((A)=>A.type==="candidate-pair"),C=n.filter((A)=>(A.type==="track"||A.type==="media-source")&&w(A,"kind")==="audio"),V=i.filter((A)=>N(A,"selected")===!0||N(A,"nominated")===!0||w(A,"state")==="succeeded").length,I=C.filter((A)=>w(A,"readyState")!=="ended"&&w(A,"trackState")!=="ended"&&N(A,"ended")!==!0).length,S=C.filter((A)=>w(A,"readyState")==="ended"||w(A,"trackState")==="ended"||N(A,"ended")===!0).length,T=g.reduce((A,d)=>A+(_(d,"packetsReceived")??0),0),h=l.reduce((A,d)=>A+(_(d,"packetsSent")??0),0),y=[...g,...l].reduce((A,d)=>A+Math.max(0,_(d,"packetsLost")??0),0),L=T+y,R=L===0?0:y/L,x=g.reduce((A,d)=>A+(_(d,"bytesReceived")??0),0),U=l.reduce((A,d)=>A+(_(d,"bytesSent")??0),0),M=$(i.map((A)=>Z(_(A,"currentRoundTripTime")??_(A,"roundTripTime"))).filter((A)=>A!==void 0)),O=$([...g,...l].map((A)=>Z(_(A,"jitter"))).filter((A)=>A!==void 0)),W=$(g.map((A)=>{let d=_(A,"jitterBufferDelay"),b=_(A,"jitterBufferEmittedCount");return d!==void 0&&b!==void 0&&b>0?d/b*1000:void 0}).filter((A)=>A!==void 0)),P=C.map((A)=>_(A,"audioLevel")).filter((A)=>A!==void 0);if(c.requireConnectedCandidatePair&&i.length>0&&V===0)D(o,"error","media.webrtc_candidate_pair_missing","No active WebRTC candidate pair was observed.");if(c.requireLiveAudioTrack&&I===0)D(o,"error","media.webrtc_audio_track_missing","No live WebRTC audio track was observed.");if(c.maxPacketLossRatio!==void 0&&R>c.maxPacketLossRatio)D(o,"warning","media.webrtc_packet_loss",`Observed WebRTC packet loss ratio ${String(R)} above ${String(c.maxPacketLossRatio)}.`);if(c.maxRoundTripTimeMs!==void 0&&M!==void 0&&M>c.maxRoundTripTimeMs)D(o,"warning","media.webrtc_round_trip_time",`Observed WebRTC RTT ${String(M)}ms above ${String(c.maxRoundTripTimeMs)}ms.`);if(c.maxJitterMs!==void 0&&O!==void 0&&O>c.maxJitterMs)D(o,"warning","media.webrtc_jitter",`Observed WebRTC jitter ${String(O)}ms above ${String(c.maxJitterMs)}ms.`);return{activeCandidatePairs:V,audioLevelAverage:wc(P),bytesReceived:x,bytesSent:U,checkedAt:Date.now(),endedAudioTracks:S,inboundPackets:T,issues:o,jitterBufferDelayMs:W,jitterMs:O,liveAudioTracks:I,outboundPackets:h,packetLossRatio:R,packetsLost:y,roundTripTimeMs:M,status:o.some((A)=>A.severity==="error")?"fail":o.length>0?"warn":"pass",totalStats:n.length}},B=async(c)=>{return[...(await c.peerConnection.getStats(c.selector??null)).values()].map(Lc)};var K=(c={})=>{let n=c.stats??[],o=c.previousStats??[],g=[],l=new Map(o.map((y)=>[X(y),y])),C=n.filter((y)=>(y.type==="inbound-rtp"||y.type==="outbound-rtp")&&w(y,"kind")!=="video"&&w(y,"mediaType")!=="video").map((y)=>{let L=y.type==="outbound-rtp"?"outbound":"inbound",R=L==="outbound"?"packetsSent":"packetsReceived",x=L==="outbound"?"bytesSent":"bytesReceived",U=l.get(X(y)),M=_(y,R),O=U?_(U,R):void 0,W=_(y,x),P=U?_(U,x):void 0,A=y.timestamp!==void 0&&U?.timestamp!==void 0?y.timestamp-U.timestamp:void 0;return{bytesDelta:W!==void 0&&P!==void 0?W-P:void 0,currentPackets:M,direction:L,id:X(y),packetDelta:M!==void 0&&O!==void 0?M-O:void 0,previousPackets:O,timeDeltaMs:A}}),V=C.filter((y)=>y.direction==="inbound"),I=C.filter((y)=>y.direction==="outbound"),S=$(C.map((y)=>y.timeDeltaMs).filter((y)=>y!==void 0)),T=V.filter((y)=>c.maxInboundPacketStallMs!==void 0&&y.timeDeltaMs!==void 0&&y.timeDeltaMs>=c.maxInboundPacketStallMs&&y.packetDelta!==void 0&&y.packetDelta<=0).length,h=I.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&&V.length===0)D(g,"error","media.webrtc_inbound_audio_missing","No inbound WebRTC audio RTP stream was observed.");if(c.requireOutboundAudio&&I.length===0)D(g,"error","media.webrtc_outbound_audio_missing","No outbound WebRTC audio RTP stream was observed.");if(c.maxGapMs!==void 0&&S!==void 0&&S>c.maxGapMs)D(g,"warning","media.webrtc_stream_gap",`Observed WebRTC stream sample gap ${String(S)}ms above ${String(c.maxGapMs)}ms.`);if(T>0)D(g,"error","media.webrtc_inbound_stalled",`${String(T)} inbound WebRTC audio stream(s) stopped receiving packets.`);if(h>0)D(g,"error","media.webrtc_outbound_stalled",`${String(h)} outbound WebRTC audio stream(s) stopped sending packets.`);return{checkedAt:Date.now(),inboundAudioStreams:V.length,issues:g,maxObservedGapMs:S,outboundAudioStreams:I.length,stalledInboundStreams:T,stalledOutboundStreams:h,status:g.some((y)=>y.severity==="error")?"fail":g.length>0?"warn":"pass",streams:C,totalStats:n.length}};var bc="/api/voice/browser-media",Uc=5000,Mc=async(c)=>c.peerConnection??await c.getPeerConnection?.()??null,Oc=async(c,n)=>{let o=n.fetch??globalThis.fetch;if(!o)return;await o(n.path??bc,{body:JSON.stringify(c),headers:{"Content-Type":"application/json"},keepalive:!0,method:"POST"})},j=(c)=>{let n=null,o=[],g=async()=>{let C=await Mc(c);if(!C)return;let V=await B({peerConnection:C}),I=z({...c,stats:V}),S=c.continuity===!1?void 0:K({...c.continuity,previousStats:o,stats:V}),T={at:Date.now(),continuity:S,report:I,scenarioId:c.getScenarioId?.()??null,sessionId:c.getSessionId?.()??null};return o=V,c.onReport?.(T),await Oc(T,c),T},l=()=>{g().catch((C)=>{c.onError?.(C)})},i=()=>{if(n)clearInterval(n),n=null};return{close:i,reportOnce:g,stop:i,start:()=>{if(n)return;l(),n=setInterval(l,c.intervalMs??Uc)}}};var E=()=>{},Dc=()=>E,sc={callControl:E,close:E,endTurn:E,send:E,sendAudio:E,simulateDisconnect:E,subscribe:Dc,getReadyState:()=>3,getScenarioId:()=>"",getSessionId:()=>"",start:()=>{}},Ec=()=>crypto.randomUUID(),xc=(c,n,o)=>{let{hostname:g,port:l,protocol:i}=window.location,C=i==="https:"?"wss:":"ws:",V=l?`:${l}`:"",I=new URL(`${C}//${g}${V}${c}`);if(I.searchParams.set("sessionId",n),o)I.searchParams.set("scenarioId",o);return I.toString()},Wc=(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}},Pc=(c)=>{if(typeof c.data!=="string")return null;try{let n=JSON.parse(c.data);return Wc(n)?n:null}catch{return null}},f=(c,n={})=>{if(typeof window>"u")return sc;let o=new Set,g=n.reconnect!==!1,l=n.maxReconnectAttempts??10,i=n.pingInterval??30000,C={isConnected:!1,pendingMessages:[],scenarioId:n.scenarioId??null,pingInterval:null,reconnectAttempts:0,reconnectTimeout:null,sessionId:n.sessionId??Ec(),ws:null},V=(A)=>{o.forEach((d)=>d(A))},I=()=>{if(C.pingInterval)clearInterval(C.pingInterval),C.pingInterval=null;if(C.reconnectTimeout)clearTimeout(C.reconnectTimeout),C.reconnectTimeout=null},S=()=>{if(C.ws?.readyState!==1)return;while(C.pendingMessages.length>0){let A=C.pendingMessages.shift();if(A!==void 0)C.ws.send(A)}},T=()=>{let A=Date.now()+500;C.reconnectAttempts+=1,V({reconnect:{attempts:C.reconnectAttempts,lastDisconnectAt:Date.now(),maxAttempts:l,nextAttemptAt:A,status:"reconnecting"},type:"connection"}),C.reconnectTimeout=setTimeout(()=>{if(C.reconnectAttempts>l){V({reconnect:{attempts:C.reconnectAttempts,maxAttempts:l,status:"exhausted"},type:"connection"});return}h()},500)},h=()=>{let A=new WebSocket(xc(c,C.sessionId,C.scenarioId));A.binaryType="arraybuffer",A.onopen=()=>{let d=C.reconnectAttempts>0;if(C.isConnected=!0,S(),d)V({reconnect:{attempts:C.reconnectAttempts,lastResumedAt:Date.now(),maxAttempts:l,status:"resumed"},type:"connection"}),C.reconnectAttempts=0;o.forEach((b)=>b({scenarioId:C.scenarioId??void 0,sessionId:C.sessionId,status:"active",type:"session"})),C.pingInterval=setInterval(()=>{if(A.readyState===1)A.send(JSON.stringify({type:"ping"}))},i)},A.onmessage=(d)=>{let b=Pc(d);if(!b)return;if(b.type==="session")C.sessionId=b.sessionId,C.scenarioId=b.scenarioId??C.scenarioId;o.forEach((gc)=>gc(b))},A.onclose=(d)=>{if(C.isConnected=!1,I(),g&&d.code!==1000&&C.reconnectAttempts<l)T();else if(g&&d.code!==1000)V({reconnect:{attempts:C.reconnectAttempts,lastDisconnectAt:Date.now(),maxAttempts:l,status:"exhausted"},type:"connection"})},C.ws=A},y=(A)=>{if(C.ws?.readyState===1){C.ws.send(A);return}C.pendingMessages.push(A)},L=(A)=>{y(JSON.stringify(A))},R=(A={})=>{if(A.sessionId)C.sessionId=A.sessionId;if(A.scenarioId)C.scenarioId=A.scenarioId;L({scenarioId:C.scenarioId??void 0,sessionId:C.sessionId,type:"start"})},x=(A)=>{y(A)},U=()=>{L({type:"end_turn"})},M=(A)=>{L({...A,type:"call_control"})},O=()=>{if(I(),C.ws)C.ws.close(1000),C.ws=null;C.isConnected=!1,o.clear()},W=()=>{if(C.ws?.readyState===1)C.ws.close(4000,"absolutejs-voice-reconnect-proof")},P=(A)=>{return o.add(A),()=>{o.delete(A)}};return h(),{callControl:M,close:O,endTurn:U,send:L,sendAudio:x,simulateDisconnect:W,start:R,subscribe:P,getReadyState:()=>C.ws?.readyState??3,getScenarioId:()=>C.scenarioId??"",getSessionId:()=>C.sessionId}};var Nc=()=>({attempts:0,maxAttempts:0,status:"idle"}),$c=()=>({assistantAudio:[],assistantTexts:[],call:null,error:null,isConnected:!1,partial:"",reconnect:Nc(),scenarioId:null,sessionId:null,sessionMetadata:null,status:"idle",turns:[]}),e=()=>{let c=$c(),n=new Set,o=()=>{n.forEach((l)=>l())};return{dispatch:(l)=>{switch(l.type){case"audio":c={...c,assistantAudio:[...c.assistantAudio,{chunk:l.chunk,format:l.format,receivedAt:l.receivedAt,turnId:l.turnId}]};break;case"assistant":c={...c,assistantTexts:[...c.assistantTexts,l.text]};break;case"complete":c={...c,sessionId:l.sessionId,status:"completed"};break;case"call_lifecycle":c={...c,call:{...c.call,disposition:l.event.type==="end"?l.event.disposition:c.call?.disposition,endedAt:l.event.type==="end"?l.event.at:c.call?.endedAt,events:[...c.call?.events??[],l.event],lastEventAt:l.event.at,startedAt:c.call?.startedAt??l.event.at},sessionId:l.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:l.reconnect};break;case"disconnected":c={...c,isConnected:!1};break;case"error":c={...c,error:l.message};break;case"final":c={...c,partial:l.transcript.text,turns:c.turns.map((i)=>i)};break;case"partial":c={...c,partial:l.transcript.text};break;case"replay":c={...c,assistantTexts:[...l.assistantTexts],call:l.call??null,error:null,isConnected:l.status==="active",partial:l.partial,reconnect:c.reconnect.status==="reconnecting"?{...c.reconnect,lastResumedAt:Date.now(),nextAttemptAt:void 0,status:"resumed"}:c.reconnect,scenarioId:l.scenarioId??c.scenarioId,sessionId:l.sessionId,sessionMetadata:l.sessionMetadata??c.sessionMetadata,status:l.status,turns:[...l.turns]};break;case"session":c={...c,error:null,scenarioId:l.scenarioId??c.scenarioId,isConnected:l.status==="active",sessionId:l.sessionId,sessionMetadata:l.sessionMetadata??c.sessionMetadata,status:l.status};break;case"turn":c={...c,partial:"",turns:[...c.turns,l.turn]};break}o()},getServerSnapshot:()=>c,getSnapshot:()=>c,subscribe:(l)=>{return n.add(l),()=>{n.delete(l)}}}};var k=(c,n={})=>{let o=f(c,n),g=e(),l=n.browserMedia&&typeof window<"u"?j({...n.browserMedia,getScenarioId:()=>n.browserMedia?n.browserMedia.getScenarioId?.()??o.getScenarioId():o.getScenarioId(),getSessionId:()=>n.browserMedia?n.browserMedia.getSessionId?.()??o.getSessionId():o.getSessionId()}):null,i=new Set,C=(T)=>Promise.resolve().then(()=>{if(!T?.sessionId&&!T?.scenarioId)return;o.start(T),l?.start()}),V=()=>{i.forEach((T)=>T())},I=()=>{if(!n.reconnectReportPath||typeof fetch>"u")return;let T=g.getSnapshot(),h=JSON.stringify({at:Date.now(),reconnect:T.reconnect,scenarioId:T.scenarioId,sessionId:o.getSessionId(),turnIds:T.turns.map((y)=>y.id)});fetch(n.reconnectReportPath,{body:h,headers:{"Content-Type":"application/json"},keepalive:!0,method:"POST"}).catch(()=>{})},S=o.subscribe((T)=>{let h=q(T);if(h){if(g.dispatch(h),T.type==="connection")I();V()}});return{start:C,get assistantAudio(){return g.getSnapshot().assistantAudio},get assistantTexts(){return g.getSnapshot().assistantTexts},get call(){return g.getSnapshot().call},callControl(T){o.callControl(T)},close(){S(),l?.close(),o.close(),g.dispatch({type:"disconnected"}),V()},endTurn(){o.endTurn()},get error(){return g.getSnapshot().error},getServerSnapshot(){return g.getServerSnapshot()},getSnapshot(){return g.getSnapshot()},get isConnected(){return g.getSnapshot().isConnected},get partial(){return g.getSnapshot().partial},get reconnect(){return g.getSnapshot().reconnect},get scenarioId(){return g.getSnapshot().scenarioId},sendAudio(T){o.sendAudio(T)},get sessionId(){return o.getSessionId()},get sessionMetadata(){return g.getSnapshot().sessionMetadata},simulateDisconnect(){o.simulateDisconnect()},get status(){return g.getSnapshot().status},subscribe(T){return i.add(T),()=>{i.delete(T)}},get turns(){return g.getSnapshot().turns}}};var t=(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 Hc={balanced:{qualityProfile:"general",silenceMs:1400,speechThreshold:0.012,transcriptStabilityMs:1000},fast:{qualityProfile:"general",silenceMs:700,speechThreshold:0.015,transcriptStabilityMs:450},"long-form":{qualityProfile:"general",silenceMs:2200,speechThreshold:0.01,transcriptStabilityMs:1500}},Gc={"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}};var F=(c)=>{let n=c?.profile??"fast",o=c?.qualityProfile??"general",g=Hc[n],l=Gc[o];return{profile:n,qualityProfile:o,silenceMs:c?.silenceMs??l.silenceMs??g.silenceMs,speechThreshold:c?.speechThreshold??l.speechThreshold??g.speechThreshold,transcriptStabilityMs:c?.transcriptStabilityMs??l.transcriptStabilityMs??g.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"}}},r=(c="default")=>{let n=Xc[c];return{audioConditioning:t(n.audioConditioning),capture:{channelCount:n.capture?.channelCount??1,sampleRateHz:n.capture?.sampleRateHz??16000},connection:{...n.connection},name:c,sttLifecycle:n.sttLifecycle??"continuous",turnDetection:F(n.turnDetection)}};var Yc=(c)=>({assistantAudio:[...c.assistantAudio],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]}),a=(c,n={})=>{let o=r(n.preset),g=k(c,{...o.connection,...n.connection}),l=null,i=Yc(g),C=new Set,V=()=>{for(let R of C)R()},I=()=>{if(i={...i,assistantAudio:[...g.assistantAudio],assistantTexts:[...g.assistantTexts],call:g.call,error:g.error,isConnected:g.isConnected,partial:g.partial,reconnect:g.reconnect,sessionId:g.sessionId,sessionMetadata:g.sessionMetadata,scenarioId:g.scenarioId,status:g.status,turns:[...g.turns]},n.autoStopOnComplete!==!1&&i.status==="completed"&&i.isRecording)l?.stop(),l=null,i={...i,isRecording:!1};V()},S=g.subscribe(I);I();let T=()=>{if(l)return l;return l=J({channelCount:n.capture?.channelCount??o.capture.channelCount,onLevel:n.capture?.onLevel,onAudio:(R)=>{if(n.capture?.onAudio){n.capture.onAudio(R,g.sendAudio);return}g.sendAudio(R)},sampleRateHz:n.capture?.sampleRateHz??o.capture.sampleRateHz}),l},h=()=>{l?.stop(),l=null,i={...i,isRecording:!1},V()},y=async()=>{if(i.isRecording)return;try{i={...i,recordingError:null},V(),await T().start(),i={...i,isRecording:!0},V()}catch(R){throw l=null,i={...i,isRecording:!1,recordingError:R instanceof Error?R.message:String(R)},V(),R}};return{close:()=>{S(),h(),g.close()},startRecording:y,stopRecording:h,get assistantAudio(){return i.assistantAudio},get assistantTexts(){return i.assistantTexts},bindHTMX(R){return Q(g,R)},get call(){return i.call},callControl:(R)=>g.callControl(R),endTurn:()=>g.endTurn(),get error(){return i.error},getServerSnapshot:()=>i,getSnapshot:()=>i,get isConnected(){return i.isConnected},get isRecording(){return i.isRecording},get partial(){return i.partial},get reconnect(){return i.reconnect},get recordingError(){return i.recordingError},get scenarioId(){return i.scenarioId},sendAudio:(R)=>g.sendAudio(R),get sessionId(){return i.sessionId},get sessionMetadata(){return i.sessionMetadata},simulateDisconnect:()=>g.simulateDisconnect(),get status(){return i.status},subscribe:(R)=>{return C.add(R),()=>{C.delete(R)}},toggleRecording:async()=>{if(i.isRecording){h();return}await y()},get turns(){return i.turns}}};var s=(c)=>String(c).replaceAll("&","&").replaceAll("<","<").replaceAll(">",">").replaceAll('"',""").replaceAll("'","'");var v=(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 Qc={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},Jc={callEnded:"Call ended",connecting:"Connecting…",endCall:"End call",idle:"Idle",listening:"Listening",mute:"Mute",speaking:"Speaking",startCall:"Start call",thinking:"Thinking",unmute:"Unmute"},qc=(c,n)=>{switch(c){case"listening":return n.listening;case"speaking":return n.speaking;case"thinking":return n.thinking;case"idle":return n.idle}},u=(c)=>{let n={...Qc,...c.theme},o={...Jc,...c.labels},g=c.state.assistantAudio.at(-1)?.receivedAt,l=c.state.turns.at(-1)?.committedAt,i=v({hasActivePartial:c.state.partial.length>0,isConnected:c.state.isConnected,isPlaying:!1,isRecording:c.state.isRecording,lastAssistantAt:g,lastTranscriptAt:l}),C=!c.state.isConnected&&c.state.status!=="idle"&&!c.state.error,V=c.state.error?"Error":C?o.connecting:c.state.status==="completed"?o.callEnded:qc(i,o);return{agentState:i,classes:{container:`absolute-voice-widget absolute-voice-widget--${i}`,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:o,partial:c.state.partial||void 0,statusLabel:V,theme:n,title:c.title??"Voice"}},Zc=(c)=>typeof c==="number"?`${c}px`:c,m=(c)=>{let n=c.theme,o=`background:${n.background};border-radius:${Zc(n.radius)};color:${n.foreground};font-family:${n.fontFamily};min-width:240px;padding:20px 22px;`,g=`background:${c.errorMessage?n.errorAccent:c.agentState==="idle"?"rgba(148,163,184,0.6)":n.accent};border-radius:50%;height:10px;width:10px;`,l=[];if(c.controls.canStart)l.push(`<button type="button" data-action="start" style="background:${n.accent};border:none;border-radius:12px;color:${n.foreground};cursor:pointer;font-size:14px;font-weight:500;padding:10px 14px;">${s(c.labels.startCall)}</button>`);if(c.controls.canMute)l.push(`<button type="button" data-action="mute" style="background:transparent;border:1px solid rgba(255,255,255,0.18);border-radius:12px;color:${n.foreground};cursor:pointer;font-size:14px;font-weight:500;padding:10px 14px;">${s(c.labels.mute)}</button>`);if(c.controls.canEnd)l.push(`<button type="button" data-action="end" style="background:${n.errorAccent};border:none;border-radius:12px;color:${n.foreground};cursor:pointer;font-size:14px;font-weight:500;padding:10px 14px;">${s(c.labels.endCall)}</button>`);return`<div role="region" aria-live="polite" data-agent-state="${c.agentState}" class="${s(c.classes.container)}" style="${o}">
|
|
1
|
+
(()=>{var{defineProperty:H,getOwnPropertyNames:oc,getOwnPropertyDescriptor:lc}=Object,Ac=Object.prototype.hasOwnProperty;function ic(c){return this[c]}var Cc=(c)=>{var n=(Y??=new WeakMap).get(c),o;if(n)return n;if(n=H({},"__esModule",{value:!0}),c&&typeof c==="object"||typeof c==="function"){for(var g of oc(c))if(!Ac.call(n,g))H(n,g,{get:ic.bind(c,g),enumerable:!(o=lc(c,g))||o.enumerable})}return Y.set(c,n),n},Y;var Tc=(c)=>c;function yc(c,n){this[c]=Tc.bind(null,n)}var Vc=(c,n)=>{for(var o in n)H(c,o,{get:n[o],enumerable:!0,configurable:!0,set:yc.bind(n,o)})};var ec={};Vc(ec,{mount:()=>p,default:()=>Bc,VOICE_EMBED_VERSION:()=>cc});var Ic=(c)=>{if(typeof c!=="string")return c;return document.querySelector(c)},Sc=(c,n,o,g)=>{let l=n??c.getAttribute("hx-get")??"";if(!l)return"";let C=new URL(l,window.location.origin);if(g)C.searchParams.set(o,g);else C.searchParams.delete(o);return`${C.pathname}${C.search}${C.hash}`},Q=(c,n)=>{if(typeof window>"u"||typeof document>"u")return()=>{};let o=Ic(n.element);if(!o)return()=>{};let g=n.eventName??"voice-refresh",l=n.sessionQueryParam??"sessionId",C=()=>{let V=window,I=Sc(o,n.route,l,c.sessionId);if(I)o.setAttribute("hx-get",I);V.htmx?.process?.(o),V.htmx?.trigger?.(o,g)},i=c.subscribe(C);return C(),()=>{i()}};var dc=(c)=>Math.max(-1,Math.min(1,c)),Rc=(c)=>{let n=new Int16Array(c.length);for(let o=0;o<c.length;o+=1){let g=dc(c[o]??0);n[o]=g<0?g*32768:g*32767}return new Uint8Array(n.buffer)},hc=(c)=>{let n=c instanceof Uint8Array?c:new Uint8Array(c);if(n.byteLength<2)return 0;let o=new Int16Array(n.buffer,n.byteOffset,Math.floor(n.byteLength/2));if(o.length===0)return 0;let g=0;for(let l of o){let C=l/32768;g+=C*C}return Math.min(1,Math.max(0,Math.sqrt(g/o.length)*5.5))},_c=(c,n,o)=>{if(n===o)return c;let g=n/o,l=Math.round(c.length/g),C=new Float32Array(l),i=0,V=0;while(i<C.length){let I=Math.round((i+1)*g),R=0,y=0;for(let d=V;d<I&&d<c.length;d+=1)R+=c[d]??0,y+=1;C[i]=y>0?R/y:0,i+=1,V=I}return C},J=(c)=>{let n=null,o=null,g=null,l=null;return{start:async()=>{if(typeof navigator>"u"||!navigator.mediaDevices?.getUserMedia)throw Error("Browser microphone capture requires navigator.mediaDevices.getUserMedia.");let V=(typeof window<"u"?window.AudioContext??window.webkitAudioContext:void 0)??AudioContext;if(!V)throw Error("Browser microphone capture requires AudioContext support.");l=await navigator.mediaDevices.getUserMedia({audio:{channelCount:c.channelCount??1}}),n=new V,o=n.createMediaStreamSource(l),g=n.createScriptProcessor(4096,1,1),g.onaudioprocess=(I)=>{let R=I.inputBuffer.getChannelData(0),y=_c(R,n?.sampleRate??48000,c.sampleRateHz??16000),d=Rc(y);c.onLevel?.(hc(d)),c.onAudio(d)},o.connect(g),g.connect(n.destination)},stop:()=>{g?.disconnect(),o?.disconnect(),l?.getTracks().forEach((V)=>V.stop()),n?.close(),c.onLevel?.(0),n=null,l=null,g=null,o=null}}};var G=(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 n=c;for(let o of["message","reason","description"]){let g=n[o];if(typeof g==="string"&&g.trim())return g}if("error"in n)return G(n.error);if("cause"in n)return G(n.cause);try{return JSON.stringify(c)}catch{}}return"Unexpected error"},q=(c)=>{switch(c.type){case"audio":return{chunk:Uint8Array.from(atob(c.chunkBase64),(n)=>n.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:G(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 kc=Math.PI*2;var x=(c,n,o,g)=>{c.push({code:o,message:g,severity:n})};var sc=(c)=>c.length===0?void 0:c.reduce((n,o)=>n+o,0)/c.length,N=(c)=>c.length===0?void 0:Math.max(...c);var _=(c,n)=>{let o=c[n];return typeof o==="number"&&Number.isFinite(o)?o:void 0},$=(c,n)=>{let o=c[n];return typeof o==="boolean"?o:void 0},s=(c,n)=>{let o=c[n];return typeof o==="string"?o:void 0},X=(c)=>String(c.id??s(c,"ssrc")??_(c,"ssrc")??s(c,"trackIdentifier")??s(c,"mid")??"unknown"),Z=(c)=>c===void 0?void 0:c*1000;var wc=(c)=>{let n={};for(let[o,g]of Object.entries(c))if(g===null||typeof g==="boolean"||typeof g==="number"||typeof g==="string")n[o]=g;return n};var z=(c={})=>{let n=c.stats??[],o=[],g=n.filter((A)=>A.type==="inbound-rtp"&&s(A,"kind")!=="video"),l=n.filter((A)=>A.type==="outbound-rtp"&&s(A,"kind")!=="video"),C=n.filter((A)=>A.type==="candidate-pair"),i=n.filter((A)=>(A.type==="track"||A.type==="media-source")&&s(A,"kind")==="audio"),V=C.filter((A)=>$(A,"selected")===!0||$(A,"nominated")===!0||s(A,"state")==="succeeded").length,I=i.filter((A)=>s(A,"readyState")!=="ended"&&s(A,"trackState")!=="ended"&&$(A,"ended")!==!0).length,R=i.filter((A)=>s(A,"readyState")==="ended"||s(A,"trackState")==="ended"||$(A,"ended")===!0).length,y=g.reduce((A,h)=>A+(_(h,"packetsReceived")??0),0),d=l.reduce((A,h)=>A+(_(h,"packetsSent")??0),0),T=[...g,...l].reduce((A,h)=>A+Math.max(0,_(h,"packetsLost")??0),0),w=y+T,S=w===0?0:T/w,E=g.reduce((A,h)=>A+(_(h,"bytesReceived")??0),0),b=l.reduce((A,h)=>A+(_(h,"bytesSent")??0),0),U=N(C.map((A)=>Z(_(A,"currentRoundTripTime")??_(A,"roundTripTime"))).filter((A)=>A!==void 0)),M=N([...g,...l].map((A)=>Z(_(A,"jitter"))).filter((A)=>A!==void 0)),W=N(g.map((A)=>{let h=_(A,"jitterBufferDelay"),L=_(A,"jitterBufferEmittedCount");return h!==void 0&&L!==void 0&&L>0?h/L*1000:void 0}).filter((A)=>A!==void 0)),P=i.map((A)=>_(A,"audioLevel")).filter((A)=>A!==void 0);if(c.requireConnectedCandidatePair&&C.length>0&&V===0)x(o,"error","media.webrtc_candidate_pair_missing","No active WebRTC candidate pair was observed.");if(c.requireLiveAudioTrack&&I===0)x(o,"error","media.webrtc_audio_track_missing","No live WebRTC audio track was observed.");if(c.maxPacketLossRatio!==void 0&&S>c.maxPacketLossRatio)x(o,"warning","media.webrtc_packet_loss",`Observed WebRTC packet loss ratio ${String(S)} above ${String(c.maxPacketLossRatio)}.`);if(c.maxRoundTripTimeMs!==void 0&&U!==void 0&&U>c.maxRoundTripTimeMs)x(o,"warning","media.webrtc_round_trip_time",`Observed WebRTC RTT ${String(U)}ms above ${String(c.maxRoundTripTimeMs)}ms.`);if(c.maxJitterMs!==void 0&&M!==void 0&&M>c.maxJitterMs)x(o,"warning","media.webrtc_jitter",`Observed WebRTC jitter ${String(M)}ms above ${String(c.maxJitterMs)}ms.`);return{activeCandidatePairs:V,audioLevelAverage:sc(P),bytesReceived:E,bytesSent:b,checkedAt:Date.now(),endedAudioTracks:R,inboundPackets:y,issues:o,jitterBufferDelayMs:W,jitterMs:M,liveAudioTracks:I,outboundPackets:d,packetLossRatio:S,packetsLost:T,roundTripTimeMs:U,status:o.some((A)=>A.severity==="error")?"fail":o.length>0?"warn":"pass",totalStats:n.length}},e=async(c)=>{return[...(await c.peerConnection.getStats(c.selector??null)).values()].map(wc)};var B=(c={})=>{let n=c.stats??[],o=c.previousStats??[],g=[],l=new Map(o.map((T)=>[X(T),T])),i=n.filter((T)=>(T.type==="inbound-rtp"||T.type==="outbound-rtp")&&s(T,"kind")!=="video"&&s(T,"mediaType")!=="video").map((T)=>{let w=T.type==="outbound-rtp"?"outbound":"inbound",S=w==="outbound"?"packetsSent":"packetsReceived",E=w==="outbound"?"bytesSent":"bytesReceived",b=l.get(X(T)),U=_(T,S),M=b?_(b,S):void 0,W=_(T,E),P=b?_(b,E):void 0,A=T.timestamp!==void 0&&b?.timestamp!==void 0?T.timestamp-b.timestamp:void 0;return{bytesDelta:W!==void 0&&P!==void 0?W-P:void 0,currentPackets:U,direction:w,id:X(T),packetDelta:U!==void 0&&M!==void 0?U-M:void 0,previousPackets:M,timeDeltaMs:A}}),V=i.filter((T)=>T.direction==="inbound"),I=i.filter((T)=>T.direction==="outbound"),R=N(i.map((T)=>T.timeDeltaMs).filter((T)=>T!==void 0)),y=V.filter((T)=>c.maxInboundPacketStallMs!==void 0&&T.timeDeltaMs!==void 0&&T.timeDeltaMs>=c.maxInboundPacketStallMs&&T.packetDelta!==void 0&&T.packetDelta<=0).length,d=I.filter((T)=>c.maxOutboundPacketStallMs!==void 0&&T.timeDeltaMs!==void 0&&T.timeDeltaMs>=c.maxOutboundPacketStallMs&&T.packetDelta!==void 0&&T.packetDelta<=0).length;if(c.requireInboundAudio&&V.length===0)x(g,"error","media.webrtc_inbound_audio_missing","No inbound WebRTC audio RTP stream was observed.");if(c.requireOutboundAudio&&I.length===0)x(g,"error","media.webrtc_outbound_audio_missing","No outbound WebRTC audio RTP stream was observed.");if(c.maxGapMs!==void 0&&R!==void 0&&R>c.maxGapMs)x(g,"warning","media.webrtc_stream_gap",`Observed WebRTC stream sample gap ${String(R)}ms above ${String(c.maxGapMs)}ms.`);if(y>0)x(g,"error","media.webrtc_inbound_stalled",`${String(y)} inbound WebRTC audio stream(s) stopped receiving packets.`);if(d>0)x(g,"error","media.webrtc_outbound_stalled",`${String(d)} outbound WebRTC audio stream(s) stopped sending packets.`);return{checkedAt:Date.now(),inboundAudioStreams:V.length,issues:g,maxObservedGapMs:R,outboundAudioStreams:I.length,stalledInboundStreams:y,stalledOutboundStreams:d,status:g.some((T)=>T.severity==="error")?"fail":g.length>0?"warn":"pass",streams:i,totalStats:n.length}};var Lc="/api/voice/browser-media",bc=5000,Uc=async(c)=>c.peerConnection??await c.getPeerConnection?.()??null,Mc=async(c,n)=>{let o=n.fetch??globalThis.fetch;if(!o)return;await o(n.path??Lc,{body:JSON.stringify(c),headers:{"Content-Type":"application/json"},keepalive:!0,method:"POST"})},K=(c)=>{let n=null,o=[],g=async()=>{let i=await Uc(c);if(!i)return;let V=await e({peerConnection:i}),I=z({...c,stats:V}),R=c.continuity===!1?void 0:B({...c.continuity,previousStats:o,stats:V}),y={at:Date.now(),continuity:R,report:I,scenarioId:c.getScenarioId?.()??null,sessionId:c.getSessionId?.()??null};return o=V,c.onReport?.(y),await Mc(y,c),y},l=()=>{g().catch((i)=>{c.onError?.(i)})},C=()=>{if(n)clearInterval(n),n=null};return{close:C,reportOnce:g,stop:C,start:()=>{if(n)return;l(),n=setInterval(l,c.intervalMs??bc)}}};var D=()=>{},xc=()=>D,Oc={callControl:D,close:D,endTurn:D,send:D,sendAudio:D,simulateDisconnect:D,subscribe:xc,getReadyState:()=>3,getScenarioId:()=>"",getSessionId:()=>"",start:()=>{}},Dc=()=>crypto.randomUUID(),Ec=(c,n,o)=>{let{hostname:g,port:l,protocol:C}=window.location,i=C==="https:"?"wss:":"ws:",V=l?`:${l}`:"",I=new URL(`${i}//${g}${V}${c}`);if(I.searchParams.set("sessionId",n),o)I.searchParams.set("scenarioId",o);return I.toString()},Wc=(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}},Pc=(c)=>{if(typeof c.data!=="string")return null;try{let n=JSON.parse(c.data);return Wc(n)?n:null}catch{return null}},j=(c,n={})=>{if(typeof window>"u")return Oc;let o=new Set,g=n.reconnect!==!1,l=n.maxReconnectAttempts??10,C=n.pingInterval??30000,i={isConnected:!1,pendingMessages:[],scenarioId:n.scenarioId??null,pingInterval:null,reconnectAttempts:0,reconnectTimeout:null,sessionId:n.sessionId??Dc(),ws:null},V=(A)=>{o.forEach((h)=>h(A))},I=()=>{if(i.pingInterval)clearInterval(i.pingInterval),i.pingInterval=null;if(i.reconnectTimeout)clearTimeout(i.reconnectTimeout),i.reconnectTimeout=null},R=()=>{if(i.ws?.readyState!==1)return;while(i.pendingMessages.length>0){let A=i.pendingMessages.shift();if(A!==void 0)i.ws.send(A)}},y=()=>{let A=Date.now()+500;i.reconnectAttempts+=1,V({reconnect:{attempts:i.reconnectAttempts,lastDisconnectAt:Date.now(),maxAttempts:l,nextAttemptAt:A,status:"reconnecting"},type:"connection"}),i.reconnectTimeout=setTimeout(()=>{if(i.reconnectAttempts>l){V({reconnect:{attempts:i.reconnectAttempts,maxAttempts:l,status:"exhausted"},type:"connection"});return}d()},500)},d=()=>{let A=new WebSocket(Ec(c,i.sessionId,i.scenarioId));A.binaryType="arraybuffer",A.onopen=()=>{let h=i.reconnectAttempts>0;if(i.isConnected=!0,R(),h)V({reconnect:{attempts:i.reconnectAttempts,lastResumedAt:Date.now(),maxAttempts:l,status:"resumed"},type:"connection"}),i.reconnectAttempts=0;o.forEach((L)=>L({scenarioId:i.scenarioId??void 0,sessionId:i.sessionId,status:"active",type:"session"})),i.pingInterval=setInterval(()=>{if(A.readyState===1)A.send(JSON.stringify({type:"ping"}))},C)},A.onmessage=(h)=>{let L=Pc(h);if(!L)return;if(L.type==="session")i.sessionId=L.sessionId,i.scenarioId=L.scenarioId??i.scenarioId;o.forEach((gc)=>gc(L))},A.onclose=(h)=>{if(i.isConnected=!1,I(),g&&h.code!==1000&&i.reconnectAttempts<l)y();else if(g&&h.code!==1000)V({reconnect:{attempts:i.reconnectAttempts,lastDisconnectAt:Date.now(),maxAttempts:l,status:"exhausted"},type:"connection"})},i.ws=A},T=(A)=>{if(i.ws?.readyState===1){i.ws.send(A);return}i.pendingMessages.push(A)},w=(A)=>{T(JSON.stringify(A))},S=(A={})=>{if(A.sessionId)i.sessionId=A.sessionId;if(A.scenarioId)i.scenarioId=A.scenarioId;w({scenarioId:i.scenarioId??void 0,sessionId:i.sessionId,type:"start"})},E=(A)=>{T(A)},b=()=>{w({type:"end_turn"})},U=(A)=>{w({...A,type:"call_control"})},M=()=>{if(I(),i.ws)i.ws.close(1000),i.ws=null;i.isConnected=!1,o.clear()},W=()=>{if(i.ws?.readyState===1)i.ws.close(4000,"absolutejs-voice-reconnect-proof")},P=(A)=>{return o.add(A),()=>{o.delete(A)}};return d(),{callControl:U,close:M,endTurn:b,send:w,sendAudio:E,simulateDisconnect:W,start:S,subscribe:P,getReadyState:()=>i.ws?.readyState??3,getScenarioId:()=>i.scenarioId??"",getSessionId:()=>i.sessionId}};var $c=()=>({attempts:0,maxAttempts:0,status:"idle"}),Nc=()=>({assistantAudio:[],assistantStreamingText:"",assistantTexts:[],call:null,error:null,isConnected:!1,partial:"",reconnect:$c(),scenarioId:null,sessionId:null,sessionMetadata:null,status:"idle",turns:[]}),t=()=>{let c=Nc(),n=new Set,o=()=>{n.forEach((l)=>l())};return{dispatch:(l)=>{switch(l.type){case"audio":c={...c,assistantAudio:[...c.assistantAudio,{chunk:l.chunk,format:l.format,receivedAt:l.receivedAt,turnId:l.turnId}]};break;case"assistant":c={...c,assistantStreamingText:"",assistantTexts:[...c.assistantTexts,l.text]};break;case"assistant_delta":c={...c,assistantStreamingText:`${c.assistantStreamingText}${l.delta}`};break;case"complete":c={...c,sessionId:l.sessionId,status:"completed"};break;case"call_lifecycle":c={...c,call:{...c.call,disposition:l.event.type==="end"?l.event.disposition:c.call?.disposition,endedAt:l.event.type==="end"?l.event.at:c.call?.endedAt,events:[...c.call?.events??[],l.event],lastEventAt:l.event.at,startedAt:c.call?.startedAt??l.event.at},sessionId:l.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:l.reconnect};break;case"disconnected":c={...c,isConnected:!1};break;case"error":c={...c,error:l.message};break;case"final":c={...c,partial:l.transcript.text,turns:c.turns.map((C)=>C)};break;case"partial":c={...c,partial:l.transcript.text};break;case"replay":c={...c,assistantStreamingText:"",assistantTexts:[...l.assistantTexts],call:l.call??null,error:null,isConnected:l.status==="active",partial:l.partial,reconnect:c.reconnect.status==="reconnecting"?{...c.reconnect,lastResumedAt:Date.now(),nextAttemptAt:void 0,status:"resumed"}:c.reconnect,scenarioId:l.scenarioId??c.scenarioId,sessionId:l.sessionId,sessionMetadata:l.sessionMetadata??c.sessionMetadata,status:l.status,turns:[...l.turns]};break;case"session":c={...c,error:null,scenarioId:l.scenarioId??c.scenarioId,isConnected:l.status==="active",sessionId:l.sessionId,sessionMetadata:l.sessionMetadata??c.sessionMetadata,status:l.status};break;case"turn":c={...c,partial:"",turns:[...c.turns,l.turn]};break}o()},getServerSnapshot:()=>c,getSnapshot:()=>c,subscribe:(l)=>{return n.add(l),()=>{n.delete(l)}}}};var f=(c,n={})=>{let o=j(c,n),g=t(),l=n.browserMedia&&typeof window<"u"?K({...n.browserMedia,getScenarioId:()=>n.browserMedia?n.browserMedia.getScenarioId?.()??o.getScenarioId():o.getScenarioId(),getSessionId:()=>n.browserMedia?n.browserMedia.getSessionId?.()??o.getSessionId():o.getSessionId()}):null,C=new Set,i=(y)=>Promise.resolve().then(()=>{if(!y?.sessionId&&!y?.scenarioId)return;o.start(y),l?.start()}),V=()=>{C.forEach((y)=>y())},I=()=>{if(!n.reconnectReportPath||typeof fetch>"u")return;let y=g.getSnapshot(),d=JSON.stringify({at:Date.now(),reconnect:y.reconnect,scenarioId:y.scenarioId,sessionId:o.getSessionId(),turnIds:y.turns.map((T)=>T.id)});fetch(n.reconnectReportPath,{body:d,headers:{"Content-Type":"application/json"},keepalive:!0,method:"POST"}).catch(()=>{})},R=o.subscribe((y)=>{let d=q(y);if(d){if(g.dispatch(d),y.type==="connection")I();V()}});return{start:i,get assistantAudio(){return g.getSnapshot().assistantAudio},get assistantTexts(){return g.getSnapshot().assistantTexts},get assistantStreamingText(){return g.getSnapshot().assistantStreamingText},get call(){return g.getSnapshot().call},callControl(y){o.callControl(y)},close(){R(),l?.close(),o.close(),g.dispatch({type:"disconnected"}),V()},endTurn(){o.endTurn()},get error(){return g.getSnapshot().error},getServerSnapshot(){return g.getServerSnapshot()},getSnapshot(){return g.getSnapshot()},get isConnected(){return g.getSnapshot().isConnected},get partial(){return g.getSnapshot().partial},get reconnect(){return g.getSnapshot().reconnect},get scenarioId(){return g.getSnapshot().scenarioId},sendAudio(y){o.sendAudio(y)},get sessionId(){return o.getSessionId()},get sessionMetadata(){return g.getSnapshot().sessionMetadata},simulateDisconnect(){o.simulateDisconnect()},get status(){return g.getSnapshot().status},subscribe(y){return C.add(y),()=>{C.delete(y)}},get turns(){return g.getSnapshot().turns}}};var k=(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 Hc={balanced:{qualityProfile:"general",silenceMs:1400,speechThreshold:0.012,transcriptStabilityMs:1000},fast:{qualityProfile:"general",silenceMs:700,speechThreshold:0.015,transcriptStabilityMs:450},"long-form":{qualityProfile:"general",silenceMs:2200,speechThreshold:0.01,transcriptStabilityMs:1500}},Gc={"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}};var F=(c)=>{let n=c?.profile??"fast",o=c?.qualityProfile??"general",g=Hc[n],l=Gc[o];return{profile:n,qualityProfile:o,silenceMs:c?.silenceMs??l.silenceMs??g.silenceMs,speechThreshold:c?.speechThreshold??l.speechThreshold??g.speechThreshold,transcriptStabilityMs:c?.transcriptStabilityMs??l.transcriptStabilityMs??g.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"}}},r=(c="default")=>{let n=Xc[c];return{audioConditioning:k(n.audioConditioning),capture:{channelCount:n.capture?.channelCount??1,sampleRateHz:n.capture?.sampleRateHz??16000},connection:{...n.connection},name:c,sttLifecycle:n.sttLifecycle??"continuous",turnDetection:F(n.turnDetection)}};var Yc=(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]}),a=(c,n={})=>{let o=r(n.preset),g=f(c,{...o.connection,...n.connection}),l=null,C=Yc(g),i=new Set,V=()=>{for(let S of i)S()},I=()=>{if(C={...C,assistantAudio:[...g.assistantAudio],assistantStreamingText:g.assistantStreamingText,assistantTexts:[...g.assistantTexts],call:g.call,error:g.error,isConnected:g.isConnected,partial:g.partial,reconnect:g.reconnect,sessionId:g.sessionId,sessionMetadata:g.sessionMetadata,scenarioId:g.scenarioId,status:g.status,turns:[...g.turns]},n.autoStopOnComplete!==!1&&C.status==="completed"&&C.isRecording)l?.stop(),l=null,C={...C,isRecording:!1};V()},R=g.subscribe(I);I();let y=()=>{if(l)return l;return l=J({channelCount:n.capture?.channelCount??o.capture.channelCount,onLevel:n.capture?.onLevel,onAudio:(S)=>{if(n.capture?.onAudio){n.capture.onAudio(S,g.sendAudio);return}g.sendAudio(S)},sampleRateHz:n.capture?.sampleRateHz??o.capture.sampleRateHz}),l},d=()=>{l?.stop(),l=null,C={...C,isRecording:!1},V()},T=async()=>{if(C.isRecording)return;try{C={...C,recordingError:null},V(),await y().start(),C={...C,isRecording:!0},V()}catch(S){throw l=null,C={...C,isRecording:!1,recordingError:S instanceof Error?S.message:String(S)},V(),S}};return{close:()=>{R(),d(),g.close()},startRecording:T,stopRecording:d,get assistantAudio(){return C.assistantAudio},get assistantTexts(){return C.assistantTexts},get assistantStreamingText(){return C.assistantStreamingText},bindHTMX(S){return Q(g,S)},get call(){return C.call},callControl:(S)=>g.callControl(S),endTurn:()=>g.endTurn(),get error(){return C.error},getServerSnapshot:()=>C,getSnapshot:()=>C,get isConnected(){return C.isConnected},get isRecording(){return C.isRecording},get partial(){return C.partial},get reconnect(){return C.reconnect},get recordingError(){return C.recordingError},get scenarioId(){return C.scenarioId},sendAudio:(S)=>g.sendAudio(S),get sessionId(){return C.sessionId},get sessionMetadata(){return C.sessionMetadata},simulateDisconnect:()=>g.simulateDisconnect(),get status(){return C.status},subscribe:(S)=>{return i.add(S),()=>{i.delete(S)}},toggleRecording:async()=>{if(C.isRecording){d();return}await T()},get turns(){return C.turns}}};var O=(c)=>String(c).replaceAll("&","&").replaceAll("<","<").replaceAll(">",">").replaceAll('"',""").replaceAll("'","'");var v=(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 Qc={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},Jc={callEnded:"Call ended",connecting:"Connecting…",endCall:"End call",idle:"Idle",listening:"Listening",mute:"Mute",speaking:"Speaking",startCall:"Start call",thinking:"Thinking",unmute:"Unmute"},qc=(c,n)=>{switch(c){case"listening":return n.listening;case"speaking":return n.speaking;case"thinking":return n.thinking;case"idle":return n.idle}},u=(c)=>{let n={...Qc,...c.theme},o={...Jc,...c.labels},g=c.state.assistantAudio.at(-1)?.receivedAt,l=c.state.turns.at(-1)?.committedAt,C=v({hasActivePartial:c.state.partial.length>0,isConnected:c.state.isConnected,isPlaying:!1,isRecording:c.state.isRecording,lastAssistantAt:g,lastTranscriptAt:l}),i=!c.state.isConnected&&c.state.status!=="idle"&&!c.state.error,V=c.state.error?"Error":i?o.connecting:c.state.status==="completed"?o.callEnded:qc(C,o);return{agentState:C,classes:{container:`absolute-voice-widget absolute-voice-widget--${C}`,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:o,partial:c.state.partial||void 0,statusLabel:V,theme:n,title:c.title??"Voice"}},Zc=(c)=>typeof c==="number"?`${c}px`:c,m=(c)=>{let n=c.theme,o=`background:${n.background};border-radius:${Zc(n.radius)};color:${n.foreground};font-family:${n.fontFamily};min-width:240px;padding:20px 22px;`,g=`background:${c.errorMessage?n.errorAccent:c.agentState==="idle"?"rgba(148,163,184,0.6)":n.accent};border-radius:50%;height:10px;width:10px;`,l=[];if(c.controls.canStart)l.push(`<button type="button" data-action="start" style="background:${n.accent};border:none;border-radius:12px;color:${n.foreground};cursor:pointer;font-size:14px;font-weight:500;padding:10px 14px;">${O(c.labels.startCall)}</button>`);if(c.controls.canMute)l.push(`<button type="button" data-action="mute" style="background:transparent;border:1px solid rgba(255,255,255,0.18);border-radius:12px;color:${n.foreground};cursor:pointer;font-size:14px;font-weight:500;padding:10px 14px;">${O(c.labels.mute)}</button>`);if(c.controls.canEnd)l.push(`<button type="button" data-action="end" style="background:${n.errorAccent};border:none;border-radius:12px;color:${n.foreground};cursor:pointer;font-size:14px;font-weight:500;padding:10px 14px;">${O(c.labels.endCall)}</button>`);return`<div role="region" aria-live="polite" data-agent-state="${c.agentState}" class="${O(c.classes.container)}" style="${o}">
|
|
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="${O(c.classes.dot)}" style="${g}"></span>
|
|
4
|
+
<strong style="font-size:15px;">${O(c.title)}</strong>
|
|
5
|
+
<span style="font-size:13px;margin-left:auto;opacity:0.7;">${O(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;">“${
|
|
7
|
+
${c.partial?`<p style="font-size:13px;margin:8px 0 12px;opacity:0.85;word-break:break-word;">“${O(c.partial)}”</p>`:""}
|
|
8
8
|
<div style="display:flex;gap:10px;">${l.join("")}</div>
|
|
9
|
-
${c.errorMessage?`<p style="color:${n.errorAccent};font-size:12px;margin-top:12px;">${
|
|
10
|
-
</div>`};var zc=(c)=>{if(typeof c!=="string")return c;let n=document.querySelector(c);if(!n)throw Error(`AbsoluteVoice.mount: no element matches "${c}"`);return n},p=(c,n={})=>{let o=zc(c),g=a(n.path??"/voice",n.controllerOptions),l=null,
|
|
9
|
+
${c.errorMessage?`<p style="color:${n.errorAccent};font-size:12px;margin-top:12px;">${O(c.errorMessage)}</p>`:""}
|
|
10
|
+
</div>`};var zc=(c)=>{if(typeof c!=="string")return c;let n=document.querySelector(c);if(!n)throw Error(`AbsoluteVoice.mount: no element matches "${c}"`);return n},p=(c,n={})=>{let o=zc(c),g=a(n.path??"/voice",n.controllerOptions),l=null,C=null,i=()=>{let I=u({...n.labels!==void 0?{labels:n.labels}:{},state:{assistantAudio:g.assistantAudio,error:g.error,isConnected:g.isConnected,isRecording:g.isRecording,partial:g.partial,status:g.status,turns:g.turns},...n.theme!==void 0?{theme:n.theme}:{},...n.title!==void 0?{title:n.title}:{}});o.innerHTML=m(I);for(let R of o.querySelectorAll("button[data-action]")){let{action:y}=R.dataset;R.addEventListener("click",()=>{if(y==="start")g.startRecording();else if(y==="mute")g.stopRecording();else if(y==="end")g.close()})}if(g.error&&g.error!==l)l=g.error,n.onError?.(g.error);if(g.status!==C)C=g.status,n.onStatusChange?.(g.status)},V=g.subscribe(i);if(i(),n.autoStart)g.startRecording();return{controller:g,async end(){await g.close()},mute(){g.stopRecording()},async start(){await g.startRecording()},unmount(){V(),g.close(),o.innerHTML=""}}},cc="0.0.22-beta.516",nc={mount:p,version:cc};if(typeof globalThis<"u")globalThis.AbsoluteVoice=nc;var Bc=nc;})();
|
package/dist/index.js
CHANGED
|
@@ -5290,6 +5290,7 @@ var createVoiceSession = (options) => {
|
|
|
5290
5290
|
return;
|
|
5291
5291
|
streamed = true;
|
|
5292
5292
|
full += delta;
|
|
5293
|
+
send({ delta, turnId: turn.id, type: "assistant_delta" });
|
|
5293
5294
|
buffer += delta;
|
|
5294
5295
|
let boundary = nextSpeakableBoundary(buffer);
|
|
5295
5296
|
while (boundary !== -1) {
|
package/dist/react/index.js
CHANGED
|
@@ -11281,8 +11281,15 @@ var serverMessageToAction = (message) => {
|
|
|
11281
11281
|
case "assistant":
|
|
11282
11282
|
return {
|
|
11283
11283
|
text: message.text,
|
|
11284
|
+
turnId: message.turnId,
|
|
11284
11285
|
type: "assistant"
|
|
11285
11286
|
};
|
|
11287
|
+
case "assistant_delta":
|
|
11288
|
+
return {
|
|
11289
|
+
delta: message.delta,
|
|
11290
|
+
turnId: message.turnId,
|
|
11291
|
+
type: "assistant_delta"
|
|
11292
|
+
};
|
|
11286
11293
|
case "complete":
|
|
11287
11294
|
return {
|
|
11288
11295
|
sessionId: message.sessionId,
|
|
@@ -11701,6 +11708,7 @@ var createInitialReconnectState = () => ({
|
|
|
11701
11708
|
});
|
|
11702
11709
|
var createInitialState = () => ({
|
|
11703
11710
|
assistantAudio: [],
|
|
11711
|
+
assistantStreamingText: "",
|
|
11704
11712
|
assistantTexts: [],
|
|
11705
11713
|
call: null,
|
|
11706
11714
|
error: null,
|
|
@@ -11738,9 +11746,16 @@ var createVoiceStreamStore = () => {
|
|
|
11738
11746
|
case "assistant":
|
|
11739
11747
|
state = {
|
|
11740
11748
|
...state,
|
|
11749
|
+
assistantStreamingText: "",
|
|
11741
11750
|
assistantTexts: [...state.assistantTexts, action.text]
|
|
11742
11751
|
};
|
|
11743
11752
|
break;
|
|
11753
|
+
case "assistant_delta":
|
|
11754
|
+
state = {
|
|
11755
|
+
...state,
|
|
11756
|
+
assistantStreamingText: `${state.assistantStreamingText}${action.delta}`
|
|
11757
|
+
};
|
|
11758
|
+
break;
|
|
11744
11759
|
case "complete":
|
|
11745
11760
|
state = {
|
|
11746
11761
|
...state,
|
|
@@ -11808,6 +11823,7 @@ var createVoiceStreamStore = () => {
|
|
|
11808
11823
|
case "replay":
|
|
11809
11824
|
state = {
|
|
11810
11825
|
...state,
|
|
11826
|
+
assistantStreamingText: "",
|
|
11811
11827
|
assistantTexts: [...action.assistantTexts],
|
|
11812
11828
|
call: action.call ?? null,
|
|
11813
11829
|
error: null,
|
|
@@ -11919,6 +11935,9 @@ var createVoiceStream = (path, options = {}) => {
|
|
|
11919
11935
|
get assistantTexts() {
|
|
11920
11936
|
return store.getSnapshot().assistantTexts;
|
|
11921
11937
|
},
|
|
11938
|
+
get assistantStreamingText() {
|
|
11939
|
+
return store.getSnapshot().assistantStreamingText;
|
|
11940
|
+
},
|
|
11922
11941
|
get call() {
|
|
11923
11942
|
return store.getSnapshot().call;
|
|
11924
11943
|
},
|
|
@@ -12482,6 +12501,7 @@ var resolveVoiceRuntimePreset = (name = "default") => {
|
|
|
12482
12501
|
// src/client/controller.ts
|
|
12483
12502
|
var createInitialState2 = (stream) => ({
|
|
12484
12503
|
assistantAudio: [...stream.assistantAudio],
|
|
12504
|
+
assistantStreamingText: stream.assistantStreamingText,
|
|
12485
12505
|
assistantTexts: [...stream.assistantTexts],
|
|
12486
12506
|
call: stream.call,
|
|
12487
12507
|
error: stream.error,
|
|
@@ -12514,6 +12534,7 @@ var createVoiceController = (path, options = {}) => {
|
|
|
12514
12534
|
state = {
|
|
12515
12535
|
...state,
|
|
12516
12536
|
assistantAudio: [...stream.assistantAudio],
|
|
12537
|
+
assistantStreamingText: stream.assistantStreamingText,
|
|
12517
12538
|
assistantTexts: [...stream.assistantTexts],
|
|
12518
12539
|
call: stream.call,
|
|
12519
12540
|
error: stream.error,
|
|
@@ -12607,6 +12628,9 @@ var createVoiceController = (path, options = {}) => {
|
|
|
12607
12628
|
get assistantTexts() {
|
|
12608
12629
|
return state.assistantTexts;
|
|
12609
12630
|
},
|
|
12631
|
+
get assistantStreamingText() {
|
|
12632
|
+
return state.assistantStreamingText;
|
|
12633
|
+
},
|
|
12610
12634
|
bindHTMX(bindingOptions) {
|
|
12611
12635
|
return bindVoiceHTMX(stream, bindingOptions);
|
|
12612
12636
|
},
|
|
@@ -18,6 +18,7 @@ export declare const useVoiceController: <TResult = unknown>(path: string, optio
|
|
|
18
18
|
partial: string;
|
|
19
19
|
turns: import("..").VoiceTurnRecord<TResult>[];
|
|
20
20
|
assistantTexts: string[];
|
|
21
|
+
assistantStreamingText: string;
|
|
21
22
|
assistantAudio: Array<{
|
|
22
23
|
chunk: Uint8Array;
|
|
23
24
|
format: import("..").AudioFormat;
|
|
@@ -14,6 +14,7 @@ export declare const useVoiceStream: <TResult = unknown>(path: string, options?:
|
|
|
14
14
|
partial: string;
|
|
15
15
|
turns: import("..").VoiceTurnRecord<TResult>[];
|
|
16
16
|
assistantTexts: string[];
|
|
17
|
+
assistantStreamingText: string;
|
|
17
18
|
assistantAudio: Array<{
|
|
18
19
|
chunk: Uint8Array;
|
|
19
20
|
format: import("..").AudioFormat;
|
package/dist/svelte/index.js
CHANGED
|
@@ -598,8 +598,15 @@ var serverMessageToAction = (message) => {
|
|
|
598
598
|
case "assistant":
|
|
599
599
|
return {
|
|
600
600
|
text: message.text,
|
|
601
|
+
turnId: message.turnId,
|
|
601
602
|
type: "assistant"
|
|
602
603
|
};
|
|
604
|
+
case "assistant_delta":
|
|
605
|
+
return {
|
|
606
|
+
delta: message.delta,
|
|
607
|
+
turnId: message.turnId,
|
|
608
|
+
type: "assistant_delta"
|
|
609
|
+
};
|
|
603
610
|
case "complete":
|
|
604
611
|
return {
|
|
605
612
|
sessionId: message.sessionId,
|
|
@@ -1018,6 +1025,7 @@ var createInitialReconnectState = () => ({
|
|
|
1018
1025
|
});
|
|
1019
1026
|
var createInitialState = () => ({
|
|
1020
1027
|
assistantAudio: [],
|
|
1028
|
+
assistantStreamingText: "",
|
|
1021
1029
|
assistantTexts: [],
|
|
1022
1030
|
call: null,
|
|
1023
1031
|
error: null,
|
|
@@ -1055,9 +1063,16 @@ var createVoiceStreamStore = () => {
|
|
|
1055
1063
|
case "assistant":
|
|
1056
1064
|
state = {
|
|
1057
1065
|
...state,
|
|
1066
|
+
assistantStreamingText: "",
|
|
1058
1067
|
assistantTexts: [...state.assistantTexts, action.text]
|
|
1059
1068
|
};
|
|
1060
1069
|
break;
|
|
1070
|
+
case "assistant_delta":
|
|
1071
|
+
state = {
|
|
1072
|
+
...state,
|
|
1073
|
+
assistantStreamingText: `${state.assistantStreamingText}${action.delta}`
|
|
1074
|
+
};
|
|
1075
|
+
break;
|
|
1061
1076
|
case "complete":
|
|
1062
1077
|
state = {
|
|
1063
1078
|
...state,
|
|
@@ -1125,6 +1140,7 @@ var createVoiceStreamStore = () => {
|
|
|
1125
1140
|
case "replay":
|
|
1126
1141
|
state = {
|
|
1127
1142
|
...state,
|
|
1143
|
+
assistantStreamingText: "",
|
|
1128
1144
|
assistantTexts: [...action.assistantTexts],
|
|
1129
1145
|
call: action.call ?? null,
|
|
1130
1146
|
error: null,
|
|
@@ -1236,6 +1252,9 @@ var createVoiceStream = (path, options = {}) => {
|
|
|
1236
1252
|
get assistantTexts() {
|
|
1237
1253
|
return store.getSnapshot().assistantTexts;
|
|
1238
1254
|
},
|
|
1255
|
+
get assistantStreamingText() {
|
|
1256
|
+
return store.getSnapshot().assistantStreamingText;
|
|
1257
|
+
},
|
|
1239
1258
|
get call() {
|
|
1240
1259
|
return store.getSnapshot().call;
|
|
1241
1260
|
},
|
|
@@ -1619,6 +1638,7 @@ var resolveVoiceRuntimePreset = (name = "default") => {
|
|
|
1619
1638
|
// src/client/controller.ts
|
|
1620
1639
|
var createInitialState2 = (stream) => ({
|
|
1621
1640
|
assistantAudio: [...stream.assistantAudio],
|
|
1641
|
+
assistantStreamingText: stream.assistantStreamingText,
|
|
1622
1642
|
assistantTexts: [...stream.assistantTexts],
|
|
1623
1643
|
call: stream.call,
|
|
1624
1644
|
error: stream.error,
|
|
@@ -1651,6 +1671,7 @@ var createVoiceController = (path, options = {}) => {
|
|
|
1651
1671
|
state = {
|
|
1652
1672
|
...state,
|
|
1653
1673
|
assistantAudio: [...stream.assistantAudio],
|
|
1674
|
+
assistantStreamingText: stream.assistantStreamingText,
|
|
1654
1675
|
assistantTexts: [...stream.assistantTexts],
|
|
1655
1676
|
call: stream.call,
|
|
1656
1677
|
error: stream.error,
|
|
@@ -1744,6 +1765,9 @@ var createVoiceController = (path, options = {}) => {
|
|
|
1744
1765
|
get assistantTexts() {
|
|
1745
1766
|
return state.assistantTexts;
|
|
1746
1767
|
},
|
|
1768
|
+
get assistantStreamingText() {
|
|
1769
|
+
return state.assistantStreamingText;
|
|
1770
|
+
},
|
|
1747
1771
|
bindHTMX(bindingOptions) {
|
|
1748
1772
|
return bindVoiceHTMX(stream, bindingOptions);
|
|
1749
1773
|
},
|
package/dist/testing/index.js
CHANGED
|
@@ -1579,6 +1579,7 @@ var buildSessionCorrectionAudit = (raw, generic, experimental, benchmarkSeeded,
|
|
|
1579
1579
|
};
|
|
1580
1580
|
// src/client/audioPlayer.ts
|
|
1581
1581
|
var DEFAULT_LOOKAHEAD_MS = 15;
|
|
1582
|
+
var DEFAULT_VOLUME = 1;
|
|
1582
1583
|
var createInitialState = () => ({
|
|
1583
1584
|
activeSourceCount: 0,
|
|
1584
1585
|
error: null,
|
|
@@ -1595,6 +1596,12 @@ var getAudioContextCtor = () => {
|
|
|
1595
1596
|
}
|
|
1596
1597
|
return window.AudioContext ?? window.webkitAudioContext;
|
|
1597
1598
|
};
|
|
1599
|
+
var clampVolume = (volume) => {
|
|
1600
|
+
if (typeof volume !== "number" || !Number.isFinite(volume)) {
|
|
1601
|
+
return DEFAULT_VOLUME;
|
|
1602
|
+
}
|
|
1603
|
+
return Math.min(1, Math.max(0, volume));
|
|
1604
|
+
};
|
|
1598
1605
|
var decodePCM16LEChunk = (audioContext, chunk) => {
|
|
1599
1606
|
const { format } = chunk;
|
|
1600
1607
|
if (format.container !== "raw" || format.encoding !== "pcm_s16le") {
|
|
@@ -1627,6 +1634,7 @@ var createVoiceAudioPlayer = (source, options = {}) => {
|
|
|
1627
1634
|
let state = createInitialState();
|
|
1628
1635
|
let audioContext = null;
|
|
1629
1636
|
let outputNode = null;
|
|
1637
|
+
let volume = clampVolume(options.volume);
|
|
1630
1638
|
let queueEndTime = 0;
|
|
1631
1639
|
let syncPromise = Promise.resolve();
|
|
1632
1640
|
let interruptStartedAt = null;
|
|
@@ -1675,11 +1683,11 @@ var createVoiceAudioPlayer = (source, options = {}) => {
|
|
|
1675
1683
|
}
|
|
1676
1684
|
return Math.max(0, ((context.baseLatency ?? 0) + (context.outputLatency ?? 0)) * 1000);
|
|
1677
1685
|
};
|
|
1678
|
-
const
|
|
1686
|
+
const applyOutputGain = (context) => {
|
|
1679
1687
|
if (!outputNode) {
|
|
1680
1688
|
return;
|
|
1681
1689
|
}
|
|
1682
|
-
const gainValue =
|
|
1690
|
+
const gainValue = volume;
|
|
1683
1691
|
if (outputNode.gain.setValueAtTime) {
|
|
1684
1692
|
outputNode.gain.setValueAtTime(gainValue, context?.currentTime ?? 0);
|
|
1685
1693
|
return;
|
|
@@ -1890,11 +1898,15 @@ var createVoiceAudioPlayer = (source, options = {}) => {
|
|
|
1890
1898
|
get queuedChunkCount() {
|
|
1891
1899
|
return state.queuedChunkCount;
|
|
1892
1900
|
},
|
|
1901
|
+
setVolume: (nextVolume) => {
|
|
1902
|
+
volume = clampVolume(nextVolume);
|
|
1903
|
+
applyOutputGain(audioContext);
|
|
1904
|
+
},
|
|
1893
1905
|
start: async () => {
|
|
1894
1906
|
try {
|
|
1895
1907
|
clearError();
|
|
1896
1908
|
const context = await ensureAudioContext();
|
|
1897
|
-
|
|
1909
|
+
applyOutputGain(context);
|
|
1898
1910
|
if (context.state === "suspended") {
|
|
1899
1911
|
await context.resume();
|
|
1900
1912
|
}
|
|
@@ -1918,6 +1930,9 @@ var createVoiceAudioPlayer = (source, options = {}) => {
|
|
|
1918
1930
|
return () => {
|
|
1919
1931
|
subscribers.delete(subscriber);
|
|
1920
1932
|
};
|
|
1933
|
+
},
|
|
1934
|
+
get volume() {
|
|
1935
|
+
return volume;
|
|
1921
1936
|
}
|
|
1922
1937
|
};
|
|
1923
1938
|
return player;
|
|
@@ -2107,8 +2122,15 @@ var serverMessageToAction = (message) => {
|
|
|
2107
2122
|
case "assistant":
|
|
2108
2123
|
return {
|
|
2109
2124
|
text: message.text,
|
|
2125
|
+
turnId: message.turnId,
|
|
2110
2126
|
type: "assistant"
|
|
2111
2127
|
};
|
|
2128
|
+
case "assistant_delta":
|
|
2129
|
+
return {
|
|
2130
|
+
delta: message.delta,
|
|
2131
|
+
turnId: message.turnId,
|
|
2132
|
+
type: "assistant_delta"
|
|
2133
|
+
};
|
|
2112
2134
|
case "complete":
|
|
2113
2135
|
return {
|
|
2114
2136
|
sessionId: message.sessionId,
|
|
@@ -2527,6 +2549,7 @@ var createInitialReconnectState = () => ({
|
|
|
2527
2549
|
});
|
|
2528
2550
|
var createInitialState2 = () => ({
|
|
2529
2551
|
assistantAudio: [],
|
|
2552
|
+
assistantStreamingText: "",
|
|
2530
2553
|
assistantTexts: [],
|
|
2531
2554
|
call: null,
|
|
2532
2555
|
error: null,
|
|
@@ -2564,9 +2587,16 @@ var createVoiceStreamStore = () => {
|
|
|
2564
2587
|
case "assistant":
|
|
2565
2588
|
state = {
|
|
2566
2589
|
...state,
|
|
2590
|
+
assistantStreamingText: "",
|
|
2567
2591
|
assistantTexts: [...state.assistantTexts, action.text]
|
|
2568
2592
|
};
|
|
2569
2593
|
break;
|
|
2594
|
+
case "assistant_delta":
|
|
2595
|
+
state = {
|
|
2596
|
+
...state,
|
|
2597
|
+
assistantStreamingText: `${state.assistantStreamingText}${action.delta}`
|
|
2598
|
+
};
|
|
2599
|
+
break;
|
|
2570
2600
|
case "complete":
|
|
2571
2601
|
state = {
|
|
2572
2602
|
...state,
|
|
@@ -2634,6 +2664,7 @@ var createVoiceStreamStore = () => {
|
|
|
2634
2664
|
case "replay":
|
|
2635
2665
|
state = {
|
|
2636
2666
|
...state,
|
|
2667
|
+
assistantStreamingText: "",
|
|
2637
2668
|
assistantTexts: [...action.assistantTexts],
|
|
2638
2669
|
call: action.call ?? null,
|
|
2639
2670
|
error: null,
|
|
@@ -2745,6 +2776,9 @@ var createVoiceStream = (path, options = {}) => {
|
|
|
2745
2776
|
get assistantTexts() {
|
|
2746
2777
|
return store.getSnapshot().assistantTexts;
|
|
2747
2778
|
},
|
|
2779
|
+
get assistantStreamingText() {
|
|
2780
|
+
return store.getSnapshot().assistantStreamingText;
|
|
2781
|
+
},
|
|
2748
2782
|
get call() {
|
|
2749
2783
|
return store.getSnapshot().call;
|
|
2750
2784
|
},
|
|
@@ -3128,6 +3162,7 @@ var resolveVoiceRuntimePreset = (name = "default") => {
|
|
|
3128
3162
|
// src/client/controller.ts
|
|
3129
3163
|
var createInitialState3 = (stream) => ({
|
|
3130
3164
|
assistantAudio: [...stream.assistantAudio],
|
|
3165
|
+
assistantStreamingText: stream.assistantStreamingText,
|
|
3131
3166
|
assistantTexts: [...stream.assistantTexts],
|
|
3132
3167
|
call: stream.call,
|
|
3133
3168
|
error: stream.error,
|
|
@@ -3160,6 +3195,7 @@ var createVoiceController = (path, options = {}) => {
|
|
|
3160
3195
|
state = {
|
|
3161
3196
|
...state,
|
|
3162
3197
|
assistantAudio: [...stream.assistantAudio],
|
|
3198
|
+
assistantStreamingText: stream.assistantStreamingText,
|
|
3163
3199
|
assistantTexts: [...stream.assistantTexts],
|
|
3164
3200
|
call: stream.call,
|
|
3165
3201
|
error: stream.error,
|
|
@@ -3253,6 +3289,9 @@ var createVoiceController = (path, options = {}) => {
|
|
|
3253
3289
|
get assistantTexts() {
|
|
3254
3290
|
return state.assistantTexts;
|
|
3255
3291
|
},
|
|
3292
|
+
get assistantStreamingText() {
|
|
3293
|
+
return state.assistantStreamingText;
|
|
3294
|
+
},
|
|
3256
3295
|
bindHTMX(bindingOptions) {
|
|
3257
3296
|
return bindVoiceHTMX(stream, bindingOptions);
|
|
3258
3297
|
},
|
|
@@ -7161,6 +7200,7 @@ var createVoiceSession = (options) => {
|
|
|
7161
7200
|
return;
|
|
7162
7201
|
streamed = true;
|
|
7163
7202
|
full += delta;
|
|
7203
|
+
send({ delta, turnId: turn.id, type: "assistant_delta" });
|
|
7164
7204
|
buffer += delta;
|
|
7165
7205
|
let boundary = nextSpeakableBoundary(buffer);
|
|
7166
7206
|
while (boundary !== -1) {
|