@absolutejs/voice 0.0.22-beta.461 → 0.0.22-beta.464

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/index.js CHANGED
@@ -5186,7 +5186,7 @@ var createVoiceSession = (options) => {
5186
5186
  };
5187
5187
 
5188
5188
  // src/generated/htmxBootstrapBundle.ts
5189
- var HTMX_BOOTSTRAP_BUNDLE = 'var Ue=(e)=>{if(typeof e!=="string")return e;return document.querySelector(e)},Ne=(e,n,t,o)=>{let r=n??e.getAttribute("hx-get")??"";if(!r)return"";let i=new URL(r,window.location.origin);if(o)i.searchParams.set(t,o);else i.searchParams.delete(t);return`${i.pathname}${i.search}${i.hash}`},de=(e,n)=>{if(typeof window>"u"||typeof document>"u")return()=>{};let t=Ue(n.element);if(!t)return()=>{};let o=n.eventName??"voice-refresh",r=n.sessionQueryParam??"sessionId",i=()=>{let l=window,g=Ne(t,n.route,r,e.sessionId);if(g)t.setAttribute("hx-get",g);l.htmx?.process?.(t),l.htmx?.trigger?.(t,o)},c=e.subscribe(i);return i(),()=>{c()}};var He=(e)=>Math.max(-1,Math.min(1,e)),Ge=(e)=>{let n=new Int16Array(e.length);for(let t=0;t<e.length;t+=1){let o=He(e[t]??0);n[t]=o<0?o*32768:o*32767}return new Uint8Array(n.buffer)},Be=(e)=>{let n=e instanceof Uint8Array?e:new Uint8Array(e);if(n.byteLength<2)return 0;let t=new Int16Array(n.buffer,n.byteOffset,Math.floor(n.byteLength/2));if(t.length===0)return 0;let o=0;for(let r of t){let i=r/32768;o+=i*i}return Math.min(1,Math.max(0,Math.sqrt(o/t.length)*5.5))},We=(e,n,t)=>{if(n===t)return e;let o=n/t,r=Math.round(e.length/o),i=new Float32Array(r),c=0,l=0;while(c<i.length){let g=Math.round((c+1)*o),y=0,d=0;for(let h=l;h<g&&h<e.length;h+=1)y+=e[h]??0,d+=1;i[c]=d>0?y/d:0,c+=1,l=g}return i},ge=(e)=>{let n=null,t=null,o=null,r=null;return{start:async()=>{if(typeof navigator>"u"||!navigator.mediaDevices?.getUserMedia)throw Error("Browser microphone capture requires navigator.mediaDevices.getUserMedia.");let l=(typeof window<"u"?window.AudioContext??window.webkitAudioContext:void 0)??AudioContext;if(!l)throw Error("Browser microphone capture requires AudioContext support.");r=await navigator.mediaDevices.getUserMedia({audio:{channelCount:e.channelCount??1}}),n=new l,t=n.createMediaStreamSource(r),o=n.createScriptProcessor(4096,1,1),o.onaudioprocess=(g)=>{let y=g.inputBuffer.getChannelData(0),d=We(y,n?.sampleRate??48000,e.sampleRateHz??16000),h=Ge(d);e.onLevel?.(Be(h)),e.onAudio(h)},t.connect(o),o.connect(n.destination)},stop:()=>{o?.disconnect(),t?.disconnect(),r?.getTracks().forEach((l)=>l.stop()),n?.close(),e.onLevel?.(0),n=null,r=null,o=null,t=null}}};var ee=(e)=>{if(typeof e==="string"&&e.trim())return e;if(e instanceof Error&&e.message.trim())return e.message;if(e&&typeof e==="object"){let n=e;for(let t of["message","reason","description"]){let o=n[t];if(typeof o==="string"&&o.trim())return o}if("error"in n)return ee(n.error);if("cause"in n)return ee(n.cause);try{return JSON.stringify(e)}catch{}}return"Unexpected error"},Ae=(e)=>{switch(e.type){case"audio":return{chunk:Uint8Array.from(atob(e.chunkBase64),(n)=>n.charCodeAt(0)),format:e.format,receivedAt:e.receivedAt,turnId:e.turnId,type:"audio"};case"assistant":return{text:e.text,type:"assistant"};case"complete":return{sessionId:e.sessionId,type:"complete"};case"connection":return{reconnect:e.reconnect,type:"connection"};case"call_lifecycle":return{event:e.event,sessionId:e.sessionId,type:"call_lifecycle"};case"error":return{message:ee(e.message),type:"error"};case"final":return{transcript:e.transcript,type:"final"};case"partial":return{transcript:e.transcript,type:"partial"};case"replay":return{assistantTexts:e.assistantTexts,call:e.call,partial:e.partial,scenarioId:e.scenarioId,sessionId:e.sessionId,sessionMetadata:e.sessionMetadata,status:e.status,turns:e.turns,type:"replay"};case"session":return{sessionId:e.sessionId,sessionMetadata:e.sessionMetadata,scenarioId:e.scenarioId,status:e.status,type:"session"};case"turn":return{turn:e.turn,type:"turn"};default:return null}};var H=(e,n,t,o)=>{e.push({code:t,message:o,severity:n})};var $e=(e)=>e.length===0?void 0:e.reduce((n,t)=>n+t,0)/e.length,K=(e)=>e.length===0?void 0:Math.max(...e);var b=(e,n)=>{let t=e[n];return typeof t==="number"&&Number.isFinite(t)?t:void 0},Z=(e,n)=>{let t=e[n];return typeof t==="boolean"?t:void 0},D=(e,n)=>{let t=e[n];return typeof t==="string"?t:void 0},ne=(e)=>String(e.id??D(e,"ssrc")??b(e,"ssrc")??D(e,"trackIdentifier")??D(e,"mid")??"unknown"),he=(e)=>e===void 0?void 0:e*1000;var ke=(e)=>{let n={};for(let[t,o]of Object.entries(e))if(o===null||typeof o==="boolean"||typeof o==="number"||typeof o==="string")n[t]=o;return n};var ye=(e={})=>{let n=e.stats??[],t=[],o=n.filter((s)=>s.type==="inbound-rtp"&&D(s,"kind")!=="video"),r=n.filter((s)=>s.type==="outbound-rtp"&&D(s,"kind")!=="video"),i=n.filter((s)=>s.type==="candidate-pair"),c=n.filter((s)=>(s.type==="track"||s.type==="media-source")&&D(s,"kind")==="audio"),l=i.filter((s)=>Z(s,"selected")===!0||Z(s,"nominated")===!0||D(s,"state")==="succeeded").length,g=c.filter((s)=>D(s,"readyState")!=="ended"&&D(s,"trackState")!=="ended"&&Z(s,"ended")!==!0).length,y=c.filter((s)=>D(s,"readyState")==="ended"||D(s,"trackState")==="ended"||Z(s,"ended")===!0).length,d=o.reduce((s,S)=>s+(b(S,"packetsReceived")??0),0),h=r.reduce((s,S)=>s+(b(S,"packetsSent")??0),0),a=[...o,...r].reduce((s,S)=>s+Math.max(0,b(S,"packetsLost")??0),0),M=d+a,C=M===0?0:a/M,I=o.reduce((s,S)=>s+(b(S,"bytesReceived")??0),0),w=r.reduce((s,S)=>s+(b(S,"bytesSent")??0),0),R=K(i.map((s)=>he(b(s,"currentRoundTripTime")??b(s,"roundTripTime"))).filter((s)=>s!==void 0)),u=K([...o,...r].map((s)=>he(b(s,"jitter"))).filter((s)=>s!==void 0)),O=K(o.map((s)=>{let S=b(s,"jitterBufferDelay"),L=b(s,"jitterBufferEmittedCount");return S!==void 0&&L!==void 0&&L>0?S/L*1000:void 0}).filter((s)=>s!==void 0)),U=c.map((s)=>b(s,"audioLevel")).filter((s)=>s!==void 0);if(e.requireConnectedCandidatePair&&i.length>0&&l===0)H(t,"error","media.webrtc_candidate_pair_missing","No active WebRTC candidate pair was observed.");if(e.requireLiveAudioTrack&&g===0)H(t,"error","media.webrtc_audio_track_missing","No live WebRTC audio track was observed.");if(e.maxPacketLossRatio!==void 0&&C>e.maxPacketLossRatio)H(t,"warning","media.webrtc_packet_loss",`Observed WebRTC packet loss ratio ${String(C)} above ${String(e.maxPacketLossRatio)}.`);if(e.maxRoundTripTimeMs!==void 0&&R!==void 0&&R>e.maxRoundTripTimeMs)H(t,"warning","media.webrtc_round_trip_time",`Observed WebRTC RTT ${String(R)}ms above ${String(e.maxRoundTripTimeMs)}ms.`);if(e.maxJitterMs!==void 0&&u!==void 0&&u>e.maxJitterMs)H(t,"warning","media.webrtc_jitter",`Observed WebRTC jitter ${String(u)}ms above ${String(e.maxJitterMs)}ms.`);return{activeCandidatePairs:l,audioLevelAverage:$e(U),bytesReceived:I,bytesSent:w,checkedAt:Date.now(),endedAudioTracks:y,inboundPackets:d,issues:t,jitterBufferDelayMs:O,jitterMs:u,liveAudioTracks:g,outboundPackets:h,packetLossRatio:C,packetsLost:a,roundTripTimeMs:R,status:t.some((s)=>s.severity==="error")?"fail":t.length>0?"warn":"pass",totalStats:n.length}},Ce=async(e)=>{return[...(await e.peerConnection.getStats(e.selector??null)).values()].map(ke)};var fe=(e={})=>{let n=e.stats??[],t=e.previousStats??[],o=[],r=new Map(t.map((a)=>[ne(a),a])),c=n.filter((a)=>(a.type==="inbound-rtp"||a.type==="outbound-rtp")&&D(a,"kind")!=="video"&&D(a,"mediaType")!=="video").map((a)=>{let M=a.type==="outbound-rtp"?"outbound":"inbound",C=M==="outbound"?"packetsSent":"packetsReceived",I=M==="outbound"?"bytesSent":"bytesReceived",w=r.get(ne(a)),R=b(a,C),u=w?b(w,C):void 0,O=b(a,I),U=w?b(w,I):void 0,s=a.timestamp!==void 0&&w?.timestamp!==void 0?a.timestamp-w.timestamp:void 0;return{bytesDelta:O!==void 0&&U!==void 0?O-U:void 0,currentPackets:R,direction:M,id:ne(a),packetDelta:R!==void 0&&u!==void 0?R-u:void 0,previousPackets:u,timeDeltaMs:s}}),l=c.filter((a)=>a.direction==="inbound"),g=c.filter((a)=>a.direction==="outbound"),y=K(c.map((a)=>a.timeDeltaMs).filter((a)=>a!==void 0)),d=l.filter((a)=>e.maxInboundPacketStallMs!==void 0&&a.timeDeltaMs!==void 0&&a.timeDeltaMs>=e.maxInboundPacketStallMs&&a.packetDelta!==void 0&&a.packetDelta<=0).length,h=g.filter((a)=>e.maxOutboundPacketStallMs!==void 0&&a.timeDeltaMs!==void 0&&a.timeDeltaMs>=e.maxOutboundPacketStallMs&&a.packetDelta!==void 0&&a.packetDelta<=0).length;if(e.requireInboundAudio&&l.length===0)H(o,"error","media.webrtc_inbound_audio_missing","No inbound WebRTC audio RTP stream was observed.");if(e.requireOutboundAudio&&g.length===0)H(o,"error","media.webrtc_outbound_audio_missing","No outbound WebRTC audio RTP stream was observed.");if(e.maxGapMs!==void 0&&y!==void 0&&y>e.maxGapMs)H(o,"warning","media.webrtc_stream_gap",`Observed WebRTC stream sample gap ${String(y)}ms above ${String(e.maxGapMs)}ms.`);if(d>0)H(o,"error","media.webrtc_inbound_stalled",`${String(d)} inbound WebRTC audio stream(s) stopped receiving packets.`);if(h>0)H(o,"error","media.webrtc_outbound_stalled",`${String(h)} outbound WebRTC audio stream(s) stopped sending packets.`);return{checkedAt:Date.now(),inboundAudioStreams:l.length,issues:o,maxObservedGapMs:y,outboundAudioStreams:g.length,stalledInboundStreams:d,stalledOutboundStreams:h,status:o.some((a)=>a.severity==="error")?"fail":o.length>0?"warn":"pass",streams:c,totalStats:n.length}};var qe="/api/voice/browser-media",Xe=5000,ze=async(e)=>e.peerConnection??await e.getPeerConnection?.()??null,Ye=async(e,n)=>{let t=n.fetch??globalThis.fetch;if(!t)return;await t(n.path??qe,{body:JSON.stringify(e),headers:{"Content-Type":"application/json"},keepalive:!0,method:"POST"})},Te=(e)=>{let n=null,t=[],o=async()=>{let c=await ze(e);if(!c)return;let l=await Ce({peerConnection:c}),g=ye({...e,stats:l}),y=e.continuity===!1?void 0:fe({...e.continuity,previousStats:t,stats:l}),d={at:Date.now(),continuity:y,report:g,scenarioId:e.getScenarioId?.()??null,sessionId:e.getSessionId?.()??null};return t=l,e.onReport?.(d),await Ye(d,e),d},r=()=>{o().catch((c)=>{e.onError?.(c)})},i=()=>{if(n)clearInterval(n),n=null};return{close:i,reportOnce:o,start:()=>{if(n)return;r(),n=setInterval(r,e.intervalMs??Xe)},stop:i}};var B=()=>{},Je=()=>B,Qe={callControl:B,close:B,endTurn:B,getReadyState:()=>3,getScenarioId:()=>"",getSessionId:()=>"",send:B,sendAudio:B,simulateDisconnect:B,start:()=>{},subscribe:Je},Ze=()=>crypto.randomUUID(),Ke=(e,n,t)=>{let{hostname:o,port:r,protocol:i}=window.location,c=i==="https:"?"wss:":"ws:",l=r?`:${r}`:"",g=new URL(`${c}//${o}${l}${e}`);if(g.searchParams.set("sessionId",n),t)g.searchParams.set("scenarioId",t);return g.toString()},me=(e)=>{if(!e||typeof e!=="object"||!("type"in e))return!1;switch(e.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}},je=(e)=>{if(typeof e.data!=="string")return null;try{let n=JSON.parse(e.data);return me(n)?n:null}catch{return null}},Se=(e,n={})=>{if(typeof window>"u")return Qe;let t=new Set,o=n.reconnect!==!1,r=n.maxReconnectAttempts??10,i=n.pingInterval??30000,c={isConnected:!1,pendingMessages:[],scenarioId:n.scenarioId??null,pingInterval:null,reconnectAttempts:0,reconnectTimeout:null,sessionId:n.sessionId??Ze(),ws:null},l=(s)=>{t.forEach((S)=>S(s))},g=()=>{if(c.pingInterval)clearInterval(c.pingInterval),c.pingInterval=null;if(c.reconnectTimeout)clearTimeout(c.reconnectTimeout),c.reconnectTimeout=null},y=()=>{if(c.ws?.readyState!==1)return;while(c.pendingMessages.length>0){let s=c.pendingMessages.shift();if(s!==void 0)c.ws.send(s)}},d=()=>{let s=Date.now()+500;c.reconnectAttempts+=1,l({reconnect:{attempts:c.reconnectAttempts,lastDisconnectAt:Date.now(),maxAttempts:r,nextAttemptAt:s,status:"reconnecting"},type:"connection"}),c.reconnectTimeout=setTimeout(()=>{if(c.reconnectAttempts>r){l({reconnect:{attempts:c.reconnectAttempts,maxAttempts:r,status:"exhausted"},type:"connection"});return}h()},500)},h=()=>{let s=new WebSocket(Ke(e,c.sessionId,c.scenarioId));s.binaryType="arraybuffer",s.onopen=()=>{let S=c.reconnectAttempts>0;if(c.isConnected=!0,y(),S)l({reconnect:{attempts:c.reconnectAttempts,lastResumedAt:Date.now(),maxAttempts:r,status:"resumed"},type:"connection"}),c.reconnectAttempts=0;t.forEach((L)=>L({scenarioId:c.scenarioId??void 0,sessionId:c.sessionId,status:"active",type:"session"})),c.pingInterval=setInterval(()=>{if(s.readyState===1)s.send(JSON.stringify({type:"ping"}))},i)},s.onmessage=(S)=>{let L=je(S);if(!L)return;if(L.type==="session")c.sessionId=L.sessionId,c.scenarioId=L.scenarioId??c.scenarioId;t.forEach((X)=>X(L))},s.onclose=(S)=>{if(c.isConnected=!1,g(),o&&S.code!==1000&&c.reconnectAttempts<r)d();else if(o&&S.code!==1000)l({reconnect:{attempts:c.reconnectAttempts,lastDisconnectAt:Date.now(),maxAttempts:r,status:"exhausted"},type:"connection"})},c.ws=s},a=(s)=>{if(c.ws?.readyState===1){c.ws.send(s);return}c.pendingMessages.push(s)},M=(s)=>{a(JSON.stringify(s))},C=(s={})=>{if(s.sessionId)c.sessionId=s.sessionId;if(s.scenarioId)c.scenarioId=s.scenarioId;M({type:"start",sessionId:c.sessionId,scenarioId:c.scenarioId??void 0})},I=(s)=>{a(s)},w=()=>{M({type:"end_turn"})},R=(s)=>{M({...s,type:"call_control"})},u=()=>{if(g(),c.ws)c.ws.close(1000),c.ws=null;c.isConnected=!1,t.clear()},O=()=>{if(c.ws?.readyState===1)c.ws.close(4000,"absolutejs-voice-reconnect-proof")},U=(s)=>{return t.add(s),()=>{t.delete(s)}};return h(),{callControl:R,close:u,endTurn:w,getReadyState:()=>c.ws?.readyState??3,getScenarioId:()=>c.scenarioId??"",getSessionId:()=>c.sessionId,send:M,sendAudio:I,simulateDisconnect:O,start:C,subscribe:U}};var ve=()=>({attempts:0,maxAttempts:0,status:"idle"}),Fe=()=>({assistantAudio:[],assistantTexts:[],call:null,error:null,isConnected:!1,sessionMetadata:null,scenarioId:null,partial:"",reconnect:ve(),sessionId:null,status:"idle",turns:[]}),Me=()=>{let e=Fe(),n=new Set,t=()=>{n.forEach((r)=>r())};return{dispatch:(r)=>{switch(r.type){case"audio":e={...e,assistantAudio:[...e.assistantAudio,{chunk:r.chunk,format:r.format,receivedAt:r.receivedAt,turnId:r.turnId}]};break;case"assistant":e={...e,assistantTexts:[...e.assistantTexts,r.text]};break;case"complete":e={...e,sessionId:r.sessionId,status:"completed"};break;case"call_lifecycle":e={...e,call:{...e.call,disposition:r.event.type==="end"?r.event.disposition:e.call?.disposition,endedAt:r.event.type==="end"?r.event.at:e.call?.endedAt,events:[...e.call?.events??[],r.event],lastEventAt:r.event.at,startedAt:e.call?.startedAt??r.event.at},sessionId:r.sessionId};break;case"connected":e={...e,isConnected:!0,reconnect:e.reconnect.status==="reconnecting"?{...e.reconnect,lastResumedAt:Date.now(),nextAttemptAt:void 0,status:"resumed"}:e.reconnect};break;case"connection":e={...e,reconnect:r.reconnect};break;case"disconnected":e={...e,isConnected:!1};break;case"error":e={...e,error:r.message};break;case"final":e={...e,partial:r.transcript.text,turns:e.turns.map((i)=>i)};break;case"partial":e={...e,partial:r.transcript.text};break;case"replay":e={...e,assistantTexts:[...r.assistantTexts],call:r.call??null,error:null,isConnected:r.status==="active",partial:r.partial,reconnect:e.reconnect.status==="reconnecting"?{...e.reconnect,lastResumedAt:Date.now(),nextAttemptAt:void 0,status:"resumed"}:e.reconnect,scenarioId:r.scenarioId??e.scenarioId,sessionId:r.sessionId,sessionMetadata:r.sessionMetadata??e.sessionMetadata,status:r.status,turns:[...r.turns]};break;case"session":e={...e,error:null,scenarioId:r.scenarioId??e.scenarioId,isConnected:r.status==="active",sessionId:r.sessionId,sessionMetadata:r.sessionMetadata??e.sessionMetadata,status:r.status};break;case"turn":e={...e,partial:"",turns:[...e.turns,r.turn]};break}t()},getServerSnapshot:()=>e,getSnapshot:()=>e,subscribe:(r)=>{return n.add(r),()=>{n.delete(r)}}}};var Ie=(e,n={})=>{let t=Se(e,n),o=Me(),r=n.browserMedia&&typeof window<"u"?Te({...n.browserMedia,getScenarioId:()=>n.browserMedia?n.browserMedia.getScenarioId?.()??t.getScenarioId():t.getScenarioId(),getSessionId:()=>n.browserMedia?n.browserMedia.getSessionId?.()??t.getSessionId():t.getSessionId()}):null,i=new Set,c=(d)=>Promise.resolve().then(()=>{if(!d?.sessionId&&!d?.scenarioId)return;t.start(d),r?.start()}),l=()=>{i.forEach((d)=>d())},g=()=>{if(!n.reconnectReportPath||typeof fetch>"u")return;let d=o.getSnapshot(),h=JSON.stringify({at:Date.now(),reconnect:d.reconnect,scenarioId:d.scenarioId,sessionId:t.getSessionId(),turnIds:d.turns.map((a)=>a.id)});fetch(n.reconnectReportPath,{body:h,headers:{"Content-Type":"application/json"},keepalive:!0,method:"POST"}).catch(()=>{})},y=t.subscribe((d)=>{let h=Ae(d);if(h){if(o.dispatch(h),d.type==="connection")g();l()}});return{callControl(d){t.callControl(d)},close(){y(),r?.close(),t.close(),o.dispatch({type:"disconnected"}),l()},endTurn(){t.endTurn()},get error(){return o.getSnapshot().error},getServerSnapshot(){return o.getServerSnapshot()},getSnapshot(){return o.getSnapshot()},get isConnected(){return o.getSnapshot().isConnected},get scenarioId(){return o.getSnapshot().scenarioId},get sessionMetadata(){return o.getSnapshot().sessionMetadata},start:c,get partial(){return o.getSnapshot().partial},get reconnect(){return o.getSnapshot().reconnect},get sessionId(){return t.getSessionId()},get status(){return o.getSnapshot().status},get turns(){return o.getSnapshot().turns},get assistantTexts(){return o.getSnapshot().assistantTexts},get assistantAudio(){return o.getSnapshot().assistantAudio},get call(){return o.getSnapshot().call},sendAudio(d){t.sendAudio(d)},simulateDisconnect(){t.simulateDisconnect()},subscribe(d){return i.add(d),()=>{i.delete(d)}}}};var Ve=(e)=>{if(!e||e.enabled===!1)return;return{enabled:!0,maxGain:e.maxGain??3,noiseGateAttenuation:e.noiseGateAttenuation??0.15,noiseGateThreshold:e.noiseGateThreshold??0.006,targetLevel:e.targetLevel??0.08}};var pe={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}},en={general:{},"accent-heavy":{silenceMs:1200,speechThreshold:0.01,transcriptStabilityMs:1200},"noisy-room":{silenceMs:2000,speechThreshold:0.02,transcriptStabilityMs:1600},"short-command":{silenceMs:500,speechThreshold:0.016,transcriptStabilityMs:420}};var we=(e)=>{let n=e?.profile??"fast",t=e?.qualityProfile??"general",o=pe[n],r=en[t];return{profile:n,qualityProfile:t,silenceMs:e?.silenceMs??r.silenceMs??o.silenceMs,speechThreshold:e?.speechThreshold??r.speechThreshold??o.speechThreshold,transcriptStabilityMs:e?.transcriptStabilityMs??r.transcriptStabilityMs??o.transcriptStabilityMs}};var nn={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:{qualityProfile:"short-command",profile:"balanced"}},default:{capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:10,pingInterval:30000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{qualityProfile:"general",profile:"fast"}},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:{qualityProfile:"accent-heavy",profile:"long-form"}},"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:{qualityProfile:"accent-heavy",profile:"long-form"}},"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:{qualityProfile:"noisy-room",profile:"long-form",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:{qualityProfile:"noisy-room",profile:"long-form",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:{qualityProfile:"noisy-room",profile:"long-form",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:{qualityProfile:"noisy-room",profile:"long-form"}}},Le=(e="default")=>{let n=nn[e];return{audioConditioning:Ve(n.audioConditioning),capture:{channelCount:n.capture?.channelCount??1,sampleRateHz:n.capture?.sampleRateHz??16000},connection:{...n.connection},name:e,sttLifecycle:n.sttLifecycle??"continuous",turnDetection:we(n.turnDetection)}};var on=(e)=>({assistantAudio:[...e.assistantAudio],assistantTexts:[...e.assistantTexts],call:e.call,error:e.error,isConnected:e.isConnected,isRecording:!1,partial:e.partial,reconnect:e.reconnect,recordingError:null,sessionId:e.sessionId,sessionMetadata:e.sessionMetadata,scenarioId:e.scenarioId,status:e.status,turns:[...e.turns]}),m=(e,n={})=>{let t=Le(n.preset),o=Ie(e,{...t.connection,...n.connection}),r=null,i=on(o),c=new Set,l=()=>{for(let C of c)C()},g=()=>{if(i={...i,assistantAudio:[...o.assistantAudio],assistantTexts:[...o.assistantTexts],call:o.call,error:o.error,isConnected:o.isConnected,partial:o.partial,reconnect:o.reconnect,sessionId:o.sessionId,sessionMetadata:o.sessionMetadata,scenarioId:o.scenarioId,status:o.status,turns:[...o.turns]},n.autoStopOnComplete!==!1&&i.status==="completed"&&i.isRecording)r?.stop(),r=null,i={...i,isRecording:!1};l()},y=o.subscribe(g);g();let d=()=>{if(r)return r;return r=ge({channelCount:n.capture?.channelCount??t.capture.channelCount,onLevel:n.capture?.onLevel,onAudio:(C)=>{if(n.capture?.onAudio){n.capture.onAudio(C,o.sendAudio);return}o.sendAudio(C)},sampleRateHz:n.capture?.sampleRateHz??t.capture.sampleRateHz}),r},h=()=>{r?.stop(),r=null,i={...i,isRecording:!1},l()},a=async()=>{if(i.isRecording)return;try{i={...i,recordingError:null},l(),await d().start(),i={...i,isRecording:!0},l()}catch(C){throw r=null,i={...i,isRecording:!1,recordingError:C instanceof Error?C.message:String(C)},l(),C}};return{bindHTMX(C){return de(o,C)},callControl:(C)=>o.callControl(C),close:()=>{y(),h(),o.close()},endTurn:()=>o.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 recordingError(){return i.recordingError},get reconnect(){return i.reconnect},sendAudio:(C)=>o.sendAudio(C),simulateDisconnect:()=>o.simulateDisconnect(),get sessionId(){return i.sessionId},get sessionMetadata(){return i.sessionMetadata},get scenarioId(){return i.scenarioId},startRecording:a,get status(){return i.status},stopRecording:h,subscribe:(C)=>{return c.add(C),()=>{c.delete(C)}},toggleRecording:async()=>{if(i.isRecording){h();return}await a()},get turns(){return i.turns},get assistantTexts(){return i.assistantTexts},get assistantAudio(){return i.assistantAudio},get call(){return i.call}}};var tn=()=>({activeSourceCount:0,error:null,isActive:!1,isPlaying:!1,lastInterruptLatencyMs:void 0,lastPlaybackStopLatencyMs:void 0,processedChunkCount:0,queuedChunkCount:0}),cn=()=>{if(typeof window>"u")return typeof AudioContext>"u"?void 0:AudioContext;return window.AudioContext??window.webkitAudioContext},rn=(e,n)=>{let t=n.format;if(t.container!=="raw"||t.encoding!=="pcm_s16le")throw Error(`Unsupported assistant audio format: ${t.container}/${t.encoding}`);let o=n.chunk,r=Math.max(1,t.channels),i=Math.floor(o.byteLength/2),c=Math.max(1,Math.floor(i/r)),l=e.createBuffer(r,c,t.sampleRateHz),g=new DataView(o.buffer,o.byteOffset,o.byteLength);for(let y=0;y<r;y+=1){let d=l.getChannelData(y);for(let h=0;h<c;h+=1){let M=(h*r+y)*2;if(M+1>=o.byteLength){d[h]=0;continue}d[h]=g.getInt16(M,!0)/32768}}return l},j=(e,n={})=>{let t=new Set,o=new Set,r=(n.lookaheadMs??15)/1000,i=tn(),c=null,l=null,g=0,y=Promise.resolve(),d=null,h=null,a=null,M=null,C=()=>{for(let A of t)A()},I=(A)=>{i={...i,...A},C()},w=()=>{if(i.error!==null)I({error:null})},R=()=>{if(M!==null)clearTimeout(M),M=null},u=(A)=>{R(),d=null,I({activeSourceCount:o.size,isPlaying:!1,lastInterruptLatencyMs:A,lastPlaybackStopLatencyMs:i.lastPlaybackStopLatencyMs??A}),a?.(),a=null,h=null},O=(A)=>{if(!A)return 0;return Math.max(0,((A.baseLatency??0)+(A.outputLatency??0))*1000)},U=(A)=>{if(!l)return;let f=1;if(l.gain.setValueAtTime){l.gain.setValueAtTime(f,A?.currentTime??0);return}l.gain.value=f},s=(A)=>{if(!l)return;let f=0;if(l.gain.setValueAtTime){l.gain.setValueAtTime(f,A?.currentTime??0);return}l.gain.value=f},S=()=>{if(d===null||o.size>0)return;u(Date.now()-d)},L=async()=>{if(c)return c;if(n.createAudioContext)c=n.createAudioContext();else{let A=cn();if(!A)throw Error("Assistant audio playback requires AudioContext support.");c=new A}if(c.createGain)l=c.createGain(),l.connect?.(c.destination);return g=c.currentTime,c},X=async(A)=>{let f=await L(),E=rn(f,A),V=f.createBufferSource();V.buffer=E,V.connect(l??f.destination),V.onended=()=>{o.delete(V),V.disconnect?.(),I({activeSourceCount:o.size,isPlaying:o.size>0&&i.isActive}),S()};let Y=Math.max(f.currentTime+r,g);g=Y+E.duration,o.add(V),I({activeSourceCount:o.size,isPlaying:!0}),V.start(Y)},_=(A)=>{for(let f of[...o])f.stop?.();if(g=c?c.currentTime:0,A?.forceClear){for(let f of o)f.disconnect?.();o.clear(),S()}},W=async()=>{if(!i.isActive)return;let A=e.assistantAudio.slice(i.processedChunkCount);if(A.length===0)return;try{w();for(let f of A)await X(f);I({processedChunkCount:e.assistantAudio.length,queuedChunkCount:i.queuedChunkCount+A.length})}catch(f){I({error:f instanceof Error?f.message:String(f)})}},P=()=>{return y=y.then(()=>W(),()=>W()),y},$=e.subscribe(()=>{if(n.autoStart&&!i.isActive&&e.assistantAudio.length>0){N.start();return}if(i.isActive)P()}),N={close:async()=>{if($(),_({forceClear:!0}),R(),a?.(),a=null,h=null,d=null,c&&c.state!=="closed")await c.close();c=null,l?.disconnect?.(),l=null,g=0,I({activeSourceCount:0,isActive:!1,isPlaying:!1})},get activeSourceCount(){return i.activeSourceCount},get error(){return i.error},getSnapshot:()=>i,get isActive(){return i.isActive},get isPlaying(){return i.isPlaying},interrupt:async()=>{let A=Date.now(),f=await L();d=A,s(f);let E=Date.now()-A+O(f);if(I({isActive:!1,isPlaying:o.size>0,lastPlaybackStopLatencyMs:E}),o.size===0){u(E);return}if(!h)h=new Promise((V)=>{a=V});R(),M=setTimeout(()=>{for(let V of o)V.disconnect?.();o.clear(),u(Date.now()-A)},250),_(),await h},get lastInterruptLatencyMs(){return i.lastInterruptLatencyMs},get lastPlaybackStopLatencyMs(){return i.lastPlaybackStopLatencyMs},pause:async()=>{if(!c){I({activeSourceCount:0,isActive:!1,isPlaying:!1});return}await c.suspend(),I({activeSourceCount:o.size,isActive:!1,isPlaying:!1})},get processedChunkCount(){return i.processedChunkCount},get queuedChunkCount(){return i.queuedChunkCount},start:async()=>{try{w();let A=await L();if(U(A),A.state==="suspended")await A.resume();I({activeSourceCount:o.size,isActive:!0,isPlaying:A.state==="running"}),await P()}catch(A){throw I({error:A instanceof Error?A.message:String(A),isActive:!1,isPlaying:!1}),A}},subscribe:(A)=>{return t.add(A),()=>{t.delete(A)}}};return N};var sn=()=>`barge-in:${Date.now()}:${crypto.randomUUID?.()??Math.random().toString(36).slice(2)}`,ln=(e,n)=>{let t=e.filter((c)=>c.status==="stopped"),o=t.map((c)=>c.latencyMs).filter((c)=>typeof c==="number"),r=t.filter((c)=>typeof c.latencyMs==="number"&&c.latencyMs>n).length,i=t.length-r;return{averageLatencyMs:o.length>0?Math.round(o.reduce((c,l)=>c+l,0)/o.length):void 0,events:[...e],failed:r,lastEvent:e.at(-1),passed:i,status:e.length===0?"empty":r>0?"fail":t.length===0?"warn":"pass",thresholdMs:n,total:t.length}},ue=(e={})=>{let n=new Set,t=e.thresholdMs??250,o=e.fetch??globalThis.fetch,r=[],i=()=>{for(let g of n)g()},c=(g)=>{if(!e.path||typeof o!=="function")return;o(e.path,{body:JSON.stringify(g),headers:{"Content-Type":"application/json"},method:"POST"}).catch(()=>{})},l=(g,y)=>{let d={at:Date.now(),id:sn(),latencyMs:y.latencyMs,playbackStopLatencyMs:y.playbackStopLatencyMs,reason:y.reason,sessionId:y.sessionId,status:g,thresholdMs:t};return r.push(d),c(d),i(),d};return{getSnapshot:()=>ln(r,t),recordRequested:(g)=>l("requested",g),recordSkipped:(g)=>l("skipped",g),recordStopped:(g)=>l("stopped",g),subscribe:(g)=>{return n.add(g),()=>{n.delete(g)}}}};var an=0.08,dn=(e,n={})=>(n.enabled??!0)&&e>=(n.interruptThreshold??an),oe=(e,n,t={})=>{let o=e.partial,r=(c)=>{if(!n.isPlaying||t.enabled===!1){t.monitor?.recordSkipped({reason:c,sessionId:e.sessionId});return}t.monitor?.recordRequested({reason:c,sessionId:e.sessionId}),n.interrupt().then(()=>{t.monitor?.recordStopped({latencyMs:n.lastInterruptLatencyMs,playbackStopLatencyMs:n.lastPlaybackStopLatencyMs,reason:c,sessionId:e.sessionId})})},i=e.subscribe(()=>{if(t.interruptOnPartial===!1){o=e.partial;return}if(!o&&e.partial)r("partial-transcript");o=e.partial});return{close:()=>{i()},handleLevel:(c)=>{if(dn(c,t))r("input-level")},sendAudio:(c)=>{r("manual-audio"),e.sendAudio(c)}}};var se=48,gn=320,An=88,hn="Guided test",yn="General recording",Cn="Pick a scenario to begin the demo.",fn="I can walk you through a short guided voice test.",Tn="I can capture one freeform recording and confirm that it landed.",Sn="Choose a scenario to begin. Guided test asks follow-up prompts. General recording just captures what you say.",Mn="Click Start general recording to capture one freeform answer.",_e="Speak freely. When you pause, the recording will be captured.",re="Recording saved. Start again if you want another capture.",Ee="Guided test complete. Review the saved summary below.",Pe="All prompts are covered. You can stop the microphone or keep speaking for extra detail.",In="Ready. Start guided test or general recording to begin.",Vn="Live. Answer the prompt, then click Stop microphone when finished.",Re=["Start with a quick introduction about who you are.","Now describe what you are trying to do or test.","Finish with any detail that feels blocked, risky, or unclear."],De=(e,n,t)=>Math.min(t,Math.max(n,e)),q=(e)=>e.replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;").replaceAll(\'"\',"&quot;").replaceAll("\'","&#39;"),te=(e,n)=>{let t=e[n];if(typeof t==="string"&&t.trim())return t;return null},ie=(e)=>{if(typeof e==="string"&&e.trim())return e;if(e instanceof Error&&e.message.trim())return e.message;if(e&&typeof e==="object"){let n=e,t=te(n,"message")??te(n,"reason")??te(n,"description");if(t)return t;if("error"in n)return ie(n.error);if("cause"in n)return ie(n.cause);try{return JSON.stringify(e)}catch{}}return"Unexpected error"},wn=(e)=>{let n=[e.status];if(e.attempts>0||e.maxAttempts>0)n.push(`${e.attempts}/${e.maxAttempts} attempts`);if(e.nextAttemptAt){let t=Math.max(0,e.nextAttemptAt-Date.now());n.push(`retry in ${Math.ceil(t/100)/10}s`)}return n.join(" \xB7 ")},v=(e=se)=>Array.from({length:e},()=>0),be=(e,n,t=se)=>{let o=e.slice(-(t-1));o.push(De(n,0,1));while(o.length<t)o.unshift(0);return o},Ln=(e,n=gn,t=An)=>{let o=e.length>1?e:v(se),r=n/(o.length-1),i=t/2,c=t*0.34;if(Math.max(...o,0)<=0.015)return`M 0 ${i} L ${n} ${i}`;let g=o.map((d,h)=>{let a=h*0.76,M=Math.sin(a)*0.78+Math.sin(a*0.41)*0.22,C=d*c,I=r*h,w=De(i+M*C,8,t-8);return{x:I,y:w}});if(g.length===0)return`M 0 ${i} L ${n} ${i}`;let y=`M ${g[0]?.x??0} ${g[0]?.y??i}`;for(let d=1;d<g.length;d+=1){let h=g[d-1],a=g[d];if(!h||!a)continue;let M=(h.x+a.x)/2;y+=` Q ${M} ${h.y} ${a.x} ${a.y}`}return y},un=(e)=>{if(!e)return Re;try{let n=JSON.parse(e);if(Array.isArray(n)){let t=n.filter((o)=>typeof o==="string").map((o)=>o.trim()).filter(Boolean);if(t.length>0)return t}}catch{}return Re},ce=(e)=>{if(!e)return;let n=Number(e);return Number.isFinite(n)?n:void 0},Rn=(e,n,t)=>{if(!n)return null;let o=document.querySelector(n);return o instanceof t?o:null},x=(e,n,t,o)=>{let r=n?document.querySelector(n):null;if(r instanceof t)return r;let i=e.querySelector(`#${o}`);if(i instanceof t)return i;throw Error(`Voice HTMX bootstrap could not find the required element "${o}".`)},bn=(e)=>{if(!e.mode)return Cn;if(!e.hasStarted)return e.mode==="guided"?fn:Tn;if(e.status==="completed")return e.mode==="guided"?Ee:re;if(e.mode==="general")return _e;return e.guidedPrompts[e.turnCount]??Pe},_n=(e)=>{if(!e.mode)return Sn;if(e.status==="completed")return e.mode==="guided"?Ee:re;if(!e.hasStarted)return e.mode==="guided"?`Click Start guided test to begin. First prompt: ${e.guidedPrompts[0]??"Answer the first prompt."}`:Mn;if(e.mode==="general")return e.turnCount===0?_e:re;return e.guidedPrompts[e.turnCount]??Pe},En=(e)=>{let n=e.dataset.voiceGuidedPath,t=e.dataset.voiceGeneralPath;if(!n||!t)throw Error("Voice HTMX bootstrap requires data-voice-guided-path and data-voice-general-path.");let o=un(e.dataset.voiceGuidedPrompts),r=e.dataset.voiceGuidedLabel??hn,i=e.dataset.voiceGeneralLabel??yn,c=e.dataset.voiceReconnectReportPath,l=e.dataset.voiceBargeInPath,g=l?ue({path:l,thresholdMs:ce(e.dataset.voiceBargeInThresholdMs)}):null,y=ce(e.dataset.voiceBargeInRecentWindowMs)??4000,d=ce(e.dataset.voiceBargeInSpeechThreshold)??0.04,h=x(document,e.dataset.voiceSync,HTMLElement,"voice-htmx-sync"),a=x(e,e.dataset.voiceConnection,HTMLElement,"metric-connection"),M=x(e,e.dataset.voiceError,HTMLElement,"status-error"),C=x(e,e.dataset.voiceMicrophone,HTMLElement,"status-mic"),I=x(e,e.dataset.voicePrompt,HTMLElement,"status-prompt"),w=Rn(e,e.dataset.voiceReconnect,HTMLElement),R=x(e,e.dataset.voiceChat,HTMLElement,"chat-list"),u=x(e,e.dataset.voiceStartGuided,HTMLButtonElement,"start-guided"),O=x(e,e.dataset.voiceStartGeneral,HTMLButtonElement,"start-general"),U=x(e,e.dataset.voiceStop,HTMLButtonElement,"stop-mic"),s=x(e,e.dataset.voiceMonitor,HTMLElement,"voice-monitor"),S=x(e,e.dataset.voiceMonitorCopy,HTMLElement,"voice-monitor-copy"),L=x(e,e.dataset.voiceWaveGlow,SVGPathElement,"voice-wave-glow"),X=x(e,e.dataset.voiceWavePath,SVGPathElement,"voice-wave-path"),_=null,W={general:!1,guided:!1},P=!1,$=null,N=v(),A=null,f=null,E=m(n,{capture:{onAudio:(T,G)=>{if(A){A.sendAudio(T);return}G(T)},onLevel:(T)=>{A?.handleLevel(T),N=be(N,T),F()}},connection:{reconnectReportPath:c},preset:"guided-intake"}),V=m(t,{capture:{onAudio:(T,G)=>{if(f){f.sendAudio(T);return}G(T)},onLevel:(T)=>{f?.handleLevel(T),N=be(N,T),F()}},connection:{reconnectReportPath:c},preset:"dictation"}),Y=E.bindHTMX({element:h}),xe=V.bindHTMX({element:h}),J=j(E),Q=j(V);A=oe(E,J,{interruptThreshold:d,monitor:g??void 0}),f=oe(V,Q,{interruptThreshold:d,monitor:g??void 0});let z=()=>_==="general"?V:E,Dn=()=>_==="general"?Q:J,F=()=>{let T=Ln(N);L.setAttribute("d",T),X.setAttribute("d",T),S.innerHTML=`<span class="voice-live-dot"></span>${P?"Microphone live":"Microphone idle"}`,S.classList.toggle("is-live",P),s.classList.toggle("is-live",P)},k=()=>{let T=z(),G=(_?W[_]:!1)||T.turns.length>0,ae=T.status;if(a.textContent=T.isConnected?"Connected":"Waiting",M.textContent=$||T.error||"None",w)w.textContent=wn(T.reconnect);C.textContent=P?Vn:In,I.textContent=_n({guidedPrompts:o,hasStarted:G,mode:_,status:ae,turnCount:T.turns.length}),u.hidden=P,O.hidden=P,U.hidden=!P,R.innerHTML=`<article class="voice-chat-message assistant">\n <div class="voice-chat-role">${q(_==="general"?i:_==="guided"?r:"Voice demo")}</div>\n <p class="voice-turn-text">${q(bn({generalLabel:i,guidedLabel:r,guidedPrompts:o,hasStarted:G,mode:_,status:ae,turnCount:T.turns.length}))}</p>\n</article>${T.turns.map((p)=>`<div class="voice-chat-stack">\n <article class="voice-chat-message user">\n <div class="voice-chat-role">You</div>\n <p class="voice-turn-text">${q(p.text)}</p>\n </article>\n ${p.assistantText?`<article class="voice-chat-message assistant">\n <div class="voice-chat-role">${q(_==="general"?i:_==="guided"?r:"Guide")}</div>\n <p class="voice-turn-text">${q(p.assistantText)}</p>\n </article>`:""}\n</div>`).join("")}${T.partial?`<article class="voice-chat-message user pending">\n <div class="voice-chat-role">Speaking</div>\n <p class="voice-turn-text">${q(T.partial)}</p>\n</article>`:""}`,F()},Oe=()=>{z().stopRecording(),P=!1,$=null,N=v(),k()},le=async(T)=>{_=T,W={...W,[T]:!0};try{await z().startRecording(),$=null,P=!0,k()}catch(G){z().stopRecording(),P=!1,N=v(),$=ie(G),k()}};E.subscribe(()=>{if(E.assistantAudio.length>0)J.start().catch(()=>{});k()}),V.subscribe(()=>{if(V.assistantAudio.length>0)Q.start().catch(()=>{});k()}),u.addEventListener("click",()=>{le("guided")}),O.addEventListener("click",()=>{le("general")}),U.addEventListener("click",()=>{Oe()}),e.addEventListener("absolute-voice-simulate-disconnect",()=>{z().simulateDisconnect()}),window.addEventListener("beforeunload",()=>{E.stopRecording(),V.stopRecording(),A?.close(),f?.close(),J.close(),Q.close(),Y(),xe(),E.close(),V.close()}),k()},Pn=()=>{if(typeof window>"u"||typeof document>"u")return;let e=Array.from(document.querySelectorAll("[data-voice-htmx]"));for(let n of e)if(n instanceof HTMLElement)En(n)};Pn();export{Pn as initVoiceHTMX};\n';
5189
+ var HTMX_BOOTSTRAP_BUNDLE = 'var We=(e)=>{if(typeof e!=="string")return e;return document.querySelector(e)},$e=(e,n,c,o)=>{let s=n??e.getAttribute("hx-get")??"";if(!s)return"";let t=new URL(s,window.location.origin);if(o)t.searchParams.set(c,o);else t.searchParams.delete(c);return`${t.pathname}${t.search}${t.hash}`},fe=(e,n)=>{if(typeof window>"u"||typeof document>"u")return()=>{};let c=We(n.element);if(!c)return()=>{};let o=n.eventName??"voice-refresh",s=n.sessionQueryParam??"sessionId",t=()=>{let r=window,d=$e(c,n.route,s,e.sessionId);if(d)c.setAttribute("hx-get",d);r.htmx?.process?.(c),r.htmx?.trigger?.(c,o)},i=e.subscribe(t);return t(),()=>{i()}};var ke=(e)=>Math.max(-1,Math.min(1,e)),qe=(e)=>{let n=new Int16Array(e.length);for(let c=0;c<e.length;c+=1){let o=ke(e[c]??0);n[c]=o<0?o*32768:o*32767}return new Uint8Array(n.buffer)},Xe=(e)=>{let n=e instanceof Uint8Array?e:new Uint8Array(e);if(n.byteLength<2)return 0;let c=new Int16Array(n.buffer,n.byteOffset,Math.floor(n.byteLength/2));if(c.length===0)return 0;let o=0;for(let s of c){let t=s/32768;o+=t*t}return Math.min(1,Math.max(0,Math.sqrt(o/c.length)*5.5))},ze=(e,n,c)=>{if(n===c)return e;let o=n/c,s=Math.round(e.length/o),t=new Float32Array(s),i=0,r=0;while(i<t.length){let d=Math.round((i+1)*o),f=0,a=0;for(let A=r;A<d&&A<e.length;A+=1)f+=e[A]??0,a+=1;t[i]=a>0?f/a:0,i+=1,r=d}return t},Ae=(e)=>{let n=null,c=null,o=null,s=null;return{start:async()=>{if(typeof navigator>"u"||!navigator.mediaDevices?.getUserMedia)throw Error("Browser microphone capture requires navigator.mediaDevices.getUserMedia.");let r=(typeof window<"u"?window.AudioContext??window.webkitAudioContext:void 0)??AudioContext;if(!r)throw Error("Browser microphone capture requires AudioContext support.");s=await navigator.mediaDevices.getUserMedia({audio:{channelCount:e.channelCount??1}}),n=new r,c=n.createMediaStreamSource(s),o=n.createScriptProcessor(4096,1,1),o.onaudioprocess=(d)=>{let f=d.inputBuffer.getChannelData(0),a=ze(f,n?.sampleRate??48000,e.sampleRateHz??16000),A=qe(a);e.onLevel?.(Xe(A)),e.onAudio(A)},c.connect(o),o.connect(n.destination)},stop:()=>{o?.disconnect(),c?.disconnect(),s?.getTracks().forEach((r)=>r.stop()),n?.close(),e.onLevel?.(0),n=null,s=null,o=null,c=null}}};var ne=(e)=>{if(typeof e==="string"&&e.trim())return e;if(e instanceof Error&&e.message.trim())return e.message;if(e&&typeof e==="object"){let n=e;for(let c of["message","reason","description"]){let o=n[c];if(typeof o==="string"&&o.trim())return o}if("error"in n)return ne(n.error);if("cause"in n)return ne(n.cause);try{return JSON.stringify(e)}catch{}}return"Unexpected error"},he=(e)=>{switch(e.type){case"audio":return{chunk:Uint8Array.from(atob(e.chunkBase64),(n)=>n.charCodeAt(0)),format:e.format,receivedAt:e.receivedAt,turnId:e.turnId,type:"audio"};case"assistant":return{text:e.text,type:"assistant"};case"complete":return{sessionId:e.sessionId,type:"complete"};case"connection":return{reconnect:e.reconnect,type:"connection"};case"call_lifecycle":return{event:e.event,sessionId:e.sessionId,type:"call_lifecycle"};case"error":return{message:ne(e.message),type:"error"};case"final":return{transcript:e.transcript,type:"final"};case"partial":return{transcript:e.transcript,type:"partial"};case"replay":return{assistantTexts:e.assistantTexts,call:e.call,partial:e.partial,scenarioId:e.scenarioId,sessionId:e.sessionId,sessionMetadata:e.sessionMetadata,status:e.status,turns:e.turns,type:"replay"};case"session":return{sessionId:e.sessionId,sessionMetadata:e.sessionMetadata,scenarioId:e.scenarioId,status:e.status,type:"session"};case"turn":return{turn:e.turn,type:"turn"};default:return null}};var{mkdir:pn,writeFile:ec}=(()=>({}));function H(e){if(typeof e!=="string")throw TypeError("Path must be a string. Received "+JSON.stringify(e))}function Ce(e,n){var c="",o=0,s=-1,t=0,i;for(var r=0;r<=e.length;++r){if(r<e.length)i=e.charCodeAt(r);else if(i===47)break;else i=47;if(i===47){if(s===r-1||t===1);else if(s!==r-1&&t===2){if(c.length<2||o!==2||c.charCodeAt(c.length-1)!==46||c.charCodeAt(c.length-2)!==46){if(c.length>2){var d=c.lastIndexOf("/");if(d!==c.length-1){if(d===-1)c="",o=0;else c=c.slice(0,d),o=c.length-1-c.lastIndexOf("/");s=r,t=0;continue}}else if(c.length===2||c.length===1){c="",o=0,s=r,t=0;continue}}if(n){if(c.length>0)c+="/..";else c="..";o=2}}else{if(c.length>0)c+="/"+e.slice(s+1,r);else c=e.slice(s+1,r);o=r-s-1}s=r,t=0}else if(i===46&&t!==-1)++t;else t=-1}return c}function Ye(e,n){var c=n.dir||n.root,o=n.base||(n.name||"")+(n.ext||"");if(!c)return o;if(c===n.root)return c+o;return c+e+o}function ce(){var e="",n=!1,c;for(var o=arguments.length-1;o>=-1&&!n;o--){var s;if(o>=0)s=arguments[o];else{if(c===void 0)c=process.cwd();s=c}if(H(s),s.length===0)continue;e=s+"/"+e,n=s.charCodeAt(0)===47}if(e=Ce(e,!n),n)if(e.length>0)return"/"+e;else return"/";else if(e.length>0)return e;else return"."}function ye(e){if(H(e),e.length===0)return".";var n=e.charCodeAt(0)===47,c=e.charCodeAt(e.length-1)===47;if(e=Ce(e,!n),e.length===0&&!n)e=".";if(e.length>0&&c)e+="/";if(n)return"/"+e;return e}function Je(e){return H(e),e.length>0&&e.charCodeAt(0)===47}function Te(){if(arguments.length===0)return".";var e;for(var n=0;n<arguments.length;++n){var c=arguments[n];if(H(c),c.length>0)if(e===void 0)e=c;else e+="/"+c}if(e===void 0)return".";return ye(e)}function Qe(e,n){if(H(e),H(n),e===n)return"";if(e=ce(e),n=ce(n),e===n)return"";var c=1;for(;c<e.length;++c)if(e.charCodeAt(c)!==47)break;var o=e.length,s=o-c,t=1;for(;t<n.length;++t)if(n.charCodeAt(t)!==47)break;var i=n.length,r=i-t,d=s<r?s:r,f=-1,a=0;for(;a<=d;++a){if(a===d){if(r>d){if(n.charCodeAt(t+a)===47)return n.slice(t+a+1);else if(a===0)return n.slice(t+a)}else if(s>d){if(e.charCodeAt(c+a)===47)f=a;else if(a===0)f=0}break}var A=e.charCodeAt(c+a),g=n.charCodeAt(t+a);if(A!==g)break;else if(A===47)f=a}var y="";for(a=c+f+1;a<=o;++a)if(a===o||e.charCodeAt(a)===47)if(y.length===0)y+="..";else y+="/..";if(y.length>0)return y+n.slice(t+f);else{if(t+=f,n.charCodeAt(t)===47)++t;return n.slice(t)}}function Ze(e){return e}function Ke(e){if(H(e),e.length===0)return".";var n=e.charCodeAt(0),c=n===47,o=-1,s=!0;for(var t=e.length-1;t>=1;--t)if(n=e.charCodeAt(t),n===47){if(!s){o=t;break}}else s=!1;if(o===-1)return c?"/":".";if(c&&o===1)return"//";return e.slice(0,o)}function me(e,n){if(n!==void 0&&typeof n!=="string")throw TypeError(\'"ext" argument must be a string\');H(e);var c=0,o=-1,s=!0,t;if(n!==void 0&&n.length>0&&n.length<=e.length){if(n.length===e.length&&n===e)return"";var i=n.length-1,r=-1;for(t=e.length-1;t>=0;--t){var d=e.charCodeAt(t);if(d===47){if(!s){c=t+1;break}}else{if(r===-1)s=!1,r=t+1;if(i>=0)if(d===n.charCodeAt(i)){if(--i===-1)o=t}else i=-1,o=r}}if(c===o)o=r;else if(o===-1)o=e.length;return e.slice(c,o)}else{for(t=e.length-1;t>=0;--t)if(e.charCodeAt(t)===47){if(!s){c=t+1;break}}else if(o===-1)s=!1,o=t+1;if(o===-1)return"";return e.slice(c,o)}}function je(e){H(e);var n=-1,c=0,o=-1,s=!0,t=0;for(var i=e.length-1;i>=0;--i){var r=e.charCodeAt(i);if(r===47){if(!s){c=i+1;break}continue}if(o===-1)s=!1,o=i+1;if(r===46){if(n===-1)n=i;else if(t!==1)t=1}else if(n!==-1)t=-1}if(n===-1||o===-1||t===0||t===1&&n===o-1&&n===c+1)return"";return e.slice(n,o)}function Fe(e){if(e===null||typeof e!=="object")throw TypeError(\'The "pathObject" argument must be of type Object. Received type \'+typeof e);return Ye("/",e)}function ve(e){H(e);var n={root:"",dir:"",base:"",ext:"",name:""};if(e.length===0)return n;var c=e.charCodeAt(0),o=c===47,s;if(o)n.root="/",s=1;else s=0;var t=-1,i=0,r=-1,d=!0,f=e.length-1,a=0;for(;f>=s;--f){if(c=e.charCodeAt(f),c===47){if(!d){i=f+1;break}continue}if(r===-1)d=!1,r=f+1;if(c===46){if(t===-1)t=f;else if(a!==1)a=1}else if(t!==-1)a=-1}if(t===-1||r===-1||a===0||a===1&&t===r-1&&t===i+1){if(r!==-1)if(i===0&&o)n.base=n.name=e.slice(1,r);else n.base=n.name=e.slice(i,r)}else{if(i===0&&o)n.name=e.slice(1,t),n.base=e.slice(1,r);else n.name=e.slice(i,t),n.base=e.slice(i,r);n.ext=e.slice(t,r)}if(i>0)n.dir=e.slice(0,i-1);else if(o)n.dir="/";return n}var pe="/",en=":",jn=((e)=>(e.posix=e,e))({resolve:ce,normalize:ye,isAbsolute:Je,join:Te,relative:Qe,_makeLong:Ze,dirname:Ke,basename:me,extname:je,format:Fe,parse:ve,sep:pe,delimiter:en,win32:null,posix:null});var G=(e,n,c,o)=>{e.push({code:c,message:o,severity:n})};var nn=(e)=>e.length===0?void 0:e.reduce((n,c)=>n+c,0)/e.length,m=(e)=>e.length===0?void 0:Math.max(...e);var u=(e,n)=>{let c=e[n];return typeof c==="number"&&Number.isFinite(c)?c:void 0},K=(e,n)=>{let c=e[n];return typeof c==="boolean"?c:void 0},D=(e,n)=>{let c=e[n];return typeof c==="string"?c:void 0},oe=(e)=>String(e.id??D(e,"ssrc")??u(e,"ssrc")??D(e,"trackIdentifier")??D(e,"mid")??"unknown"),Se=(e)=>e===void 0?void 0:e*1000;var cn=(e)=>{let n={};for(let[c,o]of Object.entries(e))if(o===null||typeof o==="boolean"||typeof o==="number"||typeof o==="string")n[c]=o;return n};var Me=(e={})=>{let n=e.stats??[],c=[],o=n.filter((l)=>l.type==="inbound-rtp"&&D(l,"kind")!=="video"),s=n.filter((l)=>l.type==="outbound-rtp"&&D(l,"kind")!=="video"),t=n.filter((l)=>l.type==="candidate-pair"),i=n.filter((l)=>(l.type==="track"||l.type==="media-source")&&D(l,"kind")==="audio"),r=t.filter((l)=>K(l,"selected")===!0||K(l,"nominated")===!0||D(l,"state")==="succeeded").length,d=i.filter((l)=>D(l,"readyState")!=="ended"&&D(l,"trackState")!=="ended"&&K(l,"ended")!==!0).length,f=i.filter((l)=>D(l,"readyState")==="ended"||D(l,"trackState")==="ended"||K(l,"ended")===!0).length,a=o.reduce((l,M)=>l+(u(M,"packetsReceived")??0),0),A=s.reduce((l,M)=>l+(u(M,"packetsSent")??0),0),g=[...o,...s].reduce((l,M)=>l+Math.max(0,u(M,"packetsLost")??0),0),y=a+g,C=y===0?0:g/y,I=o.reduce((l,M)=>l+(u(M,"bytesReceived")??0),0),L=s.reduce((l,M)=>l+(u(M,"bytesSent")??0),0),R=m(t.map((l)=>Se(u(l,"currentRoundTripTime")??u(l,"roundTripTime"))).filter((l)=>l!==void 0)),w=m([...o,...s].map((l)=>Se(u(l,"jitter"))).filter((l)=>l!==void 0)),x=m(o.map((l)=>{let M=u(l,"jitterBufferDelay"),b=u(l,"jitterBufferEmittedCount");return M!==void 0&&b!==void 0&&b>0?M/b*1000:void 0}).filter((l)=>l!==void 0)),U=i.map((l)=>u(l,"audioLevel")).filter((l)=>l!==void 0);if(e.requireConnectedCandidatePair&&t.length>0&&r===0)G(c,"error","media.webrtc_candidate_pair_missing","No active WebRTC candidate pair was observed.");if(e.requireLiveAudioTrack&&d===0)G(c,"error","media.webrtc_audio_track_missing","No live WebRTC audio track was observed.");if(e.maxPacketLossRatio!==void 0&&C>e.maxPacketLossRatio)G(c,"warning","media.webrtc_packet_loss",`Observed WebRTC packet loss ratio ${String(C)} above ${String(e.maxPacketLossRatio)}.`);if(e.maxRoundTripTimeMs!==void 0&&R!==void 0&&R>e.maxRoundTripTimeMs)G(c,"warning","media.webrtc_round_trip_time",`Observed WebRTC RTT ${String(R)}ms above ${String(e.maxRoundTripTimeMs)}ms.`);if(e.maxJitterMs!==void 0&&w!==void 0&&w>e.maxJitterMs)G(c,"warning","media.webrtc_jitter",`Observed WebRTC jitter ${String(w)}ms above ${String(e.maxJitterMs)}ms.`);return{activeCandidatePairs:r,audioLevelAverage:nn(U),bytesReceived:I,bytesSent:L,checkedAt:Date.now(),endedAudioTracks:f,inboundPackets:a,issues:c,jitterBufferDelayMs:x,jitterMs:w,liveAudioTracks:d,outboundPackets:A,packetLossRatio:C,packetsLost:g,roundTripTimeMs:R,status:c.some((l)=>l.severity==="error")?"fail":c.length>0?"warn":"pass",totalStats:n.length}},Ie=async(e)=>{return[...(await e.peerConnection.getStats(e.selector??null)).values()].map(cn)};var Ve=(e={})=>{let n=e.stats??[],c=e.previousStats??[],o=[],s=new Map(c.map((g)=>[oe(g),g])),i=n.filter((g)=>(g.type==="inbound-rtp"||g.type==="outbound-rtp")&&D(g,"kind")!=="video"&&D(g,"mediaType")!=="video").map((g)=>{let y=g.type==="outbound-rtp"?"outbound":"inbound",C=y==="outbound"?"packetsSent":"packetsReceived",I=y==="outbound"?"bytesSent":"bytesReceived",L=s.get(oe(g)),R=u(g,C),w=L?u(L,C):void 0,x=u(g,I),U=L?u(L,I):void 0,l=g.timestamp!==void 0&&L?.timestamp!==void 0?g.timestamp-L.timestamp:void 0;return{bytesDelta:x!==void 0&&U!==void 0?x-U:void 0,currentPackets:R,direction:y,id:oe(g),packetDelta:R!==void 0&&w!==void 0?R-w:void 0,previousPackets:w,timeDeltaMs:l}}),r=i.filter((g)=>g.direction==="inbound"),d=i.filter((g)=>g.direction==="outbound"),f=m(i.map((g)=>g.timeDeltaMs).filter((g)=>g!==void 0)),a=r.filter((g)=>e.maxInboundPacketStallMs!==void 0&&g.timeDeltaMs!==void 0&&g.timeDeltaMs>=e.maxInboundPacketStallMs&&g.packetDelta!==void 0&&g.packetDelta<=0).length,A=d.filter((g)=>e.maxOutboundPacketStallMs!==void 0&&g.timeDeltaMs!==void 0&&g.timeDeltaMs>=e.maxOutboundPacketStallMs&&g.packetDelta!==void 0&&g.packetDelta<=0).length;if(e.requireInboundAudio&&r.length===0)G(o,"error","media.webrtc_inbound_audio_missing","No inbound WebRTC audio RTP stream was observed.");if(e.requireOutboundAudio&&d.length===0)G(o,"error","media.webrtc_outbound_audio_missing","No outbound WebRTC audio RTP stream was observed.");if(e.maxGapMs!==void 0&&f!==void 0&&f>e.maxGapMs)G(o,"warning","media.webrtc_stream_gap",`Observed WebRTC stream sample gap ${String(f)}ms above ${String(e.maxGapMs)}ms.`);if(a>0)G(o,"error","media.webrtc_inbound_stalled",`${String(a)} inbound WebRTC audio stream(s) stopped receiving packets.`);if(A>0)G(o,"error","media.webrtc_outbound_stalled",`${String(A)} outbound WebRTC audio stream(s) stopped sending packets.`);return{checkedAt:Date.now(),inboundAudioStreams:r.length,issues:o,maxObservedGapMs:f,outboundAudioStreams:d.length,stalledInboundStreams:a,stalledOutboundStreams:A,status:o.some((g)=>g.severity==="error")?"fail":o.length>0?"warn":"pass",streams:i,totalStats:n.length}};var on="/api/voice/browser-media",tn=5000,sn=async(e)=>e.peerConnection??await e.getPeerConnection?.()??null,rn=async(e,n)=>{let c=n.fetch??globalThis.fetch;if(!c)return;await c(n.path??on,{body:JSON.stringify(e),headers:{"Content-Type":"application/json"},keepalive:!0,method:"POST"})},Le=(e)=>{let n=null,c=[],o=async()=>{let i=await sn(e);if(!i)return;let r=await Ie({peerConnection:i}),d=Me({...e,stats:r}),f=e.continuity===!1?void 0:Ve({...e.continuity,previousStats:c,stats:r}),a={at:Date.now(),continuity:f,report:d,scenarioId:e.getScenarioId?.()??null,sessionId:e.getSessionId?.()??null};return c=r,e.onReport?.(a),await rn(a,e),a},s=()=>{o().catch((i)=>{e.onError?.(i)})},t=()=>{if(n)clearInterval(n),n=null};return{close:t,reportOnce:o,start:()=>{if(n)return;s(),n=setInterval(s,e.intervalMs??tn)},stop:t}};var W=()=>{},ln=()=>W,an={callControl:W,close:W,endTurn:W,getReadyState:()=>3,getScenarioId:()=>"",getSessionId:()=>"",send:W,sendAudio:W,simulateDisconnect:W,start:()=>{},subscribe:ln},dn=()=>crypto.randomUUID(),gn=(e,n,c)=>{let{hostname:o,port:s,protocol:t}=window.location,i=t==="https:"?"wss:":"ws:",r=s?`:${s}`:"",d=new URL(`${i}//${o}${r}${e}`);if(d.searchParams.set("sessionId",n),c)d.searchParams.set("scenarioId",c);return d.toString()},fn=(e)=>{if(!e||typeof e!=="object"||!("type"in e))return!1;switch(e.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}},An=(e)=>{if(typeof e.data!=="string")return null;try{let n=JSON.parse(e.data);return fn(n)?n:null}catch{return null}},be=(e,n={})=>{if(typeof window>"u")return an;let c=new Set,o=n.reconnect!==!1,s=n.maxReconnectAttempts??10,t=n.pingInterval??30000,i={isConnected:!1,pendingMessages:[],scenarioId:n.scenarioId??null,pingInterval:null,reconnectAttempts:0,reconnectTimeout:null,sessionId:n.sessionId??dn(),ws:null},r=(l)=>{c.forEach((M)=>M(l))},d=()=>{if(i.pingInterval)clearInterval(i.pingInterval),i.pingInterval=null;if(i.reconnectTimeout)clearTimeout(i.reconnectTimeout),i.reconnectTimeout=null},f=()=>{if(i.ws?.readyState!==1)return;while(i.pendingMessages.length>0){let l=i.pendingMessages.shift();if(l!==void 0)i.ws.send(l)}},a=()=>{let l=Date.now()+500;i.reconnectAttempts+=1,r({reconnect:{attempts:i.reconnectAttempts,lastDisconnectAt:Date.now(),maxAttempts:s,nextAttemptAt:l,status:"reconnecting"},type:"connection"}),i.reconnectTimeout=setTimeout(()=>{if(i.reconnectAttempts>s){r({reconnect:{attempts:i.reconnectAttempts,maxAttempts:s,status:"exhausted"},type:"connection"});return}A()},500)},A=()=>{let l=new WebSocket(gn(e,i.sessionId,i.scenarioId));l.binaryType="arraybuffer",l.onopen=()=>{let M=i.reconnectAttempts>0;if(i.isConnected=!0,f(),M)r({reconnect:{attempts:i.reconnectAttempts,lastResumedAt:Date.now(),maxAttempts:s,status:"resumed"},type:"connection"}),i.reconnectAttempts=0;c.forEach((b)=>b({scenarioId:i.scenarioId??void 0,sessionId:i.sessionId,status:"active",type:"session"})),i.pingInterval=setInterval(()=>{if(l.readyState===1)l.send(JSON.stringify({type:"ping"}))},t)},l.onmessage=(M)=>{let b=An(M);if(!b)return;if(b.type==="session")i.sessionId=b.sessionId,i.scenarioId=b.scenarioId??i.scenarioId;c.forEach((z)=>z(b))},l.onclose=(M)=>{if(i.isConnected=!1,d(),o&&M.code!==1000&&i.reconnectAttempts<s)a();else if(o&&M.code!==1000)r({reconnect:{attempts:i.reconnectAttempts,lastDisconnectAt:Date.now(),maxAttempts:s,status:"exhausted"},type:"connection"})},i.ws=l},g=(l)=>{if(i.ws?.readyState===1){i.ws.send(l);return}i.pendingMessages.push(l)},y=(l)=>{g(JSON.stringify(l))},C=(l={})=>{if(l.sessionId)i.sessionId=l.sessionId;if(l.scenarioId)i.scenarioId=l.scenarioId;y({type:"start",sessionId:i.sessionId,scenarioId:i.scenarioId??void 0})},I=(l)=>{g(l)},L=()=>{y({type:"end_turn"})},R=(l)=>{y({...l,type:"call_control"})},w=()=>{if(d(),i.ws)i.ws.close(1000),i.ws=null;i.isConnected=!1,c.clear()},x=()=>{if(i.ws?.readyState===1)i.ws.close(4000,"absolutejs-voice-reconnect-proof")},U=(l)=>{return c.add(l),()=>{c.delete(l)}};return A(),{callControl:R,close:w,endTurn:L,getReadyState:()=>i.ws?.readyState??3,getScenarioId:()=>i.scenarioId??"",getSessionId:()=>i.sessionId,send:y,sendAudio:I,simulateDisconnect:x,start:C,subscribe:U}};var hn=()=>({attempts:0,maxAttempts:0,status:"idle"}),Cn=()=>({assistantAudio:[],assistantTexts:[],call:null,error:null,isConnected:!1,sessionMetadata:null,scenarioId:null,partial:"",reconnect:hn(),sessionId:null,status:"idle",turns:[]}),we=()=>{let e=Cn(),n=new Set,c=()=>{n.forEach((s)=>s())};return{dispatch:(s)=>{switch(s.type){case"audio":e={...e,assistantAudio:[...e.assistantAudio,{chunk:s.chunk,format:s.format,receivedAt:s.receivedAt,turnId:s.turnId}]};break;case"assistant":e={...e,assistantTexts:[...e.assistantTexts,s.text]};break;case"complete":e={...e,sessionId:s.sessionId,status:"completed"};break;case"call_lifecycle":e={...e,call:{...e.call,disposition:s.event.type==="end"?s.event.disposition:e.call?.disposition,endedAt:s.event.type==="end"?s.event.at:e.call?.endedAt,events:[...e.call?.events??[],s.event],lastEventAt:s.event.at,startedAt:e.call?.startedAt??s.event.at},sessionId:s.sessionId};break;case"connected":e={...e,isConnected:!0,reconnect:e.reconnect.status==="reconnecting"?{...e.reconnect,lastResumedAt:Date.now(),nextAttemptAt:void 0,status:"resumed"}:e.reconnect};break;case"connection":e={...e,reconnect:s.reconnect};break;case"disconnected":e={...e,isConnected:!1};break;case"error":e={...e,error:s.message};break;case"final":e={...e,partial:s.transcript.text,turns:e.turns.map((t)=>t)};break;case"partial":e={...e,partial:s.transcript.text};break;case"replay":e={...e,assistantTexts:[...s.assistantTexts],call:s.call??null,error:null,isConnected:s.status==="active",partial:s.partial,reconnect:e.reconnect.status==="reconnecting"?{...e.reconnect,lastResumedAt:Date.now(),nextAttemptAt:void 0,status:"resumed"}:e.reconnect,scenarioId:s.scenarioId??e.scenarioId,sessionId:s.sessionId,sessionMetadata:s.sessionMetadata??e.sessionMetadata,status:s.status,turns:[...s.turns]};break;case"session":e={...e,error:null,scenarioId:s.scenarioId??e.scenarioId,isConnected:s.status==="active",sessionId:s.sessionId,sessionMetadata:s.sessionMetadata??e.sessionMetadata,status:s.status};break;case"turn":e={...e,partial:"",turns:[...e.turns,s.turn]};break}c()},getServerSnapshot:()=>e,getSnapshot:()=>e,subscribe:(s)=>{return n.add(s),()=>{n.delete(s)}}}};var Re=(e,n={})=>{let c=be(e,n),o=we(),s=n.browserMedia&&typeof window<"u"?Le({...n.browserMedia,getScenarioId:()=>n.browserMedia?n.browserMedia.getScenarioId?.()??c.getScenarioId():c.getScenarioId(),getSessionId:()=>n.browserMedia?n.browserMedia.getSessionId?.()??c.getSessionId():c.getSessionId()}):null,t=new Set,i=(a)=>Promise.resolve().then(()=>{if(!a?.sessionId&&!a?.scenarioId)return;c.start(a),s?.start()}),r=()=>{t.forEach((a)=>a())},d=()=>{if(!n.reconnectReportPath||typeof fetch>"u")return;let a=o.getSnapshot(),A=JSON.stringify({at:Date.now(),reconnect:a.reconnect,scenarioId:a.scenarioId,sessionId:c.getSessionId(),turnIds:a.turns.map((g)=>g.id)});fetch(n.reconnectReportPath,{body:A,headers:{"Content-Type":"application/json"},keepalive:!0,method:"POST"}).catch(()=>{})},f=c.subscribe((a)=>{let A=he(a);if(A){if(o.dispatch(A),a.type==="connection")d();r()}});return{callControl(a){c.callControl(a)},close(){f(),s?.close(),c.close(),o.dispatch({type:"disconnected"}),r()},endTurn(){c.endTurn()},get error(){return o.getSnapshot().error},getServerSnapshot(){return o.getServerSnapshot()},getSnapshot(){return o.getSnapshot()},get isConnected(){return o.getSnapshot().isConnected},get scenarioId(){return o.getSnapshot().scenarioId},get sessionMetadata(){return o.getSnapshot().sessionMetadata},start:i,get partial(){return o.getSnapshot().partial},get reconnect(){return o.getSnapshot().reconnect},get sessionId(){return c.getSessionId()},get status(){return o.getSnapshot().status},get turns(){return o.getSnapshot().turns},get assistantTexts(){return o.getSnapshot().assistantTexts},get assistantAudio(){return o.getSnapshot().assistantAudio},get call(){return o.getSnapshot().call},sendAudio(a){c.sendAudio(a)},simulateDisconnect(){c.simulateDisconnect()},subscribe(a){return t.add(a),()=>{t.delete(a)}}}};var ue=(e)=>{if(!e||e.enabled===!1)return;return{enabled:!0,maxGain:e.maxGain??3,noiseGateAttenuation:e.noiseGateAttenuation??0.15,noiseGateThreshold:e.noiseGateThreshold??0.006,targetLevel:e.targetLevel??0.08}};var yn={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}},Tn={general:{},"accent-heavy":{silenceMs:1200,speechThreshold:0.01,transcriptStabilityMs:1200},"noisy-room":{silenceMs:2000,speechThreshold:0.02,transcriptStabilityMs:1600},"short-command":{silenceMs:500,speechThreshold:0.016,transcriptStabilityMs:420}};var _e=(e)=>{let n=e?.profile??"fast",c=e?.qualityProfile??"general",o=yn[n],s=Tn[c];return{profile:n,qualityProfile:c,silenceMs:e?.silenceMs??s.silenceMs??o.silenceMs,speechThreshold:e?.speechThreshold??s.speechThreshold??o.speechThreshold,transcriptStabilityMs:e?.transcriptStabilityMs??s.transcriptStabilityMs??o.transcriptStabilityMs}};var Sn={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:{qualityProfile:"short-command",profile:"balanced"}},default:{capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:10,pingInterval:30000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{qualityProfile:"general",profile:"fast"}},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:{qualityProfile:"accent-heavy",profile:"long-form"}},"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:{qualityProfile:"accent-heavy",profile:"long-form"}},"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:{qualityProfile:"noisy-room",profile:"long-form",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:{qualityProfile:"noisy-room",profile:"long-form",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:{qualityProfile:"noisy-room",profile:"long-form",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:{qualityProfile:"noisy-room",profile:"long-form"}}},Ee=(e="default")=>{let n=Sn[e];return{audioConditioning:ue(n.audioConditioning),capture:{channelCount:n.capture?.channelCount??1,sampleRateHz:n.capture?.sampleRateHz??16000},connection:{...n.connection},name:e,sttLifecycle:n.sttLifecycle??"continuous",turnDetection:_e(n.turnDetection)}};var Mn=(e)=>({assistantAudio:[...e.assistantAudio],assistantTexts:[...e.assistantTexts],call:e.call,error:e.error,isConnected:e.isConnected,isRecording:!1,partial:e.partial,reconnect:e.reconnect,recordingError:null,sessionId:e.sessionId,sessionMetadata:e.sessionMetadata,scenarioId:e.scenarioId,status:e.status,turns:[...e.turns]}),j=(e,n={})=>{let c=Ee(n.preset),o=Re(e,{...c.connection,...n.connection}),s=null,t=Mn(o),i=new Set,r=()=>{for(let C of i)C()},d=()=>{if(t={...t,assistantAudio:[...o.assistantAudio],assistantTexts:[...o.assistantTexts],call:o.call,error:o.error,isConnected:o.isConnected,partial:o.partial,reconnect:o.reconnect,sessionId:o.sessionId,sessionMetadata:o.sessionMetadata,scenarioId:o.scenarioId,status:o.status,turns:[...o.turns]},n.autoStopOnComplete!==!1&&t.status==="completed"&&t.isRecording)s?.stop(),s=null,t={...t,isRecording:!1};r()},f=o.subscribe(d);d();let a=()=>{if(s)return s;return s=Ae({channelCount:n.capture?.channelCount??c.capture.channelCount,onLevel:n.capture?.onLevel,onAudio:(C)=>{if(n.capture?.onAudio){n.capture.onAudio(C,o.sendAudio);return}o.sendAudio(C)},sampleRateHz:n.capture?.sampleRateHz??c.capture.sampleRateHz}),s},A=()=>{s?.stop(),s=null,t={...t,isRecording:!1},r()},g=async()=>{if(t.isRecording)return;try{t={...t,recordingError:null},r(),await a().start(),t={...t,isRecording:!0},r()}catch(C){throw s=null,t={...t,isRecording:!1,recordingError:C instanceof Error?C.message:String(C)},r(),C}};return{bindHTMX(C){return fe(o,C)},callControl:(C)=>o.callControl(C),close:()=>{f(),A(),o.close()},endTurn:()=>o.endTurn(),get error(){return t.error},getServerSnapshot:()=>t,getSnapshot:()=>t,get isConnected(){return t.isConnected},get isRecording(){return t.isRecording},get partial(){return t.partial},get recordingError(){return t.recordingError},get reconnect(){return t.reconnect},sendAudio:(C)=>o.sendAudio(C),simulateDisconnect:()=>o.simulateDisconnect(),get sessionId(){return t.sessionId},get sessionMetadata(){return t.sessionMetadata},get scenarioId(){return t.scenarioId},startRecording:g,get status(){return t.status},stopRecording:A,subscribe:(C)=>{return i.add(C),()=>{i.delete(C)}},toggleRecording:async()=>{if(t.isRecording){A();return}await g()},get turns(){return t.turns},get assistantTexts(){return t.assistantTexts},get assistantAudio(){return t.assistantAudio},get call(){return t.call}}};var In=()=>({activeSourceCount:0,error:null,isActive:!1,isPlaying:!1,lastInterruptLatencyMs:void 0,lastPlaybackStopLatencyMs:void 0,processedChunkCount:0,queuedChunkCount:0}),Vn=()=>{if(typeof window>"u")return typeof AudioContext>"u"?void 0:AudioContext;return window.AudioContext??window.webkitAudioContext},Ln=(e,n)=>{let c=n.format;if(c.container!=="raw"||c.encoding!=="pcm_s16le")throw Error(`Unsupported assistant audio format: ${c.container}/${c.encoding}`);let o=n.chunk,s=Math.max(1,c.channels),t=Math.floor(o.byteLength/2),i=Math.max(1,Math.floor(t/s)),r=e.createBuffer(s,i,c.sampleRateHz),d=new DataView(o.buffer,o.byteOffset,o.byteLength);for(let f=0;f<s;f+=1){let a=r.getChannelData(f);for(let A=0;A<i;A+=1){let y=(A*s+f)*2;if(y+1>=o.byteLength){a[A]=0;continue}a[A]=d.getInt16(y,!0)/32768}}return r},F=(e,n={})=>{let c=new Set,o=new Set,s=(n.lookaheadMs??15)/1000,t=In(),i=null,r=null,d=0,f=Promise.resolve(),a=null,A=null,g=null,y=null,C=()=>{for(let h of c)h()},I=(h)=>{t={...t,...h},C()},L=()=>{if(t.error!==null)I({error:null})},R=()=>{if(y!==null)clearTimeout(y),y=null},w=(h)=>{R(),a=null,I({activeSourceCount:o.size,isPlaying:!1,lastInterruptLatencyMs:h,lastPlaybackStopLatencyMs:t.lastPlaybackStopLatencyMs??h}),g?.(),g=null,A=null},x=(h)=>{if(!h)return 0;return Math.max(0,((h.baseLatency??0)+(h.outputLatency??0))*1000)},U=(h)=>{if(!r)return;let T=1;if(r.gain.setValueAtTime){r.gain.setValueAtTime(T,h?.currentTime??0);return}r.gain.value=T},l=(h)=>{if(!r)return;let T=0;if(r.gain.setValueAtTime){r.gain.setValueAtTime(T,h?.currentTime??0);return}r.gain.value=T},M=()=>{if(a===null||o.size>0)return;w(Date.now()-a)},b=async()=>{if(i)return i;if(n.createAudioContext)i=n.createAudioContext();else{let h=Vn();if(!h)throw Error("Assistant audio playback requires AudioContext support.");i=new h}if(i.createGain)r=i.createGain(),r.connect?.(i.destination);return d=i.currentTime,i},z=async(h)=>{let T=await b(),E=Ln(T,h),V=T.createBufferSource();V.buffer=E,V.connect(r??T.destination),V.onended=()=>{o.delete(V),V.disconnect?.(),I({activeSourceCount:o.size,isPlaying:o.size>0&&t.isActive}),M()};let J=Math.max(T.currentTime+s,d);d=J+E.duration,o.add(V),I({activeSourceCount:o.size,isPlaying:!0}),V.start(J)},_=(h)=>{for(let T of[...o])T.stop?.();if(d=i?i.currentTime:0,h?.forceClear){for(let T of o)T.disconnect?.();o.clear(),M()}},$=async()=>{if(!t.isActive)return;let h=e.assistantAudio.slice(t.processedChunkCount);if(h.length===0)return;try{L();for(let T of h)await z(T);I({processedChunkCount:e.assistantAudio.length,queuedChunkCount:t.queuedChunkCount+h.length})}catch(T){I({error:T instanceof Error?T.message:String(T)})}},P=()=>{return f=f.then(()=>$(),()=>$()),f},k=e.subscribe(()=>{if(n.autoStart&&!t.isActive&&e.assistantAudio.length>0){N.start();return}if(t.isActive)P()}),N={close:async()=>{if(k(),_({forceClear:!0}),R(),g?.(),g=null,A=null,a=null,i&&i.state!=="closed")await i.close();i=null,r?.disconnect?.(),r=null,d=0,I({activeSourceCount:0,isActive:!1,isPlaying:!1})},get activeSourceCount(){return t.activeSourceCount},get error(){return t.error},getSnapshot:()=>t,get isActive(){return t.isActive},get isPlaying(){return t.isPlaying},interrupt:async()=>{let h=Date.now(),T=await b();a=h,l(T);let E=Date.now()-h+x(T);if(I({isActive:!1,isPlaying:o.size>0,lastPlaybackStopLatencyMs:E}),o.size===0){w(E);return}if(!A)A=new Promise((V)=>{g=V});R(),y=setTimeout(()=>{for(let V of o)V.disconnect?.();o.clear(),w(Date.now()-h)},250),_(),await A},get lastInterruptLatencyMs(){return t.lastInterruptLatencyMs},get lastPlaybackStopLatencyMs(){return t.lastPlaybackStopLatencyMs},pause:async()=>{if(!i){I({activeSourceCount:0,isActive:!1,isPlaying:!1});return}await i.suspend(),I({activeSourceCount:o.size,isActive:!1,isPlaying:!1})},get processedChunkCount(){return t.processedChunkCount},get queuedChunkCount(){return t.queuedChunkCount},start:async()=>{try{L();let h=await b();if(U(h),h.state==="suspended")await h.resume();I({activeSourceCount:o.size,isActive:!0,isPlaying:h.state==="running"}),await P()}catch(h){throw I({error:h instanceof Error?h.message:String(h),isActive:!1,isPlaying:!1}),h}},subscribe:(h)=>{return c.add(h),()=>{c.delete(h)}}};return N};var bn=()=>`barge-in:${Date.now()}:${crypto.randomUUID?.()??Math.random().toString(36).slice(2)}`,wn=(e,n)=>{let c=e.filter((i)=>i.status==="stopped"),o=c.map((i)=>i.latencyMs).filter((i)=>typeof i==="number"),s=c.filter((i)=>typeof i.latencyMs==="number"&&i.latencyMs>n).length,t=c.length-s;return{averageLatencyMs:o.length>0?Math.round(o.reduce((i,r)=>i+r,0)/o.length):void 0,events:[...e],failed:s,lastEvent:e.at(-1),passed:t,status:e.length===0?"empty":s>0?"fail":c.length===0?"warn":"pass",thresholdMs:n,total:c.length}},Pe=(e={})=>{let n=new Set,c=e.thresholdMs??250,o=e.fetch??globalThis.fetch,s=[],t=()=>{for(let d of n)d()},i=(d)=>{if(!e.path||typeof o!=="function")return;o(e.path,{body:JSON.stringify(d),headers:{"Content-Type":"application/json"},method:"POST"}).catch(()=>{})},r=(d,f)=>{let a={at:Date.now(),id:bn(),latencyMs:f.latencyMs,playbackStopLatencyMs:f.playbackStopLatencyMs,reason:f.reason,sessionId:f.sessionId,status:d,thresholdMs:c};return s.push(a),i(a),t(),a};return{getSnapshot:()=>wn(s,c),recordRequested:(d)=>r("requested",d),recordSkipped:(d)=>r("skipped",d),recordStopped:(d)=>r("stopped",d),subscribe:(d)=>{return n.add(d),()=>{n.delete(d)}}}};var Rn=0.08,un=(e,n={})=>(n.enabled??!0)&&e>=(n.interruptThreshold??Rn),te=(e,n,c={})=>{let o=e.partial,s=(i)=>{if(!n.isPlaying||c.enabled===!1){c.monitor?.recordSkipped({reason:i,sessionId:e.sessionId});return}c.monitor?.recordRequested({reason:i,sessionId:e.sessionId}),n.interrupt().then(()=>{c.monitor?.recordStopped({latencyMs:n.lastInterruptLatencyMs,playbackStopLatencyMs:n.lastPlaybackStopLatencyMs,reason:i,sessionId:e.sessionId})})},t=e.subscribe(()=>{if(c.interruptOnPartial===!1){o=e.partial;return}if(!o&&e.partial)s("partial-transcript");o=e.partial});return{close:()=>{t()},handleLevel:(i)=>{if(un(i,c))s("input-level")},sendAudio:(i)=>{s("manual-audio"),e.sendAudio(i)}}};var ae=48,_n=320,En=88,Pn="Guided test",Dn="General recording",On="Pick a scenario to begin the demo.",xn="I can walk you through a short guided voice test.",Un="I can capture one freeform recording and confirm that it landed.",Nn="Choose a scenario to begin. Guided test asks follow-up prompts. General recording just captures what you say.",Hn="Click Start general recording to capture one freeform answer.",xe="Speak freely. When you pause, the recording will be captured.",re="Recording saved. Start again if you want another capture.",Ue="Guided test complete. Review the saved summary below.",Ne="All prompts are covered. You can stop the microphone or keep speaking for extra detail.",Gn="Ready. Start guided test or general recording to begin.",Bn="Live. Answer the prompt, then click Stop microphone when finished.",De=["Start with a quick introduction about who you are.","Now describe what you are trying to do or test.","Finish with any detail that feels blocked, risky, or unclear."],He=(e,n,c)=>Math.min(c,Math.max(n,e)),X=(e)=>e.replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;").replaceAll(\'"\',"&quot;").replaceAll("\'","&#39;"),ie=(e,n)=>{let c=e[n];if(typeof c==="string"&&c.trim())return c;return null},le=(e)=>{if(typeof e==="string"&&e.trim())return e;if(e instanceof Error&&e.message.trim())return e.message;if(e&&typeof e==="object"){let n=e,c=ie(n,"message")??ie(n,"reason")??ie(n,"description");if(c)return c;if("error"in n)return le(n.error);if("cause"in n)return le(n.cause);try{return JSON.stringify(e)}catch{}}return"Unexpected error"},Wn=(e)=>{let n=[e.status];if(e.attempts>0||e.maxAttempts>0)n.push(`${e.attempts}/${e.maxAttempts} attempts`);if(e.nextAttemptAt){let c=Math.max(0,e.nextAttemptAt-Date.now());n.push(`retry in ${Math.ceil(c/100)/10}s`)}return n.join(" \xB7 ")},v=(e=ae)=>Array.from({length:e},()=>0),Oe=(e,n,c=ae)=>{let o=e.slice(-(c-1));o.push(He(n,0,1));while(o.length<c)o.unshift(0);return o},$n=(e,n=_n,c=En)=>{let o=e.length>1?e:v(ae),s=n/(o.length-1),t=c/2,i=c*0.34;if(Math.max(...o,0)<=0.015)return`M 0 ${t} L ${n} ${t}`;let d=o.map((a,A)=>{let g=A*0.76,y=Math.sin(g)*0.78+Math.sin(g*0.41)*0.22,C=a*i,I=s*A,L=He(t+y*C,8,c-8);return{x:I,y:L}});if(d.length===0)return`M 0 ${t} L ${n} ${t}`;let f=`M ${d[0]?.x??0} ${d[0]?.y??t}`;for(let a=1;a<d.length;a+=1){let A=d[a-1],g=d[a];if(!A||!g)continue;let y=(A.x+g.x)/2;f+=` Q ${y} ${A.y} ${g.x} ${g.y}`}return f},kn=(e)=>{if(!e)return De;try{let n=JSON.parse(e);if(Array.isArray(n)){let c=n.filter((o)=>typeof o==="string").map((o)=>o.trim()).filter(Boolean);if(c.length>0)return c}}catch{}return De},se=(e)=>{if(!e)return;let n=Number(e);return Number.isFinite(n)?n:void 0},qn=(e,n,c)=>{if(!n)return null;let o=document.querySelector(n);return o instanceof c?o:null},O=(e,n,c,o)=>{let s=n?document.querySelector(n):null;if(s instanceof c)return s;let t=e.querySelector(`#${o}`);if(t instanceof c)return t;throw Error(`Voice HTMX bootstrap could not find the required element "${o}".`)},Xn=(e)=>{if(!e.mode)return On;if(!e.hasStarted)return e.mode==="guided"?xn:Un;if(e.status==="completed")return e.mode==="guided"?Ue:re;if(e.mode==="general")return xe;return e.guidedPrompts[e.turnCount]??Ne},zn=(e)=>{if(!e.mode)return Nn;if(e.status==="completed")return e.mode==="guided"?Ue:re;if(!e.hasStarted)return e.mode==="guided"?`Click Start guided test to begin. First prompt: ${e.guidedPrompts[0]??"Answer the first prompt."}`:Hn;if(e.mode==="general")return e.turnCount===0?xe:re;return e.guidedPrompts[e.turnCount]??Ne},Yn=(e)=>{let n=e.dataset.voiceGuidedPath,c=e.dataset.voiceGeneralPath;if(!n||!c)throw Error("Voice HTMX bootstrap requires data-voice-guided-path and data-voice-general-path.");let o=kn(e.dataset.voiceGuidedPrompts),s=e.dataset.voiceGuidedLabel??Pn,t=e.dataset.voiceGeneralLabel??Dn,i=e.dataset.voiceReconnectReportPath,r=e.dataset.voiceBargeInPath,d=r?Pe({path:r,thresholdMs:se(e.dataset.voiceBargeInThresholdMs)}):null,f=se(e.dataset.voiceBargeInRecentWindowMs)??4000,a=se(e.dataset.voiceBargeInSpeechThreshold)??0.04,A=O(document,e.dataset.voiceSync,HTMLElement,"voice-htmx-sync"),g=O(e,e.dataset.voiceConnection,HTMLElement,"metric-connection"),y=O(e,e.dataset.voiceError,HTMLElement,"status-error"),C=O(e,e.dataset.voiceMicrophone,HTMLElement,"status-mic"),I=O(e,e.dataset.voicePrompt,HTMLElement,"status-prompt"),L=qn(e,e.dataset.voiceReconnect,HTMLElement),R=O(e,e.dataset.voiceChat,HTMLElement,"chat-list"),w=O(e,e.dataset.voiceStartGuided,HTMLButtonElement,"start-guided"),x=O(e,e.dataset.voiceStartGeneral,HTMLButtonElement,"start-general"),U=O(e,e.dataset.voiceStop,HTMLButtonElement,"stop-mic"),l=O(e,e.dataset.voiceMonitor,HTMLElement,"voice-monitor"),M=O(e,e.dataset.voiceMonitorCopy,HTMLElement,"voice-monitor-copy"),b=O(e,e.dataset.voiceWaveGlow,SVGPathElement,"voice-wave-glow"),z=O(e,e.dataset.voiceWavePath,SVGPathElement,"voice-wave-path"),_=null,$={general:!1,guided:!1},P=!1,k=null,N=v(),h=null,T=null,E=j(n,{capture:{onAudio:(S,B)=>{if(h){h.sendAudio(S);return}B(S)},onLevel:(S)=>{h?.handleLevel(S),N=Oe(N,S),p()}},connection:{reconnectReportPath:i},preset:"guided-intake"}),V=j(c,{capture:{onAudio:(S,B)=>{if(T){T.sendAudio(S);return}B(S)},onLevel:(S)=>{T?.handleLevel(S),N=Oe(N,S),p()}},connection:{reconnectReportPath:i},preset:"dictation"}),J=E.bindHTMX({element:A}),Ge=V.bindHTMX({element:A}),Q=F(E),Z=F(V);h=te(E,Q,{interruptThreshold:a,monitor:d??void 0}),T=te(V,Z,{interruptThreshold:a,monitor:d??void 0});let Y=()=>_==="general"?V:E,Qn=()=>_==="general"?Z:Q,p=()=>{let S=$n(N);b.setAttribute("d",S),z.setAttribute("d",S),M.innerHTML=`<span class="voice-live-dot"></span>${P?"Microphone live":"Microphone idle"}`,M.classList.toggle("is-live",P),l.classList.toggle("is-live",P)},q=()=>{let S=Y(),B=(_?$[_]:!1)||S.turns.length>0,ge=S.status;if(g.textContent=S.isConnected?"Connected":"Waiting",y.textContent=k||S.error||"None",L)L.textContent=Wn(S.reconnect);C.textContent=P?Bn:Gn,I.textContent=zn({guidedPrompts:o,hasStarted:B,mode:_,status:ge,turnCount:S.turns.length}),w.hidden=P,x.hidden=P,U.hidden=!P,R.innerHTML=`<article class="voice-chat-message assistant">\n <div class="voice-chat-role">${X(_==="general"?t:_==="guided"?s:"Voice demo")}</div>\n <p class="voice-turn-text">${X(Xn({generalLabel:t,guidedLabel:s,guidedPrompts:o,hasStarted:B,mode:_,status:ge,turnCount:S.turns.length}))}</p>\n</article>${S.turns.map((ee)=>`<div class="voice-chat-stack">\n <article class="voice-chat-message user">\n <div class="voice-chat-role">You</div>\n <p class="voice-turn-text">${X(ee.text)}</p>\n </article>\n ${ee.assistantText?`<article class="voice-chat-message assistant">\n <div class="voice-chat-role">${X(_==="general"?t:_==="guided"?s:"Guide")}</div>\n <p class="voice-turn-text">${X(ee.assistantText)}</p>\n </article>`:""}\n</div>`).join("")}${S.partial?`<article class="voice-chat-message user pending">\n <div class="voice-chat-role">Speaking</div>\n <p class="voice-turn-text">${X(S.partial)}</p>\n</article>`:""}`,p()},Be=()=>{Y().stopRecording(),P=!1,k=null,N=v(),q()},de=async(S)=>{_=S,$={...$,[S]:!0};try{await Y().startRecording(),k=null,P=!0,q()}catch(B){Y().stopRecording(),P=!1,N=v(),k=le(B),q()}};E.subscribe(()=>{if(E.assistantAudio.length>0)Q.start().catch(()=>{});q()}),V.subscribe(()=>{if(V.assistantAudio.length>0)Z.start().catch(()=>{});q()}),w.addEventListener("click",()=>{de("guided")}),x.addEventListener("click",()=>{de("general")}),U.addEventListener("click",()=>{Be()}),e.addEventListener("absolute-voice-simulate-disconnect",()=>{Y().simulateDisconnect()}),window.addEventListener("beforeunload",()=>{E.stopRecording(),V.stopRecording(),h?.close(),T?.close(),Q.close(),Z.close(),J(),Ge(),E.close(),V.close()}),q()},Jn=()=>{if(typeof window>"u"||typeof document>"u")return;let e=Array.from(document.querySelectorAll("[data-voice-htmx]"));for(let n of e)if(n instanceof HTMLElement)Yn(n)};Jn();export{Jn as initVoiceHTMX};\n';
5190
5190
 
5191
5191
  // src/profileSwitchRecommendation.ts
5192
5192
  import { Elysia } from "elysia";
@@ -12557,6 +12557,8 @@ var createVoiceDiagnosticsRoutes = (options) => {
12557
12557
  import { Elysia as Elysia13 } from "elysia";
12558
12558
 
12559
12559
  // node_modules/@absolutejs/media/dist/index.js
12560
+ import { mkdir, writeFile } from "fs/promises";
12561
+ import { join } from "path";
12560
12562
  var formatLabel2 = (format) => `${format.container}/${format.encoding}/${String(format.sampleRateHz)}hz/${String(format.channels)}ch`;
12561
12563
  var formatMatches2 = (actual, expected) => actual.container === expected.container && actual.encoding === expected.encoding && actual.sampleRateHz === expected.sampleRateHz && actual.channels === expected.channels;
12562
12564
  var pushIssue = (issues, severity, code, message) => {
@@ -13217,6 +13219,269 @@ var buildMediaPipelineCalibrationReport = (input = {}) => {
13217
13219
  turnCommitFrames: turnCommitFrames.length
13218
13220
  };
13219
13221
  };
13222
+ var DEFAULT_METADATA_DENY = [
13223
+ "audioPayload",
13224
+ "auth",
13225
+ "authorization",
13226
+ "cookie",
13227
+ "email",
13228
+ "phone",
13229
+ "phoneNumber",
13230
+ "rawPayload",
13231
+ "secret",
13232
+ "token",
13233
+ "transcript",
13234
+ "utterance"
13235
+ ];
13236
+ var DEFAULT_TRUNCATE = 8;
13237
+ var issueCodes = (issues) => Array.from(new Set(issues.map((issue) => issue.code)));
13238
+ var lastEventKind = (events) => events[events.length - 1]?.kind;
13239
+ var formatOptionalMs = (value) => value === undefined ? "n/a" : `${String(Math.round(value))}ms`;
13240
+ var formatRatio = (value) => `${(value * 100).toFixed(1)}%`;
13241
+ var escapeMarkdownCell = (value) => value.replace(/\|/g, "\\|").replace(/\n/g, " ");
13242
+ var renderIssuesTable = (issues) => {
13243
+ if (issues.length === 0) {
13244
+ return `- No issues.
13245
+ `;
13246
+ }
13247
+ const rows = issues.map((issue) => `| ${issue.severity} | ${escapeMarkdownCell(issue.code)} | ${escapeMarkdownCell(issue.message)} |`).join(`
13248
+ `);
13249
+ return `| Severity | Code | Message |
13250
+ | --- | --- | --- |
13251
+ ${rows}
13252
+ `;
13253
+ };
13254
+ var summarizeMediaQualityReport = (report) => ({
13255
+ backpressureEvents: report.backpressureEvents,
13256
+ description: `${report.totalFrames} frame(s), ${report.gapCount} gap(s), speech ${formatRatio(report.speechRatio)}, status ${report.status}.`,
13257
+ driftMs: report.timestampDriftMs,
13258
+ frameCount: report.totalFrames,
13259
+ gapCount: report.gapCount,
13260
+ issueCodes: issueCodes(report.issues),
13261
+ issueCount: report.issues.length,
13262
+ jitterMs: report.jitterMs,
13263
+ silenceRatio: report.silenceRatio,
13264
+ speechRatio: report.speechRatio,
13265
+ status: report.status
13266
+ });
13267
+ var summarizeMediaTransportReport = (report) => ({
13268
+ backpressureEvents: report.backpressureEvents,
13269
+ description: `${report.name}: ${report.state}, in ${report.inputFrames}, out ${report.outputFrames}, backpressure ${report.backpressureEvents}.`,
13270
+ errors: report.events.filter((event) => event.kind === "error").length,
13271
+ inputFrames: report.inputFrames,
13272
+ lastEventKind: lastEventKind(report.events),
13273
+ name: report.name,
13274
+ outputFrames: report.outputFrames,
13275
+ state: report.state,
13276
+ status: report.status
13277
+ });
13278
+ var summarizeMediaProcessorGraphReport = (report) => {
13279
+ const errorIssueCodes = Array.from(new Set(report.errors.map((event) => event.kind)));
13280
+ return {
13281
+ backpressureEvents: report.backpressure.events.length,
13282
+ description: `${report.name}: ${report.state}, ${report.nodes.length} node(s), in ${report.inputFrames}, out ${report.emittedFrames}, dropped ${report.droppedFrames}.`,
13283
+ droppedFrames: report.droppedFrames,
13284
+ edgeCount: report.edges.length,
13285
+ edgeEventCount: report.edgeEvents.length,
13286
+ emittedFrames: report.emittedFrames,
13287
+ errorCount: report.errors.length,
13288
+ inputFrames: report.inputFrames,
13289
+ issueCodes: errorIssueCodes,
13290
+ lifecycleEventCount: report.lifecycleEvents.length,
13291
+ name: report.name,
13292
+ nodeCount: report.nodes.length,
13293
+ state: report.state,
13294
+ status: report.status,
13295
+ timingMaxMs: report.timing.maxNodeMs
13296
+ };
13297
+ };
13298
+ var renderMediaQualityMarkdown = (report, options = {}) => {
13299
+ const title = options.title ?? "Media Quality Report";
13300
+ const lines = [
13301
+ `# ${title}`,
13302
+ "",
13303
+ `Status: **${report.status}**`,
13304
+ "",
13305
+ "| Metric | Value |",
13306
+ "| --- | ---: |",
13307
+ `| Total frames | ${report.totalFrames} |`,
13308
+ `| Input audio | ${report.inputAudioFrames} |`,
13309
+ `| Assistant audio | ${report.assistantAudioFrames} |`,
13310
+ `| Gaps | ${report.gapCount} |`,
13311
+ `| Jitter | ${formatOptionalMs(report.jitterMs)} |`,
13312
+ `| Timestamp drift | ${formatOptionalMs(report.timestampDriftMs)} |`,
13313
+ `| Speech ratio | ${formatRatio(report.speechRatio)} |`,
13314
+ `| Silence ratio | ${formatRatio(report.silenceRatio)} |`,
13315
+ `| Backpressure events | ${report.backpressureEvents} |`,
13316
+ "",
13317
+ "## Issues",
13318
+ "",
13319
+ renderIssuesTable(report.issues).trimEnd()
13320
+ ];
13321
+ return `${lines.join(`
13322
+ `)}
13323
+ `;
13324
+ };
13325
+ var renderMediaTransportMarkdown = (report, options = {}) => {
13326
+ const title = options.title ?? `Media Transport: ${report.name}`;
13327
+ const limit = options.redact?.truncateArraysAt ?? DEFAULT_TRUNCATE;
13328
+ const events = report.events.slice(-limit);
13329
+ const eventRows = events.length === 0 ? "- No transport events recorded." : ["| At | Kind | State | Buffered | Error |", "| --- | --- | --- | ---: | --- |"].concat(events.map((event) => `| ${event.at} | ${event.kind} | ${event.state} | ${event.bufferedFrames ?? ""} | ${escapeMarkdownCell(event.error ?? "")} |`)).join(`
13330
+ `);
13331
+ const lines = [
13332
+ `# ${title}`,
13333
+ "",
13334
+ `Status: **${report.status}** \xB7 State: **${report.state}**`,
13335
+ "",
13336
+ "| Metric | Value |",
13337
+ "| --- | ---: |",
13338
+ `| Input frames | ${report.inputFrames} |`,
13339
+ `| Output frames | ${report.outputFrames} |`,
13340
+ `| Backpressure events | ${report.backpressureEvents} |`,
13341
+ `| Connected | ${report.connected ? "yes" : "no"} |`,
13342
+ `| Closed | ${report.closed ? "yes" : "no"} |`,
13343
+ `| Failed | ${report.failed ? "yes" : "no"} |`,
13344
+ "",
13345
+ `## Last ${events.length} event(s)`,
13346
+ "",
13347
+ eventRows
13348
+ ];
13349
+ return `${lines.join(`
13350
+ `)}
13351
+ `;
13352
+ };
13353
+ var renderMediaProcessorGraphMarkdown = (report, options = {}) => {
13354
+ const title = options.title ?? `Media Processor Graph: ${report.name}`;
13355
+ const limit = options.redact?.truncateArraysAt ?? DEFAULT_TRUNCATE;
13356
+ const nodeRows = report.nodes.map((node) => `| ${escapeMarkdownCell(node.name)} | ${node.kind} | ${node.status} | ${node.inputFrames} | ${node.emittedFrames} | ${node.droppedFrames} | ${node.errors.length} |`).join(`
13357
+ `);
13358
+ const edgeRows = report.edges.slice(0, limit).map((edge) => `| ${escapeMarkdownCell(edge.from)} | ${escapeMarkdownCell(edge.to)} | ${edge.status} | ${edge.emittedFrames} |`).join(`
13359
+ `);
13360
+ const issues = report.errors.map((event) => ({
13361
+ code: event.kind,
13362
+ message: event.error ?? `Processor graph ${event.kind} (state ${event.state}).`,
13363
+ severity: "error"
13364
+ }));
13365
+ const lines = [
13366
+ `# ${title}`,
13367
+ "",
13368
+ `Status: **${report.status}** \xB7 State: **${report.state}**`,
13369
+ "",
13370
+ "| Metric | Value |",
13371
+ "| --- | ---: |",
13372
+ `| Nodes | ${report.nodes.length} |`,
13373
+ `| Input frames | ${report.inputFrames} |`,
13374
+ `| Emitted frames | ${report.emittedFrames} |`,
13375
+ `| Dropped frames | ${report.droppedFrames} |`,
13376
+ `| Lifecycle events | ${report.lifecycleEvents.length} |`,
13377
+ `| Edge events | ${report.edgeEvents.length} |`,
13378
+ `| Backpressure events | ${report.backpressure.events.length} |`,
13379
+ `| Timing max | ${formatOptionalMs(report.timing.maxNodeMs)} |`,
13380
+ `| Timing average | ${formatOptionalMs(report.timing.averageNodeMs)} |`,
13381
+ "",
13382
+ "## Nodes",
13383
+ "",
13384
+ nodeRows ? `| Node | Kind | Status | In | Out | Dropped | Errors |
13385
+ | --- | --- | --- | ---: | ---: | ---: | ---: |
13386
+ ${nodeRows}` : "- No nodes.",
13387
+ "",
13388
+ `## Edges (showing up to ${limit})`,
13389
+ "",
13390
+ edgeRows ? `| From | To | Status | Frames |
13391
+ | --- | --- | --- | ---: |
13392
+ ${edgeRows}` : "- No edges.",
13393
+ "",
13394
+ "## Errors",
13395
+ "",
13396
+ renderIssuesTable(issues).trimEnd()
13397
+ ];
13398
+ return `${lines.join(`
13399
+ `)}
13400
+ `;
13401
+ };
13402
+ var truncateArrays = (value, limit, seen) => {
13403
+ if (Array.isArray(value)) {
13404
+ const head = value.slice(0, limit).map((entry) => truncateArrays(entry, limit, seen));
13405
+ if (value.length > limit) {
13406
+ return [...head, { truncated: value.length - limit }];
13407
+ }
13408
+ return head;
13409
+ }
13410
+ if (value && typeof value === "object") {
13411
+ if (seen.has(value))
13412
+ return value;
13413
+ seen.add(value);
13414
+ const next = {};
13415
+ for (const [key, entry] of Object.entries(value)) {
13416
+ next[key] = truncateArrays(entry, limit, seen);
13417
+ }
13418
+ return next;
13419
+ }
13420
+ return value;
13421
+ };
13422
+ var applyRedaction = (value, options, seen) => {
13423
+ const mode = options.mode ?? "omit";
13424
+ const maskValue = options.maskValue ?? "[redacted]";
13425
+ const allow = new Set(options.metadataAllow ?? []);
13426
+ const deny = new Set(options.metadataDeny ?? DEFAULT_METADATA_DENY);
13427
+ const walk = (input) => {
13428
+ if (Array.isArray(input)) {
13429
+ return input.map((entry) => walk(entry));
13430
+ }
13431
+ if (input && typeof input === "object") {
13432
+ if (seen.has(input))
13433
+ return input;
13434
+ seen.add(input);
13435
+ const next = {};
13436
+ for (const [key, entry] of Object.entries(input)) {
13437
+ if (allow.has(key)) {
13438
+ next[key] = entry;
13439
+ continue;
13440
+ }
13441
+ if (deny.has(key)) {
13442
+ if (mode === "mask")
13443
+ next[key] = maskValue;
13444
+ continue;
13445
+ }
13446
+ next[key] = walk(entry);
13447
+ }
13448
+ return next;
13449
+ }
13450
+ return input;
13451
+ };
13452
+ return walk(value);
13453
+ };
13454
+ var redactMediaReport = (report, options = {}) => {
13455
+ const limit = options.truncateArraysAt ?? DEFAULT_TRUNCATE;
13456
+ const truncated = truncateArrays(report, limit, new WeakSet);
13457
+ return applyRedaction(truncated, options, new WeakSet);
13458
+ };
13459
+ var buildArtifactPair = (report, summary, markdown, options) => {
13460
+ const jsonValue = options.redact ? redactMediaReport(report, options.redact) : report;
13461
+ return {
13462
+ json: JSON.stringify(jsonValue, null, 2),
13463
+ jsonValue,
13464
+ markdown,
13465
+ summary
13466
+ };
13467
+ };
13468
+ var buildMediaQualityArtifact = (report, options = {}) => buildArtifactPair(report, summarizeMediaQualityReport(report), renderMediaQualityMarkdown(report, options), options);
13469
+ var buildMediaTransportArtifact = (report, options = {}) => buildArtifactPair(report, summarizeMediaTransportReport(report), renderMediaTransportMarkdown(report, options), options);
13470
+ var buildMediaProcessorGraphArtifact = (report, options = {}) => buildArtifactPair(report, summarizeMediaProcessorGraphReport(report), renderMediaProcessorGraphMarkdown(report, options), options);
13471
+ var writeMediaArtifact = async (input) => {
13472
+ await mkdir(input.dir, { recursive: true });
13473
+ const jsonPath = join(input.dir, `${input.slug}.json`);
13474
+ const markdownPath = join(input.dir, `${input.slug}.md`);
13475
+ await Promise.all([
13476
+ writeFile(jsonPath, input.json, "utf8"),
13477
+ writeFile(markdownPath, input.markdown, "utf8")
13478
+ ]);
13479
+ return {
13480
+ jsonPath,
13481
+ markdownPath,
13482
+ summary: input.summary
13483
+ };
13484
+ };
13220
13485
 
13221
13486
  // src/mediaPipelineRoutes.ts
13222
13487
  var escapeHtml16 = (value) => String(value).replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
@@ -13460,6 +13725,70 @@ var createVoiceMediaPipelineRoutes = (options = {}) => {
13460
13725
  }
13461
13726
  return app;
13462
13727
  };
13728
+ var PROOF_SUMMARY_ISSUE_LIMIT = 8;
13729
+ var collectIssueCodes = (issues) => Array.from(new Set(issues.map((issue) => issue.code)));
13730
+ var summarizeVoiceMediaPipelineReport = (report, options = {}) => {
13731
+ const calibration = report.calibration;
13732
+ const quality = summarizeMediaQualityReport(report.quality);
13733
+ const processorGraph = report.processorGraph ? summarizeMediaProcessorGraphReport(report.processorGraph) : undefined;
13734
+ const transport = report.transport ? summarizeMediaTransportReport(report.transport) : undefined;
13735
+ const interruptionIssueCodes = collectIssueCodes(report.interruption.issues);
13736
+ const issueCodes2 = Array.from(new Set([
13737
+ ...collectIssueCodes(calibration.issues),
13738
+ ...quality.issueCodes,
13739
+ ...interruptionIssueCodes,
13740
+ ...processorGraph?.issueCodes ?? []
13741
+ ]));
13742
+ const issues = [
13743
+ ...calibration.issues,
13744
+ ...report.quality.issues,
13745
+ ...report.interruption.issues
13746
+ ].slice(0, PROOF_SUMMARY_ISSUE_LIMIT);
13747
+ return {
13748
+ artifacts: options.artifacts,
13749
+ calibration: {
13750
+ assistantAudioFrames: calibration.assistantAudioFrames,
13751
+ backpressureFrames: calibration.backpressureFrames,
13752
+ firstAudioLatencyMs: calibration.firstAudioLatencyMs,
13753
+ inputAudioFrames: calibration.inputAudioFrames,
13754
+ interruptionFrames: calibration.interruptionFrames,
13755
+ issueCodes: collectIssueCodes(calibration.issues),
13756
+ jitterMs: calibration.jitterMs,
13757
+ resamplingRequired: calibration.resamplingRequired,
13758
+ status: calibration.status,
13759
+ surface: calibration.surface,
13760
+ traceLinkedFrames: calibration.traceLinkedFrames,
13761
+ turnCommitFrames: calibration.turnCommitFrames
13762
+ },
13763
+ checkedAt: report.checkedAt,
13764
+ frames: report.frames,
13765
+ interruption: {
13766
+ interruptionFrames: report.interruption.interruptionFrames,
13767
+ issueCodes: interruptionIssueCodes,
13768
+ latenciesMs: report.interruption.latenciesMs,
13769
+ status: report.interruption.status
13770
+ },
13771
+ issueCodes: issueCodes2,
13772
+ issues,
13773
+ ok: report.ok,
13774
+ processorGraph,
13775
+ quality,
13776
+ resampling: report.resampling ? {
13777
+ ratio: report.resampling.ratio,
13778
+ required: report.resampling.required,
13779
+ status: report.resampling.status
13780
+ } : undefined,
13781
+ sessionIds: report.sessionIds,
13782
+ status: report.status,
13783
+ surface: report.surface,
13784
+ transport,
13785
+ vad: {
13786
+ inputAudioFrames: report.vad.inputAudioFrames,
13787
+ segmentCount: report.vad.segments.length,
13788
+ status: report.vad.status
13789
+ }
13790
+ };
13791
+ };
13463
13792
  // src/telephonyMediaRoutes.ts
13464
13793
  import { Elysia as Elysia14 } from "elysia";
13465
13794
  var demoPayload = Buffer.from(new Uint8Array([1, 2, 3, 4])).toString("base64");
@@ -13964,6 +14293,213 @@ var createVoiceBrowserCallProfileRoutes = (options = {}) => {
13964
14293
  }
13965
14294
  return routes;
13966
14295
  };
14296
+ // src/mediaPipelineSurfaces.ts
14297
+ var calibrationIssues = (report) => report.calibration.issues.map((issue) => ({
14298
+ code: issue.code,
14299
+ message: issue.message,
14300
+ severity: issue.severity,
14301
+ source: "calibration",
14302
+ surface: report.surface
14303
+ }));
14304
+ var qualityIssues = (report) => report.quality.issues.map((issue) => ({
14305
+ code: issue.code,
14306
+ message: issue.message,
14307
+ severity: issue.severity,
14308
+ source: "quality",
14309
+ surface: report.surface
14310
+ }));
14311
+ var interruptionIssues = (report) => report.interruption.issues.map((issue) => ({
14312
+ code: issue.code,
14313
+ message: issue.message,
14314
+ severity: issue.severity,
14315
+ source: "interruption",
14316
+ surface: report.surface
14317
+ }));
14318
+ var transportIssues = (report) => {
14319
+ if (!report.transport)
14320
+ return [];
14321
+ const entries = [];
14322
+ if (report.transport.failed) {
14323
+ entries.push({
14324
+ code: "media.transport_failed",
14325
+ message: `Media transport ${report.transport.name} entered the failed state.`,
14326
+ severity: "error",
14327
+ source: "transport",
14328
+ surface: report.surface
14329
+ });
14330
+ }
14331
+ if (report.transport.backpressureEvents > 0) {
14332
+ entries.push({
14333
+ code: "media.transport_backpressure",
14334
+ message: `Media transport ${report.transport.name} reported ${String(report.transport.backpressureEvents)} backpressure event(s).`,
14335
+ severity: "warning",
14336
+ source: "transport",
14337
+ surface: report.surface
14338
+ });
14339
+ }
14340
+ const errorEvents = report.transport.events.filter((event) => event.kind === "error");
14341
+ for (const event of errorEvents) {
14342
+ entries.push({
14343
+ code: "media.transport_error",
14344
+ message: event.error ?? "Media transport error event.",
14345
+ severity: "error",
14346
+ source: "transport",
14347
+ surface: report.surface
14348
+ });
14349
+ }
14350
+ return entries;
14351
+ };
14352
+ var processorGraphIssues = (report) => {
14353
+ if (!report.processorGraph)
14354
+ return [];
14355
+ return report.processorGraph.errors.map((event) => ({
14356
+ code: `media.graph_${event.kind}`,
14357
+ message: event.error ?? `Processor graph reported ${event.kind} (state ${event.state}).`,
14358
+ severity: "error",
14359
+ source: "processor-graph",
14360
+ surface: report.surface
14361
+ }));
14362
+ };
14363
+ var extractVoiceMediaPipelineIssueEntries = (report) => [
14364
+ ...calibrationIssues(report),
14365
+ ...qualityIssues(report),
14366
+ ...interruptionIssues(report),
14367
+ ...transportIssues(report),
14368
+ ...processorGraphIssues(report)
14369
+ ];
14370
+ var toReadinessStatus = (status) => status === "fail" ? "fail" : status === "warn" ? "warn" : "pass";
14371
+ var readinessStatusFromIssues = (issues) => {
14372
+ if (issues.some((issue) => issue.severity === "error"))
14373
+ return "fail";
14374
+ if (issues.length > 0)
14375
+ return "warn";
14376
+ return "pass";
14377
+ };
14378
+ var buildVoiceMediaPipelineReadinessChecks = (report, options = {}) => {
14379
+ const baseHref = options.baseHref ?? "/voice/media-pipeline";
14380
+ const label = options.label ?? "Media pipeline";
14381
+ const checks = [
14382
+ {
14383
+ detail: `Status ${report.status}, surface ${report.surface}, ${String(report.frames)} frame(s).`,
14384
+ href: baseHref,
14385
+ label: `${label}: overall`,
14386
+ status: toReadinessStatus(report.status)
14387
+ },
14388
+ {
14389
+ detail: `${String(report.quality.issues.length)} quality issue(s); gaps ${String(report.quality.gapCount)}, jitter ${String(report.quality.jitterMs ?? "n/a")}ms, speech ratio ${(report.quality.speechRatio * 100).toFixed(1)}%.`,
14390
+ href: baseHref,
14391
+ label: `${label}: media quality`,
14392
+ status: toReadinessStatus(report.quality.status),
14393
+ value: report.quality.gapCount
14394
+ }
14395
+ ];
14396
+ if (report.transport) {
14397
+ checks.push({
14398
+ detail: `${report.transport.state}, in ${String(report.transport.inputFrames)}, out ${String(report.transport.outputFrames)}, backpressure ${String(report.transport.backpressureEvents)}.`,
14399
+ href: baseHref,
14400
+ label: `${label}: transport`,
14401
+ status: toReadinessStatus(report.transport.status),
14402
+ value: report.transport.state
14403
+ });
14404
+ }
14405
+ if (report.processorGraph) {
14406
+ checks.push({
14407
+ detail: `${report.processorGraph.state}, nodes ${String(report.processorGraph.nodes.length)}, errors ${String(report.processorGraph.errors.length)}, dropped ${String(report.processorGraph.droppedFrames)}.`,
14408
+ href: baseHref,
14409
+ label: `${label}: processor graph`,
14410
+ status: toReadinessStatus(report.processorGraph.status),
14411
+ value: report.processorGraph.state
14412
+ });
14413
+ }
14414
+ checks.push({
14415
+ detail: `${String(report.interruption.interruptionFrames)} interruption frame(s); ${String(report.interruption.issues.length)} issue(s).`,
14416
+ href: baseHref,
14417
+ label: `${label}: interruption`,
14418
+ status: readinessStatusFromIssues(report.interruption.issues),
14419
+ value: report.interruption.interruptionFrames
14420
+ });
14421
+ return checks;
14422
+ };
14423
+ var severityToIncident = (severity) => severity === "error" ? "critical" : "warn";
14424
+ var sourceSuffix = {
14425
+ calibration: "calibration",
14426
+ interruption: "interruption",
14427
+ "processor-graph": "graph",
14428
+ quality: "quality",
14429
+ transport: "transport"
14430
+ };
14431
+ var buildVoiceMediaPipelineIncidentEvents = (report, options = {}) => {
14432
+ const baseHref = options.baseHref ?? "/voice/media-pipeline";
14433
+ const category = options.category ?? "monitor";
14434
+ const source = options.source ?? "media-pipeline";
14435
+ const now = options.now ?? (() => Date.now());
14436
+ const at = now();
14437
+ const entries = extractVoiceMediaPipelineIssueEntries(report);
14438
+ return entries.map((entry, index) => ({
14439
+ at,
14440
+ category,
14441
+ detail: entry.message,
14442
+ href: baseHref,
14443
+ id: `media-pipeline:${sourceSuffix[entry.source]}:${entry.code}:${String(index)}`,
14444
+ label: `Media ${sourceSuffix[entry.source]} ${entry.severity}: ${entry.code}`,
14445
+ severity: severityToIncident(entry.severity),
14446
+ source,
14447
+ value: entry.code
14448
+ }));
14449
+ };
14450
+ var buildHref = (base, jsonPath, fallbackSlug) => {
14451
+ if (!base)
14452
+ return;
14453
+ const filename = jsonPath.split("/").pop() ?? `${fallbackSlug}.json`;
14454
+ return `${base.replace(/\/$/, "")}/${filename}`;
14455
+ };
14456
+ var recordFromWrite = (kind, write, hrefBase, slug) => ({
14457
+ href: buildHref(hrefBase, write.jsonPath, slug),
14458
+ jsonPath: write.jsonPath,
14459
+ kind,
14460
+ markdownPath: write.markdownPath,
14461
+ summary: write.summary
14462
+ });
14463
+ var writeVoiceMediaPipelineArtifacts = async (options) => {
14464
+ const slugPrefix = options.slugPrefix ?? "media";
14465
+ const qualitySlug = `${slugPrefix}-quality`;
14466
+ const transportSlug = `${slugPrefix}-transport`;
14467
+ const graphSlug = `${slugPrefix}-processor-graph`;
14468
+ const artifacts = [];
14469
+ const hrefs = {};
14470
+ const qualityArtifact = buildMediaQualityArtifact(options.report.quality);
14471
+ const qualityWrite = await writeMediaArtifact({
14472
+ dir: options.dir,
14473
+ slug: qualitySlug,
14474
+ ...qualityArtifact
14475
+ });
14476
+ const qualityRecord = recordFromWrite("quality", qualityWrite, options.hrefBase, qualitySlug);
14477
+ artifacts.push(qualityRecord);
14478
+ hrefs.quality = qualityRecord.href;
14479
+ if (options.report.transport) {
14480
+ const transportArtifact = buildMediaTransportArtifact(options.report.transport);
14481
+ const transportWrite = await writeMediaArtifact({
14482
+ dir: options.dir,
14483
+ slug: transportSlug,
14484
+ ...transportArtifact
14485
+ });
14486
+ const transportRecord = recordFromWrite("transport", transportWrite, options.hrefBase, transportSlug);
14487
+ artifacts.push(transportRecord);
14488
+ hrefs.transport = transportRecord.href;
14489
+ }
14490
+ if (options.report.processorGraph) {
14491
+ const graphArtifact = buildMediaProcessorGraphArtifact(options.report.processorGraph);
14492
+ const graphWrite = await writeMediaArtifact({
14493
+ dir: options.dir,
14494
+ slug: graphSlug,
14495
+ ...graphArtifact
14496
+ });
14497
+ const graphRecord = recordFromWrite("processor-graph", graphWrite, options.hrefBase, graphSlug);
14498
+ artifacts.push(graphRecord);
14499
+ hrefs.processorGraph = graphRecord.href;
14500
+ }
14501
+ return { artifacts, hrefs };
14502
+ };
13967
14503
  // src/demoReadyRoutes.ts
13968
14504
  import { Elysia as Elysia17 } from "elysia";
13969
14505
  var escapeHtml20 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
@@ -16864,7 +17400,38 @@ var resolveRealCallEvidenceRuntimeReconnectReports = async (reports, options) =>
16864
17400
  }
16865
17401
  return Array.isArray(resolved) ? resolved : [resolved];
16866
17402
  };
17403
+ var resolveRealCallEvidenceRuntimeSurfaceEvidence = async (source, options) => {
17404
+ const resolved = typeof source === "function" ? await source(options) : source;
17405
+ if (!resolved) {
17406
+ return [];
17407
+ }
17408
+ return Array.isArray(resolved) ? [...resolved] : [resolved];
17409
+ };
17410
+ var createRealCallEvidenceRuntimeSessionId = (prefix, generatedAt) => `${prefix}-${Date.parse(generatedAt) || Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
17411
+ var buildVoiceRealCallProfileEvidenceFromRuntimeSurface = (input, options) => {
17412
+ const evidence = Array.isArray(input) ? input : [input];
17413
+ return evidence.map((item) => {
17414
+ const generatedAt = item.generatedAt ?? (options.now ?? (() => new Date))().toISOString();
17415
+ return {
17416
+ ...item,
17417
+ generatedAt,
17418
+ profileId: item.profileId ?? options.defaultProfileId,
17419
+ providers: item.providers ? [...item.providers] : undefined,
17420
+ sessionId: item.sessionId ?? createRealCallEvidenceRuntimeSessionId(options.defaultSessionPrefix, generatedAt),
17421
+ surfaces: [
17422
+ ...new Set([...item.surfaces ?? [], ...options.defaultSurfaces])
17423
+ ].sort()
17424
+ };
17425
+ });
17426
+ };
17427
+ var buildVoiceRealCallProfileEvidenceFromRuntimeProviderRoles = (input, options = {}) => buildVoiceRealCallProfileEvidenceFromRuntimeSurface(input, {
17428
+ defaultProfileId: options.defaultProfileId ?? "provider-role-evidence",
17429
+ defaultSessionPrefix: options.defaultSessionPrefix ?? "provider-role-evidence",
17430
+ defaultSurfaces: ["provider-path"],
17431
+ now: options.now
17432
+ });
16867
17433
  var mergeRealCallEvidenceRuntimeOptions = (base, override = {}) => ({
17434
+ browserEvidence: override.browserEvidence ?? base.browserEvidence,
16868
17435
  dedupe: override.dedupe ?? base.dedupe,
16869
17436
  evidenceStore: override.evidenceStore ?? base.evidenceStore,
16870
17437
  existingEvidenceLimit: override.existingEvidenceLimit ?? base.existingEvidenceLimit,
@@ -16873,6 +17440,8 @@ var mergeRealCallEvidenceRuntimeOptions = (base, override = {}) => ({
16873
17440
  ...override.history ?? {}
16874
17441
  },
16875
17442
  now: override.now ?? base.now,
17443
+ phoneEvidence: override.phoneEvidence ?? base.phoneEvidence,
17444
+ providerRoleEvidence: override.providerRoleEvidence ?? base.providerRoleEvidence,
16876
17445
  reconnectEvidence: {
16877
17446
  ...base.reconnectEvidence ?? {},
16878
17447
  ...override.reconnectEvidence ?? {}
@@ -16921,6 +17490,30 @@ var buildRealCallEvidenceRuntimeReport = async (options, input = {}) => {
16921
17490
  };
16922
17491
  var collectVoiceRealCallEvidenceRuntimeEvidence = async (options) => {
16923
17492
  const evidence = [];
17493
+ const browserEvidence = await resolveRealCallEvidenceRuntimeSurfaceEvidence(options.browserEvidence, options);
17494
+ if (browserEvidence.length > 0) {
17495
+ evidence.push(...buildVoiceRealCallProfileEvidenceFromRuntimeSurface(browserEvidence, {
17496
+ defaultProfileId: "browser-call",
17497
+ defaultSessionPrefix: "browser-call",
17498
+ defaultSurfaces: ["browser"],
17499
+ now: options.now
17500
+ }));
17501
+ }
17502
+ const phoneEvidence = await resolveRealCallEvidenceRuntimeSurfaceEvidence(options.phoneEvidence, options);
17503
+ if (phoneEvidence.length > 0) {
17504
+ evidence.push(...buildVoiceRealCallProfileEvidenceFromRuntimeSurface(phoneEvidence, {
17505
+ defaultProfileId: "phone-agent",
17506
+ defaultSessionPrefix: "phone-agent",
17507
+ defaultSurfaces: ["phone", "telephony"],
17508
+ now: options.now
17509
+ }));
17510
+ }
17511
+ const providerRoleEvidence = await resolveRealCallEvidenceRuntimeSurfaceEvidence(options.providerRoleEvidence, options);
17512
+ if (providerRoleEvidence.length > 0) {
17513
+ evidence.push(...buildVoiceRealCallProfileEvidenceFromRuntimeProviderRoles(providerRoleEvidence, {
17514
+ now: options.now
17515
+ }));
17516
+ }
16924
17517
  if (options.traceStore) {
16925
17518
  evidence.push(...buildVoiceRealCallProfileEvidenceFromTraceEvents(await options.traceStore.list({
16926
17519
  limit: options.traceEvidence?.limit ?? 5000
@@ -21756,8 +22349,8 @@ var createVoiceLiveOpsRoutes = (options = {}) => {
21756
22349
  };
21757
22350
  // src/deliveryRuntime.ts
21758
22351
  import { Elysia as Elysia32 } from "elysia";
21759
- import { mkdir } from "fs/promises";
21760
- import { dirname, join } from "path";
22352
+ import { mkdir as mkdir2 } from "fs/promises";
22353
+ import { dirname, join as join2 } from "path";
21761
22354
  var escapeHtml32 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
21762
22355
  var renderSummaryCard = (label, summary) => {
21763
22356
  if (!summary) {
@@ -21782,8 +22375,8 @@ var createDeliveryRuntimeFileSink = (input) => ({
21782
22375
  deliver: async ({ events }) => {
21783
22376
  const firstEvent = events[0];
21784
22377
  const fileName = `${Date.now()}-${encodeURIComponent(firstEvent?.id ?? crypto.randomUUID())}.json`;
21785
- const path = join(input.directory, input.kind, fileName);
21786
- await mkdir(dirname(path), { recursive: true });
22378
+ const path = join2(input.directory, input.kind, fileName);
22379
+ await mkdir2(dirname(path), { recursive: true });
21787
22380
  await Bun.write(path, JSON.stringify({
21788
22381
  eventCount: events.length,
21789
22382
  events,
@@ -22045,10 +22638,10 @@ var createVoiceDeliveryRuntimeRoutes = (options) => {
22045
22638
  return routes;
22046
22639
  };
22047
22640
  // src/operationalStatus.ts
22048
- import { Elysia as Elysia46 } from "elysia";
22641
+ import { Elysia as Elysia47 } from "elysia";
22049
22642
 
22050
22643
  // src/productionReadiness.ts
22051
- import { Elysia as Elysia45 } from "elysia";
22644
+ import { Elysia as Elysia46 } from "elysia";
22052
22645
 
22053
22646
  // src/handoffHealth.ts
22054
22647
  import { Elysia as Elysia33 } from "elysia";
@@ -26620,8 +27213,336 @@ var createVoiceProviderSloRoutes = (options) => {
26620
27213
  return app;
26621
27214
  };
26622
27215
 
26623
- // src/opsRecovery.ts
27216
+ // src/sessionObservability.ts
26624
27217
  import { Elysia as Elysia42 } from "elysia";
27218
+ var escapeHtml40 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
27219
+ var formatMs4 = (value) => value === undefined ? "n/a" : `${String(value)}ms`;
27220
+ var resolveHref = (href, sessionId) => {
27221
+ if (href === false) {
27222
+ return;
27223
+ }
27224
+ if (typeof href === "function") {
27225
+ return href(sessionId);
27226
+ }
27227
+ if (typeof href === "string") {
27228
+ return href.includes(":sessionId") ? href.replaceAll(":sessionId", encodeURIComponent(sessionId)) : `${href.replace(/\/$/, "")}/${encodeURIComponent(sessionId)}`;
27229
+ }
27230
+ return;
27231
+ };
27232
+ var buildLinks = (options) => {
27233
+ const links = [];
27234
+ const add = (rel, label, href) => {
27235
+ if (href) {
27236
+ links.push({ href, label, rel });
27237
+ }
27238
+ };
27239
+ add("operations-record", "Open operations record", resolveHref(options.operationsRecordHref, options.sessionId));
27240
+ add("trace-timeline", "Open trace timeline", resolveHref(options.traceTimelineHref, options.sessionId));
27241
+ add("call-debugger", "Open call debugger", resolveHref(options.callDebuggerHref, options.sessionId));
27242
+ add("incident-markdown", "Download incident Markdown", resolveHref(options.incidentMarkdownHref, options.sessionId));
27243
+ return [...links, ...options.customLinks ?? []];
27244
+ };
27245
+ var buildTurnWaterfalls = (record) => {
27246
+ const byTurn = new Map;
27247
+ const getTurn = (turnId) => {
27248
+ const existing = byTurn.get(turnId);
27249
+ if (existing) {
27250
+ return existing;
27251
+ }
27252
+ const turn = {
27253
+ assistantReplies: 0,
27254
+ errors: 0,
27255
+ providerDecisions: 0,
27256
+ stages: [],
27257
+ toolCalls: 0,
27258
+ transcripts: 0
27259
+ };
27260
+ byTurn.set(turnId, turn);
27261
+ return turn;
27262
+ };
27263
+ for (const event of record.timeline) {
27264
+ if (!event.turnId) {
27265
+ continue;
27266
+ }
27267
+ const turn = getTurn(event.turnId);
27268
+ turn.stages.push({
27269
+ at: event.at,
27270
+ elapsedMs: event.elapsedMs,
27271
+ label: event.label,
27272
+ offsetMs: event.offsetMs,
27273
+ provider: event.provider,
27274
+ status: event.status,
27275
+ type: event.type
27276
+ });
27277
+ if (event.type === "turn.transcript") {
27278
+ turn.transcripts += 1;
27279
+ }
27280
+ if (event.type === "turn.assistant") {
27281
+ turn.assistantReplies += 1;
27282
+ }
27283
+ if (event.type === "agent.tool") {
27284
+ turn.toolCalls += 1;
27285
+ }
27286
+ if (event.type === "provider.decision") {
27287
+ turn.providerDecisions += 1;
27288
+ }
27289
+ if (event.type === "session.error" || event.status === "error") {
27290
+ turn.errors += 1;
27291
+ }
27292
+ }
27293
+ for (const transcript of record.transcript) {
27294
+ const turn = getTurn(transcript.id);
27295
+ turn.assistantReplies = Math.max(turn.assistantReplies, transcript.assistantReplies.length);
27296
+ turn.errors += transcript.errors.length;
27297
+ turn.transcripts = Math.max(turn.transcripts, transcript.transcripts.length);
27298
+ }
27299
+ return [...byTurn.entries()].map(([turnId, turn]) => {
27300
+ const startedAt = turn.stages[0]?.at;
27301
+ const endedAt = turn.stages.at(-1)?.at;
27302
+ return {
27303
+ assistantReplies: turn.assistantReplies,
27304
+ durationMs: startedAt !== undefined && endedAt !== undefined ? Math.max(0, endedAt - startedAt) : undefined,
27305
+ endedAt,
27306
+ errors: turn.errors,
27307
+ providerDecisions: turn.providerDecisions,
27308
+ stages: turn.stages,
27309
+ startedAt,
27310
+ toolCalls: turn.toolCalls,
27311
+ transcripts: turn.transcripts,
27312
+ turnId
27313
+ };
27314
+ }).sort((left, right) => (left.startedAt ?? 0) - (right.startedAt ?? 0));
27315
+ };
27316
+ var buildVoiceSessionObservabilityReport = async (options) => {
27317
+ const record = await buildVoiceOperationsRecord({
27318
+ audit: options.audit,
27319
+ evaluation: options.evaluation,
27320
+ events: options.events,
27321
+ integrationEvents: options.integrationEvents,
27322
+ redact: options.redact,
27323
+ reviews: options.reviews,
27324
+ sessionId: options.sessionId,
27325
+ store: options.store,
27326
+ tasks: options.tasks
27327
+ });
27328
+ const failureReplay = buildVoiceFailureReplay(record, {
27329
+ operationsRecordHref: resolveHref(options.operationsRecordHref, options.sessionId)
27330
+ });
27331
+ const incidentMarkdown = renderVoiceOperationsRecordIncidentMarkdown(record);
27332
+ const statuses = [
27333
+ record.status,
27334
+ failureReplay.status === "failed" ? "failed" : failureReplay.status === "degraded" ? "warning" : "healthy"
27335
+ ];
27336
+ const status = statuses.includes("failed") ? "failed" : statuses.includes("warning") ? "warning" : "healthy";
27337
+ return {
27338
+ checkedAt: Date.now(),
27339
+ failureReplay,
27340
+ incidentMarkdown,
27341
+ links: buildLinks(options),
27342
+ record,
27343
+ sessionId: options.sessionId,
27344
+ status,
27345
+ summary: {
27346
+ durationMs: record.summary.callDurationMs,
27347
+ errors: record.summary.errorCount,
27348
+ events: record.summary.eventCount,
27349
+ fallbacks: record.providerDecisionSummary.fallbacks,
27350
+ guardrailBlocks: record.guardrails.blocked,
27351
+ handoffs: record.handoffs.length,
27352
+ providerRecoveryStatus: record.providerDecisionSummary.recoveryStatus,
27353
+ providers: record.providerDecisionSummary.providers,
27354
+ telephonyMediaEvents: record.telephonyMedia.total,
27355
+ toolCalls: record.tools.length,
27356
+ turns: record.summary.turnCount
27357
+ },
27358
+ turns: buildTurnWaterfalls(record)
27359
+ };
27360
+ };
27361
+ var renderLinks = (links) => links.length === 0 ? "" : `<div class="actions">${links.map((link) => `<a href="${escapeHtml40(link.href)}">${escapeHtml40(link.label)}</a>`).join("")}</div>`;
27362
+ var renderTurns = (turns) => turns.length === 0 ? '<p class="muted">No turn-level events recorded yet.</p>' : turns.map((turn) => `<article class="turn"><header><strong>${escapeHtml40(turn.turnId)}</strong><span>${formatMs4(turn.durationMs)}</span></header><dl><div><dt>Transcripts</dt><dd>${String(turn.transcripts)}</dd></div><div><dt>Assistant</dt><dd>${String(turn.assistantReplies)}</dd></div><div><dt>Tools</dt><dd>${String(turn.toolCalls)}</dd></div><div><dt>Providers</dt><dd>${String(turn.providerDecisions)}</dd></div><div><dt>Errors</dt><dd>${String(turn.errors)}</dd></div></dl><table><thead><tr><th>Offset</th><th>Type</th><th>Stage</th><th>Provider</th><th>Status</th><th>Latency</th></tr></thead><tbody>${turn.stages.map((stage) => `<tr><td>+${String(stage.offsetMs)}ms</td><td>${escapeHtml40(stage.type)}</td><td>${escapeHtml40(stage.label)}</td><td>${escapeHtml40(stage.provider ?? "")}</td><td>${escapeHtml40(stage.status ?? "")}</td><td>${formatMs4(stage.elapsedMs)}</td></tr>`).join("")}</tbody></table></article>`).join("");
27363
+ var renderVoiceSessionObservabilityMarkdown = (report) => `# Voice session observability: ${report.sessionId}
27364
+
27365
+ Status: ${report.status}
27366
+
27367
+ - Events: ${report.summary.events}
27368
+ - Turns: ${report.summary.turns}
27369
+ - Errors: ${report.summary.errors}
27370
+ - Duration: ${formatMs4(report.summary.durationMs)}
27371
+ - Providers: ${report.summary.providers.join(", ") || "none"}
27372
+ - Provider recovery: ${report.summary.providerRecoveryStatus}
27373
+ - Fallbacks: ${report.summary.fallbacks}
27374
+ - Tool calls: ${report.summary.toolCalls}
27375
+ - Handoffs: ${report.summary.handoffs}
27376
+ - Guardrail blocks: ${report.summary.guardrailBlocks}
27377
+ - Telephony media events: ${report.summary.telephonyMediaEvents}
27378
+
27379
+ ## Links
27380
+
27381
+ ${report.links.length ? report.links.map((link) => `- [${link.label}](${link.href})`).join(`
27382
+ `) : "- none"}
27383
+
27384
+ ## Turn Waterfalls
27385
+
27386
+ ${report.turns.length ? report.turns.map((turn) => `### ${turn.turnId}
27387
+
27388
+ - Duration: ${formatMs4(turn.durationMs)}
27389
+ - Transcripts: ${turn.transcripts}
27390
+ - Assistant replies: ${turn.assistantReplies}
27391
+ - Tool calls: ${turn.toolCalls}
27392
+ - Provider decisions: ${turn.providerDecisions}
27393
+ - Errors: ${turn.errors}
27394
+
27395
+ ${turn.stages.map((stage) => `- +${stage.offsetMs}ms ${stage.type}: ${stage.label}${stage.provider ? ` (${stage.provider})` : ""}${stage.status ? ` [${stage.status}]` : ""}`).join(`
27396
+ `)}`).join(`
27397
+
27398
+ `) : "No turn-level events recorded."}
27399
+
27400
+ ## Incident Handoff
27401
+
27402
+ ${report.incidentMarkdown}`;
27403
+ var renderVoiceSessionObservabilityHTML = (report, options = {}) => `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml40(options.title ?? "Voice Session Observability")}</title><style>body{background:#0d1412;color:#f7f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.eyebrow{color:#fbbf24;font-size:.78rem;font-weight:900;letter-spacing:.14em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,4.8rem);line-height:.9;margin:.2rem 0 1rem}.status{border:1px solid #425046;border-radius:999px;display:inline-flex;padding:8px 12px}.healthy{color:#86efac}.warning{color:#fbbf24}.failed,.error{color:#fca5a5}.actions{display:flex;flex-wrap:wrap;gap:10px;margin:18px 0}.actions a{background:#fbbf24;border-radius:999px;color:#111827;font-weight:900;padding:10px 14px;text-decoration:none}.grid{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));margin:22px 0}.card,.turn,.incident{background:#17201c;border:1px solid #2e3c35;border-radius:20px;padding:16px}.card span,.muted,dt{color:#a8b4ad}.card strong{display:block;font-size:2rem}section{margin-top:30px}.turn{margin:16px 0}.turn header{align-items:center;display:flex;justify-content:space-between;gap:14px}dl{display:grid;gap:10px;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));margin:14px 0}dd{font-weight:900;margin:3px 0 0}table{border-collapse:collapse;margin-top:14px;width:100%}td,th{border-top:1px solid #2e3c35;padding:10px;text-align:left}pre{background:#08100d;border:1px solid #2e3c35;border-radius:16px;color:#d9f99d;overflow:auto;padding:14px}@media(max-width:760px){main{padding:20px}table{font-size:.9rem}}</style></head><body><main><header><p class="eyebrow">Session observability</p><h1>${escapeHtml40(report.sessionId)}</h1><p class="status ${escapeHtml40(report.status)}">${escapeHtml40(report.status)}</p>${renderLinks(report.links)}<p class="muted">One support/debug report across trace timeline, operations record, provider recovery, turn waterfalls, guardrails, tools, handoffs, failure replay, and incident handoff.</p></header><section class="grid"><article class="card"><span>Events</span><strong>${String(report.summary.events)}</strong></article><article class="card"><span>Turns</span><strong>${String(report.summary.turns)}</strong></article><article class="card"><span>Errors</span><strong>${String(report.summary.errors)}</strong></article><article class="card"><span>Duration</span><strong>${formatMs4(report.summary.durationMs)}</strong></article><article class="card"><span>Fallbacks</span><strong>${String(report.summary.fallbacks)}</strong></article><article class="card"><span>Tools</span><strong>${String(report.summary.toolCalls)}</strong></article><article class="card"><span>Handoffs</span><strong>${String(report.summary.handoffs)}</strong></article><article class="card"><span>Guardrails blocked</span><strong>${String(report.summary.guardrailBlocks)}</strong></article><article class="card"><span>Telephony media</span><strong>${String(report.summary.telephonyMediaEvents)}</strong></article></section><section><h2>Turn Waterfalls</h2>${renderTurns(report.turns)}</section><section class="incident"><h2>Incident Handoff</h2><pre><code>${escapeHtml40(report.incidentMarkdown)}</code></pre></section></main></body></html>`;
27404
+ var routeSessionId = (params) => typeof params.sessionId === "string" ? params.sessionId : "";
27405
+ var linkByRel = (links) => {
27406
+ const map = new Map;
27407
+ for (const link of links) {
27408
+ map.set(link.rel, true);
27409
+ }
27410
+ return (rel) => map.get(rel) ?? false;
27411
+ };
27412
+ var evaluateVoiceSessionObservabilityEvidence = (report, input = {}) => {
27413
+ const issues = [];
27414
+ const has = linkByRel(report.links);
27415
+ const status = report.status === "healthy" ? "pass" : report.status === "warning" ? "warn" : "fail";
27416
+ const turnsWithWaterfalls = report.turns.filter((turn) => turn.stages.length > 0).length;
27417
+ const stages = report.turns.reduce((total, turn) => total + turn.stages.length, 0);
27418
+ const providerDecisions = report.turns.reduce((total, turn) => total + turn.providerDecisions, 0);
27419
+ const toolCalls = report.turns.reduce((total, turn) => total + turn.toolCalls, 0);
27420
+ if (input.requireHealthy && report.status !== "healthy") {
27421
+ issues.push("Expected a healthy session observability report.");
27422
+ }
27423
+ if (input.minTurns !== undefined && report.summary.turns < input.minTurns) {
27424
+ issues.push(`Expected at least ${String(input.minTurns)} turn(s), found ${String(report.summary.turns)}.`);
27425
+ }
27426
+ if (input.minTurnWaterfalls !== undefined && turnsWithWaterfalls < input.minTurnWaterfalls) {
27427
+ issues.push(`Expected at least ${String(input.minTurnWaterfalls)} turn(s) with stage data, found ${String(turnsWithWaterfalls)}.`);
27428
+ }
27429
+ if (input.minStageCount !== undefined && stages < input.minStageCount) {
27430
+ issues.push(`Expected at least ${String(input.minStageCount)} turn stages, found ${String(stages)}.`);
27431
+ }
27432
+ if (input.minProviderDecisions !== undefined && providerDecisions < input.minProviderDecisions) {
27433
+ issues.push(`Expected at least ${String(input.minProviderDecisions)} provider decision stage(s), found ${String(providerDecisions)}.`);
27434
+ }
27435
+ if (input.minToolCalls !== undefined && toolCalls < input.minToolCalls) {
27436
+ issues.push(`Expected at least ${String(input.minToolCalls)} tool call stage(s), found ${String(toolCalls)}.`);
27437
+ }
27438
+ if (input.maxErrors !== undefined && report.summary.errors > input.maxErrors) {
27439
+ issues.push(`Expected at most ${String(input.maxErrors)} error(s), found ${String(report.summary.errors)}.`);
27440
+ }
27441
+ if (input.maxFallbacks !== undefined && report.summary.fallbacks > input.maxFallbacks) {
27442
+ issues.push(`Expected at most ${String(input.maxFallbacks)} fallback(s), found ${String(report.summary.fallbacks)}.`);
27443
+ }
27444
+ if (input.requireOperationsRecordLink && !has("operations-record")) {
27445
+ issues.push("Expected operations-record link in session observability evidence.");
27446
+ }
27447
+ if (input.requireTraceTimelineLink && !has("trace-timeline")) {
27448
+ issues.push("Expected trace-timeline link in session observability evidence.");
27449
+ }
27450
+ if (input.requireCallDebuggerLink && !has("call-debugger")) {
27451
+ issues.push("Expected call-debugger link in session observability evidence.");
27452
+ }
27453
+ if (input.requireIncidentMarkdownLink && !has("incident-markdown")) {
27454
+ issues.push("Expected incident-markdown link in session observability evidence.");
27455
+ }
27456
+ if (input.requireIncidentMarkdown && (!report.incidentMarkdown || report.incidentMarkdown.trim().length < 24 || !report.incidentMarkdown.toLowerCase().includes("incident handoff"))) {
27457
+ issues.push("Expected readable incident markdown payload.");
27458
+ }
27459
+ if (input.requireProviderRecoveryStatus !== undefined && (Array.isArray(input.requireProviderRecoveryStatus) ? input.requireProviderRecoveryStatus : [input.requireProviderRecoveryStatus]).indexOf(report.summary.providerRecoveryStatus) === -1) {
27460
+ issues.push(`Expected provider recovery status ${String(input.requireProviderRecoveryStatus)}, found ${report.summary.providerRecoveryStatus}.`);
27461
+ }
27462
+ return {
27463
+ checkedAt: Date.now(),
27464
+ issues,
27465
+ ok: issues.length === 0,
27466
+ status: issues.length > 0 ? status === "fail" ? "fail" : "warn" : status,
27467
+ summary: {
27468
+ incidentMarkdownLength: report.incidentMarkdown.length,
27469
+ providerDecisions,
27470
+ providerRecoveryStatus: report.summary.providerRecoveryStatus,
27471
+ reportStatus: report.status,
27472
+ stages,
27473
+ turns: report.turns.length,
27474
+ turnsWithWaterfalls,
27475
+ toolCalls,
27476
+ links: {
27477
+ callDebugger: has("call-debugger"),
27478
+ incidentMarkdown: has("incident-markdown"),
27479
+ operationsRecord: has("operations-record"),
27480
+ traceTimeline: has("trace-timeline")
27481
+ }
27482
+ }
27483
+ };
27484
+ };
27485
+ var assertVoiceSessionObservabilityEvidence = (report, input = {}) => {
27486
+ const assertion = evaluateVoiceSessionObservabilityEvidence(report, input);
27487
+ if (!assertion.ok) {
27488
+ throw new Error(`Voice session observability evidence assertion failed: ${assertion.issues.join(" ")}`);
27489
+ }
27490
+ return assertion;
27491
+ };
27492
+ var createVoiceSessionObservabilityRoutes = (options) => {
27493
+ const path = options.path ?? "/api/voice/session-observability/:sessionId";
27494
+ const htmlPath = options.htmlPath ?? "/voice/session-observability/:sessionId";
27495
+ const incidentPath = options.incidentPath ?? "/api/voice/session-observability/:sessionId/incident.md";
27496
+ const title = options.title ?? "AbsoluteJS Voice Session Observability";
27497
+ const routes = new Elysia42({
27498
+ name: options.name ?? "absolutejs-voice-session-observability"
27499
+ });
27500
+ const build = (sessionId) => buildVoiceSessionObservabilityReport({
27501
+ audit: options.audit,
27502
+ callDebuggerHref: options.callDebuggerHref,
27503
+ customLinks: options.customLinks,
27504
+ evaluation: options.evaluation,
27505
+ events: options.events,
27506
+ incidentMarkdownHref: options.incidentMarkdownHref ?? (incidentPath === false ? false : incidentPath),
27507
+ integrationEvents: options.integrationEvents,
27508
+ operationsRecordHref: options.operationsRecordHref,
27509
+ redact: options.redact,
27510
+ reviews: options.reviews,
27511
+ sessionId,
27512
+ store: options.store,
27513
+ tasks: options.tasks,
27514
+ traceTimelineHref: options.traceTimelineHref
27515
+ });
27516
+ routes.get(path, async ({ params }) => Response.json(await build(routeSessionId(params))));
27517
+ if (htmlPath !== false) {
27518
+ routes.get(htmlPath, async ({ params }) => {
27519
+ const report = await build(routeSessionId(params));
27520
+ const body = await (options.render ?? ((input) => renderVoiceSessionObservabilityHTML(input, { title })))(report);
27521
+ return new Response(body, {
27522
+ headers: {
27523
+ "content-type": "text/html; charset=utf-8",
27524
+ ...options.headers
27525
+ }
27526
+ });
27527
+ });
27528
+ }
27529
+ if (incidentPath !== false) {
27530
+ routes.get(incidentPath, async ({ params }) => {
27531
+ const report = await build(routeSessionId(params));
27532
+ const body = await (options.renderIncidentMarkdown ?? renderVoiceSessionObservabilityMarkdown)(report);
27533
+ return new Response(body, {
27534
+ headers: {
27535
+ "content-type": "text/markdown; charset=utf-8",
27536
+ ...options.headers
27537
+ }
27538
+ });
27539
+ });
27540
+ }
27541
+ return routes;
27542
+ };
27543
+
27544
+ // src/opsRecovery.ts
27545
+ import { Elysia as Elysia43 } from "elysia";
26625
27546
 
26626
27547
  // src/latencySlo.ts
26627
27548
  var DEFAULT_WARN_AFTER_MS = 1800;
@@ -26927,7 +27848,7 @@ None.
26927
27848
  };
26928
27849
 
26929
27850
  // src/opsRecovery.ts
26930
- var escapeHtml40 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
27851
+ var escapeHtml41 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
26931
27852
  var getString15 = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
26932
27853
  var hrefForSession = (value, sessionId) => {
26933
27854
  if (typeof value === "function") {
@@ -27141,19 +28062,19 @@ ${failedSessions || "None."}
27141
28062
  ${report.latency ? renderVoiceLatencySLOMarkdown(report.latency, { title: "Latency SLO" }) : "Latency SLO disabled."}
27142
28063
  `;
27143
28064
  };
27144
- var renderDeliverySummary = (label, summary) => summary ? `<article><span>${escapeHtml40(label)}</span><strong>${String(summary.failed + summary.deadLettered)} failed</strong><small>${String(summary.pending)} pending \xB7 ${String(summary.retryEligible)} retry eligible \xB7 ${String(summary.total)} total</small></article>` : `<article><span>${escapeHtml40(label)}</span><strong>not configured</strong></article>`;
28065
+ var renderDeliverySummary = (label, summary) => summary ? `<article><span>${escapeHtml41(label)}</span><strong>${String(summary.failed + summary.deadLettered)} failed</strong><small>${String(summary.pending)} pending \xB7 ${String(summary.retryEligible)} retry eligible \xB7 ${String(summary.total)} total</small></article>` : `<article><span>${escapeHtml41(label)}</span><strong>not configured</strong></article>`;
27145
28066
  var renderVoiceOpsRecoveryHTML = (report, options = {}) => {
27146
28067
  const title = options.title ?? "Voice Ops Recovery";
27147
- const issues = report.issues.map((issue) => `<tr><td>${escapeHtml40(issue.severity)}</td><td><code>${escapeHtml40(issue.code)}</code></td><td>${issue.href ? `<a href="${escapeHtml40(issue.href)}">${escapeHtml40(issue.label)}</a>` : escapeHtml40(issue.label)}</td><td>${escapeHtml40(String(issue.value ?? ""))}</td><td>${escapeHtml40(issue.detail ?? "")}</td></tr>`).join("");
27148
- const providers = report.providers.providers.map((provider) => `<tr><td>${escapeHtml40(provider.provider)}</td><td>${escapeHtml40(provider.status)}</td><td>${String(provider.runCount)}</td><td>${String(provider.errorCount)}</td><td>${String(provider.fallbackCount)}</td><td>${escapeHtml40(provider.lastError ?? "")}</td></tr>`).join("");
27149
- const failedSessions = report.failedSessions.map((session) => `<li>${session.operationsRecordHref ? `<a href="${escapeHtml40(session.operationsRecordHref)}">${escapeHtml40(session.sessionId)}</a>` : escapeHtml40(session.sessionId)}${session.provider ? ` via ${escapeHtml40(session.provider)}` : ""}${session.error ? `: ${escapeHtml40(session.error)}` : ""}</li>`).join("");
27150
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml40(title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;background:#f8fafc;color:#172033;margin:2rem;line-height:1.45}main{max-width:1180px;margin:auto}.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:.75rem;margin:1rem 0}article{background:white;border:1px solid #dbe3ef;border-radius:14px;padding:1rem;box-shadow:0 10px 28px rgba(15,23,42,.05)}article span{display:block;color:#64748b;font-size:.85rem}article strong{display:block;font-size:1.5rem;margin:.2rem 0}article small{color:#64748b}table{border-collapse:collapse;width:100%;background:white;border:1px solid #dbe3ef;border-radius:14px;overflow:hidden}th,td{border-bottom:1px solid #e2e8f0;padding:.7rem;text-align:left;vertical-align:top}code{font-size:.85em}.status{display:inline-flex;border-radius:999px;padding:.35rem .7rem;background:${report.status === "fail" ? "#fee2e2" : report.status === "warn" ? "#fef3c7" : "#dcfce7"};color:${report.status === "fail" ? "#991b1b" : report.status === "warn" ? "#92400e" : "#166534"};font-weight:700}</style></head><body><main><h1>${escapeHtml40(title)}</h1><p><span class="status">${escapeHtml40(report.status)}</span> Checked ${escapeHtml40(new Date(report.checkedAt).toLocaleString())}</p><section class="grid"><article><span>Recovered fallbacks</span><strong>${String(report.providers.recoveredFallbacks)}</strong></article><article><span>Unresolved providers</span><strong>${String(report.providers.unresolvedFailures)}</strong></article><article><span>Operator interventions</span><strong>${String(report.interventions.total)}</strong></article><article><span>Latency status</span><strong>${escapeHtml40(report.latency?.status ?? "disabled")}</strong></article>${renderDeliverySummary("Audit delivery", report.auditDeliveries)}${renderDeliverySummary("Trace delivery", report.traceDeliveries)}${renderDeliverySummary("Handoff delivery", report.handoffDeliveries)}</section><h2>Issues</h2><table><thead><tr><th>Severity</th><th>Code</th><th>Label</th><th>Value</th><th>Detail</th></tr></thead><tbody>${issues || '<tr><td colspan="5">No recovery issues.</td></tr>'}</tbody></table><h2>Providers</h2><table><thead><tr><th>Provider</th><th>Status</th><th>Runs</th><th>Errors</th><th>Fallbacks</th><th>Last error</th></tr></thead><tbody>${providers || '<tr><td colspan="6">No provider activity.</td></tr>'}</tbody></table><h2>Failed Sessions</h2><ul>${failedSessions || "<li>None.</li>"}</ul></main></body></html>`;
28068
+ const issues = report.issues.map((issue) => `<tr><td>${escapeHtml41(issue.severity)}</td><td><code>${escapeHtml41(issue.code)}</code></td><td>${issue.href ? `<a href="${escapeHtml41(issue.href)}">${escapeHtml41(issue.label)}</a>` : escapeHtml41(issue.label)}</td><td>${escapeHtml41(String(issue.value ?? ""))}</td><td>${escapeHtml41(issue.detail ?? "")}</td></tr>`).join("");
28069
+ const providers = report.providers.providers.map((provider) => `<tr><td>${escapeHtml41(provider.provider)}</td><td>${escapeHtml41(provider.status)}</td><td>${String(provider.runCount)}</td><td>${String(provider.errorCount)}</td><td>${String(provider.fallbackCount)}</td><td>${escapeHtml41(provider.lastError ?? "")}</td></tr>`).join("");
28070
+ const failedSessions = report.failedSessions.map((session) => `<li>${session.operationsRecordHref ? `<a href="${escapeHtml41(session.operationsRecordHref)}">${escapeHtml41(session.sessionId)}</a>` : escapeHtml41(session.sessionId)}${session.provider ? ` via ${escapeHtml41(session.provider)}` : ""}${session.error ? `: ${escapeHtml41(session.error)}` : ""}</li>`).join("");
28071
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml41(title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;background:#f8fafc;color:#172033;margin:2rem;line-height:1.45}main{max-width:1180px;margin:auto}.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:.75rem;margin:1rem 0}article{background:white;border:1px solid #dbe3ef;border-radius:14px;padding:1rem;box-shadow:0 10px 28px rgba(15,23,42,.05)}article span{display:block;color:#64748b;font-size:.85rem}article strong{display:block;font-size:1.5rem;margin:.2rem 0}article small{color:#64748b}table{border-collapse:collapse;width:100%;background:white;border:1px solid #dbe3ef;border-radius:14px;overflow:hidden}th,td{border-bottom:1px solid #e2e8f0;padding:.7rem;text-align:left;vertical-align:top}code{font-size:.85em}.status{display:inline-flex;border-radius:999px;padding:.35rem .7rem;background:${report.status === "fail" ? "#fee2e2" : report.status === "warn" ? "#fef3c7" : "#dcfce7"};color:${report.status === "fail" ? "#991b1b" : report.status === "warn" ? "#92400e" : "#166534"};font-weight:700}</style></head><body><main><h1>${escapeHtml41(title)}</h1><p><span class="status">${escapeHtml41(report.status)}</span> Checked ${escapeHtml41(new Date(report.checkedAt).toLocaleString())}</p><section class="grid"><article><span>Recovered fallbacks</span><strong>${String(report.providers.recoveredFallbacks)}</strong></article><article><span>Unresolved providers</span><strong>${String(report.providers.unresolvedFailures)}</strong></article><article><span>Operator interventions</span><strong>${String(report.interventions.total)}</strong></article><article><span>Latency status</span><strong>${escapeHtml41(report.latency?.status ?? "disabled")}</strong></article>${renderDeliverySummary("Audit delivery", report.auditDeliveries)}${renderDeliverySummary("Trace delivery", report.traceDeliveries)}${renderDeliverySummary("Handoff delivery", report.handoffDeliveries)}</section><h2>Issues</h2><table><thead><tr><th>Severity</th><th>Code</th><th>Label</th><th>Value</th><th>Detail</th></tr></thead><tbody>${issues || '<tr><td colspan="5">No recovery issues.</td></tr>'}</tbody></table><h2>Providers</h2><table><thead><tr><th>Provider</th><th>Status</th><th>Runs</th><th>Errors</th><th>Fallbacks</th><th>Last error</th></tr></thead><tbody>${providers || '<tr><td colspan="6">No provider activity.</td></tr>'}</tbody></table><h2>Failed Sessions</h2><ul>${failedSessions || "<li>None.</li>"}</ul></main></body></html>`;
27151
28072
  };
27152
28073
  var createVoiceOpsRecoveryRoutes = (options = {}) => {
27153
28074
  const path = options.path ?? "/api/voice/ops-recovery";
27154
28075
  const htmlPath = options.htmlPath === undefined ? "/ops-recovery" : options.htmlPath;
27155
28076
  const markdownPath = options.markdownPath === undefined ? `${path}.md` : options.markdownPath;
27156
- const routes = new Elysia42({
28077
+ const routes = new Elysia43({
27157
28078
  name: options.name ?? "absolutejs-voice-ops-recovery"
27158
28079
  }).get(path, async () => buildVoiceOpsRecoveryReport(options));
27159
28080
  if (htmlPath) {
@@ -27183,8 +28104,8 @@ var createVoiceOpsRecoveryRoutes = (options = {}) => {
27183
28104
  };
27184
28105
 
27185
28106
  // src/incidentTimeline.ts
27186
- import { Elysia as Elysia43 } from "elysia";
27187
- var escapeHtml41 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
28107
+ import { Elysia as Elysia44 } from "elysia";
28108
+ var escapeHtml42 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
27188
28109
  var resolveValue = async (value) => typeof value === "function" ? await value() : value;
27189
28110
  var linkForSession = (link, sessionId) => {
27190
28111
  if (!link || !sessionId) {
@@ -27305,8 +28226,8 @@ var buildVoiceIncidentRecoveryOutcomeReport = async (options) => {
27305
28226
  };
27306
28227
  var renderVoiceIncidentRecoveryOutcomeHTML = (report, options = {}) => {
27307
28228
  const title = options.title ?? "AbsoluteJS Voice Incident Recovery Outcomes";
27308
- const rows = report.entries.map((entry) => `<article class="${escapeHtml41(entry.outcome)}"><span>${escapeHtml41(entry.outcome.toUpperCase())}</span><h2>${escapeHtml41(entry.actionId)}</h2><p>${escapeHtml41(new Date(entry.at).toLocaleString())}</p><strong>${escapeHtml41(entry.beforeStatus ?? "unknown")} -> ${escapeHtml41(entry.afterStatus ?? "unknown")}</strong>${entry.detail ? `<p>${escapeHtml41(entry.detail)}</p>` : ""}</article>`).join("");
27309
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml41(title)}</title><style>body{background:#10120d;color:#fbf4df;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:980px;padding:32px}.hero,article{background:#181711;border:1px solid #39301d;border-radius:24px;padding:20px}.hero{margin-bottom:16px}h1{font-size:clamp(2rem,6vw,4.5rem);line-height:.95}.summary{display:flex;flex-wrap:wrap;gap:10px}.summary span{border:1px solid #4a3f23;border-radius:999px;padding:8px 12px}section{display:grid;gap:12px}article.improved{border-color:rgba(34,197,94,.65)}article.failed,article.regressed{border-color:rgba(239,68,68,.8)}article.unchanged{border-color:rgba(245,158,11,.7)}article span{color:#fcd34d;font-weight:900;letter-spacing:.08em}article strong{display:block;font-size:1.4rem;margin:.5rem 0}p{color:#cfc5a8}</style></head><body><main><section class="hero"><span>Recovery proof</span><h1>${escapeHtml41(title)}</h1><div class="summary"><span>${String(report.improved)} improved</span><span>${String(report.unchanged)} unchanged</span><span>${String(report.regressed)} regressed</span><span>${String(report.failed)} failed</span><span>${String(report.total)} total</span></div></section><section>${rows || "<p>No incident recovery actions have been recorded.</p>"}</section></main></body></html>`;
28229
+ const rows = report.entries.map((entry) => `<article class="${escapeHtml42(entry.outcome)}"><span>${escapeHtml42(entry.outcome.toUpperCase())}</span><h2>${escapeHtml42(entry.actionId)}</h2><p>${escapeHtml42(new Date(entry.at).toLocaleString())}</p><strong>${escapeHtml42(entry.beforeStatus ?? "unknown")} -> ${escapeHtml42(entry.afterStatus ?? "unknown")}</strong>${entry.detail ? `<p>${escapeHtml42(entry.detail)}</p>` : ""}</article>`).join("");
28230
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml42(title)}</title><style>body{background:#10120d;color:#fbf4df;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:980px;padding:32px}.hero,article{background:#181711;border:1px solid #39301d;border-radius:24px;padding:20px}.hero{margin-bottom:16px}h1{font-size:clamp(2rem,6vw,4.5rem);line-height:.95}.summary{display:flex;flex-wrap:wrap;gap:10px}.summary span{border:1px solid #4a3f23;border-radius:999px;padding:8px 12px}section{display:grid;gap:12px}article.improved{border-color:rgba(34,197,94,.65)}article.failed,article.regressed{border-color:rgba(239,68,68,.8)}article.unchanged{border-color:rgba(245,158,11,.7)}article span{color:#fcd34d;font-weight:900;letter-spacing:.08em}article strong{display:block;font-size:1.4rem;margin:.5rem 0}p{color:#cfc5a8}</style></head><body><main><section class="hero"><span>Recovery proof</span><h1>${escapeHtml42(title)}</h1><div class="summary"><span>${String(report.improved)} improved</span><span>${String(report.unchanged)} unchanged</span><span>${String(report.regressed)} regressed</span><span>${String(report.failed)} failed</span><span>${String(report.total)} total</span></div></section><section>${rows || "<p>No incident recovery actions have been recorded.</p>"}</section></main></body></html>`;
27310
28231
  };
27311
28232
  var buildVoiceIncidentRecoveryOutcomeReadinessCheck = (report, options = {}) => {
27312
28233
  const failOnFailed = options.failOnFailed ?? true;
@@ -27503,8 +28424,8 @@ ${rows || "| n/a | 0 | 0 | 0 | 0 | 0 | n/a | n/a |"}
27503
28424
  };
27504
28425
  var renderVoiceIncidentRecoveryTrendHTML = (report, options = {}) => {
27505
28426
  const title = options.title ?? "AbsoluteJS Voice Incident Recovery Trend";
27506
- const rows = report.cycles.map((cycle) => `<tr><td>${escapeHtml41(new Date(cycle.checkedAt).toLocaleString())}</td><td>${String(cycle.total)}</td><td>${String(cycle.improved)}</td><td>${String(cycle.unchanged)}</td><td>${String(cycle.regressed)}</td><td>${String(cycle.failed)}</td><td>${escapeHtml41(percent(cycle.improvementRate))}</td><td>${escapeHtml41(percent(cycle.regressionRate))}</td></tr>`).join("");
27507
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml41(title)}</title><style>body{background:#10120d;color:#fbf4df;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1080px;padding:32px}.hero,table{background:#181711;border:1px solid #39301d;border-radius:24px}.hero{margin-bottom:16px;padding:24px}h1{font-size:clamp(2rem,6vw,4.5rem);line-height:.95}.summary{display:flex;flex-wrap:wrap;gap:10px}.summary span{border:1px solid #4a3f23;border-radius:999px;padding:8px 12px}table{border-collapse:collapse;overflow:hidden;width:100%}td,th{border-bottom:1px solid #39301d;padding:12px;text-align:left}.pass{color:#86efac}.warn,.empty{color:#fcd34d}.fail{color:#fca5a5}p{color:#cfc5a8}</style></head><body><main><section class="hero"><span>Recovery trend</span><h1>${escapeHtml41(title)}</h1><p class="${escapeHtml41(report.status)}">Status: ${escapeHtml41(report.status)}</p><div class="summary"><span>${String(report.summary.cycles)} cycles</span><span>${String(report.summary.total)} actions</span><span>${escapeHtml41(percent(report.summary.improvementRate))} improved</span><span>${escapeHtml41(percent(report.summary.regressionRate))} regressed</span><span>${escapeHtml41(percent(report.trend.improvementRateDelta))} improvement delta</span></div></section><table><thead><tr><th>Checked at</th><th>Total</th><th>Improved</th><th>Unchanged</th><th>Regressed</th><th>Failed</th><th>Improve %</th><th>Regress %</th></tr></thead><tbody>${rows || '<tr><td colspan="8">No recovery outcome history has been recorded.</td></tr>'}</tbody></table></main></body></html>`;
28427
+ const rows = report.cycles.map((cycle) => `<tr><td>${escapeHtml42(new Date(cycle.checkedAt).toLocaleString())}</td><td>${String(cycle.total)}</td><td>${String(cycle.improved)}</td><td>${String(cycle.unchanged)}</td><td>${String(cycle.regressed)}</td><td>${String(cycle.failed)}</td><td>${escapeHtml42(percent(cycle.improvementRate))}</td><td>${escapeHtml42(percent(cycle.regressionRate))}</td></tr>`).join("");
28428
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml42(title)}</title><style>body{background:#10120d;color:#fbf4df;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1080px;padding:32px}.hero,table{background:#181711;border:1px solid #39301d;border-radius:24px}.hero{margin-bottom:16px;padding:24px}h1{font-size:clamp(2rem,6vw,4.5rem);line-height:.95}.summary{display:flex;flex-wrap:wrap;gap:10px}.summary span{border:1px solid #4a3f23;border-radius:999px;padding:8px 12px}table{border-collapse:collapse;overflow:hidden;width:100%}td,th{border-bottom:1px solid #39301d;padding:12px;text-align:left}.pass{color:#86efac}.warn,.empty{color:#fcd34d}.fail{color:#fca5a5}p{color:#cfc5a8}</style></head><body><main><section class="hero"><span>Recovery trend</span><h1>${escapeHtml42(title)}</h1><p class="${escapeHtml42(report.status)}">Status: ${escapeHtml42(report.status)}</p><div class="summary"><span>${String(report.summary.cycles)} cycles</span><span>${String(report.summary.total)} actions</span><span>${escapeHtml42(percent(report.summary.improvementRate))} improved</span><span>${escapeHtml42(percent(report.summary.regressionRate))} regressed</span><span>${escapeHtml42(percent(report.trend.improvementRateDelta))} improvement delta</span></div></section><table><thead><tr><th>Checked at</th><th>Total</th><th>Improved</th><th>Unchanged</th><th>Regressed</th><th>Failed</th><th>Improve %</th><th>Regress %</th></tr></thead><tbody>${rows || '<tr><td colspan="8">No recovery outcome history has been recorded.</td></tr>'}</tbody></table></main></body></html>`;
27508
28429
  };
27509
28430
  var pushOperationalStatusEvents = (events, report, links) => {
27510
28431
  if (!report) {
@@ -27730,22 +28651,22 @@ ${report.actions.map((action) => `- ${action.method ?? "GET"} ${action.id}: ${ac
27730
28651
  var renderVoiceIncidentTimelineHTML = (report, options = {}) => {
27731
28652
  const title = options.title ?? "AbsoluteJS Voice Incident Timeline";
27732
28653
  const actionPath = options.actionPath ?? "/api/voice/incident-timeline/actions";
27733
- const events = report.events.map((event) => `<article class="${escapeHtml41(event.severity)}">
27734
- <span>${escapeHtml41(event.severity.toUpperCase())} / ${escapeHtml41(event.category)}</span>
27735
- <h2>${escapeHtml41(event.label)}</h2>
27736
- <p>${escapeHtml41(new Date(event.at).toLocaleString())}${event.sessionId ? ` \xB7 session ${escapeHtml41(event.sessionId)}` : ""}</p>
27737
- ${event.value === undefined ? "" : `<strong>${escapeHtml41(String(event.value))}</strong>`}
27738
- ${event.detail ? `<p>${escapeHtml41(event.detail)}</p>` : ""}
27739
- <div>${event.href ? `<a href="${escapeHtml41(event.href)}">Open source</a>` : ""}${event.action?.href ? `<a href="${escapeHtml41(event.action.href)}">${escapeHtml41(event.action.label)}</a>` : ""}</div>
28654
+ const events = report.events.map((event) => `<article class="${escapeHtml42(event.severity)}">
28655
+ <span>${escapeHtml42(event.severity.toUpperCase())} / ${escapeHtml42(event.category)}</span>
28656
+ <h2>${escapeHtml42(event.label)}</h2>
28657
+ <p>${escapeHtml42(new Date(event.at).toLocaleString())}${event.sessionId ? ` \xB7 session ${escapeHtml42(event.sessionId)}` : ""}</p>
28658
+ ${event.value === undefined ? "" : `<strong>${escapeHtml42(String(event.value))}</strong>`}
28659
+ ${event.detail ? `<p>${escapeHtml42(event.detail)}</p>` : ""}
28660
+ <div>${event.href ? `<a href="${escapeHtml42(event.href)}">Open source</a>` : ""}${event.action?.href ? `<a href="${escapeHtml42(event.action.href)}">${escapeHtml42(event.action.label)}</a>` : ""}</div>
27740
28661
  </article>`).join("");
27741
28662
  const actions = report.actions.map((action) => {
27742
- const label = escapeHtml41(action.label);
27743
- const detail = action.detail ? `<p>${escapeHtml41(action.detail)}</p>` : "";
27744
- const href = action.href ? `<a href="${escapeHtml41(action.href)}">Open target</a>` : "";
27745
- const control = action.method === "POST" ? `<button type="button" data-voice-incident-action="${escapeHtml41(action.id)}" ${action.disabled ? "disabled" : ""}>${label}</button>` : href;
27746
- return `<article class="action"><span>${escapeHtml41(action.method ?? "GET")}</span><h2>${label}</h2>${detail}<div>${control}${href && action.method === "POST" ? href : ""}</div></article>`;
28663
+ const label = escapeHtml42(action.label);
28664
+ const detail = action.detail ? `<p>${escapeHtml42(action.detail)}</p>` : "";
28665
+ const href = action.href ? `<a href="${escapeHtml42(action.href)}">Open target</a>` : "";
28666
+ const control = action.method === "POST" ? `<button type="button" data-voice-incident-action="${escapeHtml42(action.id)}" ${action.disabled ? "disabled" : ""}>${label}</button>` : href;
28667
+ return `<article class="action"><span>${escapeHtml42(action.method ?? "GET")}</span><h2>${label}</h2>${detail}<div>${control}${href && action.method === "POST" ? href : ""}</div></article>`;
27747
28668
  }).join("");
27748
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml41(title)}</title><style>body{background:#11110d;color:#faf4df;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1100px;padding:32px}.hero{background:linear-gradient(135deg,rgba(248,113,113,.2),rgba(245,158,11,.13),rgba(34,197,94,.12));border:1px solid #39301d;border-radius:30px;margin-bottom:18px;padding:28px}.eyebrow{color:#fcd34d;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}.status{border:1px solid #575030;border-radius:999px;display:inline-flex;font-weight:900;padding:8px 12px}.status.pass{border-color:rgba(34,197,94,.65)}.status.warn{border-color:rgba(245,158,11,.75)}.status.fail{border-color:rgba(239,68,68,.85)}.grid{display:grid;gap:14px}.actions{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));margin:0 0 18px}.summary{display:flex;flex-wrap:wrap;gap:10px}.summary span{background:#181711;border:1px solid #39301d;border-radius:999px;padding:8px 12px}article{background:#181711;border:1px solid #39301d;border-radius:22px;padding:18px}article.critical{border-color:rgba(239,68,68,.85)}article.warn{border-color:rgba(245,158,11,.75)}article.info{border-color:rgba(34,197,94,.55)}article.action{border-color:#5b4a22}article span{color:#fcd34d;font-size:.78rem;font-weight:900;letter-spacing:.08em}article h2{margin:.35rem 0}.muted,article p{color:#cfc5a8}article strong{display:block;font-size:1.3rem;margin:.5rem 0}a{color:#fde68a;margin-right:12px}button{background:#fcd34d;border:0;border-radius:999px;color:#171307;cursor:pointer;font-weight:900;padding:10px 14px}button:disabled{cursor:not-allowed;opacity:.55}</style></head><body><main><section class="hero"><p class="eyebrow">Operational triage</p><h1>${escapeHtml41(title)}</h1><p class="status ${escapeHtml41(report.status)}">Overall: ${escapeHtml41(report.status.toUpperCase())}</p><p class="muted">Generated ${escapeHtml41(new Date(report.generatedAt).toLocaleString())}</p><div class="summary"><span>${String(report.summary.critical)} critical</span><span>${String(report.summary.warn)} warn</span><span>${String(report.summary.info)} info</span><span>${String(report.summary.total)} total</span></div></section><h2>Recovery actions</h2><section class="actions">${actions || '<article class="action"><span>NONE</span><h2>No recovery actions</h2><p>No executable actions are available for this report.</p></article>'}</section><h2>Timeline</h2><section class="grid">${events || '<article class="info"><span>INFO</span><h2>No incident events</h2><p>No non-pass operational events were found in this window.</p></article>'}</section></main><script>const voiceIncidentActionPath=${JSON.stringify(actionPath)};document.querySelectorAll("[data-voice-incident-action]").forEach((button)=>{button.addEventListener("click",async()=>{const id=button.getAttribute("data-voice-incident-action");if(!id)return;button.disabled=true;const original=button.textContent;button.textContent="Running...";try{const response=await fetch(voiceIncidentActionPath+"/"+encodeURIComponent(id),{method:"POST"});button.textContent=response.ok?"Done":"Failed";if(response.ok)setTimeout(()=>location.reload(),700)}catch{button.textContent="Failed"}finally{setTimeout(()=>{button.disabled=false;button.textContent=original},1600)}})});</script></body></html>`;
28669
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml42(title)}</title><style>body{background:#11110d;color:#faf4df;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1100px;padding:32px}.hero{background:linear-gradient(135deg,rgba(248,113,113,.2),rgba(245,158,11,.13),rgba(34,197,94,.12));border:1px solid #39301d;border-radius:30px;margin-bottom:18px;padding:28px}.eyebrow{color:#fcd34d;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}.status{border:1px solid #575030;border-radius:999px;display:inline-flex;font-weight:900;padding:8px 12px}.status.pass{border-color:rgba(34,197,94,.65)}.status.warn{border-color:rgba(245,158,11,.75)}.status.fail{border-color:rgba(239,68,68,.85)}.grid{display:grid;gap:14px}.actions{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));margin:0 0 18px}.summary{display:flex;flex-wrap:wrap;gap:10px}.summary span{background:#181711;border:1px solid #39301d;border-radius:999px;padding:8px 12px}article{background:#181711;border:1px solid #39301d;border-radius:22px;padding:18px}article.critical{border-color:rgba(239,68,68,.85)}article.warn{border-color:rgba(245,158,11,.75)}article.info{border-color:rgba(34,197,94,.55)}article.action{border-color:#5b4a22}article span{color:#fcd34d;font-size:.78rem;font-weight:900;letter-spacing:.08em}article h2{margin:.35rem 0}.muted,article p{color:#cfc5a8}article strong{display:block;font-size:1.3rem;margin:.5rem 0}a{color:#fde68a;margin-right:12px}button{background:#fcd34d;border:0;border-radius:999px;color:#171307;cursor:pointer;font-weight:900;padding:10px 14px}button:disabled{cursor:not-allowed;opacity:.55}</style></head><body><main><section class="hero"><p class="eyebrow">Operational triage</p><h1>${escapeHtml42(title)}</h1><p class="status ${escapeHtml42(report.status)}">Overall: ${escapeHtml42(report.status.toUpperCase())}</p><p class="muted">Generated ${escapeHtml42(new Date(report.generatedAt).toLocaleString())}</p><div class="summary"><span>${String(report.summary.critical)} critical</span><span>${String(report.summary.warn)} warn</span><span>${String(report.summary.info)} info</span><span>${String(report.summary.total)} total</span></div></section><h2>Recovery actions</h2><section class="actions">${actions || '<article class="action"><span>NONE</span><h2>No recovery actions</h2><p>No executable actions are available for this report.</p></article>'}</section><h2>Timeline</h2><section class="grid">${events || '<article class="info"><span>INFO</span><h2>No incident events</h2><p>No non-pass operational events were found in this window.</p></article>'}</section></main><script>const voiceIncidentActionPath=${JSON.stringify(actionPath)};document.querySelectorAll("[data-voice-incident-action]").forEach((button)=>{button.addEventListener("click",async()=>{const id=button.getAttribute("data-voice-incident-action");if(!id)return;button.disabled=true;const original=button.textContent;button.textContent="Running...";try{const response=await fetch(voiceIncidentActionPath+"/"+encodeURIComponent(id),{method:"POST"});button.textContent=response.ok?"Done":"Failed";if(response.ok)setTimeout(()=>location.reload(),700)}catch{button.textContent="Failed"}finally{setTimeout(()=>{button.disabled=false;button.textContent=original},1600)}})});</script></body></html>`;
27749
28670
  };
27750
28671
  var createVoiceIncidentTimelineRoutes = (options) => {
27751
28672
  const path = options.path ?? "/api/voice/incident-timeline";
@@ -27765,7 +28686,7 @@ var createVoiceIncidentTimelineRoutes = (options) => {
27765
28686
  })
27766
28687
  ]);
27767
28688
  };
27768
- const routes = new Elysia43({
28689
+ const routes = new Elysia44({
27769
28690
  name: options.name ?? "absolutejs-voice-incident-timeline"
27770
28691
  }).get(path, async () => {
27771
28692
  const report = await buildVoiceIncidentTimelineReport(options);
@@ -27957,11 +28878,11 @@ var createVoiceIncidentTimelineRoutes = (options) => {
27957
28878
  };
27958
28879
 
27959
28880
  // src/observabilityExport.ts
27960
- import { Elysia as Elysia44 } from "elysia";
28881
+ import { Elysia as Elysia45 } from "elysia";
27961
28882
  import { Database as Database4 } from "bun:sqlite";
27962
28883
  import { createHash } from "crypto";
27963
- import { mkdir as mkdir2, readFile, stat, unlink } from "fs/promises";
27964
- import { join as join2 } from "path";
28884
+ import { mkdir as mkdir3, readFile, stat, unlink } from "fs/promises";
28885
+ import { join as join3 } from "path";
27965
28886
  var voiceObservabilityExportSchemaVersion = "1.0.0";
27966
28887
  var voiceObservabilityExportSchemaId = "com.absolutejs.voice.observability-export";
27967
28888
  var createVoiceObservabilityExportSchema = () => ({
@@ -28536,15 +29457,15 @@ var loadVoiceObservabilityExportReplaySource = async (source) => {
28536
29457
  return source;
28537
29458
  }
28538
29459
  if (source.kind === "file") {
28539
- const root = join2(source.directory, source.runId);
28540
- const receiptPath = source.receiptDirectory ? join2(source.receiptDirectory, `${encodeURIComponent(deliveryReceiptId(source.runId))}.json`) : undefined;
29460
+ const root = join3(source.directory, source.runId);
29461
+ const receiptPath = source.receiptDirectory ? join3(source.receiptDirectory, `${encodeURIComponent(deliveryReceiptId(source.runId))}.json`) : undefined;
28541
29462
  const deliveryReceipt = receiptPath ? await Bun.file(receiptPath).text().then(JSON.parse).catch(() => {
28542
29463
  return;
28543
29464
  }) : undefined;
28544
29465
  return {
28545
- artifactIndex: JSON.parse(await Bun.file(join2(root, "artifact-index.json")).text()),
29466
+ artifactIndex: JSON.parse(await Bun.file(join3(root, "artifact-index.json")).text()),
28546
29467
  deliveryReceipt,
28547
- manifest: JSON.parse(await Bun.file(join2(root, "manifest.json")).text())
29468
+ manifest: JSON.parse(await Bun.file(join3(root, "manifest.json")).text())
28548
29469
  };
28549
29470
  }
28550
29471
  if (source.kind === "s3") {
@@ -28622,7 +29543,7 @@ var createVoiceObservabilityExportReplayRoutes = (options) => {
28622
29543
  ...options.headers ?? {}
28623
29544
  };
28624
29545
  const buildReport = () => resolveVoiceObservabilityExportReplayReport(options.source);
28625
- const app = new Elysia44({
29546
+ const app = new Elysia45({
28626
29547
  name: options.name ?? "absolute-voice-observability-export-replay"
28627
29548
  });
28628
29549
  app.get(path, async () => Response.json(await buildReport(), { headers }));
@@ -28754,7 +29675,7 @@ var createVoiceMemoryObservabilityExportDeliveryReceiptStore = () => {
28754
29675
  };
28755
29676
  };
28756
29677
  var createVoiceFileObservabilityExportDeliveryReceiptStore = (options) => {
28757
- const receiptPath = (id) => join2(options.directory, `${encodeURIComponent(id)}.json`);
29678
+ const receiptPath = (id) => join3(options.directory, `${encodeURIComponent(id)}.json`);
28758
29679
  return {
28759
29680
  get: async (id) => {
28760
29681
  const file = Bun.file(receiptPath(id));
@@ -28764,10 +29685,10 @@ var createVoiceFileObservabilityExportDeliveryReceiptStore = (options) => {
28764
29685
  return JSON.parse(await file.text());
28765
29686
  },
28766
29687
  list: async () => {
28767
- await mkdir2(options.directory, { recursive: true });
29688
+ await mkdir3(options.directory, { recursive: true });
28768
29689
  const receipts = [];
28769
29690
  for (const entry of await Array.fromAsync(new Bun.Glob("*.json").scan(options.directory))) {
28770
- const file = Bun.file(join2(options.directory, entry));
29691
+ const file = Bun.file(join3(options.directory, entry));
28771
29692
  receipts.push(JSON.parse(await file.text()));
28772
29693
  }
28773
29694
  return receipts.sort((left, right) => right.checkedAt - left.checkedAt);
@@ -28778,7 +29699,7 @@ var createVoiceFileObservabilityExportDeliveryReceiptStore = (options) => {
28778
29699
  });
28779
29700
  },
28780
29701
  set: async (id, receipt) => {
28781
- await mkdir2(options.directory, { recursive: true });
29702
+ await mkdir3(options.directory, { recursive: true });
28782
29703
  await Bun.write(receiptPath(id), `${JSON.stringify(receipt, null, 2)}
28783
29704
  `);
28784
29705
  }
@@ -29284,16 +30205,16 @@ var deliverVoiceObservabilityExport = async (options) => {
29284
30205
  const label = destination.label ?? (destination.kind === "file" ? "File observability export" : destination.kind === "s3" ? "S3 observability export" : destination.kind === "sqlite" ? "SQLite observability export" : destination.kind === "postgres" ? "Postgres observability export" : "Webhook observability export");
29285
30206
  try {
29286
30207
  if (destination.kind === "file") {
29287
- const target = join2(destination.directory, runId);
29288
- await mkdir2(join2(target, "artifacts"), { recursive: true });
29289
- await Bun.write(join2(target, "manifest.json"), manifest);
29290
- await Bun.write(join2(target, "artifact-index.json"), index);
30208
+ const target = join3(destination.directory, runId);
30209
+ await mkdir3(join3(target, "artifacts"), { recursive: true });
30210
+ await Bun.write(join3(target, "manifest.json"), manifest);
30211
+ await Bun.write(join3(target, "artifact-index.json"), index);
29291
30212
  if (destination.includeArtifacts !== false) {
29292
30213
  for (const artifact of options.report.artifacts) {
29293
30214
  if (!artifact.path) {
29294
30215
  continue;
29295
30216
  }
29296
- await Bun.write(join2(target, "artifacts", safeArtifactFileName(artifact)), await readFile(stripArtifactPathAnchor(artifact.path)));
30217
+ await Bun.write(join3(target, "artifacts", safeArtifactFileName(artifact)), await readFile(stripArtifactPathAnchor(artifact.path)));
29297
30218
  }
29298
30219
  }
29299
30220
  return {
@@ -29488,7 +30409,7 @@ var createVoiceObservabilityExportRoutes = (options = {}) => {
29488
30409
  artifactDownload: options.links?.artifactDownload ?? (artifactDownloadPath ? (artifact) => `${artifactDownloadPath}/${encodeURIComponent(artifact.id)}` : undefined)
29489
30410
  }
29490
30411
  });
29491
- const app = new Elysia44({
30412
+ const app = new Elysia45({
29492
30413
  name: options.name ?? "absolute-voice-observability-export"
29493
30414
  });
29494
30415
  app.get(path, async () => Response.json(await buildReport(), { headers }));
@@ -29595,7 +30516,7 @@ var buildVoiceReadinessRecoveryActions = (input, options = {}) => {
29595
30516
  sourceChecks: sourceChecks.length
29596
30517
  };
29597
30518
  };
29598
- var escapeHtml42 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
30519
+ var escapeHtml43 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
29599
30520
  var formatVoiceProofFreshnessDuration = (valueMs) => {
29600
30521
  if (valueMs < 1000) {
29601
30522
  return `${Math.max(0, Math.round(valueMs))}ms`;
@@ -29795,6 +30716,7 @@ var readinessGateCodes = {
29795
30716
  "Reconnect recovery contracts": "voice.readiness.reconnect_contracts",
29796
30717
  "Routing evidence": "voice.readiness.routing_evidence",
29797
30718
  "Session health": "voice.readiness.session_health",
30719
+ "Session observability evidence": "voice.readiness.session_observability_evidence",
29798
30720
  "Trace sink delivery": "voice.readiness.trace_sink_delivery"
29799
30721
  };
29800
30722
  var readinessGateCodeForCheck = (check) => readinessGateCodes[check.label] ?? `voice.readiness.${check.label.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "")}`;
@@ -29960,6 +30882,18 @@ var resolveMonitoringNotifierDelivery = async (options, input) => {
29960
30882
  }
29961
30883
  return typeof options.monitoringNotifierDelivery === "function" ? await options.monitoringNotifierDelivery(input) : options.monitoringNotifierDelivery;
29962
30884
  };
30885
+ var resolveSessionObservability = async (options, input) => {
30886
+ if (options.sessionObservability === false || options.sessionObservability === undefined) {
30887
+ return;
30888
+ }
30889
+ return typeof options.sessionObservability === "function" ? await options.sessionObservability(input) : options.sessionObservability;
30890
+ };
30891
+ var resolveSessionObservabilityEvidence = async (options, input) => {
30892
+ if (options.sessionObservabilityEvidence === false || options.sessionObservabilityEvidence === undefined) {
30893
+ return;
30894
+ }
30895
+ return typeof options.sessionObservabilityEvidence === "function" ? await options.sessionObservabilityEvidence(input) : options.sessionObservabilityEvidence;
30896
+ };
29963
30897
  var resolveMediaPipeline = async (options, input) => {
29964
30898
  if (options.mediaPipeline === false || options.mediaPipeline === undefined) {
29965
30899
  return;
@@ -30481,6 +31415,8 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
30481
31415
  mediaPipeline,
30482
31416
  browserMedia,
30483
31417
  telephonyMedia,
31418
+ sessionObservability,
31419
+ sessionObservabilityEvidence,
30484
31420
  telephonyWebhookSecurity,
30485
31421
  reconnectContracts,
30486
31422
  bargeInReports,
@@ -30530,6 +31466,8 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
30530
31466
  time("mediaPipeline", () => resolveMediaPipeline(options, { query, request })),
30531
31467
  time("browserMedia", () => resolveBrowserMedia(options, { query, request })),
30532
31468
  time("telephonyMedia", () => resolveTelephonyMedia(options, { query, request })),
31469
+ time("sessionObservability", () => resolveSessionObservability(options, { query, request })),
31470
+ time("sessionObservabilityEvidence", () => resolveSessionObservabilityEvidence(options, { query, request })),
30533
31471
  time("telephonyWebhookSecurity", () => resolveTelephonyWebhookSecurity(options, { query, request })),
30534
31472
  time("reconnectContracts", () => resolveReconnectContracts(options, { query, request })),
30535
31473
  time("bargeInReports", () => resolveBargeInReports(options, { query, request })),
@@ -30573,6 +31511,15 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
30573
31511
  warnWhenEmpty: options.incidentRecoveryTrendSLO?.warnWhenEmpty,
30574
31512
  mode: options.incidentRecoveryTrendSLO?.mode
30575
31513
  }) : undefined;
31514
+ const sessionObservabilityEvidenceSummary = sessionObservability ? evaluateVoiceSessionObservabilityEvidence(sessionObservability, sessionObservabilityEvidence ?? {}) : undefined;
31515
+ const sessionObservabilitySummary = sessionObservability && sessionObservabilityEvidenceSummary ? {
31516
+ failed: sessionObservabilityEvidenceSummary.status === "fail" ? 1 : 0,
31517
+ passed: sessionObservabilityEvidenceSummary.status === "pass" ? 1 : 0,
31518
+ status: sessionObservabilityEvidenceSummary.status,
31519
+ total: 1,
31520
+ warnings: sessionObservabilityEvidenceSummary.status === "warn" ? 1 : 0
31521
+ } : undefined;
31522
+ const proofSource = (...keys) => keys.map((key) => proofSources?.[key]).find((source) => source !== undefined);
30576
31523
  const checks = [
30577
31524
  {
30578
31525
  detail: quality.status === "pass" ? "Quality gates are passing." : "Quality gates need attention.",
@@ -30693,6 +31640,23 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
30693
31640
  }
30694
31641
  ] : []
30695
31642
  },
31643
+ ...sessionObservability && sessionObservabilitySummary ? [
31644
+ {
31645
+ detail: sessionObservabilitySummary.status === "pass" ? `Session observability is healthy with ${sessionObservabilityEvidenceSummary?.summary.turnsWithWaterfalls ?? 0} turn(s) containing waterfall stages and ${sessionObservabilityEvidenceSummary?.summary.providerDecisions ?? 0} provider decision stage(s).` : `${sessionObservabilityEvidenceSummary?.issues.join("; ") ?? "Session observability has unresolved issues."}`,
31646
+ href: options.links?.sessionObservability ?? "/voice/session-observability",
31647
+ label: "Session observability evidence",
31648
+ proofSource: proofSource("sessionObservability", "sessionObservability"),
31649
+ status: sessionObservabilitySummary.status,
31650
+ value: `${sessionObservabilitySummary.passed}/${sessionObservabilitySummary.total}`,
31651
+ actions: sessionObservabilitySummary.status === "pass" ? [] : [
31652
+ {
31653
+ description: "Open session observability report and address missing turns, provider decisions, tool calls, links, and incident markdown coverage.",
31654
+ href: options.links?.sessionObservability ?? "/voice/session-observability",
31655
+ label: "Open session observability"
31656
+ }
31657
+ ]
31658
+ }
31659
+ ] : [],
30696
31660
  {
30697
31661
  detail: routingEvents.length > 0 ? `${routingSessions.length} session(s) have provider routing evidence.` : "No provider routing traces are recorded yet.",
30698
31662
  href: options.links?.resilience ?? "/resilience",
@@ -30709,7 +31673,6 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
30709
31673
  }
30710
31674
  ];
30711
31675
  checks.push(...additionalChecks);
30712
- const proofSource = (...keys) => keys.map((key) => proofSources?.[key]).find((source) => source !== undefined);
30713
31676
  const calibratedThresholdActions = () => options.links?.sloReadinessThresholds ? [
30714
31677
  {
30715
31678
  description: "Open the calibrated thresholds currently driving this readiness gate.",
@@ -31556,6 +32519,7 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
31556
32519
  profileSwitchLiveDecisions: "/voice/profile-switch-live-decisions",
31557
32520
  profileSwitchPolicy: "/voice/profile-switch-policy",
31558
32521
  profileSwitchReadiness: "/voice/profile-switch-readiness",
32522
+ sessionObservability: "/voice/session-observability",
31559
32523
  telephonyMedia: "/voice/telephony-media",
31560
32524
  telephonyWebhookSecurity: "/api/voice/telephony/webhook-security",
31561
32525
  providerContracts: "/provider-contracts",
@@ -31626,6 +32590,7 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
31626
32590
  providerRoutingContracts: providerRoutingContractSummary,
31627
32591
  providerSlo: providerSloSummary,
31628
32592
  reconnectContracts: reconnectContractSummary,
32593
+ sessionObservability: sessionObservabilitySummary,
31629
32594
  quality: {
31630
32595
  status: quality.status
31631
32596
  },
@@ -31644,25 +32609,25 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
31644
32609
  var buildVoiceProductionReadinessGate = async (options, input = {}) => summarizeVoiceProductionReadinessGate(await buildVoiceProductionReadinessReport(options, input), options.gate || undefined);
31645
32610
  var renderVoiceProductionReadinessHTML = (report, options = {}) => {
31646
32611
  const title = options.title ?? "AbsoluteJS Voice Production Readiness";
31647
- const thresholdLink = report.links.sloReadinessThresholds ? `<p><a href="${escapeHtml42(report.links.sloReadinessThresholds)}">Open Calibration -&gt; Active Readiness Gate</a> to inspect the thresholds currently driving calibrated provider, latency, interruption, reconnect, and monitoring gates.</p>` : "";
31648
- const profile = report.profile ? `<section class="profile"><p class="eyebrow">Readiness profile</p><h2>${escapeHtml42(report.profile.name)}</h2><p>${escapeHtml42(report.profile.description)}</p><p>${escapeHtml42(report.profile.purpose)}</p><div class="profile-surfaces">${report.profile.surfaces.map((surface) => `<article class="${surface.configured ? "pass" : "warn"}"><span>${surface.configured ? "CONFIGURED" : "EXPECTED"}</span><strong>${surface.href ? `<a href="${escapeHtml42(surface.href)}">${escapeHtml42(surface.label)}</a>` : escapeHtml42(surface.label)}</strong></article>`).join("")}</div></section>` : "";
32612
+ const thresholdLink = report.links.sloReadinessThresholds ? `<p><a href="${escapeHtml43(report.links.sloReadinessThresholds)}">Open Calibration -&gt; Active Readiness Gate</a> to inspect the thresholds currently driving calibrated provider, latency, interruption, reconnect, and monitoring gates.</p>` : "";
32613
+ const profile = report.profile ? `<section class="profile"><p class="eyebrow">Readiness profile</p><h2>${escapeHtml43(report.profile.name)}</h2><p>${escapeHtml43(report.profile.description)}</p><p>${escapeHtml43(report.profile.purpose)}</p><div class="profile-surfaces">${report.profile.surfaces.map((surface) => `<article class="${surface.configured ? "pass" : "warn"}"><span>${surface.configured ? "CONFIGURED" : "EXPECTED"}</span><strong>${surface.href ? `<a href="${escapeHtml43(surface.href)}">${escapeHtml43(surface.label)}</a>` : escapeHtml43(surface.label)}</strong></article>`).join("")}</div></section>` : "";
31649
32614
  const checks = report.checks.map((check, index) => {
31650
- const actions = (check.actions ?? []).map((action) => action.method === "POST" ? `<button type="button" data-readiness-action="${index}" data-action-url="${escapeHtml42(action.href)}">${escapeHtml42(action.label)}</button>` : `<a href="${escapeHtml42(action.href)}">${escapeHtml42(action.label)}</a>`).join("");
31651
- const explanation = check.gateExplanation ? `<p class="gate-explanation">Why this gate is ${escapeHtml42(check.status)}: observed ${escapeHtml42(String(check.gateExplanation.observed ?? "n/a"))}${check.gateExplanation.unit ? ` ${escapeHtml42(check.gateExplanation.unit)}` : ""}; threshold ${escapeHtml42(String(check.gateExplanation.threshold ?? "n/a"))}${check.gateExplanation.unit ? ` ${escapeHtml42(check.gateExplanation.unit)}` : ""}. ${escapeHtml42(check.gateExplanation.remediation)} ${check.gateExplanation.sourceHref ? `<a href="${escapeHtml42(check.gateExplanation.sourceHref)}">Open threshold source</a>` : ""}</p>` : "";
31652
- return `<article class="check ${escapeHtml42(check.status)}">
32615
+ const actions = (check.actions ?? []).map((action) => action.method === "POST" ? `<button type="button" data-readiness-action="${index}" data-action-url="${escapeHtml43(action.href)}">${escapeHtml43(action.label)}</button>` : `<a href="${escapeHtml43(action.href)}">${escapeHtml43(action.label)}</a>`).join("");
32616
+ const explanation = check.gateExplanation ? `<p class="gate-explanation">Why this gate is ${escapeHtml43(check.status)}: observed ${escapeHtml43(String(check.gateExplanation.observed ?? "n/a"))}${check.gateExplanation.unit ? ` ${escapeHtml43(check.gateExplanation.unit)}` : ""}; threshold ${escapeHtml43(String(check.gateExplanation.threshold ?? "n/a"))}${check.gateExplanation.unit ? ` ${escapeHtml43(check.gateExplanation.unit)}` : ""}. ${escapeHtml43(check.gateExplanation.remediation)} ${check.gateExplanation.sourceHref ? `<a href="${escapeHtml43(check.gateExplanation.sourceHref)}">Open threshold source</a>` : ""}</p>` : "";
32617
+ return `<article class="check ${escapeHtml43(check.status)}">
31653
32618
  <div>
31654
- <span>${escapeHtml42(check.status.toUpperCase())}</span>
31655
- <h2>${escapeHtml42(check.label)}</h2>
31656
- ${check.detail ? `<p>${escapeHtml42(check.detail)}</p>` : ""}
32619
+ <span>${escapeHtml43(check.status.toUpperCase())}</span>
32620
+ <h2>${escapeHtml43(check.label)}</h2>
32621
+ ${check.detail ? `<p>${escapeHtml43(check.detail)}</p>` : ""}
31657
32622
  ${explanation}
31658
- ${check.proofSource ? `<p class="proof-source">Proof source: ${check.proofSource.href ? `<a href="${escapeHtml42(check.proofSource.href)}">${escapeHtml42(check.proofSource.sourceLabel)}</a>` : escapeHtml42(check.proofSource.sourceLabel)}${check.proofSource.detail ? ` \xB7 ${escapeHtml42(check.proofSource.detail)}` : ""}</p>` : ""}
32623
+ ${check.proofSource ? `<p class="proof-source">Proof source: ${check.proofSource.href ? `<a href="${escapeHtml43(check.proofSource.href)}">${escapeHtml43(check.proofSource.sourceLabel)}</a>` : escapeHtml43(check.proofSource.sourceLabel)}${check.proofSource.detail ? ` \xB7 ${escapeHtml43(check.proofSource.detail)}` : ""}</p>` : ""}
31659
32624
  ${actions ? `<p class="actions">${actions}</p>` : ""}
31660
32625
  </div>
31661
- <strong>${escapeHtml42(String(check.value ?? check.status))}</strong>
31662
- ${check.href ? `<a href="${escapeHtml42(check.href)}">Open surface</a>` : ""}
32626
+ <strong>${escapeHtml43(String(check.value ?? check.status))}</strong>
32627
+ ${check.href ? `<a href="${escapeHtml43(check.href)}">Open surface</a>` : ""}
31663
32628
  </article>`;
31664
32629
  }).join("");
31665
- const snippet = escapeHtml42(`createVoiceProductionReadinessRoutes({
32630
+ const snippet = escapeHtml43(`createVoiceProductionReadinessRoutes({
31666
32631
  htmlPath: '/production-readiness',
31667
32632
  path: '/api/production-readiness',
31668
32633
  gatePath: '/api/production-readiness/gate',
@@ -31678,13 +32643,13 @@ var renderVoiceProductionReadinessHTML = (report, options = {}) => {
31678
32643
  providerRoutingContracts: loadProviderRoutingContracts,
31679
32644
  store: traceStore
31680
32645
  });`);
31681
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml42(title)}</title><style>body{background:#0c0f14;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1060px;padding:32px}.hero,.primitive,.profile{background:linear-gradient(135deg,rgba(20,184,166,.18),rgba(245,158,11,.12));border:1px solid #26313d;border-radius:28px;margin-bottom:18px;padding:28px}.primitive,.profile{background:#111722}.primitive{border-color:#3a3f2d}.eyebrow{color:#fbbf24;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,5rem);line-height:.9;margin:.2rem 0 1rem}.status{display:inline-flex;border:1px solid #3f3f46;border-radius:999px;padding:8px 12px}.primitive code{color:#fde68a}.primitive p{color:#c8ccd3;line-height:1.55;margin:.45rem 0 0}.primitive pre{background:#0b0f16;border:1px solid #2c3440;border-radius:18px;color:#fef3c7;margin:16px 0 0;overflow:auto;padding:16px}.status.pass,.check.pass,.profile-surfaces .pass{border-color:rgba(34,197,94,.55)}.status.warn,.check.warn,.profile-surfaces .warn{border-color:rgba(245,158,11,.65)}.status.fail,.check.fail{border-color:rgba(239,68,68,.75)}.checks{display:grid;gap:14px}.check{align-items:center;background:#141922;border:1px solid #26313d;border-radius:22px;display:grid;gap:16px;grid-template-columns:1fr auto auto;padding:18px}.check span,.profile-surfaces span{color:#a8b0b8;font-size:.78rem;font-weight:900;letter-spacing:.08em}.check h2{margin:.2rem 0}.check p,.profile p{color:#b9c0c8;margin:.2rem 0 0}.check .proof-source{color:#f9d77e;font-weight:800}.check .gate-explanation{background:#0b0f16;border:1px solid #2c3440;border-radius:14px;color:#fef3c7;margin-top:10px;padding:10px}.check strong{font-size:1.5rem}.profile-surfaces{display:grid;gap:10px;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));margin-top:16px}.profile-surfaces article{background:#141922;border:1px solid #26313d;border-radius:16px;padding:14px}.profile-surfaces strong{display:block;margin-top:6px}.actions{display:flex;flex-wrap:wrap;gap:10px}.check a,a{color:#fbbf24}button{background:#fbbf24;border:0;border-radius:999px;color:#111827;cursor:pointer;font-weight:800;padding:9px 12px}button:disabled{cursor:wait;opacity:.65}@media(max-width:760px){main{padding:20px}.check{grid-template-columns:1fr}}</style></head><body><main><section class="hero"><p class="eyebrow">Self-hosted readiness</p><h1>${escapeHtml42(title)}</h1><p>One deployable pass/fail report for quality gates, provider failover, session health, handoffs, routing evidence, and optional carrier readiness.</p><p class="status ${escapeHtml42(report.status)}">Overall: ${escapeHtml42(report.status.toUpperCase())}</p><p>Checked ${escapeHtml42(new Date(report.checkedAt).toLocaleString())}</p>${thresholdLink}</section>${profile}<section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceProductionReadinessRoutes(...)</code> builds this deploy gate</h2><p>Mount one package primitive to expose JSON readiness, HTML readiness, and a machine-readable gate route. Feed it the proof stores and contract reports your app already owns.</p><pre><code>${snippet}</code></pre></section><section class="checks">${checks}</section></main><script>document.querySelectorAll("[data-readiness-action]").forEach((button)=>{button.addEventListener("click",async()=>{const url=button.getAttribute("data-action-url");if(!url)return;button.disabled=true;const original=button.textContent;button.textContent="Running...";try{const response=await fetch(url,{method:"POST"});button.textContent=response.ok?"Done. Reloading...":"Failed";if(response.ok)setTimeout(()=>location.reload(),500)}catch{button.textContent="Failed"}finally{setTimeout(()=>{button.disabled=false;button.textContent=original},1500)}})});</script></body></html>`;
32646
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml43(title)}</title><style>body{background:#0c0f14;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1060px;padding:32px}.hero,.primitive,.profile{background:linear-gradient(135deg,rgba(20,184,166,.18),rgba(245,158,11,.12));border:1px solid #26313d;border-radius:28px;margin-bottom:18px;padding:28px}.primitive,.profile{background:#111722}.primitive{border-color:#3a3f2d}.eyebrow{color:#fbbf24;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,5rem);line-height:.9;margin:.2rem 0 1rem}.status{display:inline-flex;border:1px solid #3f3f46;border-radius:999px;padding:8px 12px}.primitive code{color:#fde68a}.primitive p{color:#c8ccd3;line-height:1.55;margin:.45rem 0 0}.primitive pre{background:#0b0f16;border:1px solid #2c3440;border-radius:18px;color:#fef3c7;margin:16px 0 0;overflow:auto;padding:16px}.status.pass,.check.pass,.profile-surfaces .pass{border-color:rgba(34,197,94,.55)}.status.warn,.check.warn,.profile-surfaces .warn{border-color:rgba(245,158,11,.65)}.status.fail,.check.fail{border-color:rgba(239,68,68,.75)}.checks{display:grid;gap:14px}.check{align-items:center;background:#141922;border:1px solid #26313d;border-radius:22px;display:grid;gap:16px;grid-template-columns:1fr auto auto;padding:18px}.check span,.profile-surfaces span{color:#a8b0b8;font-size:.78rem;font-weight:900;letter-spacing:.08em}.check h2{margin:.2rem 0}.check p,.profile p{color:#b9c0c8;margin:.2rem 0 0}.check .proof-source{color:#f9d77e;font-weight:800}.check .gate-explanation{background:#0b0f16;border:1px solid #2c3440;border-radius:14px;color:#fef3c7;margin-top:10px;padding:10px}.check strong{font-size:1.5rem}.profile-surfaces{display:grid;gap:10px;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));margin-top:16px}.profile-surfaces article{background:#141922;border:1px solid #26313d;border-radius:16px;padding:14px}.profile-surfaces strong{display:block;margin-top:6px}.actions{display:flex;flex-wrap:wrap;gap:10px}.check a,a{color:#fbbf24}button{background:#fbbf24;border:0;border-radius:999px;color:#111827;cursor:pointer;font-weight:800;padding:9px 12px}button:disabled{cursor:wait;opacity:.65}@media(max-width:760px){main{padding:20px}.check{grid-template-columns:1fr}}</style></head><body><main><section class="hero"><p class="eyebrow">Self-hosted readiness</p><h1>${escapeHtml43(title)}</h1><p>One deployable pass/fail report for quality gates, provider failover, session health, handoffs, routing evidence, and optional carrier readiness.</p><p class="status ${escapeHtml43(report.status)}">Overall: ${escapeHtml43(report.status.toUpperCase())}</p><p>Checked ${escapeHtml43(new Date(report.checkedAt).toLocaleString())}</p>${thresholdLink}</section>${profile}<section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceProductionReadinessRoutes(...)</code> builds this deploy gate</h2><p>Mount one package primitive to expose JSON readiness, HTML readiness, and a machine-readable gate route. Feed it the proof stores and contract reports your app already owns.</p><pre><code>${snippet}</code></pre></section><section class="checks">${checks}</section></main><script>document.querySelectorAll("[data-readiness-action]").forEach((button)=>{button.addEventListener("click",async()=>{const url=button.getAttribute("data-action-url");if(!url)return;button.disabled=true;const original=button.textContent;button.textContent="Running...";try{const response=await fetch(url,{method:"POST"});button.textContent=response.ok?"Done. Reloading...":"Failed";if(response.ok)setTimeout(()=>location.reload(),500)}catch{button.textContent="Failed"}finally{setTimeout(()=>{button.disabled=false;button.textContent=original},1500)}})});</script></body></html>`;
31682
32647
  };
31683
32648
  var createVoiceProductionReadinessRoutes = (options) => {
31684
32649
  const path = options.path ?? "/api/production-readiness";
31685
32650
  const gatePath = options.gatePath === undefined ? "/api/production-readiness/gate" : options.gatePath;
31686
32651
  const htmlPath = options.htmlPath ?? "/production-readiness";
31687
- const routes = new Elysia45({
32652
+ const routes = new Elysia46({
31688
32653
  name: options.name ?? "absolutejs-voice-production-readiness"
31689
32654
  });
31690
32655
  let cachedReport;
@@ -31756,7 +32721,7 @@ var createVoiceProductionReadinessRoutes = (options) => {
31756
32721
  };
31757
32722
 
31758
32723
  // src/operationalStatus.ts
31759
- var escapeHtml43 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
32724
+ var escapeHtml44 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
31760
32725
  var resolveValue2 = async (value) => typeof value === "function" ? await value() : value;
31761
32726
  var isDeliveryRuntime = (value) => Boolean(value && typeof value === "object" && "isRunning" in value && "summarize" in value);
31762
32727
  var worstStatus3 = (statuses) => statuses.includes("fail") ? "fail" : statuses.includes("warn") ? "warn" : "pass";
@@ -31826,19 +32791,19 @@ var buildVoiceOperationalStatusReport = async (options) => {
31826
32791
  };
31827
32792
  var renderVoiceOperationalStatusHTML = (report, options = {}) => {
31828
32793
  const title = options.title ?? "AbsoluteJS Voice Operational Status";
31829
- const checks = report.checks.map((check) => `<article class="${escapeHtml43(check.status)}">
31830
- <span>${escapeHtml43(check.status.toUpperCase())}</span>
31831
- <h2>${escapeHtml43(check.label)}</h2>
31832
- <strong>${escapeHtml43(String(check.value ?? check.status))}</strong>
31833
- ${check.detail ? `<p>${escapeHtml43(check.detail)}</p>` : ""}
31834
- ${check.href ? `<a href="${escapeHtml43(check.href)}">Open surface</a>` : ""}
32794
+ const checks = report.checks.map((check) => `<article class="${escapeHtml44(check.status)}">
32795
+ <span>${escapeHtml44(check.status.toUpperCase())}</span>
32796
+ <h2>${escapeHtml44(check.label)}</h2>
32797
+ <strong>${escapeHtml44(String(check.value ?? check.status))}</strong>
32798
+ ${check.detail ? `<p>${escapeHtml44(check.detail)}</p>` : ""}
32799
+ ${check.href ? `<a href="${escapeHtml44(check.href)}">Open surface</a>` : ""}
31835
32800
  </article>`).join("");
31836
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml43(title)}</title><style>body{background:#10130f;color:#f8f3df;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1040px;padding:32px}.hero{background:linear-gradient(135deg,rgba(132,204,22,.18),rgba(14,165,233,.13));border:1px solid #2c3a28;border-radius:28px;margin-bottom:18px;padding:28px}.eyebrow{color:#bef264;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,4.8rem);line-height:.92;margin:.2rem 0 1rem}.status{border:1px solid #64748b;border-radius:999px;display:inline-flex;font-weight:900;padding:8px 12px}.grid{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(230px,1fr))}article{background:#171d15;border:1px solid #2c3a28;border-radius:22px;padding:18px}article.pass{border-color:rgba(34,197,94,.65)}article.warn{border-color:rgba(245,158,11,.75)}article.fail{border-color:rgba(239,68,68,.85)}article span{color:#bef264;font-size:.78rem;font-weight:900;letter-spacing:.08em}article.warn span{color:#fbbf24}article.fail span{color:#fca5a5}article strong{display:block;font-size:1.6rem;margin:.4rem 0}article p{color:#c5ceb9}a{color:#bef264}</style></head><body><main><section class="hero"><p class="eyebrow">Operational status</p><h1>${escapeHtml43(title)}</h1><p class="status ${escapeHtml43(report.status)}">Overall: ${escapeHtml43(report.status.toUpperCase())}</p><p>${String(report.summary.pass)}/${String(report.summary.total)} checks passing. Checked ${escapeHtml43(new Date(report.checkedAt).toLocaleString())}.</p></section><section class="grid">${checks || '<article class="pass"><span>PASS</span><h2>No operational checks configured</h2><strong>0/0</strong></article>'}</section></main></body></html>`;
32801
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml44(title)}</title><style>body{background:#10130f;color:#f8f3df;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1040px;padding:32px}.hero{background:linear-gradient(135deg,rgba(132,204,22,.18),rgba(14,165,233,.13));border:1px solid #2c3a28;border-radius:28px;margin-bottom:18px;padding:28px}.eyebrow{color:#bef264;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,4.8rem);line-height:.92;margin:.2rem 0 1rem}.status{border:1px solid #64748b;border-radius:999px;display:inline-flex;font-weight:900;padding:8px 12px}.grid{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(230px,1fr))}article{background:#171d15;border:1px solid #2c3a28;border-radius:22px;padding:18px}article.pass{border-color:rgba(34,197,94,.65)}article.warn{border-color:rgba(245,158,11,.75)}article.fail{border-color:rgba(239,68,68,.85)}article span{color:#bef264;font-size:.78rem;font-weight:900;letter-spacing:.08em}article.warn span{color:#fbbf24}article.fail span{color:#fca5a5}article strong{display:block;font-size:1.6rem;margin:.4rem 0}article p{color:#c5ceb9}a{color:#bef264}</style></head><body><main><section class="hero"><p class="eyebrow">Operational status</p><h1>${escapeHtml44(title)}</h1><p class="status ${escapeHtml44(report.status)}">Overall: ${escapeHtml44(report.status.toUpperCase())}</p><p>${String(report.summary.pass)}/${String(report.summary.total)} checks passing. Checked ${escapeHtml44(new Date(report.checkedAt).toLocaleString())}.</p></section><section class="grid">${checks || '<article class="pass"><span>PASS</span><h2>No operational checks configured</h2><strong>0/0</strong></article>'}</section></main></body></html>`;
31837
32802
  };
31838
32803
  var createVoiceOperationalStatusRoutes = (options) => {
31839
32804
  const path = options.path ?? "/api/voice/operational-status";
31840
32805
  const htmlPath = options.htmlPath === undefined ? "/voice/operational-status" : options.htmlPath;
31841
- const routes = new Elysia46({
32806
+ const routes = new Elysia47({
31842
32807
  name: options.name ?? "absolutejs-voice-operational-status"
31843
32808
  }).get(path, async () => {
31844
32809
  const report = await buildVoiceOperationalStatusReport(options);
@@ -31865,7 +32830,7 @@ var createVoiceOperationalStatusRoutes = (options) => {
31865
32830
  return routes;
31866
32831
  };
31867
32832
  // src/dataControl.ts
31868
- import { Elysia as Elysia47 } from "elysia";
32833
+ import { Elysia as Elysia48 } from "elysia";
31869
32834
  var voiceComplianceRedactionDefaults = {
31870
32835
  keys: [
31871
32836
  "apiKey",
@@ -32104,7 +33069,7 @@ var parseRetentionScopes = (value) => {
32104
33069
  const allowed = new Set(allRetentionScopes);
32105
33070
  return value.split(",").map((entry) => entry.trim()).filter((entry) => allowed.has(entry));
32106
33071
  };
32107
- var escapeHtml44 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
33072
+ var escapeHtml45 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
32108
33073
  var buildStorageSurfaces = (options) => [
32109
33074
  {
32110
33075
  configured: Boolean(options.session ?? options.sessions),
@@ -32341,12 +33306,12 @@ var buildVoiceDataControlReport = async (options) => {
32341
33306
  zeroRetentionAvailable: true
32342
33307
  };
32343
33308
  };
32344
- var renderDataRetentionReportRows = (report) => report.scopes.map((scope) => `<tr><td>${escapeHtml44(scope.scope)}</td><td>${scope.scannedCount}</td><td>${scope.deletedCount}</td><td>${escapeHtml44(scope.skippedReason ?? "")}</td><td><code>${escapeHtml44(scope.deletedIds.join(", "))}</code></td></tr>`).join("");
33309
+ var renderDataRetentionReportRows = (report) => report.scopes.map((scope) => `<tr><td>${escapeHtml45(scope.scope)}</td><td>${scope.scannedCount}</td><td>${scope.deletedCount}</td><td>${escapeHtml45(scope.skippedReason ?? "")}</td><td><code>${escapeHtml45(scope.deletedIds.join(", "))}</code></td></tr>`).join("");
32345
33310
  var renderVoiceDataControlHTML = (report, options = {}) => {
32346
33311
  const title = options.title ?? "Voice Data Control";
32347
- const storageRows = report.storage.map((surface) => `<tr><td>${escapeHtml44(surface.name)}</td><td>${surface.configured ? "Configured" : "Missing"}</td><td>${escapeHtml44(surface.control)}</td><td>${surface.selfHosted ? "Yes" : "No"}</td></tr>`).join("");
32348
- const keyRows = report.providerKeys.map((key) => `<tr><td>${escapeHtml44(key.name)}</td><td><code>${escapeHtml44(key.env ?? "n/a")}</code></td><td>${key.required ? "Required" : "Optional"}</td><td>${escapeHtml44(key.recommendation)}</td></tr>`).join("");
32349
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml44(title)}</title><style>body{background:#f8f7f2;color:#181713;font-family:ui-sans-serif,system-ui,sans-serif;line-height:1.45;margin:2rem}main{max-width:1120px;margin:auto}.summary{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));margin:1rem 0}.card,table{background:white;border:1px solid #ddd6c8;border-radius:14px}.card{padding:1rem}table{border-collapse:collapse;width:100%;overflow:hidden}td,th{border-bottom:1px solid #eee8dc;padding:.7rem;text-align:left;vertical-align:top}code{white-space:pre-wrap;word-break:break-word}a{color:#9a3412}</style></head><body><main><h1>${escapeHtml44(title)}</h1><p>Self-hosted data-control proof for retention, redaction, audit export, deletion planning, customer-owned storage, and provider key handling.</p><section class="summary"><div class="card"><strong>Redaction</strong><br>${report.redaction.enabled ? "enabled" : "disabled"}</div><div class="card"><strong>Retention dry-run deletes</strong><br>${report.retentionPlan.deletedCount}</div><div class="card"><strong>Audit export events</strong><br>${report.auditExport?.events.length ?? 0}</div><div class="card"><strong>Zero retention recipe</strong><br>${report.zeroRetentionAvailable ? "available" : "missing"}</div></section><h2>Customer-Owned Storage</h2><table><thead><tr><th>Surface</th><th>Status</th><th>Control</th><th>Self-hosted</th></tr></thead><tbody>${storageRows}</tbody></table><h2>Retention Plan</h2><table><thead><tr><th>Scope</th><th>Scanned</th><th>Would delete</th><th>Skipped</th><th>Ids</th></tr></thead><tbody>${renderDataRetentionReportRows(report.retentionPlan)}</tbody></table><h2>Provider Keys</h2><table><thead><tr><th>Provider</th><th>Env</th><th>Required</th><th>Recommendation</th></tr></thead><tbody>${keyRows}</tbody></table><p><a href="./data-control/audit.md">Redacted audit Markdown</a> \xB7 <a href="./data-control/audit.html">Redacted audit HTML</a></p></main></body></html>`;
33312
+ const storageRows = report.storage.map((surface) => `<tr><td>${escapeHtml45(surface.name)}</td><td>${surface.configured ? "Configured" : "Missing"}</td><td>${escapeHtml45(surface.control)}</td><td>${surface.selfHosted ? "Yes" : "No"}</td></tr>`).join("");
33313
+ const keyRows = report.providerKeys.map((key) => `<tr><td>${escapeHtml45(key.name)}</td><td><code>${escapeHtml45(key.env ?? "n/a")}</code></td><td>${key.required ? "Required" : "Optional"}</td><td>${escapeHtml45(key.recommendation)}</td></tr>`).join("");
33314
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml45(title)}</title><style>body{background:#f8f7f2;color:#181713;font-family:ui-sans-serif,system-ui,sans-serif;line-height:1.45;margin:2rem}main{max-width:1120px;margin:auto}.summary{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));margin:1rem 0}.card,table{background:white;border:1px solid #ddd6c8;border-radius:14px}.card{padding:1rem}table{border-collapse:collapse;width:100%;overflow:hidden}td,th{border-bottom:1px solid #eee8dc;padding:.7rem;text-align:left;vertical-align:top}code{white-space:pre-wrap;word-break:break-word}a{color:#9a3412}</style></head><body><main><h1>${escapeHtml45(title)}</h1><p>Self-hosted data-control proof for retention, redaction, audit export, deletion planning, customer-owned storage, and provider key handling.</p><section class="summary"><div class="card"><strong>Redaction</strong><br>${report.redaction.enabled ? "enabled" : "disabled"}</div><div class="card"><strong>Retention dry-run deletes</strong><br>${report.retentionPlan.deletedCount}</div><div class="card"><strong>Audit export events</strong><br>${report.auditExport?.events.length ?? 0}</div><div class="card"><strong>Zero retention recipe</strong><br>${report.zeroRetentionAvailable ? "available" : "missing"}</div></section><h2>Customer-Owned Storage</h2><table><thead><tr><th>Surface</th><th>Status</th><th>Control</th><th>Self-hosted</th></tr></thead><tbody>${storageRows}</tbody></table><h2>Retention Plan</h2><table><thead><tr><th>Scope</th><th>Scanned</th><th>Would delete</th><th>Skipped</th><th>Ids</th></tr></thead><tbody>${renderDataRetentionReportRows(report.retentionPlan)}</tbody></table><h2>Provider Keys</h2><table><thead><tr><th>Provider</th><th>Env</th><th>Required</th><th>Recommendation</th></tr></thead><tbody>${keyRows}</tbody></table><p><a href="./data-control/audit.md">Redacted audit Markdown</a> \xB7 <a href="./data-control/audit.html">Redacted audit HTML</a></p></main></body></html>`;
32350
33315
  };
32351
33316
  var renderVoiceDataControlMarkdown = (report, options = {}) => [
32352
33317
  `# ${options.title ?? "Voice Data Control"}`,
@@ -32404,7 +33369,7 @@ var parseRetentionPolicyBody = (body, options, dryRun) => {
32404
33369
  var createVoiceDataControlRoutes = (options) => {
32405
33370
  const path = options.path ?? "/data-control";
32406
33371
  const title = options.title ?? "AbsoluteJS Voice Data Control";
32407
- const routes = new Elysia47({
33372
+ const routes = new Elysia48({
32408
33373
  name: options.name ?? "absolutejs-voice-data-control"
32409
33374
  });
32410
33375
  routes.get(path, async ({ query }) => {
@@ -32480,10 +33445,10 @@ var createVoiceDataControlRoutes = (options) => {
32480
33445
  return routes;
32481
33446
  };
32482
33447
  // src/evalRoutes.ts
32483
- import { Elysia as Elysia48 } from "elysia";
32484
- import { mkdir as mkdir3 } from "fs/promises";
33448
+ import { Elysia as Elysia49 } from "elysia";
33449
+ import { mkdir as mkdir4 } from "fs/promises";
32485
33450
  import { dirname as dirname2 } from "path";
32486
- var escapeHtml45 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
33451
+ var escapeHtml46 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
32487
33452
  var rate4 = (count, total) => count / Math.max(1, total);
32488
33453
  var normalizeSearchText = (value) => value.trim().toLowerCase();
32489
33454
  var getString18 = (value) => typeof value === "string" ? value : undefined;
@@ -32793,7 +33758,7 @@ var createVoiceFileEvalBaselineStore = (filePath) => ({
32793
33758
  return text.trim() ? JSON.parse(text) : undefined;
32794
33759
  },
32795
33760
  set: async (report) => {
32796
- await mkdir3(dirname2(filePath), { recursive: true });
33761
+ await mkdir4(dirname2(filePath), { recursive: true });
32797
33762
  await Bun.write(filePath, JSON.stringify(report, null, 2));
32798
33763
  }
32799
33764
  });
@@ -32814,7 +33779,7 @@ var createVoiceFileScenarioFixtureStore = (filePath) => ({
32814
33779
  var formatTime = (value) => value === undefined ? "unknown" : new Date(value).toLocaleString();
32815
33780
  var formatPercent = (value) => `${(value * 100).toFixed(2)}%`;
32816
33781
  var renderVoiceEvalPrimitiveCopy = () => {
32817
- const snippet = escapeHtml45(`app.use(
33782
+ const snippet = escapeHtml46(`app.use(
32818
33783
  createVoiceEvalRoutes({
32819
33784
  path: '/evals',
32820
33785
  store: traceStore,
@@ -32835,48 +33800,48 @@ var renderVoiceEvalPrimitiveCopy = () => {
32835
33800
  };
32836
33801
  var renderVoiceEvalHTML = (report, options = {}) => {
32837
33802
  const title = options.title ?? "AbsoluteJS Voice Evals";
32838
- const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml45(link.href)}">${escapeHtml45(link.label)}</a>`).join("")}</nav>` : "";
32839
- const trend = report.trend.length ? report.trend.map((bucket) => `<tr><td>${escapeHtml45(bucket.key)}</td><td>${bucket.total}</td><td>${bucket.passed}</td><td>${bucket.failed}</td></tr>`).join("") : '<tr><td colspan="4">No eval buckets yet.</td></tr>';
33803
+ const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml46(link.href)}">${escapeHtml46(link.label)}</a>`).join("")}</nav>` : "";
33804
+ const trend = report.trend.length ? report.trend.map((bucket) => `<tr><td>${escapeHtml46(bucket.key)}</td><td>${bucket.total}</td><td>${bucket.passed}</td><td>${bucket.failed}</td></tr>`).join("") : '<tr><td colspan="4">No eval buckets yet.</td></tr>';
32840
33805
  const sessions = report.sessions.length ? report.sessions.map((session) => {
32841
33806
  const failedMetrics = Object.entries(session.quality.metrics).filter(([, metric]) => !metric.pass).map(([, metric]) => metric.label).join(", ");
32842
- const sessionLabel = session.operationsRecordHref ? `<a href="${escapeHtml45(session.operationsRecordHref)}">${escapeHtml45(session.sessionId)}</a>` : escapeHtml45(session.sessionId);
32843
- return `<tr class="${session.status}"><td>${sessionLabel}</td><td>${escapeHtml45(session.status)}</td><td>${session.eventCount}</td><td>${session.summary.turnCount}</td><td>${session.summary.errorCount}</td><td>${escapeHtml45(formatTime(session.endedAt))}</td><td>${escapeHtml45(failedMetrics || "none")}</td></tr>`;
33807
+ const sessionLabel = session.operationsRecordHref ? `<a href="${escapeHtml46(session.operationsRecordHref)}">${escapeHtml46(session.sessionId)}</a>` : escapeHtml46(session.sessionId);
33808
+ return `<tr class="${session.status}"><td>${sessionLabel}</td><td>${escapeHtml46(session.status)}</td><td>${session.eventCount}</td><td>${session.summary.turnCount}</td><td>${session.summary.errorCount}</td><td>${escapeHtml46(formatTime(session.endedAt))}</td><td>${escapeHtml46(failedMetrics || "none")}</td></tr>`;
32844
33809
  }).join("") : '<tr><td colspan="7">No sessions found.</td></tr>';
32845
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml45(title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;margin:2rem;background:#f8f7f2;color:#181713}main{max-width:1180px;margin:auto}nav{display:flex;gap:.5rem;flex-wrap:wrap;margin-bottom:1rem}nav a{background:#181713;border-radius:999px;color:white;padding:.35rem .7rem;text-decoration:none}.eyebrow{font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.status{border-radius:999px;display:inline-flex;font-weight:800;padding:.35rem .75rem}.pass{color:#166534}.fail{color:#991b1b}.status.pass{background:#dcfce7}.status.fail{background:#fee2e2}.grid{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));margin:1rem 0}.card,.primitive{background:white;border:1px solid #e7e5e4;border-radius:1rem;padding:1rem}.primitive{background:#fffdf7;border-color:#d6c7a3;margin:1rem 0}.primitive p{line-height:1.55}.primitive pre{background:#181713;border-radius:.85rem;color:#fef3c7;overflow:auto;padding:1rem}.primitive code{color:#fef3c7}.card strong{display:block;font-size:2rem}table{border-collapse:collapse;background:white;width:100%;margin:1rem 0 2rem}td,th{border-bottom:1px solid #eee;padding:.75rem;text-align:left}tr.fail td{border-left:4px solid #dc2626}tr.pass td{border-left:4px solid #16a34a}</style></head><body><main>${links}<h1>${escapeHtml45(title)}</h1><p class="status ${report.status}">${report.status}</p><div class="grid"><article class="card"><span>Total</span><strong>${report.total}</strong></article><article class="card"><span>Passed</span><strong>${report.passed}</strong></article><article class="card"><span>Failed</span><strong>${report.failed}</strong></article></div>${renderVoiceEvalPrimitiveCopy()}<h2>Trend</h2><table><thead><tr><th>Day</th><th>Total</th><th>Passed</th><th>Failed</th></tr></thead><tbody>${trend}</tbody></table><h2>Session Eval Results</h2><table><thead><tr><th>Session</th><th>Status</th><th>Events</th><th>Turns</th><th>Errors</th><th>Last event</th><th>Failed metrics</th></tr></thead><tbody>${sessions}</tbody></table></main></body></html>`;
33810
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml46(title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;margin:2rem;background:#f8f7f2;color:#181713}main{max-width:1180px;margin:auto}nav{display:flex;gap:.5rem;flex-wrap:wrap;margin-bottom:1rem}nav a{background:#181713;border-radius:999px;color:white;padding:.35rem .7rem;text-decoration:none}.eyebrow{font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.status{border-radius:999px;display:inline-flex;font-weight:800;padding:.35rem .75rem}.pass{color:#166534}.fail{color:#991b1b}.status.pass{background:#dcfce7}.status.fail{background:#fee2e2}.grid{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));margin:1rem 0}.card,.primitive{background:white;border:1px solid #e7e5e4;border-radius:1rem;padding:1rem}.primitive{background:#fffdf7;border-color:#d6c7a3;margin:1rem 0}.primitive p{line-height:1.55}.primitive pre{background:#181713;border-radius:.85rem;color:#fef3c7;overflow:auto;padding:1rem}.primitive code{color:#fef3c7}.card strong{display:block;font-size:2rem}table{border-collapse:collapse;background:white;width:100%;margin:1rem 0 2rem}td,th{border-bottom:1px solid #eee;padding:.75rem;text-align:left}tr.fail td{border-left:4px solid #dc2626}tr.pass td{border-left:4px solid #16a34a}</style></head><body><main>${links}<h1>${escapeHtml46(title)}</h1><p class="status ${report.status}">${report.status}</p><div class="grid"><article class="card"><span>Total</span><strong>${report.total}</strong></article><article class="card"><span>Passed</span><strong>${report.passed}</strong></article><article class="card"><span>Failed</span><strong>${report.failed}</strong></article></div>${renderVoiceEvalPrimitiveCopy()}<h2>Trend</h2><table><thead><tr><th>Day</th><th>Total</th><th>Passed</th><th>Failed</th></tr></thead><tbody>${trend}</tbody></table><h2>Session Eval Results</h2><table><thead><tr><th>Session</th><th>Status</th><th>Events</th><th>Turns</th><th>Errors</th><th>Last event</th><th>Failed metrics</th></tr></thead><tbody>${sessions}</tbody></table></main></body></html>`;
32846
33811
  };
32847
33812
  var renderVoiceEvalBaselineHTML = (comparison, options = {}) => {
32848
33813
  const title = options.title ?? "AbsoluteJS Voice Eval Baseline";
32849
- const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml45(link.href)}">${escapeHtml45(link.label)}</a>`).join("")}</nav>` : "";
32850
- const reasons = comparison.reasons.length ? comparison.reasons.map((reason) => `<li>${escapeHtml45(reason)}</li>`).join("") : "<li>No baseline regressions detected.</li>";
32851
- const newFailures = comparison.newFailedSessionIds.length ? comparison.newFailedSessionIds.map((id) => `<li>${escapeHtml45(id)}</li>`).join("") : "<li>none</li>";
32852
- const recovered = comparison.recoveredSessionIds.length ? comparison.recoveredSessionIds.map((id) => `<li>${escapeHtml45(id)}</li>`).join("") : "<li>none</li>";
32853
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml45(title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;margin:2rem;background:#f8f7f2;color:#181713}main{max-width:1000px;margin:auto}nav{display:flex;gap:.5rem;flex-wrap:wrap;margin-bottom:1rem}nav a{background:#181713;border-radius:999px;color:white;padding:.35rem .7rem;text-decoration:none}.status{border-radius:999px;display:inline-flex;font-weight:800;padding:.35rem .75rem}.pass{background:#dcfce7;color:#166534}.fail{background:#fee2e2;color:#991b1b}.grid{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));margin:1rem 0}.card{background:white;border:1px solid #e7e5e4;border-radius:1rem;padding:1rem}.card strong{display:block;font-size:2rem}section{background:white;border:1px solid #e7e5e4;border-radius:1rem;margin:1rem 0;padding:1rem}</style></head><body><main>${links}<h1>${escapeHtml45(title)}</h1><p class="status ${comparison.status}">${comparison.status}</p><div class="grid"><article class="card"><span>Baseline pass rate</span><strong>${escapeHtml45(formatPercent(comparison.baseline.passRate))}</strong></article><article class="card"><span>Current pass rate</span><strong>${escapeHtml45(formatPercent(comparison.current.passRate))}</strong></article><article class="card"><span>Failed delta</span><strong>${comparison.deltas.failed}</strong></article><article class="card"><span>Pass rate delta</span><strong>${escapeHtml45(formatPercent(comparison.deltas.passRate))}</strong></article></div><section><h2>Regression Reasons</h2><ul>${reasons}</ul></section><section><h2>New Failed Sessions</h2><ul>${newFailures}</ul></section><section><h2>Recovered Sessions</h2><ul>${recovered}</ul></section></main></body></html>`;
33814
+ const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml46(link.href)}">${escapeHtml46(link.label)}</a>`).join("")}</nav>` : "";
33815
+ const reasons = comparison.reasons.length ? comparison.reasons.map((reason) => `<li>${escapeHtml46(reason)}</li>`).join("") : "<li>No baseline regressions detected.</li>";
33816
+ const newFailures = comparison.newFailedSessionIds.length ? comparison.newFailedSessionIds.map((id) => `<li>${escapeHtml46(id)}</li>`).join("") : "<li>none</li>";
33817
+ const recovered = comparison.recoveredSessionIds.length ? comparison.recoveredSessionIds.map((id) => `<li>${escapeHtml46(id)}</li>`).join("") : "<li>none</li>";
33818
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml46(title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;margin:2rem;background:#f8f7f2;color:#181713}main{max-width:1000px;margin:auto}nav{display:flex;gap:.5rem;flex-wrap:wrap;margin-bottom:1rem}nav a{background:#181713;border-radius:999px;color:white;padding:.35rem .7rem;text-decoration:none}.status{border-radius:999px;display:inline-flex;font-weight:800;padding:.35rem .75rem}.pass{background:#dcfce7;color:#166534}.fail{background:#fee2e2;color:#991b1b}.grid{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));margin:1rem 0}.card{background:white;border:1px solid #e7e5e4;border-radius:1rem;padding:1rem}.card strong{display:block;font-size:2rem}section{background:white;border:1px solid #e7e5e4;border-radius:1rem;margin:1rem 0;padding:1rem}</style></head><body><main>${links}<h1>${escapeHtml46(title)}</h1><p class="status ${comparison.status}">${comparison.status}</p><div class="grid"><article class="card"><span>Baseline pass rate</span><strong>${escapeHtml46(formatPercent(comparison.baseline.passRate))}</strong></article><article class="card"><span>Current pass rate</span><strong>${escapeHtml46(formatPercent(comparison.current.passRate))}</strong></article><article class="card"><span>Failed delta</span><strong>${comparison.deltas.failed}</strong></article><article class="card"><span>Pass rate delta</span><strong>${escapeHtml46(formatPercent(comparison.deltas.passRate))}</strong></article></div><section><h2>Regression Reasons</h2><ul>${reasons}</ul></section><section><h2>New Failed Sessions</h2><ul>${newFailures}</ul></section><section><h2>Recovered Sessions</h2><ul>${recovered}</ul></section></main></body></html>`;
32854
33819
  };
32855
33820
  var renderVoiceScenarioEvalHTML = (report, options = {}) => {
32856
33821
  const title = options.title ?? "AbsoluteJS Voice Scenario Evals";
32857
- const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml45(link.href)}">${escapeHtml45(link.label)}</a>`).join("")}</nav>` : "";
33822
+ const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml46(link.href)}">${escapeHtml46(link.label)}</a>`).join("")}</nav>` : "";
32858
33823
  const scenarios = report.scenarios.length ? report.scenarios.map((scenario) => {
32859
- const scenarioIssues = scenario.issues.length ? `<ul>${scenario.issues.map((issue) => `<li>${escapeHtml45(issue)}</li>`).join("")}</ul>` : "";
33824
+ const scenarioIssues = scenario.issues.length ? `<ul>${scenario.issues.map((issue) => `<li>${escapeHtml46(issue)}</li>`).join("")}</ul>` : "";
32860
33825
  const sessions = scenario.sessions.length ? scenario.sessions.map((session) => {
32861
- const sessionLabel = session.operationsRecordHref ? `<a href="${escapeHtml45(session.operationsRecordHref)}">${escapeHtml45(session.sessionId)}</a>` : escapeHtml45(session.sessionId);
32862
- return `<tr class="${session.status}"><td>${sessionLabel}</td><td>${escapeHtml45(session.status)}</td><td>${session.eventCount}</td><td>${escapeHtml45(session.issues.join(", ") || "none")}</td></tr>`;
33826
+ const sessionLabel = session.operationsRecordHref ? `<a href="${escapeHtml46(session.operationsRecordHref)}">${escapeHtml46(session.sessionId)}</a>` : escapeHtml46(session.sessionId);
33827
+ return `<tr class="${session.status}"><td>${sessionLabel}</td><td>${escapeHtml46(session.status)}</td><td>${session.eventCount}</td><td>${escapeHtml46(session.issues.join(", ") || "none")}</td></tr>`;
32863
33828
  }).join("") : '<tr><td colspan="4">No matching sessions.</td></tr>';
32864
- return `<section class="scenario ${scenario.status}"><h2>${escapeHtml45(scenario.label)}</h2>${scenario.description ? `<p>${escapeHtml45(scenario.description)}</p>` : ""}<p class="status ${scenario.status}">${scenario.status}</p><p>${scenario.passed} passed, ${scenario.failed} failed, ${scenario.matchedSessions} matched.</p>${scenarioIssues}<table><thead><tr><th>Session</th><th>Status</th><th>Events</th><th>Issues</th></tr></thead><tbody>${sessions}</tbody></table></section>`;
33829
+ return `<section class="scenario ${scenario.status}"><h2>${escapeHtml46(scenario.label)}</h2>${scenario.description ? `<p>${escapeHtml46(scenario.description)}</p>` : ""}<p class="status ${scenario.status}">${scenario.status}</p><p>${scenario.passed} passed, ${scenario.failed} failed, ${scenario.matchedSessions} matched.</p>${scenarioIssues}<table><thead><tr><th>Session</th><th>Status</th><th>Events</th><th>Issues</th></tr></thead><tbody>${sessions}</tbody></table></section>`;
32865
33830
  }).join("") : "<section><p>No scenarios configured.</p></section>";
32866
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml45(title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;margin:2rem;background:#f8f7f2;color:#181713}main{max-width:1180px;margin:auto}nav{display:flex;gap:.5rem;flex-wrap:wrap;margin-bottom:1rem}nav a{background:#181713;border-radius:999px;color:white;padding:.35rem .7rem;text-decoration:none}.eyebrow{font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.status{border-radius:999px;display:inline-flex;font-weight:800;padding:.35rem .75rem}.status.pass{background:#dcfce7;color:#166534}.status.fail{background:#fee2e2;color:#991b1b}.grid{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));margin:1rem 0}.card,section{background:white;border:1px solid #e7e5e4;border-radius:1rem;padding:1rem}.primitive{background:#fffdf7;border-color:#d6c7a3}.primitive p{line-height:1.55}.primitive pre{background:#181713;border-radius:.85rem;color:#fef3c7;overflow:auto;padding:1rem}.primitive code{color:#fef3c7}.card strong{display:block;font-size:2rem}section{margin:1rem 0}table{border-collapse:collapse;width:100%;margin-top:1rem}td,th{border-bottom:1px solid #eee;padding:.75rem;text-align:left}tr.fail td{border-left:4px solid #dc2626}tr.pass td{border-left:4px solid #16a34a}</style></head><body><main>${links}<h1>${escapeHtml45(title)}</h1><p class="status ${report.status}">${report.status}</p><div class="grid"><article class="card"><span>Total</span><strong>${report.total}</strong></article><article class="card"><span>Passed</span><strong>${report.passed}</strong></article><article class="card"><span>Failed</span><strong>${report.failed}</strong></article></div>${renderVoiceEvalPrimitiveCopy()}${scenarios}</main></body></html>`;
33831
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml46(title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;margin:2rem;background:#f8f7f2;color:#181713}main{max-width:1180px;margin:auto}nav{display:flex;gap:.5rem;flex-wrap:wrap;margin-bottom:1rem}nav a{background:#181713;border-radius:999px;color:white;padding:.35rem .7rem;text-decoration:none}.eyebrow{font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.status{border-radius:999px;display:inline-flex;font-weight:800;padding:.35rem .75rem}.status.pass{background:#dcfce7;color:#166534}.status.fail{background:#fee2e2;color:#991b1b}.grid{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));margin:1rem 0}.card,section{background:white;border:1px solid #e7e5e4;border-radius:1rem;padding:1rem}.primitive{background:#fffdf7;border-color:#d6c7a3}.primitive p{line-height:1.55}.primitive pre{background:#181713;border-radius:.85rem;color:#fef3c7;overflow:auto;padding:1rem}.primitive code{color:#fef3c7}.card strong{display:block;font-size:2rem}section{margin:1rem 0}table{border-collapse:collapse;width:100%;margin-top:1rem}td,th{border-bottom:1px solid #eee;padding:.75rem;text-align:left}tr.fail td{border-left:4px solid #dc2626}tr.pass td{border-left:4px solid #16a34a}</style></head><body><main>${links}<h1>${escapeHtml46(title)}</h1><p class="status ${report.status}">${report.status}</p><div class="grid"><article class="card"><span>Total</span><strong>${report.total}</strong></article><article class="card"><span>Passed</span><strong>${report.passed}</strong></article><article class="card"><span>Failed</span><strong>${report.failed}</strong></article></div>${renderVoiceEvalPrimitiveCopy()}${scenarios}</main></body></html>`;
32867
33832
  };
32868
33833
  var renderVoiceScenarioFixtureEvalHTML = (report, options = {}) => {
32869
33834
  const title = options.title ?? "AbsoluteJS Voice Fixture Evals";
32870
- const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml45(link.href)}">${escapeHtml45(link.label)}</a>`).join("")}</nav>` : "";
33835
+ const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml46(link.href)}">${escapeHtml46(link.label)}</a>`).join("")}</nav>` : "";
32871
33836
  const fixtures = report.fixtures.length ? report.fixtures.map((fixture) => {
32872
- const scenarios = fixture.report.scenarios.map((scenario) => `<tr class="${scenario.status}"><td>${escapeHtml45(scenario.label)}</td><td>${escapeHtml45(scenario.status)}</td><td>${scenario.matchedSessions}</td><td>${escapeHtml45([...scenario.issues, ...scenario.sessions.flatMap((session) => session.issues)].join(", ") || "none")}</td></tr>`).join("");
32873
- return `<section class="${fixture.status}"><h2>${escapeHtml45(fixture.label)}</h2>${fixture.description ? `<p>${escapeHtml45(fixture.description)}</p>` : ""}<p class="status ${fixture.status}">${fixture.status}</p><table><thead><tr><th>Scenario</th><th>Status</th><th>Sessions</th><th>Issues</th></tr></thead><tbody>${scenarios}</tbody></table></section>`;
33837
+ const scenarios = fixture.report.scenarios.map((scenario) => `<tr class="${scenario.status}"><td>${escapeHtml46(scenario.label)}</td><td>${escapeHtml46(scenario.status)}</td><td>${scenario.matchedSessions}</td><td>${escapeHtml46([...scenario.issues, ...scenario.sessions.flatMap((session) => session.issues)].join(", ") || "none")}</td></tr>`).join("");
33838
+ return `<section class="${fixture.status}"><h2>${escapeHtml46(fixture.label)}</h2>${fixture.description ? `<p>${escapeHtml46(fixture.description)}</p>` : ""}<p class="status ${fixture.status}">${fixture.status}</p><table><thead><tr><th>Scenario</th><th>Status</th><th>Sessions</th><th>Issues</th></tr></thead><tbody>${scenarios}</tbody></table></section>`;
32874
33839
  }).join("") : "<section><p>No scenario fixtures configured.</p></section>";
32875
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml45(title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;margin:2rem;background:#f8f7f2;color:#181713}main{max-width:1180px;margin:auto}nav{display:flex;gap:.5rem;flex-wrap:wrap;margin-bottom:1rem}nav a{background:#181713;border-radius:999px;color:white;padding:.35rem .7rem;text-decoration:none}.eyebrow{font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.status{border-radius:999px;display:inline-flex;font-weight:800;padding:.35rem .75rem}.status.pass{background:#dcfce7;color:#166534}.status.fail{background:#fee2e2;color:#991b1b}.grid{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));margin:1rem 0}.card,section{background:white;border:1px solid #e7e5e4;border-radius:1rem;padding:1rem}.primitive{background:#fffdf7;border-color:#d6c7a3}.primitive p{line-height:1.55}.primitive pre{background:#181713;border-radius:.85rem;color:#fef3c7;overflow:auto;padding:1rem}.primitive code{color:#fef3c7}.card strong{display:block;font-size:2rem}section{margin:1rem 0}table{border-collapse:collapse;width:100%;margin-top:1rem}td,th{border-bottom:1px solid #eee;padding:.75rem;text-align:left}tr.fail td{border-left:4px solid #dc2626}tr.pass td{border-left:4px solid #16a34a}</style></head><body><main>${links}<h1>${escapeHtml45(title)}</h1><p class="status ${report.status}">${report.status}</p><div class="grid"><article class="card"><span>Total</span><strong>${report.total}</strong></article><article class="card"><span>Passed</span><strong>${report.passed}</strong></article><article class="card"><span>Failed</span><strong>${report.failed}</strong></article></div>${renderVoiceEvalPrimitiveCopy()}${fixtures}</main></body></html>`;
33840
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml46(title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;margin:2rem;background:#f8f7f2;color:#181713}main{max-width:1180px;margin:auto}nav{display:flex;gap:.5rem;flex-wrap:wrap;margin-bottom:1rem}nav a{background:#181713;border-radius:999px;color:white;padding:.35rem .7rem;text-decoration:none}.eyebrow{font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.status{border-radius:999px;display:inline-flex;font-weight:800;padding:.35rem .75rem}.status.pass{background:#dcfce7;color:#166534}.status.fail{background:#fee2e2;color:#991b1b}.grid{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));margin:1rem 0}.card,section{background:white;border:1px solid #e7e5e4;border-radius:1rem;padding:1rem}.primitive{background:#fffdf7;border-color:#d6c7a3}.primitive p{line-height:1.55}.primitive pre{background:#181713;border-radius:.85rem;color:#fef3c7;overflow:auto;padding:1rem}.primitive code{color:#fef3c7}.card strong{display:block;font-size:2rem}section{margin:1rem 0}table{border-collapse:collapse;width:100%;margin-top:1rem}td,th{border-bottom:1px solid #eee;padding:.75rem;text-align:left}tr.fail td{border-left:4px solid #dc2626}tr.pass td{border-left:4px solid #16a34a}</style></head><body><main>${links}<h1>${escapeHtml46(title)}</h1><p class="status ${report.status}">${report.status}</p><div class="grid"><article class="card"><span>Total</span><strong>${report.total}</strong></article><article class="card"><span>Passed</span><strong>${report.passed}</strong></article><article class="card"><span>Failed</span><strong>${report.failed}</strong></article></div>${renderVoiceEvalPrimitiveCopy()}${fixtures}</main></body></html>`;
32876
33841
  };
32877
33842
  var createVoiceEvalRoutes = (options) => {
32878
33843
  const path = options.path ?? "/evals";
32879
- const routes = new Elysia48({
33844
+ const routes = new Elysia49({
32880
33845
  name: options.name ?? "absolutejs-voice-evals"
32881
33846
  });
32882
33847
  const getReport = () => runVoiceSessionEvals({
@@ -33013,11 +33978,11 @@ var createVoiceEvalRoutes = (options) => {
33013
33978
  return routes;
33014
33979
  };
33015
33980
  // src/simulationSuite.ts
33016
- import { Elysia as Elysia51 } from "elysia";
33981
+ import { Elysia as Elysia52 } from "elysia";
33017
33982
 
33018
33983
  // src/outcomeContract.ts
33019
- import { Elysia as Elysia49 } from "elysia";
33020
- var escapeHtml46 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
33984
+ import { Elysia as Elysia50 } from "elysia";
33985
+ var escapeHtml47 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
33021
33986
  var resolveSessionHref4 = (value, sessionId) => {
33022
33987
  if (value === false) {
33023
33988
  return;
@@ -33228,13 +34193,13 @@ var assertVoiceOutcomeContractEvidence = (report, input = {}) => {
33228
34193
  var renderVoiceOutcomeContractHTML = (report, options = {}) => {
33229
34194
  const title = options.title ?? "Voice Outcome Contracts";
33230
34195
  const contracts = report.contracts.map((contract) => {
33231
- const sessionLinks = contract.operationsRecordHrefs.length ? `<p>${contract.operationsRecordHrefs.map((href, index) => `<a href="${escapeHtml46(href)}">${escapeHtml46(contract.sessionIds[index] ?? href)}</a>`).join(" \xB7 ")}</p>` : "";
34196
+ const sessionLinks = contract.operationsRecordHrefs.length ? `<p>${contract.operationsRecordHrefs.map((href, index) => `<a href="${escapeHtml47(href)}">${escapeHtml47(contract.sessionIds[index] ?? href)}</a>`).join(" \xB7 ")}</p>` : "";
33232
34197
  return `<section class="contract ${contract.pass ? "pass" : "fail"}">
33233
34198
  <div class="contract-header">
33234
34199
  <div>
33235
- <p class="eyebrow">${escapeHtml46(contract.contractId)}</p>
33236
- <h2>${escapeHtml46(contract.label ?? contract.contractId)}</h2>
33237
- ${contract.description ? `<p>${escapeHtml46(contract.description)}</p>` : ""}
34200
+ <p class="eyebrow">${escapeHtml47(contract.contractId)}</p>
34201
+ <h2>${escapeHtml47(contract.label ?? contract.contractId)}</h2>
34202
+ ${contract.description ? `<p>${escapeHtml47(contract.description)}</p>` : ""}
33238
34203
  ${sessionLinks}
33239
34204
  </div>
33240
34205
  <strong>${contract.pass ? "pass" : "fail"}</strong>
@@ -33246,10 +34211,10 @@ var renderVoiceOutcomeContractHTML = (report, options = {}) => {
33246
34211
  <span>handoffs ${String(contract.matched.handoffs)}</span>
33247
34212
  <span>events ${String(contract.matched.integrationEvents)}</span>
33248
34213
  </div>
33249
- ${contract.issues.length ? `<ul>${contract.issues.map((issue) => `<li>${escapeHtml46(issue.message)}</li>`).join("")}</ul>` : ""}
34214
+ ${contract.issues.length ? `<ul>${contract.issues.map((issue) => `<li>${escapeHtml47(issue.message)}</li>`).join("")}</ul>` : ""}
33250
34215
  </section>`;
33251
34216
  }).join("");
33252
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml46(title)}</title><style>body{background:#101316;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.contract{background:#181d22;border:1px solid #2a323a;border-radius:20px;margin-bottom:16px;padding:20px}.hero{background:linear-gradient(135deg,rgba(34,197,94,.14),rgba(14,165,233,.12))}.eyebrow{color:#7dd3fc;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}h2{margin:.2rem 0}.summary,.grid{display:flex;flex-wrap:wrap;gap:10px}.pill,.grid span{background:#0f1217;border:1px solid #3f3f46;border-radius:999px;padding:7px 10px}.contract-header{display:flex;gap:16px;justify-content:space-between}.pass{color:#86efac}.fail{color:#fca5a5}.contract.fail{border-color:rgba(248,113,113,.45)}li{margin:8px 0}@media(max-width:800px){main{padding:18px}.contract-header{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">Business Outcome Verification</p><h1>${escapeHtml46(title)}</h1><div class="summary"><span class="pill ${report.status}">${report.status}</span><span class="pill">${String(report.passed)} passing</span><span class="pill">${String(report.failed)} failing</span><span class="pill">${String(report.total)} contracts</span></div></section>${contracts || '<section class="contract"><p>No outcome contracts configured.</p></section>'}</main></body></html>`;
34217
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml47(title)}</title><style>body{background:#101316;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.contract{background:#181d22;border:1px solid #2a323a;border-radius:20px;margin-bottom:16px;padding:20px}.hero{background:linear-gradient(135deg,rgba(34,197,94,.14),rgba(14,165,233,.12))}.eyebrow{color:#7dd3fc;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}h2{margin:.2rem 0}.summary,.grid{display:flex;flex-wrap:wrap;gap:10px}.pill,.grid span{background:#0f1217;border:1px solid #3f3f46;border-radius:999px;padding:7px 10px}.contract-header{display:flex;gap:16px;justify-content:space-between}.pass{color:#86efac}.fail{color:#fca5a5}.contract.fail{border-color:rgba(248,113,113,.45)}li{margin:8px 0}@media(max-width:800px){main{padding:18px}.contract-header{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">Business Outcome Verification</p><h1>${escapeHtml47(title)}</h1><div class="summary"><span class="pill ${report.status}">${report.status}</span><span class="pill">${String(report.passed)} passing</span><span class="pill">${String(report.failed)} failing</span><span class="pill">${String(report.total)} contracts</span></div></section>${contracts || '<section class="contract"><p>No outcome contracts configured.</p></section>'}</main></body></html>`;
33253
34218
  };
33254
34219
  var createVoiceOutcomeContractJSONHandler = (options) => async () => runVoiceOutcomeContractSuite(options);
33255
34220
  var createVoiceOutcomeContractHTMLHandler = (options) => async () => {
@@ -33265,7 +34230,7 @@ var createVoiceOutcomeContractHTMLHandler = (options) => async () => {
33265
34230
  var createVoiceOutcomeContractRoutes = (options) => {
33266
34231
  const path = options.path ?? "/api/outcome-contracts";
33267
34232
  const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
33268
- const routes = new Elysia49({
34233
+ const routes = new Elysia50({
33269
34234
  name: options.name ?? "absolutejs-voice-outcome-contracts"
33270
34235
  }).get(path, createVoiceOutcomeContractJSONHandler(options));
33271
34236
  if (htmlPath) {
@@ -33275,7 +34240,7 @@ var createVoiceOutcomeContractRoutes = (options) => {
33275
34240
  };
33276
34241
 
33277
34242
  // src/toolContract.ts
33278
- import { Elysia as Elysia50 } from "elysia";
34243
+ import { Elysia as Elysia51 } from "elysia";
33279
34244
 
33280
34245
  // src/toolRuntime.ts
33281
34246
  var toErrorMessage4 = (error) => error instanceof Error ? error.message : String(error);
@@ -33484,7 +34449,7 @@ var createDefaultTurn = (caseId) => ({
33484
34449
  });
33485
34450
  var defaultApi = {};
33486
34451
  var sameJSON = (left, right) => JSON.stringify(left) === JSON.stringify(right);
33487
- var escapeHtml47 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
34452
+ var escapeHtml48 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
33488
34453
  var resolveSessionHref5 = (value, sessionId) => {
33489
34454
  if (value === false) {
33490
34455
  return;
@@ -33735,7 +34700,7 @@ var assertVoiceToolContractEvidence = (report, input = {}) => {
33735
34700
  };
33736
34701
  var renderVoiceToolContractHTML = (report, options = {}) => {
33737
34702
  const title = options.title ?? "Voice Tool Contracts";
33738
- const snippet = escapeHtml47(`app.use(
34703
+ const snippet = escapeHtml48(`app.use(
33739
34704
  createVoiceToolContractRoutes({
33740
34705
  htmlPath: '/tool-contracts',
33741
34706
  path: '/api/tool-contracts',
@@ -33761,20 +34726,20 @@ var renderVoiceToolContractHTML = (report, options = {}) => {
33761
34726
  );`);
33762
34727
  const contracts = report.contracts.map((contract) => {
33763
34728
  const cases = contract.cases.map((testCase) => `<tr>
33764
- <td>${testCase.operationsRecordHref ? `<a href="${escapeHtml47(testCase.operationsRecordHref)}">${escapeHtml47(testCase.label ?? testCase.caseId)}</a>` : escapeHtml47(testCase.label ?? testCase.caseId)}</td>
34729
+ <td>${testCase.operationsRecordHref ? `<a href="${escapeHtml48(testCase.operationsRecordHref)}">${escapeHtml48(testCase.label ?? testCase.caseId)}</a>` : escapeHtml48(testCase.label ?? testCase.caseId)}</td>
33765
34730
  <td class="${testCase.pass ? "pass" : "fail"}">${testCase.pass ? "pass" : "fail"}</td>
33766
- <td>${escapeHtml47(testCase.status)}</td>
33767
- <td>${escapeHtml47(testCase.sessionId)}</td>
34731
+ <td>${escapeHtml48(testCase.status)}</td>
34732
+ <td>${escapeHtml48(testCase.sessionId)}</td>
33768
34733
  <td>${String(testCase.attempts)}</td>
33769
34734
  <td>${String(testCase.elapsedMs)}ms</td>
33770
34735
  <td>${testCase.timedOut ? "yes" : "no"}</td>
33771
- <td>${escapeHtml47(testCase.issues.map((issue) => issue.message).join(" ") || testCase.error || "")}</td>
34736
+ <td>${escapeHtml48(testCase.issues.map((issue) => issue.message).join(" ") || testCase.error || "")}</td>
33772
34737
  </tr>`).join("");
33773
34738
  return `<section class="contract ${contract.pass ? "pass" : "fail"}">
33774
34739
  <div class="contract-header">
33775
34740
  <div>
33776
- <p class="eyebrow">${escapeHtml47(contract.toolName)}</p>
33777
- <h2>${escapeHtml47(contract.label ?? contract.contractId)}</h2>
34741
+ <p class="eyebrow">${escapeHtml48(contract.toolName)}</p>
34742
+ <h2>${escapeHtml48(contract.label ?? contract.contractId)}</h2>
33778
34743
  </div>
33779
34744
  <strong class="${contract.pass ? "pass" : "fail"}">${contract.pass ? "Passing" : "Failing"}</strong>
33780
34745
  </div>
@@ -33784,7 +34749,7 @@ var renderVoiceToolContractHTML = (report, options = {}) => {
33784
34749
  </table>
33785
34750
  </section>`;
33786
34751
  }).join("");
33787
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml47(title)}</title><style>body{background:#101316;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.primitive,.contract{background:#181d22;border:1px solid #2a323a;border-radius:20px;margin-bottom:16px;padding:20px}.hero{background:linear-gradient(135deg,rgba(34,197,94,.14),rgba(245,158,11,.12))}.primitive{background:#151b20;border-color:#5a4421}.eyebrow{color:#fbbf24;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{background:#0f1217;border:1px solid #3f3f46;border-radius:999px;padding:7px 10px}.contract-header{align-items:flex-start;display:flex;gap:16px;justify-content:space-between}h2{margin:.2rem 0 1rem}.pass{color:#86efac}.fail{color:#fca5a5}.contract.fail{border-color:rgba(248,113,113,.45)}.primitive p{color:#d8dee6;line-height:1.55}.primitive pre{background:#0f1217;border:1px solid #2a323a;border-radius:16px;color:#fef3c7;overflow:auto;padding:14px}.primitive code{color:#fef3c7}table{border-collapse:collapse;width:100%}td,th{border-bottom:1px solid #2a323a;padding:12px;text-align:left;vertical-align:top}th{color:#a8b0b8;font-size:.82rem}@media(max-width:800px){main{padding:18px}table{display:block;overflow:auto}.contract-header{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">Tool Reliability</p><h1>${escapeHtml47(title)}</h1><div class="summary"><span class="pill ${report.status === "pass" ? "pass" : "fail"}">${escapeHtml47(report.status)}</span><span class="pill">${String(report.passed)} passing</span><span class="pill">${String(report.failed)} failing</span><span class="pill">${String(report.total)} contracts</span></div></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceToolContractRoutes(...)</code> certifies tool behavior</h2><p>Define deterministic tool cases for retries, idempotency, timeouts, result shape, and error handling so assistant tools fail in pre-production instead of live calls.</p><pre><code>${snippet}</code></pre></section>${contracts || '<section class="contract"><p>No tool contracts configured.</p></section>'}</main></body></html>`;
34752
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml48(title)}</title><style>body{background:#101316;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.primitive,.contract{background:#181d22;border:1px solid #2a323a;border-radius:20px;margin-bottom:16px;padding:20px}.hero{background:linear-gradient(135deg,rgba(34,197,94,.14),rgba(245,158,11,.12))}.primitive{background:#151b20;border-color:#5a4421}.eyebrow{color:#fbbf24;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{background:#0f1217;border:1px solid #3f3f46;border-radius:999px;padding:7px 10px}.contract-header{align-items:flex-start;display:flex;gap:16px;justify-content:space-between}h2{margin:.2rem 0 1rem}.pass{color:#86efac}.fail{color:#fca5a5}.contract.fail{border-color:rgba(248,113,113,.45)}.primitive p{color:#d8dee6;line-height:1.55}.primitive pre{background:#0f1217;border:1px solid #2a323a;border-radius:16px;color:#fef3c7;overflow:auto;padding:14px}.primitive code{color:#fef3c7}table{border-collapse:collapse;width:100%}td,th{border-bottom:1px solid #2a323a;padding:12px;text-align:left;vertical-align:top}th{color:#a8b0b8;font-size:.82rem}@media(max-width:800px){main{padding:18px}table{display:block;overflow:auto}.contract-header{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">Tool Reliability</p><h1>${escapeHtml48(title)}</h1><div class="summary"><span class="pill ${report.status === "pass" ? "pass" : "fail"}">${escapeHtml48(report.status)}</span><span class="pill">${String(report.passed)} passing</span><span class="pill">${String(report.failed)} failing</span><span class="pill">${String(report.total)} contracts</span></div></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceToolContractRoutes(...)</code> certifies tool behavior</h2><p>Define deterministic tool cases for retries, idempotency, timeouts, result shape, and error handling so assistant tools fail in pre-production instead of live calls.</p><pre><code>${snippet}</code></pre></section>${contracts || '<section class="contract"><p>No tool contracts configured.</p></section>'}</main></body></html>`;
33788
34753
  };
33789
34754
  var createVoiceToolContractJSONHandler = (options) => () => runVoiceToolContractSuite(options);
33790
34755
  var createVoiceToolContractHTMLHandler = (options) => async () => {
@@ -33801,7 +34766,7 @@ var createVoiceToolContractHTMLHandler = (options) => async () => {
33801
34766
  var createVoiceToolContractRoutes = (options) => {
33802
34767
  const path = options.path ?? "/api/tool-contracts";
33803
34768
  const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
33804
- const routes = new Elysia50({
34769
+ const routes = new Elysia51({
33805
34770
  name: options.name ?? "absolutejs-voice-tool-contracts"
33806
34771
  }).get(path, createVoiceToolContractJSONHandler(options));
33807
34772
  if (htmlPath) {
@@ -33811,7 +34776,7 @@ var createVoiceToolContractRoutes = (options) => {
33811
34776
  };
33812
34777
 
33813
34778
  // src/simulationSuite.ts
33814
- var escapeHtml48 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
34779
+ var escapeHtml49 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
33815
34780
  var summarizeSection = (report) => ({
33816
34781
  failed: report.failed,
33817
34782
  passed: report.passed,
@@ -34007,15 +34972,15 @@ var renderSection = (label, summary) => {
34007
34972
  if (!summary) {
34008
34973
  return "";
34009
34974
  }
34010
- return `<article class="${escapeHtml48(summary.status)}"><span>${escapeHtml48(label)}</span><strong>${escapeHtml48(summary.status)}</strong><p>${summary.passed}/${summary.total} passed, ${summary.failed} failed.</p></article>`;
34975
+ return `<article class="${escapeHtml49(summary.status)}"><span>${escapeHtml49(label)}</span><strong>${escapeHtml49(summary.status)}</strong><p>${summary.passed}/${summary.total} passed, ${summary.failed} failed.</p></article>`;
34011
34976
  };
34012
34977
  var renderAction = (action) => {
34013
- const content = `<strong>${escapeHtml48(action.label)}</strong><p>${escapeHtml48(action.description)}</p><span>${escapeHtml48(action.section)} / ${escapeHtml48(action.severity)}</span>`;
34014
- return action.href ? `<a class="action" href="${escapeHtml48(action.href)}">${content}</a>` : `<article class="action">${content}</article>`;
34978
+ const content = `<strong>${escapeHtml49(action.label)}</strong><p>${escapeHtml49(action.description)}</p><span>${escapeHtml49(action.section)} / ${escapeHtml49(action.severity)}</span>`;
34979
+ return action.href ? `<a class="action" href="${escapeHtml49(action.href)}">${content}</a>` : `<article class="action">${content}</article>`;
34015
34980
  };
34016
34981
  var renderVoiceSimulationSuiteHTML = (report, options = {}) => {
34017
34982
  const title = options.title ?? "Voice Simulation Suite";
34018
- const snippet = escapeHtml48(`app.use(
34983
+ const snippet = escapeHtml49(`app.use(
34019
34984
  createVoiceSimulationSuiteRoutes({
34020
34985
  htmlPath: '/voice/simulations',
34021
34986
  path: '/api/voice/simulations',
@@ -34048,12 +35013,12 @@ app.use(
34048
35013
  store: traceStore
34049
35014
  })
34050
35015
  );`);
34051
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml48(title)}</title><style>body{background:#10151c;color:#f8f3e7;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1080px;padding:32px}.hero,.primitive{background:linear-gradient(135deg,rgba(34,197,94,.18),rgba(59,130,246,.12));border:1px solid #283544;border-radius:28px;margin-bottom:18px;padding:28px}.primitive{background:#151d27;border-color:#355078}.eyebrow{color:#93c5fd;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,5rem);line-height:.9;margin:.2rem 0 1rem}.badge{border:1px solid #3f3f46;border-radius:999px;display:inline-flex;padding:8px 12px}.pass{color:#86efac}.fail{color:#fca5a5}.grid,.actions{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));margin:18px 0}.grid article,.action{background:#151d27;border:1px solid #283544;border-radius:18px;color:inherit;padding:16px;text-decoration:none}.grid span,.action span{color:#aab5c0}.grid strong{display:block;font-size:2rem;margin:.25rem 0;text-transform:uppercase}.action strong{display:block;color:#f8f3e7;margin-bottom:.35rem}.action p,.primitive p{color:#d8dee6;line-height:1.55;margin:.3rem 0 .6rem}pre{background:#151d27;border:1px solid #283544;border-radius:18px;overflow:auto;padding:16px}.primitive pre{background:#0b1118;color:#dbeafe}.primitive code{color:#bfdbfe}</style></head><body><main><section class="hero"><p class="eyebrow">Pre-production proof</p><h1>${escapeHtml48(title)}</h1><p>One report for session quality, scenario evals, fixture simulations, tool contracts, and outcome contracts.</p><p class="badge ${escapeHtml48(report.status)}">Status: ${escapeHtml48(report.status)}</p><section class="grid">${renderSection("Sessions", report.summary.sessions)}${renderSection("Scenarios", report.summary.scenarios)}${renderSection("Fixtures", report.summary.fixtures)}${renderSection("Tools", report.summary.tools)}${renderSection("Outcomes", report.summary.outcomes)}</section></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceSimulationSuiteRoutes(...)</code> builds this pre-production proof surface</h2><p>Run session quality checks, scenario evals, fixture-backed simulations, tool contracts, and outcome contracts from one route group before live traffic sees a regression.</p><pre><code>${snippet}</code></pre></section><h2>Actions</h2><section class="actions">${report.actions.length > 0 ? report.actions.map(renderAction).join("") : '<article class="action"><strong>No action required</strong><p>All enabled simulation sections are passing.</p></article>'}</section><pre>${escapeHtml48(JSON.stringify({ summary: report.summary, actions: report.actions }, null, 2))}</pre></main></body></html>`;
35016
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml49(title)}</title><style>body{background:#10151c;color:#f8f3e7;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1080px;padding:32px}.hero,.primitive{background:linear-gradient(135deg,rgba(34,197,94,.18),rgba(59,130,246,.12));border:1px solid #283544;border-radius:28px;margin-bottom:18px;padding:28px}.primitive{background:#151d27;border-color:#355078}.eyebrow{color:#93c5fd;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,5rem);line-height:.9;margin:.2rem 0 1rem}.badge{border:1px solid #3f3f46;border-radius:999px;display:inline-flex;padding:8px 12px}.pass{color:#86efac}.fail{color:#fca5a5}.grid,.actions{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));margin:18px 0}.grid article,.action{background:#151d27;border:1px solid #283544;border-radius:18px;color:inherit;padding:16px;text-decoration:none}.grid span,.action span{color:#aab5c0}.grid strong{display:block;font-size:2rem;margin:.25rem 0;text-transform:uppercase}.action strong{display:block;color:#f8f3e7;margin-bottom:.35rem}.action p,.primitive p{color:#d8dee6;line-height:1.55;margin:.3rem 0 .6rem}pre{background:#151d27;border:1px solid #283544;border-radius:18px;overflow:auto;padding:16px}.primitive pre{background:#0b1118;color:#dbeafe}.primitive code{color:#bfdbfe}</style></head><body><main><section class="hero"><p class="eyebrow">Pre-production proof</p><h1>${escapeHtml49(title)}</h1><p>One report for session quality, scenario evals, fixture simulations, tool contracts, and outcome contracts.</p><p class="badge ${escapeHtml49(report.status)}">Status: ${escapeHtml49(report.status)}</p><section class="grid">${renderSection("Sessions", report.summary.sessions)}${renderSection("Scenarios", report.summary.scenarios)}${renderSection("Fixtures", report.summary.fixtures)}${renderSection("Tools", report.summary.tools)}${renderSection("Outcomes", report.summary.outcomes)}</section></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceSimulationSuiteRoutes(...)</code> builds this pre-production proof surface</h2><p>Run session quality checks, scenario evals, fixture-backed simulations, tool contracts, and outcome contracts from one route group before live traffic sees a regression.</p><pre><code>${snippet}</code></pre></section><h2>Actions</h2><section class="actions">${report.actions.length > 0 ? report.actions.map(renderAction).join("") : '<article class="action"><strong>No action required</strong><p>All enabled simulation sections are passing.</p></article>'}</section><pre>${escapeHtml49(JSON.stringify({ summary: report.summary, actions: report.actions }, null, 2))}</pre></main></body></html>`;
34052
35017
  };
34053
35018
  var createVoiceSimulationSuiteRoutes = (options) => {
34054
35019
  const path = options.path ?? "/api/voice/simulations";
34055
35020
  const htmlPath = options.htmlPath === undefined ? "/voice/simulations" : options.htmlPath;
34056
- const app = new Elysia51({
35021
+ const app = new Elysia52({
34057
35022
  name: options.name ?? "absolutejs-voice-simulation-suite"
34058
35023
  }).get(path, () => runVoiceSimulationSuite(options));
34059
35024
  if (htmlPath) {
@@ -34680,10 +35645,10 @@ var assertVoiceAgentSquadContractEvidence = (reports, input = {}) => {
34680
35645
  return report;
34681
35646
  };
34682
35647
  // src/turnLatency.ts
34683
- import { Elysia as Elysia52 } from "elysia";
35648
+ import { Elysia as Elysia53 } from "elysia";
34684
35649
  var DEFAULT_WARN_AFTER_MS2 = 1800;
34685
35650
  var DEFAULT_FAIL_AFTER_MS2 = 3200;
34686
- var escapeHtml49 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
35651
+ var escapeHtml50 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
34687
35652
  var firstNumber4 = (values) => values.filter((value) => typeof value === "number").sort((left, right) => left - right)[0];
34688
35653
  var getString19 = (value) => typeof value === "string" && value.trim() ? value : undefined;
34689
35654
  var createTraceStageIndex = (events) => {
@@ -34798,7 +35763,7 @@ var summarizeVoiceTurnLatency = async (options) => {
34798
35763
  warnings
34799
35764
  };
34800
35765
  };
34801
- var formatMs4 = (value) => typeof value === "number" ? `${Math.round(value)}ms` : "n/a";
35766
+ var formatMs5 = (value) => typeof value === "number" ? `${Math.round(value)}ms` : "n/a";
34802
35767
  var renderVoiceTurnLatencyHTML = (report, options = {}) => {
34803
35768
  const title = options.title ?? "Voice Turn Latency";
34804
35769
  const snippet = `app.use(
@@ -34819,11 +35784,11 @@ await traceStore.append({
34819
35784
  turnId,
34820
35785
  type: 'turn_latency.stage'
34821
35786
  });`;
34822
- const turns = report.turns.map((turn) => `<article class="turn ${escapeHtml49(turn.status)}">
34823
- <header><div><p class="eyebrow">${escapeHtml49(turn.sessionId)} \xB7 ${escapeHtml49(turn.turnId)}</p><h2>${escapeHtml49(turn.text || "Empty turn")}</h2></div><strong>${escapeHtml49(turn.status)}</strong></header>
34824
- <dl>${turn.stages.map((stage) => `<div><dt>${escapeHtml49(stage.label)}</dt><dd>${escapeHtml49(formatMs4(stage.valueMs))}</dd></div>`).join("")}</dl>
35787
+ const turns = report.turns.map((turn) => `<article class="turn ${escapeHtml50(turn.status)}">
35788
+ <header><div><p class="eyebrow">${escapeHtml50(turn.sessionId)} \xB7 ${escapeHtml50(turn.turnId)}</p><h2>${escapeHtml50(turn.text || "Empty turn")}</h2></div><strong>${escapeHtml50(turn.status)}</strong></header>
35789
+ <dl>${turn.stages.map((stage) => `<div><dt>${escapeHtml50(stage.label)}</dt><dd>${escapeHtml50(formatMs5(stage.valueMs))}</dd></div>`).join("")}</dl>
34825
35790
  </article>`).join("");
34826
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml49(title)}</title><style>body{background:#101316;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.turn,.primitive{background:#181d22;border:1px solid #2a323a;border-radius:20px;margin-bottom:16px;padding:20px}.hero{background:linear-gradient(135deg,rgba(94,234,212,.16),rgba(251,191,36,.1))}.eyebrow{color:#5eead4;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}h2{margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{background:#0f1217;border:1px solid #3f3f46;border-radius:999px;padding:7px 10px}.primitive p{color:#cbd5e1}.primitive pre{background:#0a0d10;border:1px solid #2a323a;border-radius:16px;color:#d9fff7;overflow:auto;padding:16px}.turn header{align-items:flex-start;display:flex;gap:16px;justify-content:space-between}.pass{color:#86efac}.warn,.empty{color:#fde68a}.fail{color:#fca5a5}.turn.fail{border-color:rgba(248,113,113,.45)}dl{display:grid;gap:8px;grid-template-columns:repeat(auto-fit,minmax(160px,1fr))}dt{color:#a8b0b8;font-size:.8rem}dd{font-weight:900;margin:0}@media(max-width:800px){main{padding:18px}.turn header{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">End-to-end responsiveness</p><h1>${escapeHtml49(title)}</h1><div class="summary"><span class="pill ${escapeHtml49(report.status)}">${escapeHtml49(report.status)}</span><span class="pill">${String(report.total)} turns</span><span class="pill">avg ${escapeHtml49(formatMs4(report.averageTotalMs))}</span><span class="pill">${String(report.warnings)} warnings</span><span class="pill">${String(report.failed)} failed</span></div></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceTurnLatencyRoutes(...)</code> exposes the full turn waterfall</h2><p>Attach stage traces for speech detection, commit, model response, TTS send, and first audio so teams can prove where latency actually comes from.</p><pre><code>${escapeHtml49(snippet)}</code></pre></section>${turns || '<section class="turn"><p>No committed turns found.</p></section>'}</main></body></html>`;
35791
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml50(title)}</title><style>body{background:#101316;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.turn,.primitive{background:#181d22;border:1px solid #2a323a;border-radius:20px;margin-bottom:16px;padding:20px}.hero{background:linear-gradient(135deg,rgba(94,234,212,.16),rgba(251,191,36,.1))}.eyebrow{color:#5eead4;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}h2{margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{background:#0f1217;border:1px solid #3f3f46;border-radius:999px;padding:7px 10px}.primitive p{color:#cbd5e1}.primitive pre{background:#0a0d10;border:1px solid #2a323a;border-radius:16px;color:#d9fff7;overflow:auto;padding:16px}.turn header{align-items:flex-start;display:flex;gap:16px;justify-content:space-between}.pass{color:#86efac}.warn,.empty{color:#fde68a}.fail{color:#fca5a5}.turn.fail{border-color:rgba(248,113,113,.45)}dl{display:grid;gap:8px;grid-template-columns:repeat(auto-fit,minmax(160px,1fr))}dt{color:#a8b0b8;font-size:.8rem}dd{font-weight:900;margin:0}@media(max-width:800px){main{padding:18px}.turn header{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">End-to-end responsiveness</p><h1>${escapeHtml50(title)}</h1><div class="summary"><span class="pill ${escapeHtml50(report.status)}">${escapeHtml50(report.status)}</span><span class="pill">${String(report.total)} turns</span><span class="pill">avg ${escapeHtml50(formatMs5(report.averageTotalMs))}</span><span class="pill">${String(report.warnings)} warnings</span><span class="pill">${String(report.failed)} failed</span></div></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceTurnLatencyRoutes(...)</code> exposes the full turn waterfall</h2><p>Attach stage traces for speech detection, commit, model response, TTS send, and first audio so teams can prove where latency actually comes from.</p><pre><code>${escapeHtml50(snippet)}</code></pre></section>${turns || '<section class="turn"><p>No committed turns found.</p></section>'}</main></body></html>`;
34827
35792
  };
34828
35793
  var createVoiceTurnLatencyJSONHandler = (options) => async () => summarizeVoiceTurnLatency(options);
34829
35794
  var createVoiceTurnLatencyHTMLHandler = (options) => async () => {
@@ -34840,7 +35805,7 @@ var createVoiceTurnLatencyHTMLHandler = (options) => async () => {
34840
35805
  var createVoiceTurnLatencyRoutes = (options) => {
34841
35806
  const path = options.path ?? "/api/turn-latency";
34842
35807
  const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
34843
- const routes = new Elysia52({
35808
+ const routes = new Elysia53({
34844
35809
  name: options.name ?? "absolutejs-voice-turn-latency"
34845
35810
  }).get(path, createVoiceTurnLatencyJSONHandler(options));
34846
35811
  if (htmlPath) {
@@ -34849,8 +35814,8 @@ var createVoiceTurnLatencyRoutes = (options) => {
34849
35814
  return routes;
34850
35815
  };
34851
35816
  // src/liveLatency.ts
34852
- import { Elysia as Elysia53 } from "elysia";
34853
- var escapeHtml50 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
35817
+ import { Elysia as Elysia54 } from "elysia";
35818
+ var escapeHtml51 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
34854
35819
  var percentile6 = (values, percentileValue) => {
34855
35820
  if (values.length === 0) {
34856
35821
  return;
@@ -34895,7 +35860,7 @@ var summarizeVoiceLiveLatency = async (options) => {
34895
35860
  warnings
34896
35861
  };
34897
35862
  };
34898
- var formatMs5 = (value) => typeof value === "number" ? `${Math.round(value)}ms` : "n/a";
35863
+ var formatMs6 = (value) => typeof value === "number" ? `${Math.round(value)}ms` : "n/a";
34899
35864
  var renderVoiceLiveLatencyHTML = (report, options = {}) => {
34900
35865
  const title = options.title ?? "Voice Live Latency";
34901
35866
  const snippet = `app.use(
@@ -34917,13 +35882,13 @@ await traceStore.append({
34917
35882
  sessionId,
34918
35883
  type: 'client.live_latency'
34919
35884
  });`;
34920
- const rows = report.recent.map((sample) => `<tr><td>${escapeHtml50(sample.sessionId)}</td><td>${escapeHtml50(formatMs5(sample.latencyMs))}</td><td>${escapeHtml50(sample.status ?? "unknown")}</td><td>${escapeHtml50(new Date(sample.at).toLocaleString())}</td></tr>`).join("");
34921
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml50(title)}</title><style>body{background:#0c0f14;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1060px;padding:32px}.hero{background:linear-gradient(135deg,rgba(94,234,212,.16),rgba(245,158,11,.1));border:1px solid #26313d;border-radius:28px;margin-bottom:18px;padding:28px}.eyebrow{color:#5eead4;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,5rem);line-height:.9;margin:.2rem 0 1rem}.status{border:1px solid #3f3f46;border-radius:999px;display:inline-flex;padding:8px 12px}.pass{color:#86efac}.warn,.empty{color:#fbbf24}.fail{color:#fca5a5}.metrics{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));margin:18px 0}.metrics article,table,.primitive{background:#141922;border:1px solid #26313d;border-radius:18px}.metrics article,.primitive{padding:16px}.metrics span{color:#a8b0b8}.metrics strong{display:block;font-size:2rem;margin-top:.25rem}.primitive{margin:0 0 18px}.primitive h2{margin:.2rem 0 .5rem}.primitive p{color:#cbd5e1}.primitive pre{background:#080b10;border:1px solid #26313d;border-radius:16px;color:#d9fff7;overflow:auto;padding:16px}table{border-collapse:collapse;overflow:hidden;width:100%}td,th{border-bottom:1px solid #26313d;padding:12px;text-align:left}@media(max-width:760px){main{padding:20px}}</style></head><body><main><section class="hero"><p class="eyebrow">Browser proof</p><h1>${escapeHtml50(title)}</h1><p>Recent real browser speech-to-assistant response measurements from persisted <code>client.live_latency</code> traces.</p><p class="status ${escapeHtml50(report.status)}">Status: ${escapeHtml50(report.status)}</p><section class="metrics"><article><span>p50</span><strong>${escapeHtml50(formatMs5(report.p50LatencyMs))}</strong></article><article><span>p95</span><strong>${escapeHtml50(formatMs5(report.p95LatencyMs))}</strong></article><article><span>Average</span><strong>${escapeHtml50(formatMs5(report.averageLatencyMs))}</strong></article><article><span>Samples</span><strong>${String(report.total)}</strong></article></section></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceLiveLatencyRoutes(...)</code> turns real browser timing into a release gate</h2><p>Persist live timing samples into the trace store so readiness, simulations, and trace timelines all point at the same self-hosted proof.</p><pre><code>${escapeHtml50(snippet)}</code></pre></section><table><thead><tr><th>Session</th><th>Latency</th><th>Status</th><th>Measured</th></tr></thead><tbody>${rows || '<tr><td colspan="4">No live latency samples yet.</td></tr>'}</tbody></table></main></body></html>`;
35885
+ const rows = report.recent.map((sample) => `<tr><td>${escapeHtml51(sample.sessionId)}</td><td>${escapeHtml51(formatMs6(sample.latencyMs))}</td><td>${escapeHtml51(sample.status ?? "unknown")}</td><td>${escapeHtml51(new Date(sample.at).toLocaleString())}</td></tr>`).join("");
35886
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml51(title)}</title><style>body{background:#0c0f14;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1060px;padding:32px}.hero{background:linear-gradient(135deg,rgba(94,234,212,.16),rgba(245,158,11,.1));border:1px solid #26313d;border-radius:28px;margin-bottom:18px;padding:28px}.eyebrow{color:#5eead4;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,5rem);line-height:.9;margin:.2rem 0 1rem}.status{border:1px solid #3f3f46;border-radius:999px;display:inline-flex;padding:8px 12px}.pass{color:#86efac}.warn,.empty{color:#fbbf24}.fail{color:#fca5a5}.metrics{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));margin:18px 0}.metrics article,table,.primitive{background:#141922;border:1px solid #26313d;border-radius:18px}.metrics article,.primitive{padding:16px}.metrics span{color:#a8b0b8}.metrics strong{display:block;font-size:2rem;margin-top:.25rem}.primitive{margin:0 0 18px}.primitive h2{margin:.2rem 0 .5rem}.primitive p{color:#cbd5e1}.primitive pre{background:#080b10;border:1px solid #26313d;border-radius:16px;color:#d9fff7;overflow:auto;padding:16px}table{border-collapse:collapse;overflow:hidden;width:100%}td,th{border-bottom:1px solid #26313d;padding:12px;text-align:left}@media(max-width:760px){main{padding:20px}}</style></head><body><main><section class="hero"><p class="eyebrow">Browser proof</p><h1>${escapeHtml51(title)}</h1><p>Recent real browser speech-to-assistant response measurements from persisted <code>client.live_latency</code> traces.</p><p class="status ${escapeHtml51(report.status)}">Status: ${escapeHtml51(report.status)}</p><section class="metrics"><article><span>p50</span><strong>${escapeHtml51(formatMs6(report.p50LatencyMs))}</strong></article><article><span>p95</span><strong>${escapeHtml51(formatMs6(report.p95LatencyMs))}</strong></article><article><span>Average</span><strong>${escapeHtml51(formatMs6(report.averageLatencyMs))}</strong></article><article><span>Samples</span><strong>${String(report.total)}</strong></article></section></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceLiveLatencyRoutes(...)</code> turns real browser timing into a release gate</h2><p>Persist live timing samples into the trace store so readiness, simulations, and trace timelines all point at the same self-hosted proof.</p><pre><code>${escapeHtml51(snippet)}</code></pre></section><table><thead><tr><th>Session</th><th>Latency</th><th>Status</th><th>Measured</th></tr></thead><tbody>${rows || '<tr><td colspan="4">No live latency samples yet.</td></tr>'}</tbody></table></main></body></html>`;
34922
35887
  };
34923
35888
  var createVoiceLiveLatencyRoutes = (options) => {
34924
35889
  const path = options.path ?? "/api/live-latency";
34925
35890
  const htmlPath = options.htmlPath === undefined ? "/live-latency" : options.htmlPath;
34926
- const routes = new Elysia53({
35891
+ const routes = new Elysia54({
34927
35892
  name: options.name ?? "absolutejs-voice-live-latency"
34928
35893
  }).get(path, () => summarizeVoiceLiveLatency(options));
34929
35894
  if (htmlPath) {
@@ -34940,9 +35905,9 @@ var createVoiceLiveLatencyRoutes = (options) => {
34940
35905
  return routes;
34941
35906
  };
34942
35907
  // src/turnQuality.ts
34943
- import { Elysia as Elysia54 } from "elysia";
35908
+ import { Elysia as Elysia55 } from "elysia";
34944
35909
  var DEFAULT_CONFIDENCE_WARN_THRESHOLD = 0.72;
34945
- var escapeHtml51 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
35910
+ var escapeHtml52 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
34946
35911
  var getTurnLatencyMs = (turn) => {
34947
35912
  const firstTranscriptAt = turn.transcripts.map((transcript) => transcript.endedAtMs ?? transcript.startedAtMs).filter((value) => typeof value === "number").sort((left, right) => left - right)[0];
34948
35913
  if (firstTranscriptAt === undefined) {
@@ -35012,24 +35977,24 @@ var summarizeVoiceTurnQuality = async (options) => {
35012
35977
  };
35013
35978
  var renderVoiceTurnQualityHTML = (report, options = {}) => {
35014
35979
  const title = options.title ?? "Voice Turn Quality";
35015
- const turns = report.turns.map((turn) => `<article class="turn ${escapeHtml51(turn.status)}">
35980
+ const turns = report.turns.map((turn) => `<article class="turn ${escapeHtml52(turn.status)}">
35016
35981
  <div class="turn-header">
35017
35982
  <div>
35018
- <p class="eyebrow">${escapeHtml51(turn.sessionId)} \xB7 ${escapeHtml51(turn.turnId)}</p>
35019
- <h2>${escapeHtml51(turn.text || "Empty turn")}</h2>
35983
+ <p class="eyebrow">${escapeHtml52(turn.sessionId)} \xB7 ${escapeHtml52(turn.turnId)}</p>
35984
+ <h2>${escapeHtml52(turn.text || "Empty turn")}</h2>
35020
35985
  </div>
35021
- <strong>${escapeHtml51(turn.status)}</strong>
35986
+ <strong>${escapeHtml52(turn.status)}</strong>
35022
35987
  </div>
35023
35988
  <dl>
35024
- <div><dt>Source</dt><dd>${escapeHtml51(turn.source ?? "unknown")}</dd></div>
35989
+ <div><dt>Source</dt><dd>${escapeHtml52(turn.source ?? "unknown")}</dd></div>
35025
35990
  <div><dt>Confidence</dt><dd>${turn.averageConfidence === undefined ? "n/a" : `${Math.round(turn.averageConfidence * 100)}%`}</dd></div>
35026
- <div><dt>Fallback</dt><dd>${turn.fallbackUsed ? `yes (${escapeHtml51(turn.fallbackSelectionReason ?? "selected")})` : "no"}</dd></div>
35027
- <div><dt>Correction</dt><dd>${turn.correctionChanged ? `changed${turn.correctionProvider ? ` by ${escapeHtml51(turn.correctionProvider)}` : ""}` : "none"}</dd></div>
35991
+ <div><dt>Fallback</dt><dd>${turn.fallbackUsed ? `yes (${escapeHtml52(turn.fallbackSelectionReason ?? "selected")})` : "no"}</dd></div>
35992
+ <div><dt>Correction</dt><dd>${turn.correctionChanged ? `changed${turn.correctionProvider ? ` by ${escapeHtml52(turn.correctionProvider)}` : ""}` : "none"}</dd></div>
35028
35993
  <div><dt>Transcripts</dt><dd>${String(turn.selectedTranscriptCount)} selected \xB7 ${String(turn.finalTranscriptCount)} final \xB7 ${String(turn.partialTranscriptCount)} partial</dd></div>
35029
35994
  <div><dt>Cost</dt><dd>${turn.costUnits === undefined ? "n/a" : String(turn.costUnits)}</dd></div>
35030
35995
  </dl>
35031
35996
  </article>`).join("");
35032
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml51(title)}</title><style>body{background:#101316;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.turn{background:#181d22;border:1px solid #2a323a;border-radius:20px;margin-bottom:16px;padding:20px}.hero{background:linear-gradient(135deg,rgba(251,191,36,.16),rgba(34,197,94,.1))}.eyebrow{color:#fbbf24;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}h2{margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{background:#0f1217;border:1px solid #3f3f46;border-radius:999px;padding:7px 10px}.turn-header{align-items:flex-start;display:flex;gap:16px;justify-content:space-between}.pass{color:#86efac}.warn,.unknown{color:#fde68a}.fail{color:#fca5a5}.turn.fail{border-color:rgba(248,113,113,.45)}dl{display:grid;gap:8px;grid-template-columns:repeat(auto-fit,minmax(160px,1fr))}dt{color:#a8b0b8;font-size:.8rem}dd{margin:0}@media(max-width:800px){main{padding:18px}.turn-header{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">Realtime STT Debugging</p><h1>${escapeHtml51(title)}</h1><div class="summary"><span class="pill ${escapeHtml51(report.status)}">${escapeHtml51(report.status)}</span><span class="pill">${String(report.total)} turns</span><span class="pill">${String(report.warnings)} warnings</span><span class="pill">${String(report.failed)} failed</span><span class="pill">${String(report.sessions)} sessions</span></div></section>${turns || '<section class="turn"><p>No committed turns found.</p></section>'}</main></body></html>`;
35997
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml52(title)}</title><style>body{background:#101316;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.turn{background:#181d22;border:1px solid #2a323a;border-radius:20px;margin-bottom:16px;padding:20px}.hero{background:linear-gradient(135deg,rgba(251,191,36,.16),rgba(34,197,94,.1))}.eyebrow{color:#fbbf24;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}h2{margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{background:#0f1217;border:1px solid #3f3f46;border-radius:999px;padding:7px 10px}.turn-header{align-items:flex-start;display:flex;gap:16px;justify-content:space-between}.pass{color:#86efac}.warn,.unknown{color:#fde68a}.fail{color:#fca5a5}.turn.fail{border-color:rgba(248,113,113,.45)}dl{display:grid;gap:8px;grid-template-columns:repeat(auto-fit,minmax(160px,1fr))}dt{color:#a8b0b8;font-size:.8rem}dd{margin:0}@media(max-width:800px){main{padding:18px}.turn-header{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">Realtime STT Debugging</p><h1>${escapeHtml52(title)}</h1><div class="summary"><span class="pill ${escapeHtml52(report.status)}">${escapeHtml52(report.status)}</span><span class="pill">${String(report.total)} turns</span><span class="pill">${String(report.warnings)} warnings</span><span class="pill">${String(report.failed)} failed</span><span class="pill">${String(report.sessions)} sessions</span></div></section>${turns || '<section class="turn"><p>No committed turns found.</p></section>'}</main></body></html>`;
35033
35998
  };
35034
35999
  var createVoiceTurnQualityJSONHandler = (options) => async () => summarizeVoiceTurnQuality(options);
35035
36000
  var createVoiceTurnQualityHTMLHandler = (options) => async () => {
@@ -35046,7 +36011,7 @@ var createVoiceTurnQualityHTMLHandler = (options) => async () => {
35046
36011
  var createVoiceTurnQualityRoutes = (options) => {
35047
36012
  const path = options.path ?? "/api/turn-quality";
35048
36013
  const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
35049
- const routes = new Elysia54({
36014
+ const routes = new Elysia55({
35050
36015
  name: options.name ?? "absolutejs-voice-turn-quality"
35051
36016
  }).get(path, createVoiceTurnQualityJSONHandler(options));
35052
36017
  if (htmlPath) {
@@ -35055,10 +36020,10 @@ var createVoiceTurnQualityRoutes = (options) => {
35055
36020
  return routes;
35056
36021
  };
35057
36022
  // src/phoneAgent.ts
35058
- import { Elysia as Elysia56 } from "elysia";
36023
+ import { Elysia as Elysia57 } from "elysia";
35059
36024
 
35060
36025
  // src/phoneAgentProductionSmoke.ts
35061
- import { Elysia as Elysia55 } from "elysia";
36026
+ import { Elysia as Elysia56 } from "elysia";
35062
36027
  var defaultRequirements = [
35063
36028
  "media-started",
35064
36029
  "transcript",
@@ -35066,7 +36031,7 @@ var defaultRequirements = [
35066
36031
  "lifecycle-outcome",
35067
36032
  "no-session-error"
35068
36033
  ];
35069
- var escapeHtml52 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
36034
+ var escapeHtml53 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
35070
36035
  var payloadType = (event) => typeof event.payload.type === "string" ? event.payload.type : undefined;
35071
36036
  var hasTextPayload = (event) => ["text", "assistantText", "transcript"].some((key) => {
35072
36037
  const value = event.payload[key];
@@ -35175,10 +36140,10 @@ var resolveHandlerOptions = async (options, input) => ({
35175
36140
  });
35176
36141
  var renderVoicePhoneAgentProductionSmokeHTML = (report, options = {}) => {
35177
36142
  const title = options.title ?? "AbsoluteJS Voice Phone Smoke Contract";
35178
- const issues = report.issues.map((issue) => `<li><strong>${escapeHtml52(issue.requirement)}</strong>: ${escapeHtml52(issue.message)}</li>`).join("");
35179
- const outcomes = report.observed.lifecycleOutcomes.map((outcome) => `<span class="pill">${escapeHtml52(outcome)}</span>`).join("");
35180
- const requirements = report.required.map((requirement) => `<span class="pill">${escapeHtml52(requirement)}</span>`).join("");
35181
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml52(title)}</title><style>body{background:#0e141b;color:#f8f3e7;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1050px;padding:32px}.hero,.panel{background:#151d26;border:1px solid #283544;border-radius:24px;margin-bottom:16px;padding:22px}.hero{background:linear-gradient(135deg,rgba(20,184,166,.18),rgba(245,158,11,.12))}.eyebrow{color:#5eead4;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.2rem,6vw,4.8rem);line-height:.92;margin:.2rem 0 1rem}.status{border:1px solid #3f3f46;border-radius:999px;display:inline-flex;font-weight:900;padding:8px 12px}.pass{color:#86efac}.fail{color:#fca5a5}.grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}.metric{background:#0f151d;border:1px solid #283544;border-radius:16px;padding:14px}.metric strong{display:block;font-size:1.8rem}.pill{background:#0f151d;border:1px solid #3f3f46;border-radius:999px;display:inline-flex;margin:4px;padding:7px 10px}.issues{color:#fca5a5}code{color:#fde68a}@media(max-width:720px){main{padding:18px}}</style></head><body><main><section class="hero"><p class="eyebrow">Phone agent production smoke</p><h1>${escapeHtml52(title)}</h1><p class="status ${report.pass ? "pass" : "fail"}">${report.pass ? "PASS" : "FAIL"}</p><p>Contract <code>${escapeHtml52(report.contractId)}</code>${report.provider ? ` for <code>${escapeHtml52(report.provider)}</code>` : ""}${report.sessionId ? ` on session <code>${escapeHtml52(report.sessionId)}</code>` : ""}.</p></section><section class="panel"><h2>Observed Trace Evidence</h2><div class="grid"><div class="metric"><span>Media starts</span><strong>${String(report.observed.mediaStarts)}</strong></div><div class="metric"><span>Transcripts</span><strong>${String(report.observed.transcripts)}</strong></div><div class="metric"><span>Assistant responses</span><strong>${String(report.observed.assistantResponses)}</strong></div><div class="metric"><span>Session errors</span><strong>${String(report.observed.sessionErrors)}</strong></div></div><p>${outcomes || '<span class="pill">No lifecycle outcome</span>'}</p></section><section class="panel"><h2>Requirements</h2><p>${requirements}</p>${issues ? `<ul class="issues">${issues}</ul>` : '<p class="pass">All required phone-agent smoke evidence is present.</p>'}</section></main></body></html>`;
36143
+ const issues = report.issues.map((issue) => `<li><strong>${escapeHtml53(issue.requirement)}</strong>: ${escapeHtml53(issue.message)}</li>`).join("");
36144
+ const outcomes = report.observed.lifecycleOutcomes.map((outcome) => `<span class="pill">${escapeHtml53(outcome)}</span>`).join("");
36145
+ const requirements = report.required.map((requirement) => `<span class="pill">${escapeHtml53(requirement)}</span>`).join("");
36146
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml53(title)}</title><style>body{background:#0e141b;color:#f8f3e7;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1050px;padding:32px}.hero,.panel{background:#151d26;border:1px solid #283544;border-radius:24px;margin-bottom:16px;padding:22px}.hero{background:linear-gradient(135deg,rgba(20,184,166,.18),rgba(245,158,11,.12))}.eyebrow{color:#5eead4;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.2rem,6vw,4.8rem);line-height:.92;margin:.2rem 0 1rem}.status{border:1px solid #3f3f46;border-radius:999px;display:inline-flex;font-weight:900;padding:8px 12px}.pass{color:#86efac}.fail{color:#fca5a5}.grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}.metric{background:#0f151d;border:1px solid #283544;border-radius:16px;padding:14px}.metric strong{display:block;font-size:1.8rem}.pill{background:#0f151d;border:1px solid #3f3f46;border-radius:999px;display:inline-flex;margin:4px;padding:7px 10px}.issues{color:#fca5a5}code{color:#fde68a}@media(max-width:720px){main{padding:18px}}</style></head><body><main><section class="hero"><p class="eyebrow">Phone agent production smoke</p><h1>${escapeHtml53(title)}</h1><p class="status ${report.pass ? "pass" : "fail"}">${report.pass ? "PASS" : "FAIL"}</p><p>Contract <code>${escapeHtml53(report.contractId)}</code>${report.provider ? ` for <code>${escapeHtml53(report.provider)}</code>` : ""}${report.sessionId ? ` on session <code>${escapeHtml53(report.sessionId)}</code>` : ""}.</p></section><section class="panel"><h2>Observed Trace Evidence</h2><div class="grid"><div class="metric"><span>Media starts</span><strong>${String(report.observed.mediaStarts)}</strong></div><div class="metric"><span>Transcripts</span><strong>${String(report.observed.transcripts)}</strong></div><div class="metric"><span>Assistant responses</span><strong>${String(report.observed.assistantResponses)}</strong></div><div class="metric"><span>Session errors</span><strong>${String(report.observed.sessionErrors)}</strong></div></div><p>${outcomes || '<span class="pill">No lifecycle outcome</span>'}</p></section><section class="panel"><h2>Requirements</h2><p>${requirements}</p>${issues ? `<ul class="issues">${issues}</ul>` : '<p class="pass">All required phone-agent smoke evidence is present.</p>'}</section></main></body></html>`;
35182
36147
  };
35183
36148
  var createVoicePhoneAgentProductionSmokeJSONHandler = (options) => async ({
35184
36149
  query,
@@ -35201,7 +36166,7 @@ var createVoicePhoneAgentProductionSmokeHTMLHandler = (options) => async ({
35201
36166
  var createVoicePhoneAgentProductionSmokeRoutes = (options) => {
35202
36167
  const path = options.path ?? "/api/voice/phone/smoke-contract";
35203
36168
  const htmlPath = options.htmlPath === undefined ? "/voice/phone/smoke-contract" : options.htmlPath;
35204
- const routes = new Elysia55({
36169
+ const routes = new Elysia56({
35205
36170
  name: options.name ?? "absolutejs-voice-phone-smoke-contract"
35206
36171
  }).get(path, createVoicePhoneAgentProductionSmokeJSONHandler(options));
35207
36172
  if (htmlPath) {
@@ -35244,7 +36209,7 @@ var PHONE_AGENT_LIFECYCLE_STAGES = [
35244
36209
  "completed",
35245
36210
  "failed"
35246
36211
  ];
35247
- var escapeHtml53 = (value) => value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("'", "&#39;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
36212
+ var escapeHtml54 = (value) => value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("'", "&#39;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
35248
36213
  var loadRouteJson = async (input) => {
35249
36214
  const response = await input.app.handle(new Request(new URL(input.path, input.origin).toString(), {
35250
36215
  headers: {
@@ -35482,10 +36447,10 @@ var renderVoicePhoneAgentSetupHTML = (report) => {
35482
36447
  const entry = findCarrierMatrixEntry(report.matrix, carrier);
35483
36448
  const urls = entry?.setup.urls;
35484
36449
  const primaryUrl = carrier.provider === "plivo" ? urls?.twiml : urls?.twiml;
35485
- return `<tr><td>${escapeHtml53(carrier.name ?? carrier.provider)}</td><td>${escapeHtml53(carrier.provider)}</td><td><code>${escapeHtml53(carrier.setupPath || "disabled")}</code></td><td><code>${escapeHtml53(carrier.smokePath || "disabled")}</code></td><td>${entry ? `<span class="${escapeHtml53(entry.status)}">${escapeHtml53(entry.status.toUpperCase())}</span>` : "unknown"}</td><td>${primaryUrl ? `<code>${escapeHtml53(primaryUrl)}</code>` : '<span class="muted">missing</span>'}</td><td>${urls?.webhook ? `<code>${escapeHtml53(urls.webhook)}</code>` : '<span class="muted">missing</span>'}</td><td>${urls?.stream ? `<code>${escapeHtml53(urls.stream)}</code>` : '<span class="muted">missing</span>'}</td></tr>`;
36450
+ return `<tr><td>${escapeHtml54(carrier.name ?? carrier.provider)}</td><td>${escapeHtml54(carrier.provider)}</td><td><code>${escapeHtml54(carrier.setupPath || "disabled")}</code></td><td><code>${escapeHtml54(carrier.smokePath || "disabled")}</code></td><td>${entry ? `<span class="${escapeHtml54(entry.status)}">${escapeHtml54(entry.status.toUpperCase())}</span>` : "unknown"}</td><td>${primaryUrl ? `<code>${escapeHtml54(primaryUrl)}</code>` : '<span class="muted">missing</span>'}</td><td>${urls?.webhook ? `<code>${escapeHtml54(urls.webhook)}</code>` : '<span class="muted">missing</span>'}</td><td>${urls?.stream ? `<code>${escapeHtml54(urls.stream)}</code>` : '<span class="muted">missing</span>'}</td></tr>`;
35486
36451
  }).join("");
35487
- const stageList = report.lifecycleStages.map((stage) => `<li><code>${escapeHtml53(stage)}</code></li>`).join("");
35488
- const snippet = escapeHtml53(`const phoneAgent = createVoicePhoneAgent({
36452
+ const stageList = report.lifecycleStages.map((stage) => `<li><code>${escapeHtml54(stage)}</code></li>`).join("");
36453
+ const snippet = escapeHtml54(`const phoneAgent = createVoicePhoneAgent({
35489
36454
  carriers: [
35490
36455
  {
35491
36456
  provider: 'twilio',
@@ -35519,11 +36484,11 @@ app.use(
35519
36484
  );`);
35520
36485
  const checklist = report.carriers.map((carrier) => {
35521
36486
  const instruction = report.setupInstructions.find((candidate) => candidate.provider === carrier.provider && candidate.carrierName === (carrier.name ?? carrier.provider));
35522
- const issueList = instruction?.issues.map((issue) => `<li>${escapeHtml53(issue)}</li>`).join("") ?? "";
35523
- const steps = instruction?.steps.map((step) => `<li>${escapeHtml53(step)}</li>`).join("") ?? "";
35524
- return `<article><h3>${escapeHtml53(carrier.name ?? carrier.provider)}</h3><ol>${steps}</ol>${issueList ? `<ul class="issues">${issueList}</ul>` : '<p class="pass">No carrier contract issues.</p>'}</article>`;
36487
+ const issueList = instruction?.issues.map((issue) => `<li>${escapeHtml54(issue)}</li>`).join("") ?? "";
36488
+ const steps = instruction?.steps.map((step) => `<li>${escapeHtml54(step)}</li>`).join("") ?? "";
36489
+ return `<article><h3>${escapeHtml54(carrier.name ?? carrier.provider)}</h3><ol>${steps}</ol>${issueList ? `<ul class="issues">${issueList}</ul>` : '<p class="pass">No carrier contract issues.</p>'}</article>`;
35525
36490
  }).join("");
35526
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml53(report.title)}</title><style>body{background:#10151c;color:#f8f3e7;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.primitive{background:linear-gradient(135deg,rgba(20,184,166,.2),rgba(245,158,11,.12));border:1px solid #283544;border-radius:28px;margin-bottom:18px;padding:28px}.primitive{background:#151d27;border-color:#365a60}.eyebrow{color:#5eead4;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,4.8rem);line-height:.92;margin:.2rem 0 1rem}.badge{border:1px solid #3f3f46;border-radius:999px;display:inline-flex;padding:8px 12px}.pass{color:#86efac}.fail{color:#fca5a5}.warn{color:#fde68a}.muted{color:#aab5c0}table{background:#151d27;border:1px solid #283544;border-collapse:collapse;border-radius:18px;display:block;overflow:auto;width:100%}td,th{border-bottom:1px solid #283544;padding:12px;text-align:left;vertical-align:top}code{color:#fde68a;overflow-wrap:anywhere}.primitive p{color:#cbd5de;line-height:1.55}.primitive pre{background:#0b1118;border:1px solid #283544;border-radius:18px;color:#fef3c7;overflow:auto;padding:16px}.checklist{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));margin:18px 0}.checklist article{background:#151d27;border:1px solid #283544;border-radius:18px;padding:18px}.checklist ol{padding-left:20px}.issues{color:#fca5a5}.stages{display:grid;gap:8px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));padding-left:18px}a{color:#5eead4}</style></head><body><main><section class="hero"><p class="eyebrow">Phone agent setup</p><h1>${escapeHtml53(report.title)}</h1><p>One self-hosted entrypoint for carrier routes, setup reports, smoke checks, and normalized call lifecycle stages.</p><p class="badge ${report.ready ? "pass" : "fail"}">Ready: ${String(report.ready)}</p>${report.matrixPath ? `<p><a href="${escapeHtml53(report.matrixPath)}?format=html">Open carrier matrix</a></p>` : ""}</section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoicePhoneAgent(...)</code> builds this carrier control plane</h2><p>Mount carrier routes once, expose setup and smoke proof, then feed the same carrier matrix and phone-agent smoke reports into production readiness so carrier regressions block deploys.</p><pre><code>${snippet}</code></pre></section><h2>Carrier Setup Checklist</h2><section class="checklist">${checklist}</section><h2>Carrier URLs</h2><table><thead><tr><th>Name</th><th>Provider</th><th>Setup</th><th>Smoke</th><th>Status</th><th>Answer/TwiML/TeXML</th><th>Webhook</th><th>Stream</th></tr></thead><tbody>${carrierRows}</tbody></table><h2>Lifecycle Schema</h2><ul class="stages">${stageList}</ul></main></body></html>`;
36491
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml54(report.title)}</title><style>body{background:#10151c;color:#f8f3e7;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.primitive{background:linear-gradient(135deg,rgba(20,184,166,.2),rgba(245,158,11,.12));border:1px solid #283544;border-radius:28px;margin-bottom:18px;padding:28px}.primitive{background:#151d27;border-color:#365a60}.eyebrow{color:#5eead4;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,4.8rem);line-height:.92;margin:.2rem 0 1rem}.badge{border:1px solid #3f3f46;border-radius:999px;display:inline-flex;padding:8px 12px}.pass{color:#86efac}.fail{color:#fca5a5}.warn{color:#fde68a}.muted{color:#aab5c0}table{background:#151d27;border:1px solid #283544;border-collapse:collapse;border-radius:18px;display:block;overflow:auto;width:100%}td,th{border-bottom:1px solid #283544;padding:12px;text-align:left;vertical-align:top}code{color:#fde68a;overflow-wrap:anywhere}.primitive p{color:#cbd5de;line-height:1.55}.primitive pre{background:#0b1118;border:1px solid #283544;border-radius:18px;color:#fef3c7;overflow:auto;padding:16px}.checklist{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));margin:18px 0}.checklist article{background:#151d27;border:1px solid #283544;border-radius:18px;padding:18px}.checklist ol{padding-left:20px}.issues{color:#fca5a5}.stages{display:grid;gap:8px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));padding-left:18px}a{color:#5eead4}</style></head><body><main><section class="hero"><p class="eyebrow">Phone agent setup</p><h1>${escapeHtml54(report.title)}</h1><p>One self-hosted entrypoint for carrier routes, setup reports, smoke checks, and normalized call lifecycle stages.</p><p class="badge ${report.ready ? "pass" : "fail"}">Ready: ${String(report.ready)}</p>${report.matrixPath ? `<p><a href="${escapeHtml54(report.matrixPath)}?format=html">Open carrier matrix</a></p>` : ""}</section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoicePhoneAgent(...)</code> builds this carrier control plane</h2><p>Mount carrier routes once, expose setup and smoke proof, then feed the same carrier matrix and phone-agent smoke reports into production readiness so carrier regressions block deploys.</p><pre><code>${snippet}</code></pre></section><h2>Carrier Setup Checklist</h2><section class="checklist">${checklist}</section><h2>Carrier URLs</h2><table><thead><tr><th>Name</th><th>Provider</th><th>Setup</th><th>Smoke</th><th>Status</th><th>Answer/TwiML/TeXML</th><th>Webhook</th><th>Stream</th></tr></thead><tbody>${carrierRows}</tbody></table><h2>Lifecycle Schema</h2><ul class="stages">${stageList}</ul></main></body></html>`;
35527
36492
  };
35528
36493
  var createVoicePhoneAgent = (options) => {
35529
36494
  const carrierSummaries = options.carriers.map((carrier) => ({
@@ -35532,7 +36497,7 @@ var createVoicePhoneAgent = (options) => {
35532
36497
  setupPath: resolveSetupPath(carrier),
35533
36498
  smokePath: resolveSmokePath(carrier)
35534
36499
  }));
35535
- const app = new Elysia56({
36500
+ const app = new Elysia57({
35536
36501
  name: options.name ?? "absolutejs-voice-phone-agent"
35537
36502
  });
35538
36503
  for (const carrier of options.carriers) {
@@ -35624,21 +36589,21 @@ var createVoicePhoneAgent = (options) => {
35624
36589
  };
35625
36590
  // src/fileStore.ts
35626
36591
  import {
35627
- mkdir as mkdir4,
36592
+ mkdir as mkdir5,
35628
36593
  readFile as readFile2,
35629
36594
  readdir,
35630
36595
  rename,
35631
36596
  rm,
35632
36597
  stat as stat2,
35633
- writeFile
36598
+ writeFile as writeFile2
35634
36599
  } from "fs/promises";
35635
- import { join as join3 } from "path";
36600
+ import { join as join4 } from "path";
35636
36601
  var listJsonFiles = async (directory) => {
35637
36602
  try {
35638
36603
  const entries = await readdir(directory, {
35639
36604
  withFileTypes: true
35640
36605
  });
35641
- return entries.filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => join3(directory, entry.name));
36606
+ return entries.filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => join4(directory, entry.name));
35642
36607
  } catch (error) {
35643
36608
  if (error.code === "ENOENT") {
35644
36609
  return [];
@@ -35656,7 +36621,7 @@ var listRecentJsonFiles = async (directory, limit) => {
35656
36621
  }
35657
36622
  return (await rebuildRecentJsonFileIndex(directory)).slice(0, limit).map((entry) => entry.path);
35658
36623
  };
35659
- var recentJsonFileIndexPath = (directory) => join3(directory, ".recent-index");
36624
+ var recentJsonFileIndexPath = (directory) => join4(directory, ".recent-index");
35660
36625
  var sortRecentJsonFileIndexEntries = (entries) => entries.sort((left, right) => right.updatedAt - left.updatedAt);
35661
36626
  var readRecentJsonFileIndex = async (directory) => {
35662
36627
  try {
@@ -35670,12 +36635,12 @@ var readRecentJsonFileIndex = async (directory) => {
35670
36635
  }
35671
36636
  };
35672
36637
  var writeRecentJsonFileIndex = async (directory, files) => {
35673
- await mkdir4(directory, {
36638
+ await mkdir5(directory, {
35674
36639
  recursive: true
35675
36640
  });
35676
36641
  const path = recentJsonFileIndexPath(directory);
35677
36642
  const tempPath = `${path}.${crypto.randomUUID()}.tmp`;
35678
- await writeFile(tempPath, JSON.stringify({
36643
+ await writeFile2(tempPath, JSON.stringify({
35679
36644
  files: sortRecentJsonFileIndexEntries(files).slice(0, 5000),
35680
36645
  version: 1
35681
36646
  }));
@@ -35751,15 +36716,15 @@ var omitReadWindow = (filter) => {
35751
36716
  return next;
35752
36717
  };
35753
36718
  var encodeStoreId = (id) => `${encodeURIComponent(id)}.json`;
35754
- var resolveFilePath = (directory, id) => join3(directory, encodeStoreId(id));
36719
+ var resolveFilePath = (directory, id) => join4(directory, encodeStoreId(id));
35755
36720
  var createMemoryStoreId = (input) => `${input.assistantId}:${input.namespace}:${input.key}`;
35756
36721
  var readJsonFile = async (path) => JSON.parse(await readFile2(path, "utf8"));
35757
36722
  var writeJsonFile = async (path, value, options) => {
35758
- await mkdir4(options.directory, {
36723
+ await mkdir5(options.directory, {
35759
36724
  recursive: true
35760
36725
  });
35761
36726
  const tempPath = `${path}.${crypto.randomUUID()}.tmp`;
35762
- await writeFile(tempPath, JSON.stringify(value, null, options.pretty === false ? undefined : 2));
36727
+ await writeFile2(tempPath, JSON.stringify(value, null, options.pretty === false ? undefined : 2));
35763
36728
  await rename(tempPath, path);
35764
36729
  };
35765
36730
  var createVoiceFileSessionStore = (options) => {
@@ -36133,51 +37098,51 @@ var createVoiceFileIncidentBundleStore = (options) => {
36133
37098
  var createVoiceFileRuntimeStorage = (options) => ({
36134
37099
  audit: createVoiceFileAuditEventStore({
36135
37100
  ...options,
36136
- directory: join3(options.directory, "audit")
37101
+ directory: join4(options.directory, "audit")
36137
37102
  }),
36138
37103
  auditDeliveries: createVoiceFileAuditSinkDeliveryStore({
36139
37104
  ...options,
36140
- directory: join3(options.directory, "audit-deliveries")
37105
+ directory: join4(options.directory, "audit-deliveries")
36141
37106
  }),
36142
37107
  campaigns: createVoiceFileCampaignStore({
36143
37108
  ...options,
36144
- directory: join3(options.directory, "campaigns")
37109
+ directory: join4(options.directory, "campaigns")
36145
37110
  }),
36146
37111
  events: createVoiceFileIntegrationEventStore({
36147
37112
  ...options,
36148
- directory: join3(options.directory, "events")
37113
+ directory: join4(options.directory, "events")
36149
37114
  }),
36150
37115
  externalObjects: createVoiceFileExternalObjectMapStore({
36151
37116
  ...options,
36152
- directory: join3(options.directory, "external-objects")
37117
+ directory: join4(options.directory, "external-objects")
36153
37118
  }),
36154
37119
  incidentBundles: createVoiceFileIncidentBundleStore({
36155
37120
  ...options,
36156
- directory: join3(options.directory, "incident-bundles")
37121
+ directory: join4(options.directory, "incident-bundles")
36157
37122
  }),
36158
37123
  memories: createVoiceFileAssistantMemoryStore({
36159
37124
  ...options,
36160
- directory: join3(options.directory, "memories")
37125
+ directory: join4(options.directory, "memories")
36161
37126
  }),
36162
37127
  reviews: createVoiceFileReviewStore({
36163
37128
  ...options,
36164
- directory: join3(options.directory, "reviews")
37129
+ directory: join4(options.directory, "reviews")
36165
37130
  }),
36166
37131
  session: createVoiceFileSessionStore({
36167
37132
  ...options,
36168
- directory: join3(options.directory, "sessions")
37133
+ directory: join4(options.directory, "sessions")
36169
37134
  }),
36170
37135
  tasks: createVoiceFileTaskStore({
36171
37136
  ...options,
36172
- directory: join3(options.directory, "tasks")
37137
+ directory: join4(options.directory, "tasks")
36173
37138
  }),
36174
37139
  traceDeliveries: createVoiceFileTraceSinkDeliveryStore({
36175
37140
  ...options,
36176
- directory: join3(options.directory, "trace-deliveries")
37141
+ directory: join4(options.directory, "trace-deliveries")
36177
37142
  }),
36178
37143
  traces: createVoiceFileTraceEventStore({
36179
37144
  ...options,
36180
- directory: join3(options.directory, "traces")
37145
+ directory: join4(options.directory, "traces")
36181
37146
  })
36182
37147
  });
36183
37148
  var createStoredVoiceCallReviewArtifact = (id, artifact) => withVoiceCallReviewId(id, artifact);
@@ -37281,8 +38246,8 @@ var createOpenAIVoiceTTS = (options) => {
37281
38246
  };
37282
38247
  };
37283
38248
  // src/providerCapabilities.ts
37284
- import { Elysia as Elysia57 } from "elysia";
37285
- var escapeHtml54 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
38249
+ import { Elysia as Elysia58 } from "elysia";
38250
+ var escapeHtml55 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
37286
38251
  var fromProviderList = (kind, providers, options) => (providers ?? []).map((provider) => ({
37287
38252
  configured: true,
37288
38253
  features: options.features?.[provider],
@@ -37347,27 +38312,27 @@ var summarizeVoiceProviderCapabilities = async (options) => {
37347
38312
  var renderVoiceProviderCapabilityHTML = (report, options = {}) => {
37348
38313
  const title = options.title ?? "Voice Provider Capabilities";
37349
38314
  const cards = report.capabilities.map((capability) => {
37350
- const features = (capability.features ?? []).map((feature) => `<span class="pill">${escapeHtml54(feature)}</span>`).join("");
37351
- return `<article class="card ${escapeHtml54(capability.status)}">
38315
+ const features = (capability.features ?? []).map((feature) => `<span class="pill">${escapeHtml55(feature)}</span>`).join("");
38316
+ return `<article class="card ${escapeHtml55(capability.status)}">
37352
38317
  <div class="card-header">
37353
38318
  <div>
37354
- <p class="eyebrow">${escapeHtml54(capability.kind)}</p>
37355
- <h2>${escapeHtml54(capability.label ?? capability.provider)}</h2>
38319
+ <p class="eyebrow">${escapeHtml55(capability.kind)}</p>
38320
+ <h2>${escapeHtml55(capability.label ?? capability.provider)}</h2>
37356
38321
  </div>
37357
- <strong>${escapeHtml54(capability.status)}</strong>
38322
+ <strong>${escapeHtml55(capability.status)}</strong>
37358
38323
  </div>
37359
- ${capability.description ? `<p>${escapeHtml54(capability.description)}</p>` : ""}
38324
+ ${capability.description ? `<p>${escapeHtml55(capability.description)}</p>` : ""}
37360
38325
  <dl>
37361
38326
  <div><dt>Configured</dt><dd>${capability.configured ? "yes" : "no"}</dd></div>
37362
38327
  <div><dt>Selected</dt><dd>${capability.selected ? "yes" : "no"}</dd></div>
37363
- <div><dt>Model</dt><dd>${escapeHtml54(capability.model ?? "default")}</dd></div>
38328
+ <div><dt>Model</dt><dd>${escapeHtml55(capability.model ?? "default")}</dd></div>
37364
38329
  <div><dt>Runs</dt><dd>${String(capability.health?.runCount ?? 0)}</dd></div>
37365
38330
  <div><dt>Errors</dt><dd>${String(capability.health?.errorCount ?? 0)}</dd></div>
37366
38331
  </dl>
37367
38332
  ${features ? `<div class="features">${features}</div>` : ""}
37368
38333
  </article>`;
37369
38334
  }).join("");
37370
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml54(title)}</title><style>body{background:#101316;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.card{background:#181d22;border:1px solid #2a323a;border-radius:20px;margin-bottom:16px;padding:20px}.hero{background:linear-gradient(135deg,rgba(14,165,233,.16),rgba(34,197,94,.12))}.eyebrow{color:#7dd3fc;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}h2{margin:.2rem 0 1rem}.summary,.features{display:flex;flex-wrap:wrap;gap:10px}.pill{background:#0f1217;border:1px solid #3f3f46;border-radius:999px;padding:7px 10px}.grid{display:grid;gap:16px;grid-template-columns:repeat(auto-fit,minmax(260px,1fr))}.card-header{align-items:flex-start;display:flex;gap:16px;justify-content:space-between}.selected,.healthy{color:#86efac}.unconfigured,.degraded,.rate-limited,.suppressed{color:#fca5a5}.idle,.recoverable{color:#fde68a}dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr))}dt{color:#a8b0b8;font-size:.8rem}dd{margin:0}@media(max-width:800px){main{padding:18px}.card-header{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">Provider Discovery</p><h1>${escapeHtml54(title)}</h1><div class="summary"><span class="pill">${String(report.configured)} configured</span><span class="pill">${String(report.selected)} selected</span><span class="pill">${String(report.unconfigured)} missing</span><span class="pill">${String(report.total)} total</span></div></section><section class="grid">${cards || '<article class="card"><p>No provider capabilities configured.</p></article>'}</section></main></body></html>`;
38335
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml55(title)}</title><style>body{background:#101316;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.card{background:#181d22;border:1px solid #2a323a;border-radius:20px;margin-bottom:16px;padding:20px}.hero{background:linear-gradient(135deg,rgba(14,165,233,.16),rgba(34,197,94,.12))}.eyebrow{color:#7dd3fc;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}h2{margin:.2rem 0 1rem}.summary,.features{display:flex;flex-wrap:wrap;gap:10px}.pill{background:#0f1217;border:1px solid #3f3f46;border-radius:999px;padding:7px 10px}.grid{display:grid;gap:16px;grid-template-columns:repeat(auto-fit,minmax(260px,1fr))}.card-header{align-items:flex-start;display:flex;gap:16px;justify-content:space-between}.selected,.healthy{color:#86efac}.unconfigured,.degraded,.rate-limited,.suppressed{color:#fca5a5}.idle,.recoverable{color:#fde68a}dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr))}dt{color:#a8b0b8;font-size:.8rem}dd{margin:0}@media(max-width:800px){main{padding:18px}.card-header{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">Provider Discovery</p><h1>${escapeHtml55(title)}</h1><div class="summary"><span class="pill">${String(report.configured)} configured</span><span class="pill">${String(report.selected)} selected</span><span class="pill">${String(report.unconfigured)} missing</span><span class="pill">${String(report.total)} total</span></div></section><section class="grid">${cards || '<article class="card"><p>No provider capabilities configured.</p></article>'}</section></main></body></html>`;
37371
38336
  };
37372
38337
  var createVoiceProviderCapabilityJSONHandler = (options) => async () => summarizeVoiceProviderCapabilities(options);
37373
38338
  var createVoiceProviderCapabilityHTMLHandler = (options) => async () => {
@@ -37384,7 +38349,7 @@ var createVoiceProviderCapabilityHTMLHandler = (options) => async () => {
37384
38349
  var createVoiceProviderCapabilityRoutes = (options) => {
37385
38350
  const path = options.path ?? "/api/provider-capabilities";
37386
38351
  const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
37387
- const routes = new Elysia57({
38352
+ const routes = new Elysia58({
37388
38353
  name: options.name ?? "absolutejs-voice-provider-capabilities"
37389
38354
  }).get(path, createVoiceProviderCapabilityJSONHandler(options));
37390
38355
  if (htmlPath) {
@@ -37393,7 +38358,7 @@ var createVoiceProviderCapabilityRoutes = (options) => {
37393
38358
  return routes;
37394
38359
  };
37395
38360
  // src/providerOrchestration.ts
37396
- import { Elysia as Elysia58 } from "elysia";
38361
+ import { Elysia as Elysia59 } from "elysia";
37397
38362
  var defaultRequirement = {
37398
38363
  minProviders: 1,
37399
38364
  requireBudgetPolicy: false,
@@ -37406,7 +38371,7 @@ var statusRank7 = {
37406
38371
  warn: 1,
37407
38372
  fail: 2
37408
38373
  };
37409
- var escapeHtml55 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
38374
+ var escapeHtml56 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
37410
38375
  var isProviderList = (value) => Array.isArray(value) && value.every((entry) => typeof entry === "string");
37411
38376
  var uniqueSorted8 = (values) => [
37412
38377
  ...new Set(values.filter((value) => typeof value === "string"))
@@ -37549,27 +38514,27 @@ var renderVoiceProviderOrchestrationMarkdown = (report) => {
37549
38514
  };
37550
38515
  var renderVoiceProviderOrchestrationHTML = (report, options = {}) => {
37551
38516
  const title = options.title ?? "Voice Provider Orchestration";
37552
- const cards = report.surfaces.map((surface) => `<article class="card ${escapeHtml55(surface.status)}">
37553
- <div class="card-header"><div><p class="eyebrow">${escapeHtml55(surface.surface)}</p><h2>${escapeHtml55(surface.strategy ?? "default policy")}</h2></div><strong>${escapeHtml55(surface.status)}</strong></div>
38517
+ const cards = report.surfaces.map((surface) => `<article class="card ${escapeHtml56(surface.status)}">
38518
+ <div class="card-header"><div><p class="eyebrow">${escapeHtml56(surface.surface)}</p><h2>${escapeHtml56(surface.strategy ?? "default policy")}</h2></div><strong>${escapeHtml56(surface.status)}</strong></div>
37554
38519
  <dl>
37555
- <div><dt>Providers</dt><dd>${escapeHtml55(surface.providers.join(", ") || "none")}</dd></div>
37556
- <div><dt>Fallback</dt><dd>${escapeHtml55(surface.fallbackProviders.join(" -> ") || "none")}</dd></div>
38520
+ <div><dt>Providers</dt><dd>${escapeHtml56(surface.providers.join(", ") || "none")}</dd></div>
38521
+ <div><dt>Fallback</dt><dd>${escapeHtml56(surface.fallbackProviders.join(" -> ") || "none")}</dd></div>
37557
38522
  <div><dt>Circuit breaker</dt><dd>${surface.circuitBreaker ? "yes" : "no"}</dd></div>
37558
38523
  <div><dt>Timeout</dt><dd>${surface.timeoutBudget ? `${String(surface.timeoutMs)}ms` : "none"}</dd></div>
37559
38524
  <div><dt>Max cost</dt><dd>${surface.budgetPolicy.maxCost ?? "none"}</dd></div>
37560
38525
  <div><dt>Max latency</dt><dd>${surface.budgetPolicy.maxLatencyMs ? `${String(surface.budgetPolicy.maxLatencyMs)}ms` : "none"}</dd></div>
37561
38526
  <div><dt>Min quality</dt><dd>${surface.budgetPolicy.minQuality ?? "none"}</dd></div>
37562
- <div><dt>Fallback mode</dt><dd>${escapeHtml55(surface.fallbackMode || "default")}</dd></div>
38527
+ <div><dt>Fallback mode</dt><dd>${escapeHtml56(surface.fallbackMode || "default")}</dd></div>
37563
38528
  </dl>
37564
- ${surface.issues.length ? `<ul>${surface.issues.map((issue) => `<li><strong>${escapeHtml55(issue.status)}</strong> ${escapeHtml55(issue.message)}</li>`).join("")}</ul>` : "<p>No orchestration issues.</p>"}
38529
+ ${surface.issues.length ? `<ul>${surface.issues.map((issue) => `<li><strong>${escapeHtml56(issue.status)}</strong> ${escapeHtml56(issue.message)}</li>`).join("")}</ul>` : "<p>No orchestration issues.</p>"}
37565
38530
  </article>`).join("");
37566
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml55(title)}</title><style>body{background:#111827;color:#f9fafb;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.card{background:#172033;border:1px solid #2d3b55;border-radius:22px;margin-bottom:16px;padding:20px}.hero{background:linear-gradient(135deg,rgba(59,130,246,.18),rgba(20,184,166,.12))}.eyebrow{color:#93c5fd;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}h2{margin:.2rem 0}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{background:#0f172a;border:1px solid #334155;border-radius:999px;padding:7px 10px}.grid{display:grid;gap:16px;grid-template-columns:repeat(auto-fit,minmax(300px,1fr))}.card-header{align-items:flex-start;display:flex;gap:16px;justify-content:space-between}.pass strong{color:#86efac}.warn strong{color:#fde68a}.fail strong{color:#fca5a5}dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr))}dt{color:#a8b0b8;font-size:.8rem}dd{margin:0;overflow-wrap:anywhere}li{margin:.35rem 0}@media(max-width:800px){main{padding:18px}.card-header{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">Provider Policy Proof</p><h1>${escapeHtml55(title)}</h1><div class="summary"><span class="pill">${escapeHtml55(report.profileId)}</span><span class="pill">${escapeHtml55(report.status)}</span><span class="pill">${String(report.summary.surfaces)} surfaces</span><span class="pill">${String(report.summary.providers)} providers</span><span class="pill">${String(report.issues.length)} issues</span></div></section><section class="grid">${cards || '<article class="card"><p>No provider orchestration surfaces configured.</p></article>'}</section></main></body></html>`;
38531
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml56(title)}</title><style>body{background:#111827;color:#f9fafb;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.card{background:#172033;border:1px solid #2d3b55;border-radius:22px;margin-bottom:16px;padding:20px}.hero{background:linear-gradient(135deg,rgba(59,130,246,.18),rgba(20,184,166,.12))}.eyebrow{color:#93c5fd;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}h2{margin:.2rem 0}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{background:#0f172a;border:1px solid #334155;border-radius:999px;padding:7px 10px}.grid{display:grid;gap:16px;grid-template-columns:repeat(auto-fit,minmax(300px,1fr))}.card-header{align-items:flex-start;display:flex;gap:16px;justify-content:space-between}.pass strong{color:#86efac}.warn strong{color:#fde68a}.fail strong{color:#fca5a5}dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr))}dt{color:#a8b0b8;font-size:.8rem}dd{margin:0;overflow-wrap:anywhere}li{margin:.35rem 0}@media(max-width:800px){main{padding:18px}.card-header{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">Provider Policy Proof</p><h1>${escapeHtml56(title)}</h1><div class="summary"><span class="pill">${escapeHtml56(report.profileId)}</span><span class="pill">${escapeHtml56(report.status)}</span><span class="pill">${String(report.summary.surfaces)} surfaces</span><span class="pill">${String(report.summary.providers)} providers</span><span class="pill">${String(report.issues.length)} issues</span></div></section><section class="grid">${cards || '<article class="card"><p>No provider orchestration surfaces configured.</p></article>'}</section></main></body></html>`;
37567
38532
  };
37568
38533
  var createVoiceProviderOrchestrationRoutes = (options) => {
37569
38534
  const path = options.path ?? "/api/voice/provider-orchestration";
37570
38535
  const htmlPath = options.htmlPath === undefined ? "/voice/provider-orchestration" : options.htmlPath;
37571
38536
  const markdownPath = options.markdownPath === undefined ? "/voice/provider-orchestration.md" : options.markdownPath;
37572
- const routes = new Elysia58({
38537
+ const routes = new Elysia59({
37573
38538
  name: options.name ?? "absolutejs-voice-provider-orchestration"
37574
38539
  }).get(path, () => buildVoiceProviderOrchestrationReport(options));
37575
38540
  if (htmlPath) {
@@ -37742,8 +38707,8 @@ var assertVoiceProviderRoutingContractEvidence = (reports, input = {}) => {
37742
38707
  return report;
37743
38708
  };
37744
38709
  // src/voiceMonitoring.ts
37745
- import { Elysia as Elysia59 } from "elysia";
37746
- var escapeHtml56 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
38710
+ import { Elysia as Elysia60 } from "elysia";
38711
+ var escapeHtml57 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
37747
38712
  var issueIdForRun = (run) => `voice-monitor:${run.id}:${run.impactedSessions?.[0] ?? "global"}`;
37748
38713
  var rollupStatus5 = (runs) => runs.some((run) => run.status === "fail") ? "fail" : runs.some((run) => run.status === "warn") ? "warn" : "pass";
37749
38714
  var createVoiceMemoryMonitorIssueStore = (initial = []) => {
@@ -37996,14 +38961,14 @@ ${rows || "| none | pass | info | | | No monitors configured. |"}
37996
38961
  };
37997
38962
  var renderVoiceMonitorHTML = (report, options = {}) => {
37998
38963
  const title = options.title ?? "Voice Monitors";
37999
- const runs = report.runs.map((run) => `<tr><td>${escapeHtml56(run.label)}</td><td class="${escapeHtml56(run.status)}">${escapeHtml56(run.status)}</td><td>${escapeHtml56(run.severity)}</td><td>${escapeHtml56(String(run.value ?? ""))}</td><td>${escapeHtml56(String(run.threshold ?? ""))}</td><td>${escapeHtml56(run.detail ?? "")}</td></tr>`).join("");
38000
- const issues = report.issues.map((issue) => `<li><strong>${escapeHtml56(issue.label)}</strong> <span class="${escapeHtml56(issue.status)}">${escapeHtml56(issue.status)}</span> ${escapeHtml56(issue.detail ?? "")}</li>`).join("");
38001
- const snippet = escapeHtml56(`app.use(createVoiceMonitorRoutes({
38964
+ const runs = report.runs.map((run) => `<tr><td>${escapeHtml57(run.label)}</td><td class="${escapeHtml57(run.status)}">${escapeHtml57(run.status)}</td><td>${escapeHtml57(run.severity)}</td><td>${escapeHtml57(String(run.value ?? ""))}</td><td>${escapeHtml57(String(run.threshold ?? ""))}</td><td>${escapeHtml57(run.detail ?? "")}</td></tr>`).join("");
38965
+ const issues = report.issues.map((issue) => `<li><strong>${escapeHtml57(issue.label)}</strong> <span class="${escapeHtml57(issue.status)}">${escapeHtml57(issue.status)}</span> ${escapeHtml57(issue.detail ?? "")}</li>`).join("");
38966
+ const snippet = escapeHtml57(`app.use(createVoiceMonitorRoutes({
38002
38967
  evidence,
38003
38968
  issueStore,
38004
38969
  monitors: [defineVoiceMonitor(...)]
38005
38970
  }));`);
38006
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml56(title)}</title><style>body{background:#10141b;color:#f8f2df;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1100px;padding:32px}.hero,.card{background:#171f2b;border:1px solid #2e3a4b;border-radius:24px;margin-bottom:16px;padding:22px}.eyebrow{color:#93c5fd;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.2rem,6vw,4.7rem);line-height:.92;margin:.2rem 0 1rem}.pill{border:1px solid #64748b;border-radius:999px;display:inline-flex;font-weight:900;margin-right:8px;padding:8px 12px}.pass{color:#86efac}.warn,.acknowledged{color:#fde68a}.fail,.open{color:#fca5a5}.resolved,.muted{color:#cbd5e1}table{border-collapse:collapse;width:100%}td,th{border-bottom:1px solid #2e3a4b;padding:12px;text-align:left;vertical-align:top}pre{background:#0c1118;border:1px solid #2e3a4b;border-radius:16px;color:#dbeafe;overflow:auto;padding:16px}</style></head><body><main><section class="hero"><p class="eyebrow">Code-owned monitoring</p><h1>${escapeHtml56(title)}</h1><p class="pill ${escapeHtml56(report.status)}">Status: ${escapeHtml56(report.status)}</p><p class="pill">Open issues: ${String(report.summary.open)}</p><p class="pill">Critical: ${String(report.summary.criticalOpen)}</p></section><section class="card"><h2>Monitor Runs</h2><table><thead><tr><th>Monitor</th><th>Status</th><th>Severity</th><th>Value</th><th>Threshold</th><th>Detail</th></tr></thead><tbody>${runs}</tbody></table></section><section class="card"><h2>Issues</h2>${issues ? `<ul>${issues}</ul>` : '<p class="pass">No monitor issues.</p>'}</section><section class="card"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceMonitorRoutes(...)</code></h2><pre><code>${snippet}</code></pre></section></main></body></html>`;
38971
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml57(title)}</title><style>body{background:#10141b;color:#f8f2df;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1100px;padding:32px}.hero,.card{background:#171f2b;border:1px solid #2e3a4b;border-radius:24px;margin-bottom:16px;padding:22px}.eyebrow{color:#93c5fd;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.2rem,6vw,4.7rem);line-height:.92;margin:.2rem 0 1rem}.pill{border:1px solid #64748b;border-radius:999px;display:inline-flex;font-weight:900;margin-right:8px;padding:8px 12px}.pass{color:#86efac}.warn,.acknowledged{color:#fde68a}.fail,.open{color:#fca5a5}.resolved,.muted{color:#cbd5e1}table{border-collapse:collapse;width:100%}td,th{border-bottom:1px solid #2e3a4b;padding:12px;text-align:left;vertical-align:top}pre{background:#0c1118;border:1px solid #2e3a4b;border-radius:16px;color:#dbeafe;overflow:auto;padding:16px}</style></head><body><main><section class="hero"><p class="eyebrow">Code-owned monitoring</p><h1>${escapeHtml57(title)}</h1><p class="pill ${escapeHtml57(report.status)}">Status: ${escapeHtml57(report.status)}</p><p class="pill">Open issues: ${String(report.summary.open)}</p><p class="pill">Critical: ${String(report.summary.criticalOpen)}</p></section><section class="card"><h2>Monitor Runs</h2><table><thead><tr><th>Monitor</th><th>Status</th><th>Severity</th><th>Value</th><th>Threshold</th><th>Detail</th></tr></thead><tbody>${runs}</tbody></table></section><section class="card"><h2>Issues</h2>${issues ? `<ul>${issues}</ul>` : '<p class="pass">No monitor issues.</p>'}</section><section class="card"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceMonitorRoutes(...)</code></h2><pre><code>${snippet}</code></pre></section></main></body></html>`;
38007
38972
  };
38008
38973
  var actorFromRequest = async (request) => {
38009
38974
  if (!request.headers.get("content-type")?.includes("application/json")) {
@@ -38027,7 +38992,7 @@ var createVoiceMonitorRoutes = (options) => {
38027
38992
  monitors: options.monitors,
38028
38993
  now: options.now
38029
38994
  });
38030
- const routes = new Elysia59({
38995
+ const routes = new Elysia60({
38031
38996
  name: options.name ?? "absolutejs-voice-monitoring"
38032
38997
  }).get(path, report).get(`${path}.md`, async () => {
38033
38998
  return new Response(renderVoiceMonitorMarkdown(await report()), {
@@ -38074,7 +39039,7 @@ var createVoiceMonitorRoutes = (options) => {
38074
39039
  };
38075
39040
  var createVoiceMonitorRunnerRoutes = (options) => {
38076
39041
  const path = options.path ?? "/api/voice/monitor-runner";
38077
- return new Elysia59({
39042
+ return new Elysia60({
38078
39043
  name: options.name ?? "absolutejs-voice-monitor-runner"
38079
39044
  }).get(path, () => ({
38080
39045
  isRunning: options.runner.isRunning()
@@ -38462,8 +39427,8 @@ var recommendVoiceReadinessProfile = (options) => {
38462
39427
  };
38463
39428
  };
38464
39429
  // src/providerStackRecommendations.ts
38465
- import { Elysia as Elysia60 } from "elysia";
38466
- var escapeHtml57 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
39430
+ import { Elysia as Elysia61 } from "elysia";
39431
+ var escapeHtml58 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
38467
39432
  var profileProviderPriorities = {
38468
39433
  "meeting-recorder": {
38469
39434
  llm: ["openai", "anthropic", "gemini"],
@@ -38778,17 +39743,17 @@ var resolveProviderContractMatrixInput = async (matrix) => typeof matrix === "fu
38778
39743
  var renderVoiceProviderContractMatrixHTML = (report, options = {}) => {
38779
39744
  const title = options.title ?? "Voice Provider Contract Matrix";
38780
39745
  const rows = report.rows.map((row) => {
38781
- const checks = row.checks.map((check) => `<li class="${escapeHtml57(check.status)}"><strong>${escapeHtml57(check.label)}</strong><span>${escapeHtml57(check.detail ?? check.status)}</span>${check.remediation ? `<em>${check.remediation.href ? `<a href="${escapeHtml57(check.remediation.href)}">${escapeHtml57(check.remediation.label)}</a>` : escapeHtml57(check.remediation.label)}: ${escapeHtml57(check.remediation.detail)}</em>` : ""}</li>`).join("");
38782
- return `<article class="row ${escapeHtml57(row.status)}">
39746
+ const checks = row.checks.map((check) => `<li class="${escapeHtml58(check.status)}"><strong>${escapeHtml58(check.label)}</strong><span>${escapeHtml58(check.detail ?? check.status)}</span>${check.remediation ? `<em>${check.remediation.href ? `<a href="${escapeHtml58(check.remediation.href)}">${escapeHtml58(check.remediation.label)}</a>` : escapeHtml58(check.remediation.label)}: ${escapeHtml58(check.remediation.detail)}</em>` : ""}</li>`).join("");
39747
+ return `<article class="row ${escapeHtml58(row.status)}">
38783
39748
  <div>
38784
- <p class="eyebrow">${escapeHtml57(row.kind)}${row.selected ? " \xB7 selected" : ""}</p>
38785
- <h2>${escapeHtml57(row.provider)}</h2>
38786
- <p class="status ${escapeHtml57(row.status)}">${escapeHtml57(row.status.toUpperCase())}</p>
39749
+ <p class="eyebrow">${escapeHtml58(row.kind)}${row.selected ? " \xB7 selected" : ""}</p>
39750
+ <h2>${escapeHtml58(row.provider)}</h2>
39751
+ <p class="status ${escapeHtml58(row.status)}">${escapeHtml58(row.status.toUpperCase())}</p>
38787
39752
  </div>
38788
39753
  <ul>${checks}</ul>
38789
39754
  </article>`;
38790
39755
  }).join("");
38791
- const snippet = escapeHtml57(`const providerContracts = () =>
39756
+ const snippet = escapeHtml58(`const providerContracts = () =>
38792
39757
  createVoiceProviderContractMatrixPreset('phone-agent', {
38793
39758
  env: process.env,
38794
39759
  providers: {
@@ -38809,7 +39774,7 @@ createVoiceProductionReadinessRoutes({
38809
39774
  providerContractMatrix: () =>
38810
39775
  buildVoiceProviderContractMatrix(providerContracts())
38811
39776
  });`);
38812
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml57(title)}</title><style>body{background:#0f1412;color:#f7f3e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.primitive,.row{background:#17201b;border:1px solid #2d3b32;border-radius:24px;margin-bottom:16px;padding:22px}.hero{background:linear-gradient(135deg,rgba(34,197,94,.16),rgba(125,211,252,.12))}.primitive{background:#111814;border-color:#41604a}.eyebrow{color:#86efac;font-size:.78rem;font-weight:900;letter-spacing:.1em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}h2{margin:.2rem 0}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill,.status{border:1px solid #3f4f45;border-radius:999px;display:inline-flex;padding:8px 12px}.primitive code{color:#bbf7d0}.primitive p{color:#c8d8ca;line-height:1.55;margin:.45rem 0 0}.primitive pre{background:#08110d;border:1px solid #294132;border-radius:18px;color:#d9f99d;margin:16px 0 0;overflow:auto;padding:16px}.status.pass,.row.pass,.pass{border-color:rgba(34,197,94,.65)}.status.warn,.row.warn,.warn{border-color:rgba(245,158,11,.7)}.status.fail,.row.fail,.fail{border-color:rgba(239,68,68,.75)}.row{display:grid;gap:20px;grid-template-columns:minmax(180px,.45fr) 1fr}.row ul{display:grid;gap:10px;list-style:none;margin:0;padding:0}.row li{background:#111814;border:1px solid #2d3b32;border-radius:16px;display:grid;gap:4px;padding:12px}.row li span{color:#b8c2ba}.row li em{color:#f9d77e;font-style:normal}.row li a{color:#86efac}@media(max-width:760px){main{padding:18px}.row{grid-template-columns:1fr}}</style></head><body><main><section class="hero"><p class="eyebrow">Provider contracts</p><h1>${escapeHtml57(title)}</h1><p>Self-hosted provider proof for configured state, required env, latency budgets, fallback, streaming, and declared capabilities.</p><div class="summary"><span class="pill">${String(report.passed)} passing</span><span class="pill">${String(report.warned)} warning</span><span class="pill">${String(report.failed)} failing</span><span class="pill">${String(report.total)} total</span></div></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceProviderContractMatrixPreset(...)</code> builds this matrix</h2><p>Give AbsoluteJS your configured LLM, STT, and TTS providers once. It turns them into deploy-checkable proof for env, fallback, streaming, latency budgets, selected providers, and profile-required capabilities without a hosted dashboard.</p><pre><code>${snippet}</code></pre></section>${rows || '<article class="row"><p>No provider contracts configured.</p></article>'}</main></body></html>`;
39777
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml58(title)}</title><style>body{background:#0f1412;color:#f7f3e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.primitive,.row{background:#17201b;border:1px solid #2d3b32;border-radius:24px;margin-bottom:16px;padding:22px}.hero{background:linear-gradient(135deg,rgba(34,197,94,.16),rgba(125,211,252,.12))}.primitive{background:#111814;border-color:#41604a}.eyebrow{color:#86efac;font-size:.78rem;font-weight:900;letter-spacing:.1em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}h2{margin:.2rem 0}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill,.status{border:1px solid #3f4f45;border-radius:999px;display:inline-flex;padding:8px 12px}.primitive code{color:#bbf7d0}.primitive p{color:#c8d8ca;line-height:1.55;margin:.45rem 0 0}.primitive pre{background:#08110d;border:1px solid #294132;border-radius:18px;color:#d9f99d;margin:16px 0 0;overflow:auto;padding:16px}.status.pass,.row.pass,.pass{border-color:rgba(34,197,94,.65)}.status.warn,.row.warn,.warn{border-color:rgba(245,158,11,.7)}.status.fail,.row.fail,.fail{border-color:rgba(239,68,68,.75)}.row{display:grid;gap:20px;grid-template-columns:minmax(180px,.45fr) 1fr}.row ul{display:grid;gap:10px;list-style:none;margin:0;padding:0}.row li{background:#111814;border:1px solid #2d3b32;border-radius:16px;display:grid;gap:4px;padding:12px}.row li span{color:#b8c2ba}.row li em{color:#f9d77e;font-style:normal}.row li a{color:#86efac}@media(max-width:760px){main{padding:18px}.row{grid-template-columns:1fr}}</style></head><body><main><section class="hero"><p class="eyebrow">Provider contracts</p><h1>${escapeHtml58(title)}</h1><p>Self-hosted provider proof for configured state, required env, latency budgets, fallback, streaming, and declared capabilities.</p><div class="summary"><span class="pill">${String(report.passed)} passing</span><span class="pill">${String(report.warned)} warning</span><span class="pill">${String(report.failed)} failing</span><span class="pill">${String(report.total)} total</span></div></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceProviderContractMatrixPreset(...)</code> builds this matrix</h2><p>Give AbsoluteJS your configured LLM, STT, and TTS providers once. It turns them into deploy-checkable proof for env, fallback, streaming, latency budgets, selected providers, and profile-required capabilities without a hosted dashboard.</p><pre><code>${snippet}</code></pre></section>${rows || '<article class="row"><p>No provider contracts configured.</p></article>'}</main></body></html>`;
38813
39778
  };
38814
39779
  var createVoiceProviderContractMatrixJSONHandler = (matrix) => async () => buildVoiceProviderContractMatrix(await resolveProviderContractMatrixInput(matrix));
38815
39780
  var createVoiceProviderContractMatrixHTMLHandler = (options) => async () => {
@@ -38824,7 +39789,7 @@ var createVoiceProviderContractMatrixHTMLHandler = (options) => async () => {
38824
39789
  var createVoiceProviderContractMatrixRoutes = (options) => {
38825
39790
  const path = options.path ?? "/api/provider-contracts";
38826
39791
  const htmlPath = options.htmlPath ?? "/provider-contracts";
38827
- const routes = new Elysia60({
39792
+ const routes = new Elysia61({
38828
39793
  name: options.name ?? "absolutejs-voice-provider-contract-matrix"
38829
39794
  });
38830
39795
  const jsonHandler = createVoiceProviderContractMatrixJSONHandler(options.matrix);
@@ -38942,7 +39907,7 @@ var assertVoiceProviderStackEvidence = (report, input = {}) => {
38942
39907
  return assertion;
38943
39908
  };
38944
39909
  // src/opsConsoleRoutes.ts
38945
- import { Elysia as Elysia61 } from "elysia";
39910
+ import { Elysia as Elysia62 } from "elysia";
38946
39911
  var DEFAULT_LINKS = [
38947
39912
  {
38948
39913
  description: "Quality gates for CI, deploy checks, and production readiness.",
@@ -38977,7 +39942,7 @@ var DEFAULT_LINKS = [
38977
39942
  label: "Handoffs"
38978
39943
  }
38979
39944
  ];
38980
- var escapeHtml58 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
39945
+ var escapeHtml59 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
38981
39946
  var countProviderStatuses = (providers) => {
38982
39947
  const degradedStatuses = new Set(["degraded", "rate-limited", "suppressed"]);
38983
39948
  const healthy = providers.filter((provider) => provider.status === "healthy").length;
@@ -39046,20 +40011,20 @@ var buildVoiceOpsConsoleReport = async (options) => {
39046
40011
  trace
39047
40012
  };
39048
40013
  };
39049
- var renderMetricCard = (input) => `<article class="metric"><span>${escapeHtml58(input.label)}</span><strong>${escapeHtml58(String(input.value))}</strong>${input.status ? `<p class="${escapeHtml58(input.status)}">${escapeHtml58(input.status)}</p>` : ""}${input.href ? `<a href="${escapeHtml58(input.href)}">Open</a>` : ""}</article>`;
40014
+ var renderMetricCard = (input) => `<article class="metric"><span>${escapeHtml59(input.label)}</span><strong>${escapeHtml59(String(input.value))}</strong>${input.status ? `<p class="${escapeHtml59(input.status)}">${escapeHtml59(input.status)}</p>` : ""}${input.href ? `<a href="${escapeHtml59(input.href)}">Open</a>` : ""}</article>`;
39050
40015
  var renderVoiceOpsConsoleHTML = (report, options = {}) => {
39051
40016
  const links = report.links.map((link) => `<article class="surface">
39052
- <div><h2>${escapeHtml58(link.label)}</h2>${link.description ? `<p>${escapeHtml58(link.description)}</p>` : ""}</div>
39053
- <p><a href="${escapeHtml58(link.href)}">Open ${escapeHtml58(link.label)}</a>${link.statusHref ? ` \xB7 <a href="${escapeHtml58(link.statusHref)}">Status</a>` : ""}</p>
40017
+ <div><h2>${escapeHtml59(link.label)}</h2>${link.description ? `<p>${escapeHtml59(link.description)}</p>` : ""}</div>
40018
+ <p><a href="${escapeHtml59(link.href)}">Open ${escapeHtml59(link.label)}</a>${link.statusHref ? ` \xB7 <a href="${escapeHtml59(link.statusHref)}">Status</a>` : ""}</p>
39054
40019
  </article>`).join("");
39055
- const sessions = report.recentSessions.length ? report.recentSessions.map((session) => `<tr><td>${escapeHtml58(session.sessionId)}</td><td>${escapeHtml58(session.status)}</td><td>${session.turnCount}</td><td>${session.errorCount}</td><td>${session.replayHref ? `<a href="${escapeHtml58(session.replayHref)}">Replay</a>` : ""}</td></tr>`).join("") : '<tr><td colspan="5">No sessions yet.</td></tr>';
39056
- const routing = report.recentRoutingEvents.length ? report.recentRoutingEvents.map((event) => `<tr><td>${escapeHtml58(event.kind)}</td><td>${escapeHtml58(event.provider ?? "unknown")}</td><td>${escapeHtml58(event.status ?? "unknown")}</td><td>${event.elapsedMs ?? 0}ms</td><td>${escapeHtml58(event.sessionId)}</td></tr>`).join("") : '<tr><td colspan="5">No provider routing events yet.</td></tr>';
40020
+ const sessions = report.recentSessions.length ? report.recentSessions.map((session) => `<tr><td>${escapeHtml59(session.sessionId)}</td><td>${escapeHtml59(session.status)}</td><td>${session.turnCount}</td><td>${session.errorCount}</td><td>${session.replayHref ? `<a href="${escapeHtml59(session.replayHref)}">Replay</a>` : ""}</td></tr>`).join("") : '<tr><td colspan="5">No sessions yet.</td></tr>';
40021
+ const routing = report.recentRoutingEvents.length ? report.recentRoutingEvents.map((event) => `<tr><td>${escapeHtml59(event.kind)}</td><td>${escapeHtml59(event.provider ?? "unknown")}</td><td>${escapeHtml59(event.status ?? "unknown")}</td><td>${event.elapsedMs ?? 0}ms</td><td>${escapeHtml59(event.sessionId)}</td></tr>`).join("") : '<tr><td colspan="5">No provider routing events yet.</td></tr>';
39057
40022
  const title = options.title ?? "AbsoluteJS Voice Ops Console";
39058
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml58(title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;background:#101316;color:#f6f2e8;margin:0}main{max-width:1180px;margin:auto;padding:32px}a{color:#fbbf24}header{display:flex;justify-content:space-between;gap:24px;align-items:flex-start;margin-bottom:24px}.eyebrow{color:#fbbf24;font-weight:800;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.2rem,5vw,4.5rem);line-height:.95;margin:.2rem 0 1rem}.muted{color:#a8b0b8}.grid{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));margin:20px 0}.metric,.surface{background:#181d22;border:1px solid #2a323a;border-radius:20px;padding:18px}.metric strong{display:block;font-size:2.2rem;margin:.25rem 0}.pass,.healthy{color:#86efac}.fail,.failed,.degraded{color:#fca5a5}.surfaces{display:grid;gap:16px;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));margin:24px 0}table{width:100%;border-collapse:collapse;background:#181d22;border-radius:16px;overflow:hidden;margin:12px 0 28px}td,th{border-bottom:1px solid #2a323a;padding:12px;text-align:left}section{margin-top:30px}@media(max-width:700px){main{padding:20px}header{display:block}}</style></head><body><main><header><div><p class="eyebrow">Self-hosted voice operations</p><h1>${escapeHtml58(title)}</h1><p class="muted">One deployable control plane for quality gates, failover, traces, sessions, handoffs, and provider health.</p></div><p class="muted">Checked ${escapeHtml58(new Date(report.checkedAt).toLocaleString())}</p></header><div class="grid">${renderMetricCard({ label: "Quality", value: report.quality.status, status: report.quality.status, href: "/quality" })}${renderMetricCard({ label: "Events", value: report.eventCount, href: "/diagnostics" })}${renderMetricCard({ label: "Sessions", value: report.sessions.total, status: report.sessions.failed > 0 ? "failed" : "healthy", href: "/sessions" })}${renderMetricCard({ label: "Handoffs failed", value: report.handoffs.failed, status: report.handoffs.failed > 0 ? "failed" : "healthy", href: "/handoffs" })}${renderMetricCard({ label: "Providers degraded", value: report.providers.degraded, status: report.providers.degraded > 0 ? "degraded" : "healthy", href: "/resilience" })}</div><section><h2>Operational Surfaces</h2><div class="surfaces">${links}</div></section><section><h2>Recent Sessions</h2><table><thead><tr><th>Session</th><th>Status</th><th>Turns</th><th>Errors</th><th>Replay</th></tr></thead><tbody>${sessions}</tbody></table></section><section><h2>Recent Provider Routing</h2><table><thead><tr><th>Kind</th><th>Provider</th><th>Status</th><th>Elapsed</th><th>Session</th></tr></thead><tbody>${routing}</tbody></table></section></main></body></html>`;
40023
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml59(title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;background:#101316;color:#f6f2e8;margin:0}main{max-width:1180px;margin:auto;padding:32px}a{color:#fbbf24}header{display:flex;justify-content:space-between;gap:24px;align-items:flex-start;margin-bottom:24px}.eyebrow{color:#fbbf24;font-weight:800;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.2rem,5vw,4.5rem);line-height:.95;margin:.2rem 0 1rem}.muted{color:#a8b0b8}.grid{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));margin:20px 0}.metric,.surface{background:#181d22;border:1px solid #2a323a;border-radius:20px;padding:18px}.metric strong{display:block;font-size:2.2rem;margin:.25rem 0}.pass,.healthy{color:#86efac}.fail,.failed,.degraded{color:#fca5a5}.surfaces{display:grid;gap:16px;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));margin:24px 0}table{width:100%;border-collapse:collapse;background:#181d22;border-radius:16px;overflow:hidden;margin:12px 0 28px}td,th{border-bottom:1px solid #2a323a;padding:12px;text-align:left}section{margin-top:30px}@media(max-width:700px){main{padding:20px}header{display:block}}</style></head><body><main><header><div><p class="eyebrow">Self-hosted voice operations</p><h1>${escapeHtml59(title)}</h1><p class="muted">One deployable control plane for quality gates, failover, traces, sessions, handoffs, and provider health.</p></div><p class="muted">Checked ${escapeHtml59(new Date(report.checkedAt).toLocaleString())}</p></header><div class="grid">${renderMetricCard({ label: "Quality", value: report.quality.status, status: report.quality.status, href: "/quality" })}${renderMetricCard({ label: "Events", value: report.eventCount, href: "/diagnostics" })}${renderMetricCard({ label: "Sessions", value: report.sessions.total, status: report.sessions.failed > 0 ? "failed" : "healthy", href: "/sessions" })}${renderMetricCard({ label: "Handoffs failed", value: report.handoffs.failed, status: report.handoffs.failed > 0 ? "failed" : "healthy", href: "/handoffs" })}${renderMetricCard({ label: "Providers degraded", value: report.providers.degraded, status: report.providers.degraded > 0 ? "degraded" : "healthy", href: "/resilience" })}</div><section><h2>Operational Surfaces</h2><div class="surfaces">${links}</div></section><section><h2>Recent Sessions</h2><table><thead><tr><th>Session</th><th>Status</th><th>Turns</th><th>Errors</th><th>Replay</th></tr></thead><tbody>${sessions}</tbody></table></section><section><h2>Recent Provider Routing</h2><table><thead><tr><th>Kind</th><th>Provider</th><th>Status</th><th>Elapsed</th><th>Session</th></tr></thead><tbody>${routing}</tbody></table></section></main></body></html>`;
39059
40024
  };
39060
40025
  var createVoiceOpsConsoleRoutes = (options) => {
39061
40026
  const path = options.path ?? "/ops-console";
39062
- const routes = new Elysia61({
40027
+ const routes = new Elysia62({
39063
40028
  name: options.name ?? "absolutejs-voice-ops-console"
39064
40029
  });
39065
40030
  const getReport = () => buildVoiceOpsConsoleReport(options);
@@ -39075,246 +40040,6 @@ var createVoiceOpsConsoleRoutes = (options) => {
39075
40040
  routes.get(`${path}/json`, async () => getReport());
39076
40041
  return routes;
39077
40042
  };
39078
- // src/sessionObservability.ts
39079
- import { Elysia as Elysia62 } from "elysia";
39080
- var escapeHtml59 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
39081
- var formatMs6 = (value) => value === undefined ? "n/a" : `${String(value)}ms`;
39082
- var resolveHref = (href, sessionId) => {
39083
- if (href === false) {
39084
- return;
39085
- }
39086
- if (typeof href === "function") {
39087
- return href(sessionId);
39088
- }
39089
- if (typeof href === "string") {
39090
- return href.includes(":sessionId") ? href.replaceAll(":sessionId", encodeURIComponent(sessionId)) : `${href.replace(/\/$/, "")}/${encodeURIComponent(sessionId)}`;
39091
- }
39092
- return;
39093
- };
39094
- var buildLinks = (options) => {
39095
- const links = [];
39096
- const add = (rel, label, href) => {
39097
- if (href) {
39098
- links.push({ href, label, rel });
39099
- }
39100
- };
39101
- add("operations-record", "Open operations record", resolveHref(options.operationsRecordHref, options.sessionId));
39102
- add("trace-timeline", "Open trace timeline", resolveHref(options.traceTimelineHref, options.sessionId));
39103
- add("call-debugger", "Open call debugger", resolveHref(options.callDebuggerHref, options.sessionId));
39104
- add("incident-markdown", "Download incident Markdown", resolveHref(options.incidentMarkdownHref, options.sessionId));
39105
- return [...links, ...options.customLinks ?? []];
39106
- };
39107
- var buildTurnWaterfalls = (record) => {
39108
- const byTurn = new Map;
39109
- const getTurn = (turnId) => {
39110
- const existing = byTurn.get(turnId);
39111
- if (existing) {
39112
- return existing;
39113
- }
39114
- const turn = {
39115
- assistantReplies: 0,
39116
- errors: 0,
39117
- providerDecisions: 0,
39118
- stages: [],
39119
- toolCalls: 0,
39120
- transcripts: 0
39121
- };
39122
- byTurn.set(turnId, turn);
39123
- return turn;
39124
- };
39125
- for (const event of record.timeline) {
39126
- if (!event.turnId) {
39127
- continue;
39128
- }
39129
- const turn = getTurn(event.turnId);
39130
- turn.stages.push({
39131
- at: event.at,
39132
- elapsedMs: event.elapsedMs,
39133
- label: event.label,
39134
- offsetMs: event.offsetMs,
39135
- provider: event.provider,
39136
- status: event.status,
39137
- type: event.type
39138
- });
39139
- if (event.type === "turn.transcript") {
39140
- turn.transcripts += 1;
39141
- }
39142
- if (event.type === "turn.assistant") {
39143
- turn.assistantReplies += 1;
39144
- }
39145
- if (event.type === "agent.tool") {
39146
- turn.toolCalls += 1;
39147
- }
39148
- if (event.type === "provider.decision") {
39149
- turn.providerDecisions += 1;
39150
- }
39151
- if (event.type === "session.error" || event.status === "error") {
39152
- turn.errors += 1;
39153
- }
39154
- }
39155
- for (const transcript of record.transcript) {
39156
- const turn = getTurn(transcript.id);
39157
- turn.assistantReplies = Math.max(turn.assistantReplies, transcript.assistantReplies.length);
39158
- turn.errors += transcript.errors.length;
39159
- turn.transcripts = Math.max(turn.transcripts, transcript.transcripts.length);
39160
- }
39161
- return [...byTurn.entries()].map(([turnId, turn]) => {
39162
- const startedAt = turn.stages[0]?.at;
39163
- const endedAt = turn.stages.at(-1)?.at;
39164
- return {
39165
- assistantReplies: turn.assistantReplies,
39166
- durationMs: startedAt !== undefined && endedAt !== undefined ? Math.max(0, endedAt - startedAt) : undefined,
39167
- endedAt,
39168
- errors: turn.errors,
39169
- providerDecisions: turn.providerDecisions,
39170
- stages: turn.stages,
39171
- startedAt,
39172
- toolCalls: turn.toolCalls,
39173
- transcripts: turn.transcripts,
39174
- turnId
39175
- };
39176
- }).sort((left, right) => (left.startedAt ?? 0) - (right.startedAt ?? 0));
39177
- };
39178
- var buildVoiceSessionObservabilityReport = async (options) => {
39179
- const record = await buildVoiceOperationsRecord({
39180
- audit: options.audit,
39181
- evaluation: options.evaluation,
39182
- events: options.events,
39183
- integrationEvents: options.integrationEvents,
39184
- redact: options.redact,
39185
- reviews: options.reviews,
39186
- sessionId: options.sessionId,
39187
- store: options.store,
39188
- tasks: options.tasks
39189
- });
39190
- const failureReplay = buildVoiceFailureReplay(record, {
39191
- operationsRecordHref: resolveHref(options.operationsRecordHref, options.sessionId)
39192
- });
39193
- const incidentMarkdown = renderVoiceOperationsRecordIncidentMarkdown(record);
39194
- const statuses = [
39195
- record.status,
39196
- failureReplay.status === "failed" ? "failed" : failureReplay.status === "degraded" ? "warning" : "healthy"
39197
- ];
39198
- const status = statuses.includes("failed") ? "failed" : statuses.includes("warning") ? "warning" : "healthy";
39199
- return {
39200
- checkedAt: Date.now(),
39201
- failureReplay,
39202
- incidentMarkdown,
39203
- links: buildLinks(options),
39204
- record,
39205
- sessionId: options.sessionId,
39206
- status,
39207
- summary: {
39208
- durationMs: record.summary.callDurationMs,
39209
- errors: record.summary.errorCount,
39210
- events: record.summary.eventCount,
39211
- fallbacks: record.providerDecisionSummary.fallbacks,
39212
- guardrailBlocks: record.guardrails.blocked,
39213
- handoffs: record.handoffs.length,
39214
- providerRecoveryStatus: record.providerDecisionSummary.recoveryStatus,
39215
- providers: record.providerDecisionSummary.providers,
39216
- telephonyMediaEvents: record.telephonyMedia.total,
39217
- toolCalls: record.tools.length,
39218
- turns: record.summary.turnCount
39219
- },
39220
- turns: buildTurnWaterfalls(record)
39221
- };
39222
- };
39223
- var renderLinks = (links) => links.length === 0 ? "" : `<div class="actions">${links.map((link) => `<a href="${escapeHtml59(link.href)}">${escapeHtml59(link.label)}</a>`).join("")}</div>`;
39224
- var renderTurns = (turns) => turns.length === 0 ? '<p class="muted">No turn-level events recorded yet.</p>' : turns.map((turn) => `<article class="turn"><header><strong>${escapeHtml59(turn.turnId)}</strong><span>${formatMs6(turn.durationMs)}</span></header><dl><div><dt>Transcripts</dt><dd>${String(turn.transcripts)}</dd></div><div><dt>Assistant</dt><dd>${String(turn.assistantReplies)}</dd></div><div><dt>Tools</dt><dd>${String(turn.toolCalls)}</dd></div><div><dt>Providers</dt><dd>${String(turn.providerDecisions)}</dd></div><div><dt>Errors</dt><dd>${String(turn.errors)}</dd></div></dl><table><thead><tr><th>Offset</th><th>Type</th><th>Stage</th><th>Provider</th><th>Status</th><th>Latency</th></tr></thead><tbody>${turn.stages.map((stage) => `<tr><td>+${String(stage.offsetMs)}ms</td><td>${escapeHtml59(stage.type)}</td><td>${escapeHtml59(stage.label)}</td><td>${escapeHtml59(stage.provider ?? "")}</td><td>${escapeHtml59(stage.status ?? "")}</td><td>${formatMs6(stage.elapsedMs)}</td></tr>`).join("")}</tbody></table></article>`).join("");
39225
- var renderVoiceSessionObservabilityMarkdown = (report) => `# Voice session observability: ${report.sessionId}
39226
-
39227
- Status: ${report.status}
39228
-
39229
- - Events: ${report.summary.events}
39230
- - Turns: ${report.summary.turns}
39231
- - Errors: ${report.summary.errors}
39232
- - Duration: ${formatMs6(report.summary.durationMs)}
39233
- - Providers: ${report.summary.providers.join(", ") || "none"}
39234
- - Provider recovery: ${report.summary.providerRecoveryStatus}
39235
- - Fallbacks: ${report.summary.fallbacks}
39236
- - Tool calls: ${report.summary.toolCalls}
39237
- - Handoffs: ${report.summary.handoffs}
39238
- - Guardrail blocks: ${report.summary.guardrailBlocks}
39239
- - Telephony media events: ${report.summary.telephonyMediaEvents}
39240
-
39241
- ## Links
39242
-
39243
- ${report.links.length ? report.links.map((link) => `- [${link.label}](${link.href})`).join(`
39244
- `) : "- none"}
39245
-
39246
- ## Turn Waterfalls
39247
-
39248
- ${report.turns.length ? report.turns.map((turn) => `### ${turn.turnId}
39249
-
39250
- - Duration: ${formatMs6(turn.durationMs)}
39251
- - Transcripts: ${turn.transcripts}
39252
- - Assistant replies: ${turn.assistantReplies}
39253
- - Tool calls: ${turn.toolCalls}
39254
- - Provider decisions: ${turn.providerDecisions}
39255
- - Errors: ${turn.errors}
39256
-
39257
- ${turn.stages.map((stage) => `- +${stage.offsetMs}ms ${stage.type}: ${stage.label}${stage.provider ? ` (${stage.provider})` : ""}${stage.status ? ` [${stage.status}]` : ""}`).join(`
39258
- `)}`).join(`
39259
-
39260
- `) : "No turn-level events recorded."}
39261
-
39262
- ## Incident Handoff
39263
-
39264
- ${report.incidentMarkdown}`;
39265
- var renderVoiceSessionObservabilityHTML = (report, options = {}) => `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml59(options.title ?? "Voice Session Observability")}</title><style>body{background:#0d1412;color:#f7f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.eyebrow{color:#fbbf24;font-size:.78rem;font-weight:900;letter-spacing:.14em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,4.8rem);line-height:.9;margin:.2rem 0 1rem}.status{border:1px solid #425046;border-radius:999px;display:inline-flex;padding:8px 12px}.healthy{color:#86efac}.warning{color:#fbbf24}.failed,.error{color:#fca5a5}.actions{display:flex;flex-wrap:wrap;gap:10px;margin:18px 0}.actions a{background:#fbbf24;border-radius:999px;color:#111827;font-weight:900;padding:10px 14px;text-decoration:none}.grid{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));margin:22px 0}.card,.turn,.incident{background:#17201c;border:1px solid #2e3c35;border-radius:20px;padding:16px}.card span,.muted,dt{color:#a8b4ad}.card strong{display:block;font-size:2rem}section{margin-top:30px}.turn{margin:16px 0}.turn header{align-items:center;display:flex;justify-content:space-between;gap:14px}dl{display:grid;gap:10px;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));margin:14px 0}dd{font-weight:900;margin:3px 0 0}table{border-collapse:collapse;margin-top:14px;width:100%}td,th{border-top:1px solid #2e3c35;padding:10px;text-align:left}pre{background:#08100d;border:1px solid #2e3c35;border-radius:16px;color:#d9f99d;overflow:auto;padding:14px}@media(max-width:760px){main{padding:20px}table{font-size:.9rem}}</style></head><body><main><header><p class="eyebrow">Session observability</p><h1>${escapeHtml59(report.sessionId)}</h1><p class="status ${escapeHtml59(report.status)}">${escapeHtml59(report.status)}</p>${renderLinks(report.links)}<p class="muted">One support/debug report across trace timeline, operations record, provider recovery, turn waterfalls, guardrails, tools, handoffs, failure replay, and incident handoff.</p></header><section class="grid"><article class="card"><span>Events</span><strong>${String(report.summary.events)}</strong></article><article class="card"><span>Turns</span><strong>${String(report.summary.turns)}</strong></article><article class="card"><span>Errors</span><strong>${String(report.summary.errors)}</strong></article><article class="card"><span>Duration</span><strong>${formatMs6(report.summary.durationMs)}</strong></article><article class="card"><span>Fallbacks</span><strong>${String(report.summary.fallbacks)}</strong></article><article class="card"><span>Tools</span><strong>${String(report.summary.toolCalls)}</strong></article><article class="card"><span>Handoffs</span><strong>${String(report.summary.handoffs)}</strong></article><article class="card"><span>Guardrails blocked</span><strong>${String(report.summary.guardrailBlocks)}</strong></article><article class="card"><span>Telephony media</span><strong>${String(report.summary.telephonyMediaEvents)}</strong></article></section><section><h2>Turn Waterfalls</h2>${renderTurns(report.turns)}</section><section class="incident"><h2>Incident Handoff</h2><pre><code>${escapeHtml59(report.incidentMarkdown)}</code></pre></section></main></body></html>`;
39266
- var routeSessionId = (params) => typeof params.sessionId === "string" ? params.sessionId : "";
39267
- var createVoiceSessionObservabilityRoutes = (options) => {
39268
- const path = options.path ?? "/api/voice/session-observability/:sessionId";
39269
- const htmlPath = options.htmlPath ?? "/voice/session-observability/:sessionId";
39270
- const incidentPath = options.incidentPath ?? "/api/voice/session-observability/:sessionId/incident.md";
39271
- const title = options.title ?? "AbsoluteJS Voice Session Observability";
39272
- const routes = new Elysia62({
39273
- name: options.name ?? "absolutejs-voice-session-observability"
39274
- });
39275
- const build = (sessionId) => buildVoiceSessionObservabilityReport({
39276
- audit: options.audit,
39277
- callDebuggerHref: options.callDebuggerHref,
39278
- customLinks: options.customLinks,
39279
- evaluation: options.evaluation,
39280
- events: options.events,
39281
- incidentMarkdownHref: options.incidentMarkdownHref ?? (incidentPath === false ? false : incidentPath),
39282
- integrationEvents: options.integrationEvents,
39283
- operationsRecordHref: options.operationsRecordHref,
39284
- redact: options.redact,
39285
- reviews: options.reviews,
39286
- sessionId,
39287
- store: options.store,
39288
- tasks: options.tasks,
39289
- traceTimelineHref: options.traceTimelineHref
39290
- });
39291
- routes.get(path, async ({ params }) => Response.json(await build(routeSessionId(params))));
39292
- if (htmlPath !== false) {
39293
- routes.get(htmlPath, async ({ params }) => {
39294
- const report = await build(routeSessionId(params));
39295
- const body = await (options.render ?? ((input) => renderVoiceSessionObservabilityHTML(input, { title })))(report);
39296
- return new Response(body, {
39297
- headers: {
39298
- "content-type": "text/html; charset=utf-8",
39299
- ...options.headers
39300
- }
39301
- });
39302
- });
39303
- }
39304
- if (incidentPath !== false) {
39305
- routes.get(incidentPath, async ({ params }) => {
39306
- const report = await build(routeSessionId(params));
39307
- const body = await (options.renderIncidentMarkdown ?? renderVoiceSessionObservabilityMarkdown)(report);
39308
- return new Response(body, {
39309
- headers: {
39310
- "content-type": "text/markdown; charset=utf-8",
39311
- ...options.headers
39312
- }
39313
- });
39314
- });
39315
- }
39316
- return routes;
39317
- };
39318
40043
  // src/incidentBundle.ts
39319
40044
  import { Elysia as Elysia63 } from "elysia";
39320
40045
  var filterIncidentBundleArtifacts = (artifacts, filter = {}) => artifacts.filter((artifact) => {
@@ -42256,8 +42981,8 @@ var shapeTelephonyAssistantText = (text, options = {}) => {
42256
42981
  };
42257
42982
  // src/proofPack.ts
42258
42983
  import { Elysia as Elysia69 } from "elysia";
42259
- import { mkdir as mkdir5 } from "fs/promises";
42260
- import { dirname as dirname3, join as join4 } from "path";
42984
+ import { mkdir as mkdir6 } from "fs/promises";
42985
+ import { dirname as dirname3, join as join5 } from "path";
42261
42986
  var toGeneratedAt = (value) => value === undefined ? new Date().toISOString() : typeof value === "number" ? new Date(value).toISOString() : value;
42262
42987
  var getProofPackMetadata = (proofPack) => {
42263
42988
  const built = buildVoiceProofPack(proofPack);
@@ -42786,10 +43511,10 @@ var writeVoiceProofPack = async (input, options = { outputDir: ".voice-runtime/p
42786
43511
  ...input,
42787
43512
  outputDir: options.outputDir
42788
43513
  });
42789
- const jsonPath = join4(options.outputDir, options.jsonFileName ?? "latest.json");
42790
- const markdownPath = join4(options.outputDir, options.markdownFileName ?? "latest.md");
42791
- await mkdir5(dirname3(jsonPath), { recursive: true });
42792
- await mkdir5(dirname3(markdownPath), { recursive: true });
43514
+ const jsonPath = join5(options.outputDir, options.jsonFileName ?? "latest.json");
43515
+ const markdownPath = join5(options.outputDir, options.markdownFileName ?? "latest.md");
43516
+ await mkdir6(dirname3(jsonPath), { recursive: true });
43517
+ await mkdir6(dirname3(markdownPath), { recursive: true });
42793
43518
  await Promise.all([
42794
43519
  Bun.write(jsonPath, JSON.stringify(proofPack, null, 2)),
42795
43520
  Bun.write(markdownPath, renderVoiceProofPackMarkdown(proofPack))
@@ -42862,6 +43587,7 @@ var createVoiceProofPackRoutes = (options) => {
42862
43587
  };
42863
43588
  export {
42864
43589
  writeVoiceProofPack,
43590
+ writeVoiceMediaPipelineArtifacts,
42865
43591
  withVoiceOpsTaskId,
42866
43592
  withVoiceIntegrationEventId,
42867
43593
  voiceTelephonyOutcomeToRouteResult,
@@ -42899,6 +43625,7 @@ export {
42899
43625
  summarizeVoiceOpsTaskQueue,
42900
43626
  summarizeVoiceOpsTaskAnalytics,
42901
43627
  summarizeVoiceOpsStatus,
43628
+ summarizeVoiceMediaPipelineReport,
42902
43629
  summarizeVoiceLiveLatency,
42903
43630
  summarizeVoiceIntegrationEvents,
42904
43631
  summarizeVoiceHandoffHealth,
@@ -43105,6 +43832,7 @@ export {
43105
43832
  filterVoiceAuditEvents,
43106
43833
  fetchVoiceProofTarget,
43107
43834
  failVoiceOpsTask,
43835
+ extractVoiceMediaPipelineIssueEntries,
43108
43836
  exportVoiceTrace,
43109
43837
  exportVoiceAuditTrail,
43110
43838
  evaluateVoiceTrace,
@@ -43113,6 +43841,7 @@ export {
43113
43841
  evaluateVoiceTelephonyWebhookNormalizationEvidence,
43114
43842
  evaluateVoiceTelephonyContract,
43115
43843
  evaluateVoiceSimulationSuiteEvidence,
43844
+ evaluateVoiceSessionObservabilityEvidence,
43116
43845
  evaluateVoiceRealtimeProviderContractEvidence,
43117
43846
  evaluateVoiceRealtimeChannelEvidence,
43118
43847
  evaluateVoiceQuality,
@@ -43507,6 +44236,8 @@ export {
43507
44236
  buildVoiceRealCallProfileHistoryReportFromStore,
43508
44237
  buildVoiceRealCallProfileHistoryReport,
43509
44238
  buildVoiceRealCallProfileEvidenceFromTraceEvents,
44239
+ buildVoiceRealCallProfileEvidenceFromRuntimeSurface,
44240
+ buildVoiceRealCallProfileEvidenceFromRuntimeProviderRoles,
43510
44241
  buildVoiceRealCallProfileEvidenceFromReconnectProofReports,
43511
44242
  buildVoiceRealCallProfileDefaults,
43512
44243
  buildVoiceRealCallEvidenceRuntimeWorkerReadinessCheck,
@@ -43544,6 +44275,8 @@ export {
43544
44275
  buildVoiceObservabilityArtifactIndex,
43545
44276
  buildVoiceMonitorRunReport,
43546
44277
  buildVoiceMediaPipelineReport,
44278
+ buildVoiceMediaPipelineReadinessChecks,
44279
+ buildVoiceMediaPipelineIncidentEvents,
43547
44280
  buildVoiceLiveOpsControlState,
43548
44281
  buildVoiceLatencySLOGate,
43549
44282
  buildVoiceIncidentTimelineReport,
@@ -43575,6 +44308,7 @@ export {
43575
44308
  assertVoiceTelephonyWebhookNormalizationEvidence,
43576
44309
  assertVoiceSloCalibration,
43577
44310
  assertVoiceSimulationSuiteEvidence,
44311
+ assertVoiceSessionObservabilityEvidence,
43578
44312
  assertVoiceRealtimeProviderContractEvidence,
43579
44313
  assertVoiceRealtimeChannelEvidence,
43580
44314
  assertVoiceProviderStackEvidence,