@absolutejs/voice 0.0.22-beta.514 → 0.0.22-beta.516

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.
@@ -0,0 +1,10 @@
1
+ (()=>{var{defineProperty:a,getOwnPropertyNames:lc,getOwnPropertyDescriptor:ic}=Object,gc=Object.prototype.hasOwnProperty;function sc(c){return this[c]}var ec=(c)=>{var n=(W??=new WeakMap).get(c),l;if(n)return n;if(n=a({},"__esModule",{value:!0}),c&&typeof c==="object"||typeof c==="function"){for(var o of lc(c))if(!gc.call(n,o))a(n,o,{get:sc.bind(c,o),enumerable:!(l=ic(c,o))||l.enumerable})}return W.set(c,n),n},W;var Ac=(c)=>c;function dc(c,n){this[c]=Ac.bind(null,n)}var Cc=(c,n)=>{for(var l in n)a(c,l,{get:n[l],enumerable:!0,configurable:!0,set:dc.bind(n,l)})};var Yc={};Cc(Yc,{mount:()=>p,default:()=>qc,VOICE_EMBED_VERSION:()=>cc});var Tc=(c)=>{if(typeof c!=="string")return c;return document.querySelector(c)},tc=(c,n,l,o)=>{let i=n??c.getAttribute("hx-get")??"";if(!i)return"";let e=new URL(i,window.location.origin);if(o)e.searchParams.set(l,o);else e.searchParams.delete(l);return`${e.pathname}${e.search}${e.hash}`},$=(c,n)=>{if(typeof window>"u"||typeof document>"u")return()=>{};let l=Tc(n.element);if(!l)return()=>{};let o=n.eventName??"voice-refresh",i=n.sessionQueryParam??"sessionId",e=()=>{let C=window,T=tc(l,n.route,i,c.sessionId);if(T)l.setAttribute("hx-get",T);C.htmx?.process?.(l),C.htmx?.trigger?.(l,o)},s=c.subscribe(e);return e(),()=>{s()}};var hc=(c)=>Math.max(-1,Math.min(1,c)),Sc=(c)=>{let n=new Int16Array(c.length);for(let l=0;l<c.length;l+=1){let o=hc(c[l]??0);n[l]=o<0?o*32768:o*32767}return new Uint8Array(n.buffer)},yc=(c)=>{let n=c instanceof Uint8Array?c:new Uint8Array(c);if(n.byteLength<2)return 0;let l=new Int16Array(n.buffer,n.byteOffset,Math.floor(n.byteLength/2));if(l.length===0)return 0;let o=0;for(let i of l){let e=i/32768;o+=e*e}return Math.min(1,Math.max(0,Math.sqrt(o/l.length)*5.5))},Rc=(c,n,l)=>{if(n===l)return c;let o=n/l,i=Math.round(c.length/o),e=new Float32Array(i),s=0,C=0;while(s<e.length){let T=Math.round((s+1)*o),S=0,d=0;for(let h=C;h<T&&h<c.length;h+=1)S+=c[h]??0,d+=1;e[s]=d>0?S/d:0,s+=1,C=T}return e},H=(c)=>{let n=null,l=null,o=null,i=null;return{start:async()=>{if(typeof navigator>"u"||!navigator.mediaDevices?.getUserMedia)throw Error("Browser microphone capture requires navigator.mediaDevices.getUserMedia.");let C=(typeof window<"u"?window.AudioContext??window.webkitAudioContext:void 0)??AudioContext;if(!C)throw Error("Browser microphone capture requires AudioContext support.");i=await navigator.mediaDevices.getUserMedia({audio:{channelCount:c.channelCount??1}}),n=new C,l=n.createMediaStreamSource(i),o=n.createScriptProcessor(4096,1,1),o.onaudioprocess=(T)=>{let S=T.inputBuffer.getChannelData(0),d=Rc(S,n?.sampleRate??48000,c.sampleRateHz??16000),h=Sc(d);c.onLevel?.(yc(h)),c.onAudio(h)},l.connect(o),o.connect(n.destination)},stop:()=>{o?.disconnect(),l?.disconnect(),i?.getTracks().forEach((C)=>C.stop()),n?.close(),c.onLevel?.(0),n=null,i=null,o=null,l=null}}};var P=(c)=>{if(typeof c==="string"&&c.trim())return c;if(c instanceof Error&&c.message.trim())return c.message;if(c&&typeof c==="object"){let n=c;for(let l of["message","reason","description"]){let o=n[l];if(typeof o==="string"&&o.trim())return o}if("error"in n)return P(n.error);if("cause"in n)return P(n.cause);try{return JSON.stringify(c)}catch{}}return"Unexpected error"},G=(c)=>{switch(c.type){case"audio":return{chunk:Uint8Array.from(atob(c.chunkBase64),(n)=>n.charCodeAt(0)),format:c.format,receivedAt:c.receivedAt,turnId:c.turnId,type:"audio"};case"assistant":return{text:c.text,type:"assistant"};case"complete":return{sessionId:c.sessionId,type:"complete"};case"connection":return{reconnect:c.reconnect,type:"connection"};case"call_lifecycle":return{event:c.event,sessionId:c.sessionId,type:"call_lifecycle"};case"error":return{message:P(c.message),type:"error"};case"final":return{transcript:c.transcript,type:"final"};case"partial":return{transcript:c.transcript,type:"partial"};case"replay":return{assistantTexts:c.assistantTexts,call:c.call,partial:c.partial,scenarioId:c.scenarioId,sessionId:c.sessionId,sessionMetadata:c.sessionMetadata,status:c.status,turns:c.turns,type:"replay"};case"session":return{sessionId:c.sessionId,sessionMetadata:c.sessionMetadata,scenarioId:c.scenarioId,status:c.status,type:"session"};case"turn":return{turn:c.turn,type:"turn"};default:return null}};var M=(c,n,l,o)=>{c.push({code:l,message:o,severity:n})};var Vc=(c)=>c.length===0?void 0:c.reduce((n,l)=>n+l,0)/c.length,E=(c)=>c.length===0?void 0:Math.max(...c);var R=(c,n)=>{let l=c[n];return typeof l==="number"&&Number.isFinite(l)?l:void 0},O=(c,n)=>{let l=c[n];return typeof l==="boolean"?l:void 0},V=(c,n)=>{let l=c[n];return typeof l==="string"?l:void 0},N=(c)=>String(c.id??V(c,"ssrc")??R(c,"ssrc")??V(c,"trackIdentifier")??V(c,"mid")??"unknown"),z=(c)=>c===void 0?void 0:c*1000;var Ic=(c)=>{let n={};for(let[l,o]of Object.entries(c))if(o===null||typeof o==="boolean"||typeof o==="number"||typeof o==="string")n[l]=o;return n};var X=(c={})=>{let n=c.stats??[],l=[],o=n.filter((g)=>g.type==="inbound-rtp"&&V(g,"kind")!=="video"),i=n.filter((g)=>g.type==="outbound-rtp"&&V(g,"kind")!=="video"),e=n.filter((g)=>g.type==="candidate-pair"),s=n.filter((g)=>(g.type==="track"||g.type==="media-source")&&V(g,"kind")==="audio"),C=e.filter((g)=>O(g,"selected")===!0||O(g,"nominated")===!0||V(g,"state")==="succeeded").length,T=s.filter((g)=>V(g,"readyState")!=="ended"&&V(g,"trackState")!=="ended"&&O(g,"ended")!==!0).length,S=s.filter((g)=>V(g,"readyState")==="ended"||V(g,"trackState")==="ended"||O(g,"ended")===!0).length,d=o.reduce((g,y)=>g+(R(y,"packetsReceived")??0),0),h=i.reduce((g,y)=>g+(R(y,"packetsSent")??0),0),A=[...o,...i].reduce((g,y)=>g+Math.max(0,R(y,"packetsLost")??0),0),I=d+A,t=I===0?0:A/I,x=o.reduce((g,y)=>g+(R(y,"bytesReceived")??0),0),w=i.reduce((g,y)=>g+(R(y,"bytesSent")??0),0),b=E(e.map((g)=>z(R(g,"currentRoundTripTime")??R(g,"roundTripTime"))).filter((g)=>g!==void 0)),f=E([...o,...i].map((g)=>z(R(g,"jitter"))).filter((g)=>g!==void 0)),D=E(o.map((g)=>{let y=R(g,"jitterBufferDelay"),_=R(g,"jitterBufferEmittedCount");return y!==void 0&&_!==void 0&&_>0?y/_*1000:void 0}).filter((g)=>g!==void 0)),r=s.map((g)=>R(g,"audioLevel")).filter((g)=>g!==void 0);if(c.requireConnectedCandidatePair&&e.length>0&&C===0)M(l,"error","media.webrtc_candidate_pair_missing","No active WebRTC candidate pair was observed.");if(c.requireLiveAudioTrack&&T===0)M(l,"error","media.webrtc_audio_track_missing","No live WebRTC audio track was observed.");if(c.maxPacketLossRatio!==void 0&&t>c.maxPacketLossRatio)M(l,"warning","media.webrtc_packet_loss",`Observed WebRTC packet loss ratio ${String(t)} above ${String(c.maxPacketLossRatio)}.`);if(c.maxRoundTripTimeMs!==void 0&&b!==void 0&&b>c.maxRoundTripTimeMs)M(l,"warning","media.webrtc_round_trip_time",`Observed WebRTC RTT ${String(b)}ms above ${String(c.maxRoundTripTimeMs)}ms.`);if(c.maxJitterMs!==void 0&&f!==void 0&&f>c.maxJitterMs)M(l,"warning","media.webrtc_jitter",`Observed WebRTC jitter ${String(f)}ms above ${String(c.maxJitterMs)}ms.`);return{activeCandidatePairs:C,audioLevelAverage:Vc(r),bytesReceived:x,bytesSent:w,checkedAt:Date.now(),endedAudioTracks:S,inboundPackets:d,issues:l,jitterBufferDelayMs:D,jitterMs:f,liveAudioTracks:T,outboundPackets:h,packetLossRatio:t,packetsLost:A,roundTripTimeMs:b,status:l.some((g)=>g.severity==="error")?"fail":l.length>0?"warn":"pass",totalStats:n.length}},Y=async(c)=>{return[...(await c.peerConnection.getStats(c.selector??null)).values()].map(Ic)};var q=(c={})=>{let n=c.stats??[],l=c.previousStats??[],o=[],i=new Map(l.map((A)=>[N(A),A])),s=n.filter((A)=>(A.type==="inbound-rtp"||A.type==="outbound-rtp")&&V(A,"kind")!=="video"&&V(A,"mediaType")!=="video").map((A)=>{let I=A.type==="outbound-rtp"?"outbound":"inbound",t=I==="outbound"?"packetsSent":"packetsReceived",x=I==="outbound"?"bytesSent":"bytesReceived",w=i.get(N(A)),b=R(A,t),f=w?R(w,t):void 0,D=R(A,x),r=w?R(w,x):void 0,g=A.timestamp!==void 0&&w?.timestamp!==void 0?A.timestamp-w.timestamp:void 0;return{bytesDelta:D!==void 0&&r!==void 0?D-r:void 0,currentPackets:b,direction:I,id:N(A),packetDelta:b!==void 0&&f!==void 0?b-f:void 0,previousPackets:f,timeDeltaMs:g}}),C=s.filter((A)=>A.direction==="inbound"),T=s.filter((A)=>A.direction==="outbound"),S=E(s.map((A)=>A.timeDeltaMs).filter((A)=>A!==void 0)),d=C.filter((A)=>c.maxInboundPacketStallMs!==void 0&&A.timeDeltaMs!==void 0&&A.timeDeltaMs>=c.maxInboundPacketStallMs&&A.packetDelta!==void 0&&A.packetDelta<=0).length,h=T.filter((A)=>c.maxOutboundPacketStallMs!==void 0&&A.timeDeltaMs!==void 0&&A.timeDeltaMs>=c.maxOutboundPacketStallMs&&A.packetDelta!==void 0&&A.packetDelta<=0).length;if(c.requireInboundAudio&&C.length===0)M(o,"error","media.webrtc_inbound_audio_missing","No inbound WebRTC audio RTP stream was observed.");if(c.requireOutboundAudio&&T.length===0)M(o,"error","media.webrtc_outbound_audio_missing","No outbound WebRTC audio RTP stream was observed.");if(c.maxGapMs!==void 0&&S!==void 0&&S>c.maxGapMs)M(o,"warning","media.webrtc_stream_gap",`Observed WebRTC stream sample gap ${String(S)}ms above ${String(c.maxGapMs)}ms.`);if(d>0)M(o,"error","media.webrtc_inbound_stalled",`${String(d)} inbound WebRTC audio stream(s) stopped receiving packets.`);if(h>0)M(o,"error","media.webrtc_outbound_stalled",`${String(h)} outbound WebRTC audio stream(s) stopped sending packets.`);return{checkedAt:Date.now(),inboundAudioStreams:C.length,issues:o,maxObservedGapMs:S,outboundAudioStreams:T.length,stalledInboundStreams:d,stalledOutboundStreams:h,status:o.some((A)=>A.severity==="error")?"fail":o.length>0?"warn":"pass",streams:s,totalStats:n.length}};var _c="/api/voice/browser-media",wc=5000,bc=async(c)=>c.peerConnection??await c.getPeerConnection?.()??null,fc=async(c,n)=>{let l=n.fetch??globalThis.fetch;if(!l)return;await l(n.path??_c,{body:JSON.stringify(c),headers:{"Content-Type":"application/json"},keepalive:!0,method:"POST"})},Q=(c)=>{let n=null,l=[],o=async()=>{let s=await bc(c);if(!s)return;let C=await Y({peerConnection:s}),T=X({...c,stats:C}),S=c.continuity===!1?void 0:q({...c.continuity,previousStats:l,stats:C}),d={at:Date.now(),continuity:S,report:T,scenarioId:c.getScenarioId?.()??null,sessionId:c.getSessionId?.()??null};return l=C,c.onReport?.(d),await fc(d,c),d},i=()=>{o().catch((s)=>{c.onError?.(s)})},e=()=>{if(n)clearInterval(n),n=null};return{close:e,reportOnce:o,start:()=>{if(n)return;i(),n=setInterval(i,c.intervalMs??wc)},stop:e}};var U=()=>{},Mc=()=>U,Lc={callControl:U,close:U,endTurn:U,getReadyState:()=>3,getScenarioId:()=>"",getSessionId:()=>"",send:U,sendAudio:U,simulateDisconnect:U,start:()=>{},subscribe:Mc},Uc=()=>crypto.randomUUID(),xc=(c,n,l)=>{let{hostname:o,port:i,protocol:e}=window.location,s=e==="https:"?"wss:":"ws:",C=i?`:${i}`:"",T=new URL(`${s}//${o}${C}${c}`);if(T.searchParams.set("sessionId",n),l)T.searchParams.set("scenarioId",l);return T.toString()},Dc=(c)=>{if(!c||typeof c!=="object"||!("type"in c))return!1;switch(c.type){case"audio":case"assistant":case"call_lifecycle":case"complete":case"connection":case"error":case"final":case"partial":case"pong":case"replay":case"session":case"turn":return!0;default:return!1}},rc=(c)=>{if(typeof c.data!=="string")return null;try{let n=JSON.parse(c.data);return Dc(n)?n:null}catch{return null}},J=(c,n={})=>{if(typeof window>"u")return Lc;let l=new Set,o=n.reconnect!==!1,i=n.maxReconnectAttempts??10,e=n.pingInterval??30000,s={isConnected:!1,pendingMessages:[],scenarioId:n.scenarioId??null,pingInterval:null,reconnectAttempts:0,reconnectTimeout:null,sessionId:n.sessionId??Uc(),ws:null},C=(g)=>{l.forEach((y)=>y(g))},T=()=>{if(s.pingInterval)clearInterval(s.pingInterval),s.pingInterval=null;if(s.reconnectTimeout)clearTimeout(s.reconnectTimeout),s.reconnectTimeout=null},S=()=>{if(s.ws?.readyState!==1)return;while(s.pendingMessages.length>0){let g=s.pendingMessages.shift();if(g!==void 0)s.ws.send(g)}},d=()=>{let g=Date.now()+500;s.reconnectAttempts+=1,C({reconnect:{attempts:s.reconnectAttempts,lastDisconnectAt:Date.now(),maxAttempts:i,nextAttemptAt:g,status:"reconnecting"},type:"connection"}),s.reconnectTimeout=setTimeout(()=>{if(s.reconnectAttempts>i){C({reconnect:{attempts:s.reconnectAttempts,maxAttempts:i,status:"exhausted"},type:"connection"});return}h()},500)},h=()=>{let g=new WebSocket(xc(c,s.sessionId,s.scenarioId));g.binaryType="arraybuffer",g.onopen=()=>{let y=s.reconnectAttempts>0;if(s.isConnected=!0,S(),y)C({reconnect:{attempts:s.reconnectAttempts,lastResumedAt:Date.now(),maxAttempts:i,status:"resumed"},type:"connection"}),s.reconnectAttempts=0;l.forEach((_)=>_({scenarioId:s.scenarioId??void 0,sessionId:s.sessionId,status:"active",type:"session"})),s.pingInterval=setInterval(()=>{if(g.readyState===1)g.send(JSON.stringify({type:"ping"}))},e)},g.onmessage=(y)=>{let _=rc(y);if(!_)return;if(_.type==="session")s.sessionId=_.sessionId,s.scenarioId=_.scenarioId??s.scenarioId;l.forEach((oc)=>oc(_))},g.onclose=(y)=>{if(s.isConnected=!1,T(),o&&y.code!==1000&&s.reconnectAttempts<i)d();else if(o&&y.code!==1000)C({reconnect:{attempts:s.reconnectAttempts,lastDisconnectAt:Date.now(),maxAttempts:i,status:"exhausted"},type:"connection"})},s.ws=g},A=(g)=>{if(s.ws?.readyState===1){s.ws.send(g);return}s.pendingMessages.push(g)},I=(g)=>{A(JSON.stringify(g))},t=(g={})=>{if(g.sessionId)s.sessionId=g.sessionId;if(g.scenarioId)s.scenarioId=g.scenarioId;I({type:"start",sessionId:s.sessionId,scenarioId:s.scenarioId??void 0})},x=(g)=>{A(g)},w=()=>{I({type:"end_turn"})},b=(g)=>{I({...g,type:"call_control"})},f=()=>{if(T(),s.ws)s.ws.close(1000),s.ws=null;s.isConnected=!1,l.clear()},D=()=>{if(s.ws?.readyState===1)s.ws.close(4000,"absolutejs-voice-reconnect-proof")},r=(g)=>{return l.add(g),()=>{l.delete(g)}};return h(),{callControl:b,close:f,endTurn:w,getReadyState:()=>s.ws?.readyState??3,getScenarioId:()=>s.scenarioId??"",getSessionId:()=>s.sessionId,send:I,sendAudio:x,simulateDisconnect:D,start:t,subscribe:r}};var Oc=()=>({attempts:0,maxAttempts:0,status:"idle"}),Ec=()=>({assistantAudio:[],assistantTexts:[],call:null,error:null,isConnected:!1,sessionMetadata:null,scenarioId:null,partial:"",reconnect:Oc(),sessionId:null,status:"idle",turns:[]}),Z=()=>{let c=Ec(),n=new Set,l=()=>{n.forEach((i)=>i())};return{dispatch:(i)=>{switch(i.type){case"audio":c={...c,assistantAudio:[...c.assistantAudio,{chunk:i.chunk,format:i.format,receivedAt:i.receivedAt,turnId:i.turnId}]};break;case"assistant":c={...c,assistantTexts:[...c.assistantTexts,i.text]};break;case"complete":c={...c,sessionId:i.sessionId,status:"completed"};break;case"call_lifecycle":c={...c,call:{...c.call,disposition:i.event.type==="end"?i.event.disposition:c.call?.disposition,endedAt:i.event.type==="end"?i.event.at:c.call?.endedAt,events:[...c.call?.events??[],i.event],lastEventAt:i.event.at,startedAt:c.call?.startedAt??i.event.at},sessionId:i.sessionId};break;case"connected":c={...c,isConnected:!0,reconnect:c.reconnect.status==="reconnecting"?{...c.reconnect,lastResumedAt:Date.now(),nextAttemptAt:void 0,status:"resumed"}:c.reconnect};break;case"connection":c={...c,reconnect:i.reconnect};break;case"disconnected":c={...c,isConnected:!1};break;case"error":c={...c,error:i.message};break;case"final":c={...c,partial:i.transcript.text,turns:c.turns.map((e)=>e)};break;case"partial":c={...c,partial:i.transcript.text};break;case"replay":c={...c,assistantTexts:[...i.assistantTexts],call:i.call??null,error:null,isConnected:i.status==="active",partial:i.partial,reconnect:c.reconnect.status==="reconnecting"?{...c.reconnect,lastResumedAt:Date.now(),nextAttemptAt:void 0,status:"resumed"}:c.reconnect,scenarioId:i.scenarioId??c.scenarioId,sessionId:i.sessionId,sessionMetadata:i.sessionMetadata??c.sessionMetadata,status:i.status,turns:[...i.turns]};break;case"session":c={...c,error:null,scenarioId:i.scenarioId??c.scenarioId,isConnected:i.status==="active",sessionId:i.sessionId,sessionMetadata:i.sessionMetadata??c.sessionMetadata,status:i.status};break;case"turn":c={...c,partial:"",turns:[...c.turns,i.turn]};break}l()},getServerSnapshot:()=>c,getSnapshot:()=>c,subscribe:(i)=>{return n.add(i),()=>{n.delete(i)}}}};var B=(c,n={})=>{let l=J(c,n),o=Z(),i=n.browserMedia&&typeof window<"u"?Q({...n.browserMedia,getScenarioId:()=>n.browserMedia?n.browserMedia.getScenarioId?.()??l.getScenarioId():l.getScenarioId(),getSessionId:()=>n.browserMedia?n.browserMedia.getSessionId?.()??l.getSessionId():l.getSessionId()}):null,e=new Set,s=(d)=>Promise.resolve().then(()=>{if(!d?.sessionId&&!d?.scenarioId)return;l.start(d),i?.start()}),C=()=>{e.forEach((d)=>d())},T=()=>{if(!n.reconnectReportPath||typeof fetch>"u")return;let d=o.getSnapshot(),h=JSON.stringify({at:Date.now(),reconnect:d.reconnect,scenarioId:d.scenarioId,sessionId:l.getSessionId(),turnIds:d.turns.map((A)=>A.id)});fetch(n.reconnectReportPath,{body:h,headers:{"Content-Type":"application/json"},keepalive:!0,method:"POST"}).catch(()=>{})},S=l.subscribe((d)=>{let h=G(d);if(h){if(o.dispatch(h),d.type==="connection")T();C()}});return{callControl(d){l.callControl(d)},close(){S(),i?.close(),l.close(),o.dispatch({type:"disconnected"}),C()},endTurn(){l.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:s,get partial(){return o.getSnapshot().partial},get reconnect(){return o.getSnapshot().reconnect},get sessionId(){return l.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){l.sendAudio(d)},simulateDisconnect(){l.simulateDisconnect()},subscribe(d){return e.add(d),()=>{e.delete(d)}}}};var K=(c)=>{if(!c||c.enabled===!1)return;return{enabled:!0,maxGain:c.maxGain??3,noiseGateAttenuation:c.noiseGateAttenuation??0.15,noiseGateThreshold:c.noiseGateThreshold??0.006,targetLevel:c.targetLevel??0.08}};var ac={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}},Pc={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 j=(c)=>{let n=c?.profile??"fast",l=c?.qualityProfile??"general",o=ac[n],i=Pc[l];return{profile:n,qualityProfile:l,silenceMs:c?.silenceMs??i.silenceMs??o.silenceMs,speechThreshold:c?.speechThreshold??i.speechThreshold??o.speechThreshold,transcriptStabilityMs:c?.transcriptStabilityMs??i.transcriptStabilityMs??o.transcriptStabilityMs}};var Nc={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"}}},k=(c="default")=>{let n=Nc[c];return{audioConditioning:K(n.audioConditioning),capture:{channelCount:n.capture?.channelCount??1,sampleRateHz:n.capture?.sampleRateHz??16000},connection:{...n.connection},name:c,sttLifecycle:n.sttLifecycle??"continuous",turnDetection:j(n.turnDetection)}};var Wc=(c)=>({assistantAudio:[...c.assistantAudio],assistantTexts:[...c.assistantTexts],call:c.call,error:c.error,isConnected:c.isConnected,isRecording:!1,partial:c.partial,reconnect:c.reconnect,recordingError:null,sessionId:c.sessionId,sessionMetadata:c.sessionMetadata,scenarioId:c.scenarioId,status:c.status,turns:[...c.turns]}),F=(c,n={})=>{let l=k(n.preset),o=B(c,{...l.connection,...n.connection}),i=null,e=Wc(o),s=new Set,C=()=>{for(let t of s)t()},T=()=>{if(e={...e,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&&e.status==="completed"&&e.isRecording)i?.stop(),i=null,e={...e,isRecording:!1};C()},S=o.subscribe(T);T();let d=()=>{if(i)return i;return i=H({channelCount:n.capture?.channelCount??l.capture.channelCount,onLevel:n.capture?.onLevel,onAudio:(t)=>{if(n.capture?.onAudio){n.capture.onAudio(t,o.sendAudio);return}o.sendAudio(t)},sampleRateHz:n.capture?.sampleRateHz??l.capture.sampleRateHz}),i},h=()=>{i?.stop(),i=null,e={...e,isRecording:!1},C()},A=async()=>{if(e.isRecording)return;try{e={...e,recordingError:null},C(),await d().start(),e={...e,isRecording:!0},C()}catch(t){throw i=null,e={...e,isRecording:!1,recordingError:t instanceof Error?t.message:String(t)},C(),t}};return{bindHTMX(t){return $(o,t)},callControl:(t)=>o.callControl(t),close:()=>{S(),h(),o.close()},endTurn:()=>o.endTurn(),get error(){return e.error},getServerSnapshot:()=>e,getSnapshot:()=>e,get isConnected(){return e.isConnected},get isRecording(){return e.isRecording},get partial(){return e.partial},get recordingError(){return e.recordingError},get reconnect(){return e.reconnect},sendAudio:(t)=>o.sendAudio(t),simulateDisconnect:()=>o.simulateDisconnect(),get sessionId(){return e.sessionId},get sessionMetadata(){return e.sessionMetadata},get scenarioId(){return e.scenarioId},startRecording:A,get status(){return e.status},stopRecording:h,subscribe:(t)=>{return s.add(t),()=>{s.delete(t)}},toggleRecording:async()=>{if(e.isRecording){h();return}await A()},get turns(){return e.turns},get assistantTexts(){return e.assistantTexts},get assistantAudio(){return e.assistantAudio},get call(){return e.call}}};var m=(c)=>{if(!c.isConnected)return"idle";if(c.isPlaying)return"speaking";if(c.isRecording&&c.hasActivePartial)return"listening";if(c.isRecording)return"listening";if(c.lastTranscriptAt&&!c.lastAssistantAt)return"thinking";if(c.lastTranscriptAt&&c.lastAssistantAt&&c.lastTranscriptAt>c.lastAssistantAt)return"thinking";return"idle"};var $c={accent:"#3b82f6",background:"#0f172a",errorAccent:"#ef4444",fontFamily:'ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',foreground:"#f8fafc",radius:16},Hc={callEnded:"Call ended",connecting:"Connecting…",endCall:"End call",idle:"Idle",listening:"Listening",mute:"Mute",speaking:"Speaking",startCall:"Start call",thinking:"Thinking",unmute:"Unmute"},Gc=(c,n)=>{switch(c){case"listening":return n.listening;case"speaking":return n.speaking;case"thinking":return n.thinking;case"idle":return n.idle}},v=(c)=>{let n={...$c,...c.theme},l={...Hc,...c.labels},o=c.state.assistantAudio.at(-1)?.receivedAt,i=c.state.turns.at(-1)?.committedAt,e=m({hasActivePartial:c.state.partial.length>0,isConnected:c.state.isConnected,isPlaying:!1,isRecording:c.state.isRecording,lastAssistantAt:o,lastTranscriptAt:i}),s=!c.state.isConnected&&c.state.status!=="idle"&&!c.state.error,C=c.state.error?"Error":s?l.connecting:c.state.status==="completed"?l.callEnded:Gc(e,l);return{agentState:e,classes:{container:`absolute-voice-widget absolute-voice-widget--${e}`,dot:`absolute-voice-widget__dot${c.state.error?" absolute-voice-widget__dot--error":""}`},controls:{canEnd:c.state.isConnected,canMute:c.state.isRecording,canStart:!c.state.isRecording&&c.state.status!=="completed"},errorMessage:c.state.error??void 0,labels:l,partial:c.state.partial||void 0,statusLabel:C,theme:n,title:c.title??"Voice"}},L=(c)=>c.replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;").replaceAll('"',"&quot;").replaceAll("'","&#39;"),zc=(c)=>typeof c==="number"?`${c}px`:c,u=(c)=>{let n=c.theme,l=`background:${n.background};border-radius:${zc(n.radius)};color:${n.foreground};font-family:${n.fontFamily};min-width:240px;padding:20px 22px;`,o=`background:${c.errorMessage?n.errorAccent:c.agentState==="idle"?"rgba(148,163,184,0.6)":n.accent};border-radius:50%;height:10px;width:10px;`,i=[];if(c.controls.canStart)i.push(`<button type="button" data-action="start" style="background:${n.accent};border:none;border-radius:12px;color:${n.foreground};cursor:pointer;font-size:14px;font-weight:500;padding:10px 14px;">${L(c.labels.startCall)}</button>`);if(c.controls.canMute)i.push(`<button type="button" data-action="mute" style="background:transparent;border:1px solid rgba(255,255,255,0.18);border-radius:12px;color:${n.foreground};cursor:pointer;font-size:14px;font-weight:500;padding:10px 14px;">${L(c.labels.mute)}</button>`);if(c.controls.canEnd)i.push(`<button type="button" data-action="end" style="background:${n.errorAccent};border:none;border-radius:12px;color:${n.foreground};cursor:pointer;font-size:14px;font-weight:500;padding:10px 14px;">${L(c.labels.endCall)}</button>`);return`<div role="region" aria-live="polite" data-agent-state="${c.agentState}" class="${L(c.classes.container)}" style="${l}">
2
+ <div style="align-items:center;display:flex;gap:10px;margin-bottom:12px;">
3
+ <span aria-hidden="true" class="${L(c.classes.dot)}" style="${o}"></span>
4
+ <strong style="font-size:15px;">${L(c.title)}</strong>
5
+ <span style="font-size:13px;margin-left:auto;opacity:0.7;">${L(c.statusLabel)}</span>
6
+ </div>
7
+ ${c.partial?`<p style="font-size:13px;margin:8px 0 12px;opacity:0.85;word-break:break-word;">“${L(c.partial)}”</p>`:""}
8
+ <div style="display:flex;gap:10px;">${i.join("")}</div>
9
+ ${c.errorMessage?`<p style="color:${n.errorAccent};font-size:12px;margin-top:12px;">${L(c.errorMessage)}</p>`:""}
10
+ </div>`};var Xc=(c)=>{if(typeof c!=="string")return c;let n=document.querySelector(c);if(!n)throw Error(`AbsoluteVoice.mount: no element matches "${c}"`);return n},p=(c,n={})=>{let l=Xc(c),o=F(n.path??"/voice",n.controllerOptions),i=null,e=null,s=()=>{let T=v({...n.labels!==void 0?{labels:n.labels}:{},state:{assistantAudio:o.assistantAudio,error:o.error,isConnected:o.isConnected,isRecording:o.isRecording,partial:o.partial,status:o.status,turns:o.turns},...n.theme!==void 0?{theme:n.theme}:{},...n.title!==void 0?{title:n.title}:{}});l.innerHTML=u(T);for(let S of l.querySelectorAll("button[data-action]")){let d=S.dataset.action;S.addEventListener("click",()=>{if(d==="start")o.startRecording();else if(d==="mute")o.stopRecording();else if(d==="end")o.close()})}if(o.error&&o.error!==i)i=o.error,n.onError?.(o.error);if(o.status!==e)e=o.status,n.onStatusChange?.(o.status)},C=o.subscribe(s);if(s(),n.autoStart)o.startRecording();return{controller:o,async end(){await o.close()},mute(){o.stopRecording()},async start(){await o.startRecording()},unmount(){C(),o.close(),l.innerHTML=""}}},cc="0.0.22-beta.516",nc={mount:p,version:cc};if(typeof globalThis<"u")globalThis.AbsoluteVoice=nc;var qc=nc;})();
package/dist/index.d.ts CHANGED
@@ -351,4 +351,10 @@ export { compileVoicePathwayToAssistant } from "./pathwayCompiler";
351
351
  export type { CompileVoicePathwayOptions, VoicePathwayCompiledAssistant, VoicePathwayCompilerToolDefinition, } from "./pathwayCompiler";
352
352
  export { renderVoicePathwayMermaid, renderVoicePathwayText, visualizeVoicePathway, } from "./pathwayVisualizer";
353
353
  export type { VoicePathwayVisualization } from "./pathwayVisualizer";
354
+ export { createVoiceCRMRegistry } from "./crmContract";
355
+ export type { CreateVoiceCRMRegistryOptions, VoiceCRMCallActivityInput, VoiceCRMContactSummary, VoiceCRMContract, VoiceCRMLeadInput, VoiceCRMNoteInput, VoiceCRMRegistry, VoiceCRMTaskInput, } from "./crmContract";
356
+ export { createInMemoryVoiceCallerCRMLinkCache, createVoiceCallerCRMLinker, } from "./callerCRMLinker";
357
+ export type { CreateVoiceCallerCRMLinkerOptions, VoiceCallerCRMLinkCacheStore, VoiceCallerCRMLinker, VoiceCallerCRMLinkRecord, } from "./callerCRMLinker";
358
+ export { createVoiceCRMCallLogger } from "./crmCallLogger";
359
+ export type { CreateVoiceCRMCallLoggerOptions, VoiceCRMCallLogErrorPolicy, VoiceCRMCallLogger, VoiceCRMCallLoggerInput, VoiceCRMCallLogResult, } from "./crmCallLogger";
354
360
  export * from "./types";
package/dist/index.js CHANGED
@@ -51360,6 +51360,159 @@ var visualizeVoicePathway = (pathway) => ({
51360
51360
  mermaid: renderVoicePathwayMermaid(pathway),
51361
51361
  text: renderVoicePathwayText(pathway)
51362
51362
  });
51363
+ // src/crmContract.ts
51364
+ var createVoiceCRMRegistry = (options) => {
51365
+ const byVendor = new Map;
51366
+ for (const contract of options.contracts) {
51367
+ byVendor.set(contract.vendor, contract);
51368
+ }
51369
+ const defaultVendor = options.defaultVendor ?? options.contracts[0]?.vendor ?? null;
51370
+ return {
51371
+ default() {
51372
+ return defaultVendor ? byVendor.get(defaultVendor) ?? null : null;
51373
+ },
51374
+ get(vendor) {
51375
+ return byVendor.get(vendor) ?? null;
51376
+ },
51377
+ list() {
51378
+ return Array.from(byVendor.values());
51379
+ }
51380
+ };
51381
+ };
51382
+ // src/callerCRMLinker.ts
51383
+ var cacheKeyFor = (identity, vendor) => {
51384
+ const id = identity.externalId ?? identity.phone ?? identity.email ?? "anonymous";
51385
+ return `${vendor}::${id}`;
51386
+ };
51387
+ var createInMemoryVoiceCallerCRMLinkCache = () => {
51388
+ const store = new Map;
51389
+ return {
51390
+ get: (key) => store.get(key) ?? null,
51391
+ put: (record) => {
51392
+ store.set(record.callerKey, { ...record });
51393
+ },
51394
+ remove: (key) => store.delete(key)
51395
+ };
51396
+ };
51397
+ var createVoiceCallerCRMLinker = (options) => {
51398
+ const now = options.now ?? (() => Date.now());
51399
+ const cache = options.cache ?? createInMemoryVoiceCallerCRMLinkCache();
51400
+ const staleAfter = options.staleAfterMs ?? 24 * 60 * 60 * 1000;
51401
+ const isFresh = (record) => now() - record.resolvedAt < staleAfter;
51402
+ const resolve3 = async (identity) => {
51403
+ const key = cacheKeyFor(identity, options.contract.vendor);
51404
+ const cached = await Promise.resolve(cache.get(key));
51405
+ if (cached && isFresh(cached)) {
51406
+ return cached;
51407
+ }
51408
+ let contact = null;
51409
+ let source = null;
51410
+ if (identity.phone) {
51411
+ contact = await options.contract.lookupByPhone(identity.phone);
51412
+ if (contact)
51413
+ source = "phone-lookup";
51414
+ }
51415
+ if (!contact && identity.email) {
51416
+ contact = await options.contract.lookupByEmail(identity.email);
51417
+ if (contact)
51418
+ source = "email-lookup";
51419
+ }
51420
+ if (!contact || !source)
51421
+ return null;
51422
+ const record = {
51423
+ callerKey: key,
51424
+ contact,
51425
+ contactId: contact.id,
51426
+ resolvedAt: now(),
51427
+ source,
51428
+ vendor: options.contract.vendor
51429
+ };
51430
+ await Promise.resolve(cache.put(record));
51431
+ return record;
51432
+ };
51433
+ const associate = async (identity, contact) => {
51434
+ const key = cacheKeyFor(identity, options.contract.vendor);
51435
+ const record = {
51436
+ callerKey: key,
51437
+ contact,
51438
+ contactId: contact.id,
51439
+ resolvedAt: now(),
51440
+ source: "manual",
51441
+ vendor: options.contract.vendor
51442
+ };
51443
+ await Promise.resolve(cache.put(record));
51444
+ return record;
51445
+ };
51446
+ const invalidate = async (identity) => {
51447
+ const key = cacheKeyFor(identity, options.contract.vendor);
51448
+ return Promise.resolve(cache.remove(key));
51449
+ };
51450
+ return {
51451
+ associate,
51452
+ contract: options.contract,
51453
+ invalidate,
51454
+ resolve: resolve3
51455
+ };
51456
+ };
51457
+ // src/crmCallLogger.ts
51458
+ var createVoiceCRMCallLogger = (options) => {
51459
+ const now = options.now ?? (() => Date.now());
51460
+ const errorPolicy = options.errorPolicy ?? "swallow";
51461
+ const logCallEnd = async (input) => {
51462
+ const endedAt = input.endedAt ?? now();
51463
+ const duration = input.durationSeconds ?? Math.max(0, Math.round((endedAt - input.startedAt) / 1000));
51464
+ const payload = {
51465
+ durationSeconds: duration,
51466
+ endedAt,
51467
+ sessionId: input.sessionId,
51468
+ startedAt: input.startedAt,
51469
+ ...input.contactId !== undefined ? { contactId: input.contactId } : {},
51470
+ ...input.summary !== undefined ? { summary: input.summary } : {},
51471
+ ...input.disposition !== undefined ? { disposition: input.disposition } : {},
51472
+ ...input.recordingUrl !== undefined ? { recordingUrl: input.recordingUrl } : {},
51473
+ ...input.transcriptUrl !== undefined ? { transcriptUrl: input.transcriptUrl } : {},
51474
+ ...input.metadata !== undefined ? { metadata: input.metadata } : {}
51475
+ };
51476
+ try {
51477
+ const result = await options.contract.logCall(payload);
51478
+ return {
51479
+ activityId: result.activityId,
51480
+ loggedAt: now(),
51481
+ vendor: options.contract.vendor
51482
+ };
51483
+ } catch (rawError) {
51484
+ const error = rawError instanceof Error ? rawError : new Error(String(rawError));
51485
+ await options.onError?.(error, input);
51486
+ if (errorPolicy === "queue") {
51487
+ await options.enqueueOnFailure?.(input);
51488
+ return null;
51489
+ }
51490
+ if (errorPolicy === "throw")
51491
+ throw error;
51492
+ return null;
51493
+ }
51494
+ };
51495
+ const noteOnContact = async (input) => {
51496
+ try {
51497
+ return await options.contract.addNote(input);
51498
+ } catch (rawError) {
51499
+ const error = rawError instanceof Error ? rawError : new Error(String(rawError));
51500
+ await options.onError?.(error, {
51501
+ sessionId: "(note)",
51502
+ startedAt: now(),
51503
+ ...input
51504
+ });
51505
+ if (errorPolicy === "throw")
51506
+ throw error;
51507
+ return null;
51508
+ }
51509
+ };
51510
+ return {
51511
+ contract: options.contract,
51512
+ logCallEnd,
51513
+ noteOnContact
51514
+ };
51515
+ };
51363
51516
  export {
51364
51517
  writeVoiceProofPack,
51365
51518
  writeVoiceMediaPipelineArtifacts,
@@ -52031,6 +52184,7 @@ export {
52031
52184
  createVoiceCampaign,
52032
52185
  createVoiceCallingWindow,
52033
52186
  createVoiceCallerMemoryNamespace,
52187
+ createVoiceCallerCRMLinker,
52034
52188
  createVoiceCallReviewRecorder,
52035
52189
  createVoiceCallReviewFromSession,
52036
52190
  createVoiceCallReviewFromLiveTelephonyReport,
@@ -52038,6 +52192,8 @@ export {
52038
52192
  createVoiceCallDispositionTagger,
52039
52193
  createVoiceCallDebuggerRoutes,
52040
52194
  createVoiceCallCompletedEvent,
52195
+ createVoiceCRMRegistry,
52196
+ createVoiceCRMCallLogger,
52041
52197
  createVoiceCRMActivitySink,
52042
52198
  createVoiceBrowserMediaRoutes,
52043
52199
  createVoiceBrowserCallProfileRoutes,
@@ -52098,6 +52254,7 @@ export {
52098
52254
  createLiveCallViewerFromOptions,
52099
52255
  createLiveCallViewer,
52100
52256
  createJSONVoiceAssistantModel,
52257
+ createInMemoryVoiceCallerCRMLinkCache,
52101
52258
  createInMemoryVoiceCallQuota,
52102
52259
  createInMemoryDNCList,
52103
52260
  createId,
@@ -71,7 +71,7 @@ export declare const VoiceWidget: import("vue").DefineComponent<import("vue").Ex
71
71
  }>, {
72
72
  title: string;
73
73
  path: string;
74
+ labels: VoiceWidgetLabels;
74
75
  theme: VoiceWidgetTheme;
75
76
  controllerOptions: VoiceControllerOptions;
76
- labels: VoiceWidgetLabels;
77
77
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.514",
3
+ "version": "0.0.22-beta.516",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",
@@ -160,7 +160,7 @@
160
160
  "bench:stt": "bun run ./scripts/benchmark-stt.ts all",
161
161
  "bench:assemblyai:sessions": "bun run ./scripts/benchmark-session.ts assemblyai",
162
162
  "bench:openai:sessions": "bun run ./scripts/benchmark-session.ts openai",
163
- "build": "bun run ./scripts/build-htmx-bootstrap-asset.ts && rm -rf dist && bun build ./src/index.ts ./src/client/index.ts ./src/react/index.ts ./src/vue/index.ts ./src/svelte/index.ts ./src/angular/index.ts ./src/testing/index.ts --outdir dist --target bun --external elysia --external react --external vue --external @angular/core --external @absolutejs/absolute --external @absolutejs/ai --external @absolutejs/media && bun build ./src/client/htmxBootstrap.ts --outdir dist/client --target browser --format esm && tsc --emitDeclarationOnly --project tsconfig.json",
163
+ "build": "bun run ./scripts/build-htmx-bootstrap-asset.ts && rm -rf dist && bun build ./src/index.ts ./src/client/index.ts ./src/react/index.ts ./src/vue/index.ts ./src/svelte/index.ts ./src/angular/index.ts ./src/testing/index.ts --outdir dist --target bun --external elysia --external react --external vue --external @angular/core --external @absolutejs/absolute --external @absolutejs/ai --external @absolutejs/media && bun build ./src/client/htmxBootstrap.ts --outdir dist/client --target browser --format esm && bun build ./src/embed/index.ts --outfile dist/embed/voice-widget.js --target browser --format iife --minify && bun build ./src/embed/index.ts --outdir dist/embed --target browser --format esm && tsc --emitDeclarationOnly --project tsconfig.json",
164
164
  "format": "prettier --write \"./**/*.{js,jsx,ts,tsx,json,md}\"",
165
165
  "lint": "eslint ./src",
166
166
  "release": "bun run format && bun run build && bun publish",
@@ -203,7 +203,13 @@
203
203
  "./testing": {
204
204
  "import": "./dist/testing/index.js",
205
205
  "types": "./dist/testing/index.d.ts"
206
- }
206
+ },
207
+ "./embed": {
208
+ "browser": "./dist/embed/index.js",
209
+ "import": "./dist/embed/index.js",
210
+ "types": "./dist/embed/index.d.ts"
211
+ },
212
+ "./embed/voice-widget.js": "./dist/embed/voice-widget.js"
207
213
  },
208
214
  "typesVersions": {
209
215
  "*": {
@@ -224,6 +230,9 @@
224
230
  ],
225
231
  "angular": [
226
232
  "dist/angular/index.d.ts"
233
+ ],
234
+ "embed": [
235
+ "dist/embed/index.d.ts"
227
236
  ]
228
237
  }
229
238
  },