@vanira/sdk 0.0.23 → 0.0.25

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.
@@ -1,11 +1,11 @@
1
- var we=Object.defineProperty;var ue=(f,C,b)=>C in f?we(f,C,{enumerable:!0,configurable:!0,writable:!0,value:b}):f[C]=b;var o=(f,C,b)=>ue(f,typeof C!="symbol"?C+"":C,b);(function(){"use strict";var f=typeof document<"u"?document.currentScript:null;const C="https://vaniraapi.travelr.club";class b{static async fetchWidgetConfig(t,e){var s;const i={"Content-Type":"application/json"};e&&(i["X-API-Key"]=e);try{const n=await fetch(`${C}/assistant/widget/${t}/config`,{method:"GET",headers:i});if(!n.ok)throw new Error(`Widget config fetch failed: HTTP ${n.status}`);const a=await n.json();return(s=a.agent)!=null&&s.client&&(a.client=a.agent.client),a}catch(n){throw console.error("[VaniraAI] Failed to fetch widget config:",n),n}}}const q="https://coredb.travelr.club/v1/graphql";let k="https://inboxapi.travelr.club";class v{static setChatUrl(t){k=t}static async createChatProspect(t){var i,s;const e=`
1
+ var we=Object.defineProperty;var ue=(f,C,b)=>C in f?we(f,C,{enumerable:!0,configurable:!0,writable:!0,value:b}):f[C]=b;var o=(f,C,b)=>ue(f,typeof C!="symbol"?C+"":C,b);(function(){"use strict";var f=typeof document<"u"?document.currentScript:null;const C="https://api.vanira.io";class b{static async fetchWidgetConfig(t,e){var s;const i={"Content-Type":"application/json"};e&&(i["X-API-Key"]=e);try{const n=await fetch(`${C}/assistant/widget/${t}/config`,{method:"GET",headers:i});if(!n.ok)throw new Error(`Widget config fetch failed: HTTP ${n.status}`);const a=await n.json();return(s=a.agent)!=null&&s.client&&(a.client=a.agent.client),a}catch(n){throw console.error("[VaniraAI] Failed to fetch widget config:",n),n}}}const q="https://coredb.travelr.club/v1/graphql";let k="https://inboxapi.travelr.club";class v{static setChatUrl(t){k=t}static async createChatProspect(t){var i,s;const e=`
2
2
  mutation CreateChatProspect($prospectGroupId: uuid!, $name: String!) {
3
3
  insert_prospects_one(object: {prospect_group_id: $prospectGroupId, name: $name, source: WEBSITE_WIDGET}) {
4
4
  id
5
5
  }
6
6
  }
7
- `;try{const a=await(await fetch(q,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({query:e,variables:{prospectGroupId:t,name:`Widget Guest ${new Date().toLocaleString()}`}})})).json();return a.errors?(console.warn("[VaniraAI] Prospect creation failed, using anonymous ID",a.errors),`anon_${Date.now()}_${Math.random().toString(36).substr(2,9)}`):((s=(i=a.data)==null?void 0:i.insert_prospects_one)==null?void 0:s.id)||`anon_${Date.now()}`}catch(n){return console.error("[VaniraAI] Failed to create prospect:",n),`anon_${Date.now()}`}}static async fetchWelcomeMessage(t,e,i){try{const s=await fetch(`${k}/widget/chat`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({agent_id:t,...i?{widget_id:i}:{},message:"",prospect_id:e,stream:!1})});if(!s.ok)throw new Error("Failed to fetch welcome message");const n=await s.json();let a=n.response||"Hey! how can I help you ?",r;const l=n.chat_id||n.inbox_id;return n.widget&&(r=n.widget),{role:"assistant",content:a,widget:r,chatId:l}}catch(s){return console.error("[VaniraAI] Failed to fetch welcome message:",s),{role:"assistant",content:"Hey! how can I help you ?"}}}static async sendChatMessage(t,e,i,s,n,a,r,l){var c,A,d,g;try{const w={agent_id:t,message:i,prospect_id:e,stream:!0};s&&(w.inbox_id=s),l&&(w.widget_id=l);const p=await fetch(`${k}/widget/chat`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(w)});if(!p.ok)throw new Error("Chat request failed");const E=(c=p.body)==null?void 0:c.getReader(),x=new TextDecoder;if(!E)throw new Error("No reader");let M="",Q="",D=null;for(;;){const{done:he,value:ge}=await E.read();if(he)break;Q+=x.decode(ge,{stream:!0});const F=Q.split(`
8
- `);Q=F.pop()||"";for(const pe of F){const Y=pe.trim();if(Y&&Y.startsWith("data: ")){const K=Y.slice(6);if(K==="[DONE]"){r(D);return}try{const y=JSON.parse(K);if(y.type==="metadata"&&y.chat_id){D=y.chat_id;continue}const Z=(g=(d=(A=y.choices)==null?void 0:A[0])==null?void 0:d.delta)==null?void 0:g.content;Z&&(M+=Z,n(M)),y.widget&&a(y.widget),y.chat_id&&!D&&(D=y.chat_id)}catch{}}}}r(D)}catch(w){console.error("[VaniraAI] Chat error:",w),n("Sorry, I encountered an error. Please try again."),r(null)}}static listenForAdminReplies(t,e,i){const s=`${k}/inbox/stream?inbox_id=${t}&sender=${encodeURIComponent(e)}`;let n=null,a=0,r=!1;const l=()=>{r||(n=new EventSource(s),console.log(`[VaniraAI] Subscribed to SSE EventSource at ${n.url}`),n.onopen=()=>{console.log("[VaniraAI] SSE connection opened successfully."),a=0},n.onmessage=c=>{console.log("[VaniraAI] 📡 Raw SSE Event triggered:",c.data);try{const A=JSON.parse(c.data);console.log("[VaniraAI] SSE stream JSON parsed:",A);const d=A.direction==="outgoing",g=!!A.content,w=A.source!=="ai";d&&g&&w&&(console.log("[VaniraAI] đŸŽ¯ Displaying admin message in chat UI:",A.content),i(A.content))}catch(A){console.error("[VaniraAI] SSE parse error",A)}},n.onerror=c=>{if(console.error("[VaniraAI] SSE connection error or disconnect",c),n&&(n.close(),n=null),r)return;const A=Math.min(2e3*Math.pow(2,a),3e4);console.log(`[VaniraAI] Reconnecting SSE in ${A}ms (Attempt ${a+1})...`),a++,setTimeout(l,A)})};return l(),{close:()=>{r=!0,n&&(n.close(),n=null,console.log("[VaniraAI] SSE connection manually closed."))}}}static async createCall(t,e,i,s,n){try{const a="https://vaniraapi.travelr.club",r={"Content-Type":"application/json"};n&&(r["X-API-Key"]=n);const l=await fetch(`${a}/calls/create`,{method:"POST",headers:r,body:JSON.stringify({agent_id:t,prospect_id:i||void 0,type:"web"})}),c=await l.json();if(!l.ok)throw new Error(`[VaniraAI] Call creation failed HTTP ${l.status}`);if(!c.worker_url)throw new Error("[VaniraAI] Worker URL missing from response. Call cannot proceed.");let A;try{A=new URL(c.worker_url).origin}catch{A=c.worker_url}return{callId:c.call_id||c.id||`web_${Date.now()}`,workerUrl:A}}catch(a){throw console.error("[VaniraAI] Failed to create call:",a),a}}}class _{constructor(t){o(this,"config");o(this,"root",null);this.config=t}async initialize(t){this.config=t}}class ${constructor(t){o(this,"serverUrl");o(this,"agentId");o(this,"callId");o(this,"onConnected");o(this,"onDisconnected");o(this,"onError");o(this,"onTranscription");o(this,"onRemoteTrack");o(this,"onClientToolCall");o(this,"pc",null);o(this,"dataChannel",null);o(this,"audioElement",null);o(this,"connected",!1);if(!t.serverUrl)throw new Error("serverUrl is required");if(!t.agentId)throw new Error("agentId is required");this.serverUrl=t.serverUrl.replace(/\/$/,""),this.agentId=t.agentId,this.callId=t.callId||this.generateCallId(),this.onConnected=t.onConnected||(()=>{}),this.onDisconnected=t.onDisconnected||(()=>{}),this.onError=t.onError||(e=>console.error("[WebRTC]",e)),this.onTranscription=t.onTranscription||(()=>{}),this.onRemoteTrack=t.onRemoteTrack||(()=>{}),this.onClientToolCall=t.onClientToolCall||(()=>{})}async connect(){console.log("đŸ”ĩ [WebRTC] Starting connection...");try{this.pc=new RTCPeerConnection({iceServers:[{urls:"stun:stun.l.google.com:19302"},{urls:"stun:stun1.l.google.com:19302"},{urls:"stun:global.relay.metered.ca:80"},{urls:["turns:global.relay.metered.ca:443?transport=tcp","turn:global.relay.metered.ca:443?transport=tcp","turn:global.relay.metered.ca:80?transport=tcp"],username:"fa97658be3343d21da3b65e6",credential:"HXHDoqeHbvZrmCuf"}],iceTransportPolicy:"all"}),console.log("using ice servers:",[{urls:"stun:stun.l.google.com:19302"},{urls:"stun:stun1.l.google.com:19302"}]);const t=await navigator.mediaDevices.getUserMedia({audio:{echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0,sampleRate:{ideal:16e3},channelCount:1}});if(console.log("🎤 [WebRTC] Microphone access granted"),!this.pc){console.log("[WebRTC] Connection aborted: peer connection closed during setup"),t.getTracks().forEach(a=>a.stop());return}if(t.getTracks().forEach(a=>{var r;(r=this.pc)==null||r.addTrack(a,t)}),!this.pc)throw new Error("RTCPeerConnection was closed unexpectedly");this.dataChannel=this.pc.createDataChannel("control"),this.dataChannel.onopen=()=>console.log("📡 [WebRTC] DataChannel opened"),this.dataChannel.onmessage=a=>{if(typeof a.data=="string")try{this.handleControlEvent(JSON.parse(a.data))}catch{console.warn("[WebRTC] Failed to parse message:",a.data)}else if(a.data instanceof ArrayBuffer)try{const r=new TextDecoder().decode(a.data);try{const l=JSON.parse(r);l&&typeof l=="object"&&l.event==="client_tool_call"?(console.log("[VaniraAI] Safely decoding binary tool_call to JSON:",l),this.handleControlEvent(l)):console.log("[VaniraAI] Decoded JSON from binary (inspect only):",l)}catch{console.log("[VaniraAI] Decoded String from binary:",r)}}catch{console.log("[VaniraAI] Received binary data:",a.data.byteLength,"bytes (not decodable)")}else a.data instanceof Blob&&a.data.text().then(r=>{try{this.handleControlEvent(JSON.parse(r))}catch{console.warn("[WebRTC] Failed to parse blob data:",r)}})},this.dataChannel.onerror=a=>console.error("❌ [WebRTC] DataChannel error:",a),this.pc.ontrack=a=>{const r=a.track,l=a.streams[0];console.log(`đŸ“Ĩ [WebRTC] Received ${r.kind} track`),r.kind==="audio"?(console.log("🔊 [WebRTC] Received audio track from server"),this.audioElement=new Audio,this.audioElement.srcObject=l,this.audioElement.play().catch(c=>console.warn("Audio autoplay blocked:",c)),this.audioElement.onended=()=>{this.sendEvent("playedStream"),console.log("✅ [WebRTC] TTS playback complete")}):r.kind==="video"&&(console.log("📹 [WebRTC] Video track received"),this.onRemoteTrack(r,l))};const e=()=>{var l,c,A,d,g,w,p,E,x,M,Q;console.log("🔄 [WebRTC] State:",(l=this.pc)==null?void 0:l.connectionState,"| ICE:",(c=this.pc)==null?void 0:c.iceConnectionState);const a=((A=this.pc)==null?void 0:A.connectionState)==="connected"||((d=this.pc)==null?void 0:d.iceConnectionState)==="connected"||((g=this.pc)==null?void 0:g.iceConnectionState)==="completed",r=((w=this.pc)==null?void 0:w.connectionState)==="failed"||((p=this.pc)==null?void 0:p.iceConnectionState)==="failed"||((E=this.pc)==null?void 0:E.connectionState)==="closed"||((x=this.pc)==null?void 0:x.iceConnectionState)==="closed"||((M=this.pc)==null?void 0:M.connectionState)==="disconnected"||((Q=this.pc)==null?void 0:Q.iceConnectionState)==="disconnected";a&&!this.connected?(this.connected=!0,this.onConnected()):r&&this.connected&&(this.connected=!1,this.onDisconnected())};this.pc.onconnectionstatechange=e,this.pc.oniceconnectionstatechange=e;const i=await this.pc.createOffer();await this.pc.setLocalDescription(i),console.log("📝 [WebRTC] Created offer, waiting for ICE gathering..."),await this.waitForIceGathering(),console.log("🧊 [WebRTC] ICE gathering complete"),console.log("📤 [WebRTC] Sending offer via HTTP...");const s=await fetch(`${this.serverUrl}/webrtc?agent=${this.agentId}_${this.callId}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({offer:this.pc.localDescription,agentId:this.agentId,callId:this.callId})});if(!s.ok){const a=await s.json();throw new Error(a.error||`HTTP ${s.status}`)}const{answer:n}=await s.json();console.log("đŸ“Ĩ [WebRTC] Received answer from server"),await this.pc.setRemoteDescription(n),console.log("✅ [WebRTC] Connection established!")}catch(t){throw console.error("❌ [WebRTC] Connection failed:",t),this.disconnect(),this.onError(t.message||t),t}}waitForIceGathering(){return new Promise(t=>{if(!this.pc)return t();if(this.pc.iceGatheringState==="complete")t();else{const e=()=>{var i,s;((i=this.pc)==null?void 0:i.iceGatheringState)==="complete"&&((s=this.pc)==null||s.removeEventListener("icegatheringstatechange",e),t())};this.pc.addEventListener("icegatheringstatechange",e),setTimeout(()=>{var i;(i=this.pc)==null||i.removeEventListener("icegatheringstatechange",e),console.warn("âš ī¸ [WebRTC] ICE gathering timeout, proceeding anyway"),t()},5e3)}})}sendEvent(t,e={}){var i;((i=this.dataChannel)==null?void 0:i.readyState)==="open"&&this.dataChannel.send(JSON.stringify({event:t,...e}))}handleControlEvent(t){var e;switch(t.event){case"clearAudio":console.log("🛑 [WebRTC] Interrupt: clearAudio received (leaving stream unpaused)");break;case"transcription":console.log("📝 [WebRTC] Transcription:",t.text),this.onTranscription(t.text,t.isFinal);break;case"mark":console.log("đŸˇī¸ [WebRTC] Mark:",t.name);break;case"client_tool_call":{const i=t.tool_call||t.data||t,s=(i==null?void 0:i.tool_call_id)||(i==null?void 0:i.call_id)||t.tool_call_id||"";s&&((e=this.dataChannel)==null?void 0:e.readyState)==="open"?(this.dataChannel.send(JSON.stringify({event:"client_tool_ack",data:{tool_call_id:s}})),console.log("✅ [VaniraAI] Sent client_tool_ack for:",s)):s||console.warn("âš ī¸ [VaniraAI] client_tool_call received without tool_call_id — ack skipped"),console.log("đŸ› ī¸ [VaniraAI] Client Tool Call:",t),this.onClientToolCall(i);break}default:console.log("â„šī¸ [WebRTC] Unknown event:",t.event)}}disconnect(){console.log("🔴 [WebRTC] Disconnecting..."),this.audioElement&&(this.audioElement.pause(),this.audioElement.srcObject=null),this.dataChannel&&(this.dataChannel.close(),this.dataChannel=null),this.pc&&(this.pc.getSenders().forEach(t=>{t.track&&t.track.stop()}),this.pc.close(),this.pc=null),this.connected=!1,this.onDisconnected()}generateCallId(){return"web_"+Date.now()+"_"+Math.random().toString(36).substr(2,8)}sendToolResult(t,e){this.sendEvent("client_tool_result",{call_id:t,result:e})}sendToolAck(t){var e;((e=this.dataChannel)==null?void 0:e.readyState)==="open"?(this.dataChannel.send(JSON.stringify({event:"client_tool_ack",data:{tool_call_id:t}})),console.log("✅ [VaniraAI] Sent client_tool_ack for:",t)):console.warn("âš ī¸ [VaniraAI] Cannot send tool_ack: DataChannel not open")}sendContextUpdate(t){this.sendEvent("client_context_update",{data:{context:t}})}sendActionTrigger(t,e={}){this.sendEvent("client_action_trigger",{data:{action_name:t,data:e}})}triggerActionInterrupt(){this.sendEvent("action_interrupt"),console.log("🛑 [VaniraAI] Triggered client-side action interrupt")}static async fetchIceServers(t,e="https://coredb.travelr.club/v1/graphql"){var i;try{const n=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json",Authorization:t},body:JSON.stringify({query:`
7
+ `;try{const a=await(await fetch(q,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({query:e,variables:{prospectGroupId:t,name:`Widget Guest ${new Date().toLocaleString()}`}})})).json();return a.errors?(console.warn("[VaniraAI] Prospect creation failed, using anonymous ID",a.errors),`anon_${Date.now()}_${Math.random().toString(36).substr(2,9)}`):((s=(i=a.data)==null?void 0:i.insert_prospects_one)==null?void 0:s.id)||`anon_${Date.now()}`}catch(n){return console.error("[VaniraAI] Failed to create prospect:",n),`anon_${Date.now()}`}}static async fetchWelcomeMessage(t,e,i){try{const s=await fetch(`${k}/widget/chat`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({agent_id:t,...i?{widget_id:i}:{},message:"",prospect_id:e,stream:!1})});if(!s.ok)throw new Error("Failed to fetch welcome message");const n=await s.json();let a=n.response||"Hey! how can I help you ?",r;const l=n.chat_id||n.inbox_id;return n.widget&&(r=n.widget),{role:"assistant",content:a,widget:r,chatId:l}}catch(s){return console.error("[VaniraAI] Failed to fetch welcome message:",s),{role:"assistant",content:"Hey! how can I help you ?"}}}static async sendChatMessage(t,e,i,s,n,a,r,l){var c,A,d,g;try{const w={agent_id:t,message:i,prospect_id:e,stream:!0};s&&(w.inbox_id=s),l&&(w.widget_id=l);const p=await fetch(`${k}/widget/chat`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(w)});if(!p.ok)throw new Error("Chat request failed");const E=(c=p.body)==null?void 0:c.getReader(),x=new TextDecoder;if(!E)throw new Error("No reader");let M="",Q="",D=null;for(;;){const{done:he,value:ge}=await E.read();if(he)break;Q+=x.decode(ge,{stream:!0});const K=Q.split(`
8
+ `);Q=K.pop()||"";for(const pe of K){const Y=pe.trim();if(Y&&Y.startsWith("data: ")){const F=Y.slice(6);if(F==="[DONE]"){r(D);return}try{const y=JSON.parse(F);if(y.type==="metadata"&&y.chat_id){D=y.chat_id;continue}const Z=(g=(d=(A=y.choices)==null?void 0:A[0])==null?void 0:d.delta)==null?void 0:g.content;Z&&(M+=Z,n(M)),y.widget&&a(y.widget),y.chat_id&&!D&&(D=y.chat_id)}catch{}}}}r(D)}catch(w){console.error("[VaniraAI] Chat error:",w),n("Sorry, I encountered an error. Please try again."),r(null)}}static listenForAdminReplies(t,e,i){const s=`${k}/inbox/stream?inbox_id=${t}&sender=${encodeURIComponent(e)}`;let n=null,a=0,r=!1;const l=()=>{r||(n=new EventSource(s),console.log(`[VaniraAI] Subscribed to SSE EventSource at ${n.url}`),n.onopen=()=>{console.log("[VaniraAI] SSE connection opened successfully."),a=0},n.onmessage=c=>{console.log("[VaniraAI] 📡 Raw SSE Event triggered:",c.data);try{const A=JSON.parse(c.data);console.log("[VaniraAI] SSE stream JSON parsed:",A);const d=A.direction==="outgoing",g=!!A.content,w=A.source!=="ai";d&&g&&w&&(console.log("[VaniraAI] đŸŽ¯ Displaying admin message in chat UI:",A.content),i(A.content))}catch(A){console.error("[VaniraAI] SSE parse error",A)}},n.onerror=c=>{if(console.error("[VaniraAI] SSE connection error or disconnect",c),n&&(n.close(),n=null),r)return;const A=Math.min(2e3*Math.pow(2,a),3e4);console.log(`[VaniraAI] Reconnecting SSE in ${A}ms (Attempt ${a+1})...`),a++,setTimeout(l,A)})};return l(),{close:()=>{r=!0,n&&(n.close(),n=null,console.log("[VaniraAI] SSE connection manually closed."))}}}static async createCall(t,e,i,s,n){try{const a="https://api.vanira.io",r={"Content-Type":"application/json"};n&&(r["X-API-Key"]=n);const l=await fetch(`${a}/calls/create`,{method:"POST",headers:r,body:JSON.stringify({agent_id:t,prospect_id:i||void 0,type:"web"})}),c=await l.json();if(!l.ok)throw new Error(`[VaniraAI] Call creation failed HTTP ${l.status}`);if(!c.worker_url)throw new Error("[VaniraAI] Worker URL missing from response. Call cannot proceed.");let A;try{A=new URL(c.worker_url).origin}catch{A=c.worker_url}return{callId:c.call_id||c.id||`web_${Date.now()}`,workerUrl:A}}catch(a){throw console.error("[VaniraAI] Failed to create call:",a),a}}}class _{constructor(t){o(this,"config");o(this,"root",null);this.config=t}async initialize(t){this.config=t}}class ${constructor(t){o(this,"serverUrl");o(this,"agentId");o(this,"callId");o(this,"apiKey");o(this,"backendUrl");o(this,"onConnected");o(this,"onDisconnected");o(this,"onError");o(this,"onTranscription");o(this,"onRemoteTrack");o(this,"onClientToolCall");o(this,"pc",null);o(this,"dataChannel",null);o(this,"audioElement",null);o(this,"connected",!1);if(!t.agentId)throw new Error("agentId is required");if(!t.serverUrl&&!t.apiKey)throw new Error("Provide either serverUrl or apiKey (to use createCall())");this.agentId=t.agentId,this.serverUrl=t.serverUrl?t.serverUrl.replace(/\/$/,""):"",this.callId=t.callId||this.generateCallId(),this.apiKey=t.apiKey,this.backendUrl=(t.backendUrl||"https://api.vanira.io").replace(/\/$/,""),this.onConnected=t.onConnected||(()=>{}),this.onDisconnected=t.onDisconnected||(()=>{}),this.onError=t.onError||(e=>console.error("[WebRTC]",e)),this.onTranscription=t.onTranscription||(()=>{}),this.onRemoteTrack=t.onRemoteTrack||(()=>{}),this.onClientToolCall=t.onClientToolCall||(()=>{})}async createCall(){var s;if(!this.apiKey)throw new Error("[VaniraAI] apiKey is required to use createCall()");const t={"Content-Type":"application/json","X-API-Key":this.apiKey},e=await fetch(`${this.backendUrl}/calls/create`,{method:"POST",headers:t,body:JSON.stringify({agent_id:this.agentId,type:"web"})});if(!e.ok){const n=await e.json().catch(()=>({}));throw new Error(`[VaniraAI] createCall failed (${e.status}): ${((s=n==null?void 0:n.detail)==null?void 0:s.message)||(n==null?void 0:n.message)||e.statusText}`)}const i=await e.json();if(!i.call_id||!i.worker_url)throw new Error("[VaniraAI] createCall response missing call_id or worker_url");this.callId=i.call_id,this.serverUrl=i.worker_url.replace(/\/$/,""),await this.connect()}async connect(){if(this.apiKey&&!this.serverUrl){await this.createCall();return}if(!this.serverUrl)throw new Error("[VaniraAI] serverUrl is missing. Provide apiKey or serverUrl.");console.log("đŸ”ĩ [WebRTC] Starting connection...");try{this.pc=new RTCPeerConnection({iceServers:[{urls:"stun:stun.l.google.com:19302"},{urls:"stun:stun1.l.google.com:19302"},{urls:"stun:global.relay.metered.ca:80"},{urls:["turns:global.relay.metered.ca:443?transport=tcp","turn:global.relay.metered.ca:443?transport=tcp","turn:global.relay.metered.ca:80?transport=tcp"],username:"fa97658be3343d21da3b65e6",credential:"HXHDoqeHbvZrmCuf"}],iceTransportPolicy:"all"}),console.log("using ice servers:",[{urls:"stun:stun.l.google.com:19302"},{urls:"stun:stun1.l.google.com:19302"}]);const t=await navigator.mediaDevices.getUserMedia({audio:{echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0,sampleRate:{ideal:16e3},channelCount:1}});if(console.log("🎤 [WebRTC] Microphone access granted"),!this.pc){console.log("[WebRTC] Connection aborted: peer connection closed during setup"),t.getTracks().forEach(a=>a.stop());return}if(t.getTracks().forEach(a=>{var r;(r=this.pc)==null||r.addTrack(a,t)}),!this.pc)throw new Error("RTCPeerConnection was closed unexpectedly");this.dataChannel=this.pc.createDataChannel("control"),this.dataChannel.onopen=()=>console.log("📡 [WebRTC] DataChannel opened"),this.dataChannel.onmessage=a=>{if(typeof a.data=="string")try{this.handleControlEvent(JSON.parse(a.data))}catch{console.warn("[WebRTC] Failed to parse message:",a.data)}else if(a.data instanceof ArrayBuffer)try{const r=new TextDecoder().decode(a.data);try{const l=JSON.parse(r);l&&typeof l=="object"&&l.event==="client_tool_call"?(console.log("[VaniraAI] Safely decoding binary tool_call to JSON:",l),this.handleControlEvent(l)):console.log("[VaniraAI] Decoded JSON from binary (inspect only):",l)}catch{console.log("[VaniraAI] Decoded String from binary:",r)}}catch{console.log("[VaniraAI] Received binary data:",a.data.byteLength,"bytes (not decodable)")}else a.data instanceof Blob&&a.data.text().then(r=>{try{this.handleControlEvent(JSON.parse(r))}catch{console.warn("[WebRTC] Failed to parse blob data:",r)}})},this.dataChannel.onerror=a=>console.error("❌ [WebRTC] DataChannel error:",a),this.pc.ontrack=a=>{const r=a.track,l=a.streams[0];console.log(`đŸ“Ĩ [WebRTC] Received ${r.kind} track`),r.kind==="audio"?(console.log("🔊 [WebRTC] Received audio track from server"),this.audioElement=new Audio,this.audioElement.srcObject=l,this.audioElement.play().catch(c=>console.warn("Audio autoplay blocked:",c)),this.audioElement.onended=()=>{this.sendEvent("playedStream"),console.log("✅ [WebRTC] TTS playback complete")}):r.kind==="video"&&(console.log("📹 [WebRTC] Video track received"),this.onRemoteTrack(r,l))};const e=()=>{var l,c,A,d,g,w,p,E,x,M,Q;console.log("🔄 [WebRTC] State:",(l=this.pc)==null?void 0:l.connectionState,"| ICE:",(c=this.pc)==null?void 0:c.iceConnectionState);const a=((A=this.pc)==null?void 0:A.connectionState)==="connected"||((d=this.pc)==null?void 0:d.iceConnectionState)==="connected"||((g=this.pc)==null?void 0:g.iceConnectionState)==="completed",r=((w=this.pc)==null?void 0:w.connectionState)==="failed"||((p=this.pc)==null?void 0:p.iceConnectionState)==="failed"||((E=this.pc)==null?void 0:E.connectionState)==="closed"||((x=this.pc)==null?void 0:x.iceConnectionState)==="closed"||((M=this.pc)==null?void 0:M.connectionState)==="disconnected"||((Q=this.pc)==null?void 0:Q.iceConnectionState)==="disconnected";a&&!this.connected?(this.connected=!0,this.onConnected()):r&&this.connected&&(this.connected=!1,this.onDisconnected())};this.pc.onconnectionstatechange=e,this.pc.oniceconnectionstatechange=e;const i=await this.pc.createOffer();await this.pc.setLocalDescription(i),console.log("📝 [WebRTC] Created offer, waiting for ICE gathering..."),await this.waitForIceGathering(),console.log("🧊 [WebRTC] ICE gathering complete"),console.log("📤 [WebRTC] Sending offer via HTTP...");const s=await fetch(`${this.serverUrl}/webrtc?agent=${this.agentId}_${this.callId}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({offer:this.pc.localDescription,agentId:this.agentId,callId:this.callId})});if(!s.ok){const a=await s.json();throw new Error(a.error||`HTTP ${s.status}`)}const{answer:n}=await s.json();console.log("đŸ“Ĩ [WebRTC] Received answer from server"),await this.pc.setRemoteDescription(n),console.log("✅ [WebRTC] Connection established!")}catch(t){throw console.error("❌ [WebRTC] Connection failed:",t),this.disconnect(),this.onError(t.message||t),t}}waitForIceGathering(){return new Promise(t=>{if(!this.pc)return t();if(this.pc.iceGatheringState==="complete")t();else{const e=()=>{var i,s;((i=this.pc)==null?void 0:i.iceGatheringState)==="complete"&&((s=this.pc)==null||s.removeEventListener("icegatheringstatechange",e),t())};this.pc.addEventListener("icegatheringstatechange",e),setTimeout(()=>{var i;(i=this.pc)==null||i.removeEventListener("icegatheringstatechange",e),console.warn("âš ī¸ [WebRTC] ICE gathering timeout, proceeding anyway"),t()},5e3)}})}sendEvent(t,e={}){var i;((i=this.dataChannel)==null?void 0:i.readyState)==="open"&&this.dataChannel.send(JSON.stringify({event:t,...e}))}handleControlEvent(t){var e;switch(t.event){case"clearAudio":console.log("🛑 [WebRTC] Interrupt: clearAudio received (leaving stream unpaused)");break;case"transcription":console.log("📝 [WebRTC] Transcription:",t.text),this.onTranscription(t.text,t.isFinal);break;case"mark":console.log("đŸˇī¸ [WebRTC] Mark:",t.name);break;case"client_tool_call":{const i=t.tool_call||t.data||t,s=(i==null?void 0:i.tool_call_id)||(i==null?void 0:i.call_id)||t.tool_call_id||"";s&&((e=this.dataChannel)==null?void 0:e.readyState)==="open"?(this.dataChannel.send(JSON.stringify({event:"client_tool_ack",data:{tool_call_id:s}})),console.log("✅ [VaniraAI] Sent client_tool_ack for:",s)):s||console.warn("âš ī¸ [VaniraAI] client_tool_call received without tool_call_id — ack skipped"),console.log("đŸ› ī¸ [VaniraAI] Client Tool Call:",t),this.onClientToolCall(i);break}default:console.log("â„šī¸ [WebRTC] Unknown event:",t.event)}}disconnect(){console.log("🔴 [WebRTC] Disconnecting..."),this.audioElement&&(this.audioElement.pause(),this.audioElement.srcObject=null),this.dataChannel&&(this.dataChannel.close(),this.dataChannel=null),this.pc&&(this.pc.getSenders().forEach(t=>{t.track&&t.track.stop()}),this.pc.close(),this.pc=null),this.connected=!1,this.onDisconnected()}generateCallId(){return"web_"+Date.now()+"_"+Math.random().toString(36).substr(2,8)}sendToolResult(t,e){this.sendEvent("client_tool_result",{call_id:t,result:e})}sendToolAck(t){var e;((e=this.dataChannel)==null?void 0:e.readyState)==="open"?(this.dataChannel.send(JSON.stringify({event:"client_tool_ack",data:{tool_call_id:t}})),console.log("✅ [VaniraAI] Sent client_tool_ack for:",t)):console.warn("âš ī¸ [VaniraAI] Cannot send tool_ack: DataChannel not open")}sendContextUpdate(t){this.sendEvent("client_context_update",{data:{context:t}})}sendActionTrigger(t,e={}){this.sendEvent("client_action_trigger",{data:{action_name:t,data:e}})}triggerActionInterrupt(){this.sendEvent("action_interrupt"),console.log("🛑 [VaniraAI] Triggered client-side action interrupt")}static async fetchIceServers(t,e="https://coredb.travelr.club/v1/graphql"){var i;try{const n=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json",Authorization:t},body:JSON.stringify({query:`
9
9
  query GetIceServers {
10
10
  ice_servers(where: {enabled: {_eq: true}}) {
11
11
  urls
@@ -976,7 +976,7 @@ overflow: hidden;
976
976
  cursor: pointer; pointer-events: auto;
977
977
  transition: background-color 0.2s;
978
978
  box-shadow: 0 4px 6px -1px rgba(0,0,0,0.1);
979
- `,this.hangupBtn.onmouseover=()=>this.hangupBtn.style.backgroundColor="#dc2626",this.hangupBtn.onmouseout=()=>this.hangupBtn.style.backgroundColor="#ef4444",this.hangupBtn.onclick=()=>{const g=this.callStartedAt?Date.now()-this.callStartedAt:0,w=this.callStartedAt??Date.now();this.onCallEnded&&g>0&&this.onCallEnded(g,w),this.onHangup()},d.appendChild(this.hangupBtn),this.element.appendChild(d)}getElement(){return this.element}setMode(t){this.isAvatarMode=t==="avatar"}setVideoTrack(t){if(this.isAvatarMode=!0,t.kind==="video"&&this.videoElement){const e=new MediaStream([t]);this.videoElement.srcObject=e,this.videoContainer.style.display="block",this.orbWrapper.style.display="none",this.connectingLabel.style.display="none",this.timerEl.style.display="none",this.videoElement.onplaying=()=>{this.prepareBadge.style.display="none",this.statusBadge.style.display="flex"},this.videoElement.play().catch(i=>console.warn("Video play error",i))}}setStatus(t){if(t==="connecting")this.centerIcon.style.background="#4b5563",this.centerIcon.innerHTML='<div style="width:18px;height:18px;border:2px solid #ffffff;border-top-color:transparent;border-radius:50%;animation:spin 1s linear infinite;"></div>',this.isAvatarMode?(this.videoContainer.style.display="block",this.orbWrapper.style.display="none",this.prepareBadge.textContent="CONNECTING...",this.prepareBadge.style.display="block",this.statusBadge.style.display="none",this.connectingLabel.style.display="none"):(this.orbWrapper.style.display="flex",this.videoContainer.style.display="none",this.connectingRing.style.display="block",this.errorRing.style.display="none",this.waveLayers.forEach(e=>e.style.display="none"),this.connectingLabel.style.display="block",this.connectedBadge.style.display="none",this.timerEl.style.display="none",this.errorLabel.style.display="none",this.retryBtn.style.display="none"),this.stopTimer();else if(t==="connected"){this.centerIcon.style.background="#1f2937",this.centerIcon.innerHTML=u.phone;const e=this.centerIcon.querySelector("svg");e&&(e.style.cssText="width:20px;height:20px;"),this.isAvatarMode?this.videoElement&&!this.videoElement.paused&&this.videoElement.readyState>2?(this.prepareBadge.style.display="none",this.statusBadge.style.display="flex"):(this.prepareBadge.textContent="AGENT IS ON THE WAY...",this.prepareBadge.style.display="block",setTimeout(()=>{this.prepareBadge.style.display!=="none"&&(this.prepareBadge.style.display="none",this.statusBadge.style.display="flex")},5e3)):(this.connectingRing.style.display="none",this.errorRing.style.display="none",this.waveLayers.forEach(i=>i.style.display="flex"),this.connectingLabel.style.display="none",this.connectedBadge.style.display="flex",this.timerEl.style.display="block",this.errorLabel.style.display="none",this.retryBtn.style.display="none",this.startTimer())}else t==="error"&&(this.centerIcon.style.background="#dc2626",this.centerIcon.innerHTML=u.phone,this.connectingRing.style.display="none",this.errorRing.style.display="block",this.waveLayers.forEach(e=>e.style.display="none"),this.connectingLabel.style.display="none",this.connectedBadge.style.display="none",this.timerEl.style.display="none",this.errorLabel.style.display="block",this.retryBtn.style.display="block",this.stopTimer())}setTranscription(t,e){this.transcriptionEl.textContent=`"${t}"`,this.transcriptionEl.style.color=e?"#1f2937":"#9ca3af",this.transcriptionEl.style.fontStyle=e?"normal":"italic"}show(){this.callStartedAt=Date.now(),this.element.style.display="flex",this.setStatus("connecting")}hide(){this.element.style.display="none",this.reset()}reset(){this.videoElement&&(this.videoElement.srcObject=null),this.isAvatarMode=!1,this.callStartedAt=null,this.stopTimer(),this.transcriptionEl.textContent="",this.videoContainer.style.display="none",this.orbWrapper.style.display="flex",this.connectingRing.style.display="none",this.errorRing.style.display="none",this.waveLayers.forEach(e=>e.style.display="none"),this.connectingLabel.style.display="none",this.connectedBadge.style.display="none",this.timerEl.style.display="none",this.errorLabel.style.display="none",this.retryBtn.style.display="none",this.prepareBadge.style.display="none",this.statusBadge.style.display="none",this.centerIcon.style.background="#374151",this.centerIcon.innerHTML=u.phone;const t=this.centerIcon.querySelector("svg");t&&(t.style.cssText="width:20px;height:20px;")}startTimer(){this.timerInterval&&clearInterval(this.timerInterval),this.startTime=Date.now(),this.timerEl.textContent="00:00",this.timerInterval=setInterval(()=>{if(!this.startTime)return;const t=Math.floor((Date.now()-this.startTime)/1e3),e=Math.floor(t/60).toString().padStart(2,"0"),i=(t%60).toString().padStart(2,"0");this.timerEl.textContent=`${e}:${i}`},1e3)}stopTimer(){this.timerInterval&&(clearInterval(this.timerInterval),this.timerInterval=null),this.timerEl.textContent=""}setFullScreen(t){t?(this.videoContainer.style.position="absolute",this.videoContainer.style.top="0",this.videoContainer.style.left="0",this.videoContainer.style.width="100%",this.videoContainer.style.height="100%",this.videoContainer.style.maxWidth="none",this.videoContainer.style.borderRadius="0",this.videoContainer.style.margin="0",this.videoContainer.style.zIndex="0"):(this.videoContainer.style.position="relative",this.videoContainer.style.width="100%",this.videoContainer.style.maxWidth="260px",this.videoContainer.style.height="auto",this.videoContainer.style.aspectRatio="1/1",this.videoContainer.style.borderRadius="16px",this.videoContainer.style.marginBottom="16px")}}class W{constructor(t){o(this,"element");o(this,"messageContainer");o(this,"inputArea");o(this,"input");o(this,"sendBtn");o(this,"typingIndicator",null);this.onSend=t,this.element=document.createElement("div"),this.element.style.display="flex",this.element.style.flexDirection="column",this.element.style.flex="1",this.element.style.overflow="hidden",this.element.style.minHeight="0",this.messageContainer=document.createElement("div"),this.messageContainer.className="chat-messages",this.inputArea=document.createElement("div"),this.inputArea.className="chat-input-area",this.input=document.createElement("input"),this.input.className="chat-input",this.input.placeholder="Type a message...",this.input.addEventListener("keypress",i=>{i.key==="Enter"&&this.handleSend()}),this.sendBtn=document.createElement("button"),this.sendBtn.className="chat-send-btn",this.sendBtn.innerHTML=u.send,this.sendBtn.onclick=()=>this.handleSend(),this.inputArea.appendChild(this.input),this.inputArea.appendChild(this.sendBtn);const e=document.createElement("div");e.className="branding-footer",e.innerHTML="Technology Powered by <b>Vanira AI</b>",this.element.appendChild(this.messageContainer),this.element.appendChild(this.inputArea),this.element.appendChild(e)}getElement(){return this.element}formatTime(t=new Date){return t.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})}addMessage(t,e,i){const s=document.createElement("div");s.style.cssText=`
979
+ `,this.hangupBtn.onmouseover=()=>this.hangupBtn.style.backgroundColor="#dc2626",this.hangupBtn.onmouseout=()=>this.hangupBtn.style.backgroundColor="#ef4444",this.hangupBtn.onclick=()=>{const g=this.callStartedAt?Date.now()-this.callStartedAt:0,w=this.callStartedAt??Date.now();this.onCallEnded&&g>0&&this.onCallEnded(g,w),this.onHangup()},d.appendChild(this.hangupBtn),this.element.appendChild(d)}getElement(){return this.element}setMode(t){this.isAvatarMode=t==="avatar"}setVideoTrack(t){if(this.isAvatarMode=!0,t.kind==="video"&&this.videoElement){const e=new MediaStream([t]);this.videoElement.srcObject=e,this.videoContainer.style.display="block",this.orbWrapper.style.display="none",this.connectingLabel.style.display="none",this.timerEl.style.display="none",this.videoElement.onplaying=()=>{this.prepareBadge.style.display="none",this.statusBadge.style.display="flex"},this.videoElement.play().catch(i=>console.warn("Video play error",i))}}setStatus(t){if(t==="connecting")this.centerIcon.style.background="#4b5563",this.centerIcon.innerHTML='<div style="width:18px;height:18px;border:2px solid #ffffff;border-top-color:transparent;border-radius:50%;animation:spin 1s linear infinite;"></div>',this.isAvatarMode?(this.videoContainer.style.display="block",this.orbWrapper.style.display="none",this.prepareBadge.textContent="CONNECTING...",this.prepareBadge.style.display="block",this.statusBadge.style.display="none",this.connectingLabel.style.display="none"):(this.orbWrapper.style.display="flex",this.videoContainer.style.display="none",this.connectingRing.style.display="block",this.errorRing.style.display="none",this.waveLayers.forEach(e=>e.style.display="none"),this.connectingLabel.style.display="block",this.connectedBadge.style.display="none",this.timerEl.style.display="none",this.errorLabel.style.display="none",this.retryBtn.style.display="none"),this.stopTimer();else if(t==="connected"){this.centerIcon.style.background="#1f2937",this.centerIcon.innerHTML=u.phone;const e=this.centerIcon.querySelector("svg");e&&(e.style.cssText="width:20px;height:20px;"),this.isAvatarMode?this.videoElement&&!this.videoElement.paused&&this.videoElement.readyState>2?(this.prepareBadge.style.display="none",this.statusBadge.style.display="flex"):(this.prepareBadge.textContent="AGENT IS ON THE WAY...",this.prepareBadge.style.display="block",setTimeout(()=>{this.prepareBadge.style.display!=="none"&&(this.prepareBadge.style.display="none",this.statusBadge.style.display="flex")},5e3)):(this.connectingRing.style.display="none",this.errorRing.style.display="none",this.waveLayers.forEach(i=>i.style.display="flex"),this.connectingLabel.style.display="none",this.connectedBadge.style.display="flex",this.timerEl.style.display="block",this.errorLabel.style.display="none",this.retryBtn.style.display="none",this.startTimer())}else t==="error"&&(this.centerIcon.style.background="#dc2626",this.centerIcon.innerHTML=u.phone,this.connectingRing.style.display="none",this.errorRing.style.display="block",this.waveLayers.forEach(e=>e.style.display="none"),this.connectingLabel.style.display="none",this.connectedBadge.style.display="none",this.timerEl.style.display="none",this.errorLabel.style.display="block",this.retryBtn.style.display="block",this.stopTimer())}setTranscription(t,e){this.transcriptionEl.textContent=`"${t}"`,this.transcriptionEl.style.color=e?"#1f2937":"#9ca3af",this.transcriptionEl.style.fontStyle=e?"normal":"italic"}show(){this.callStartedAt=Date.now(),this.element.style.display="flex",this.setStatus("connecting")}hide(){this.element.style.display="none",this.reset()}reset(){this.videoElement&&(this.videoElement.srcObject=null),this.isAvatarMode=!1,this.callStartedAt=null,this.stopTimer(),this.transcriptionEl.textContent="",this.videoContainer.style.display="none",this.orbWrapper.style.display="flex",this.connectingRing.style.display="none",this.errorRing.style.display="none",this.waveLayers.forEach(e=>e.style.display="none"),this.connectingLabel.style.display="none",this.connectedBadge.style.display="none",this.timerEl.style.display="none",this.errorLabel.style.display="none",this.retryBtn.style.display="none",this.prepareBadge.style.display="none",this.statusBadge.style.display="none",this.centerIcon.style.background="#374151",this.centerIcon.innerHTML=u.phone;const t=this.centerIcon.querySelector("svg");t&&(t.style.cssText="width:20px;height:20px;")}startTimer(){this.timerInterval&&clearInterval(this.timerInterval),this.startTime=Date.now(),this.timerEl.textContent="00:00",this.timerInterval=setInterval(()=>{if(!this.startTime)return;const t=Math.floor((Date.now()-this.startTime)/1e3),e=Math.floor(t/60).toString().padStart(2,"0"),i=(t%60).toString().padStart(2,"0");this.timerEl.textContent=`${e}:${i}`},1e3)}stopTimer(){this.timerInterval&&(clearInterval(this.timerInterval),this.timerInterval=null),this.timerEl.textContent=""}setFullScreen(t){t?(this.videoContainer.style.position="absolute",this.videoContainer.style.top="0",this.videoContainer.style.left="0",this.videoContainer.style.width="100%",this.videoContainer.style.height="100%",this.videoContainer.style.maxWidth="none",this.videoContainer.style.borderRadius="0",this.videoContainer.style.margin="0",this.videoContainer.style.zIndex="0"):(this.videoContainer.style.position="relative",this.videoContainer.style.width="100%",this.videoContainer.style.maxWidth="260px",this.videoContainer.style.height="auto",this.videoContainer.style.aspectRatio="1/1",this.videoContainer.style.borderRadius="16px",this.videoContainer.style.marginBottom="16px")}}class U{constructor(t){o(this,"element");o(this,"messageContainer");o(this,"inputArea");o(this,"input");o(this,"sendBtn");o(this,"typingIndicator",null);this.onSend=t,this.element=document.createElement("div"),this.element.style.display="flex",this.element.style.flexDirection="column",this.element.style.flex="1",this.element.style.overflow="hidden",this.element.style.minHeight="0",this.messageContainer=document.createElement("div"),this.messageContainer.className="chat-messages",this.inputArea=document.createElement("div"),this.inputArea.className="chat-input-area",this.input=document.createElement("input"),this.input.className="chat-input",this.input.placeholder="Type a message...",this.input.addEventListener("keypress",i=>{i.key==="Enter"&&this.handleSend()}),this.sendBtn=document.createElement("button"),this.sendBtn.className="chat-send-btn",this.sendBtn.innerHTML=u.send,this.sendBtn.onclick=()=>this.handleSend(),this.inputArea.appendChild(this.input),this.inputArea.appendChild(this.sendBtn);const e=document.createElement("div");e.className="branding-footer",e.innerHTML="Technology Powered by <b>Vanira AI</b>",this.element.appendChild(this.messageContainer),this.element.appendChild(this.inputArea),this.element.appendChild(e)}getElement(){return this.element}formatTime(t=new Date){return t.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})}addMessage(t,e,i){const s=document.createElement("div");s.style.cssText=`
980
980
  display: flex;
981
981
  flex-direction: column;
982
982
  align-items: ${t==="user"?"flex-end":"flex-start"};
@@ -1017,7 +1017,7 @@ overflow: hidden;
1017
1017
  </div>
1018
1018
  <div class="voice-status-text">Tap to speak</div>
1019
1019
  <div class="voice-status-subtext">Start a conversation</div>
1020
- `;const e=this.element.querySelector(".central-orb-container");e&&(e.onclick=this.onClick)}getElement(){return this.element}}class O{constructor(t){o(this,"element");o(this,"chips",[]);this.onChipClick=t,this.element=document.createElement("div"),this.element.className="welcome-chips-container"}setChips(t){this.chips=t,this.render()}getElement(){return this.element}setPosition(t){this.element.style.cssText="",t.split(";").filter(i=>i.trim()).forEach(i=>{const[s,n]=i.split(":").map(a=>a.trim());s&&n&&(this.element.style[s]=n)}),this.element.style.bottom?this.element.style.bottom=parseInt(this.element.style.bottom)+76+"px":this.element.style.top&&(this.element.style.top=parseInt(this.element.style.top)+76+"px"),this.element.style.position="fixed",this.element.style.zIndex="2147483646",this.element.style.alignItems=this.element.style.left?"flex-start":"flex-end"}updateCoordinates(t,e,i=!0){this.element.style.left=`${t}px`,i?(this.element.style.top="auto",this.element.style.bottom=`${window.innerHeight-e+16}px`):(this.element.style.bottom="auto",this.element.style.top=`${e+76}px`),this.element.style.right="auto"}render(){this.element.innerHTML="",this.chips.forEach((t,e)=>{const i=document.createElement("button");i.className="welcome-chip-btn",i.textContent=t.title,i.onclick=s=>{s.stopPropagation(),this.onChipClick(t.title)},i.style.animationDelay=`${e*.1}s`,this.element.appendChild(i)})}static get styles(){return`
1020
+ `;const e=this.element.querySelector(".central-orb-container");e&&(e.onclick=this.onClick)}getElement(){return this.element}}class W{constructor(t){o(this,"element");o(this,"chips",[]);this.onChipClick=t,this.element=document.createElement("div"),this.element.className="welcome-chips-container"}setChips(t){this.chips=t,this.render()}getElement(){return this.element}setPosition(t){this.element.style.cssText="",t.split(";").filter(i=>i.trim()).forEach(i=>{const[s,n]=i.split(":").map(a=>a.trim());s&&n&&(this.element.style[s]=n)}),this.element.style.bottom?this.element.style.bottom=parseInt(this.element.style.bottom)+76+"px":this.element.style.top&&(this.element.style.top=parseInt(this.element.style.top)+76+"px"),this.element.style.position="fixed",this.element.style.zIndex="2147483646",this.element.style.alignItems=this.element.style.left?"flex-start":"flex-end"}updateCoordinates(t,e,i=!0){this.element.style.left=`${t}px`,i?(this.element.style.top="auto",this.element.style.bottom=`${window.innerHeight-e+16}px`):(this.element.style.bottom="auto",this.element.style.top=`${e+76}px`),this.element.style.right="auto"}render(){this.element.innerHTML="",this.chips.forEach((t,e)=>{const i=document.createElement("button");i.className="welcome-chip-btn",i.textContent=t.title,i.onclick=s=>{s.stopPropagation(),this.onChipClick(t.title)},i.style.animationDelay=`${e*.1}s`,this.element.appendChild(i)})}static get styles(){return`
1021
1021
  .welcome-chips-container {
1022
1022
  position: fixed;
1023
1023
  z-index: 9998;
@@ -1073,7 +1073,7 @@ overflow: hidden;
1073
1073
  transform: translateY(0);
1074
1074
  }
1075
1075
  }
1076
- `}}class U{constructor(t,e,i="#6366f1",s="#a855f7",n){o(this,"element");o(this,"overlay");o(this,"onStartCall");o(this,"onHangup");o(this,"primaryColor");o(this,"secondaryColor");o(this,"onCallEnded");this.onStartCall=t,this.onHangup=e,this.primaryColor=i,this.secondaryColor=s,this.onCallEnded=n,this.element=document.createElement("div"),this.element.style.height="100%",this.element.style.position="relative"}initOverlay(){this.overlay=new j(()=>this.onHangup(),this.primaryColor,this.secondaryColor,this.onCallEnded),this.element.appendChild(this.overlay.getElement())}getElement(){return this.element}setCallActive(t){t?this.overlay.show():this.overlay.hide()}setStatus(t){this.overlay.setStatus(t)}setTranscription(t,e){this.overlay.setTranscription(t,e)}setVideoTrack(t){this.overlay.setVideoTrack(t)}}class oe extends U{constructor(e,i,s="#6366f1",n="#a855f7",a){super(e,i,s,n,a);o(this,"voiceOrb");this.element.style.background="#f9fafb",this.voiceOrb=new ne(()=>this.onStartCall()),this.element.appendChild(this.voiceOrb.getElement()),this.initOverlay()}}class ae{constructor(t){o(this,"element");o(this,"chatWindow");this.onSendMessage=t,this.element=document.createElement("div"),this.element.style.flex="1",this.element.style.width="100%",this.element.style.minHeight="0",this.element.style.display="flex",this.element.style.flexDirection="column",this.chatWindow=new W(e=>this.onSendMessage(e)),this.element.appendChild(this.chatWindow.getElement())}getElement(){return this.element}getChatWindow(){return this.chatWindow}}class V{constructor(t,e,i,s="#6366f1",n="#a855f7",a){o(this,"element");o(this,"chatWindow");o(this,"overlay");o(this,"voiceTrigger");this.onSendMessage=t,this.onStartCall=e,this.onHangup=i,this.primaryColor=s,this.secondaryColor=n,this.onCallEnded=a,this.element=document.createElement("div"),this.element.style.flex="1",this.element.style.display="flex",this.element.style.flexDirection="column",this.element.style.minHeight="0",this.element.style.position="relative"}setupChat(){this.chatWindow=new W(e=>this.onSendMessage(e));const t=this.chatWindow.getElement();t.style.flex="1",this.element.appendChild(t),this.injectVoiceTrigger(),this.overlay=new j(()=>this.onHangup(),this.primaryColor,this.secondaryColor,this.onCallEnded),this.element.appendChild(this.overlay.getElement())}injectVoiceTrigger(){const t=document.createElement("button");this.voiceTrigger=t,t.className="voice-btn-simple",t.innerHTML=`<div class="voice-btn-icon">${u.audioLines}</div>`,t.onclick=()=>this.onStartCall();const e=this.chatWindow.getElement().querySelector(".chat-input-area");e?e.insertBefore(this.voiceTrigger,e.firstChild):console.warn("VaniraSDK: Failed to inject voice trigger",{inputArea:e})}getElement(){return this.element}getChatWindow(){return this.chatWindow}setCallActive(t){t?(this.overlay.show(),this.chatWindow&&(this.chatWindow.getElement().style.display="none")):(this.overlay.hide(),this.chatWindow&&(this.chatWindow.getElement().style.display="flex"))}setStatus(t){this.overlay.setStatus(t)}setTranscription(t,e){this.overlay.setTranscription(t,e)}setVideoTrack(t){this.overlay.setVideoTrack(t)}}class re extends V{constructor(t,e,i,s="#6366f1",n="#a855f7",a){super(t,e,i,s,n,a),this.setupChat()}}class le extends U{constructor(e,i,s="#6366f1",n="#a855f7",a){super(e,i,s,n,a);o(this,"avatarView");o(this,"startCallBtn");o(this,"controlsContainer");this.element.style.display="flex",this.element.style.flexDirection="column",this.avatarView=new se;const r=this.avatarView.getElement();r.style.width="100%",r.style.maxWidth="300px",r.style.aspectRatio="1/1",r.style.borderRadius="16px",r.style.overflow="hidden",r.style.margin="auto",r.style.position="relative",this.element.appendChild(r),this.controlsContainer=document.createElement("div"),this.controlsContainer.className="widget-body",this.controlsContainer.style.position="absolute",this.controlsContainer.style.bottom="20px",this.controlsContainer.style.width="100%",this.controlsContainer.style.zIndex="10";const l=document.createElement("div");l.className="controls",this.startCallBtn=document.createElement("button"),this.startCallBtn.className="control-btn primary",this.startCallBtn.innerHTML=`${u.phone} <span>Start Call</span>`,this.startCallBtn.onclick=()=>this.onStartCall(),l.appendChild(this.startCallBtn),this.controlsContainer.appendChild(l),this.element.appendChild(this.controlsContainer),this.initOverlay(),this.overlay.setMode("avatar")}getAvatarView(){return this.avatarView}setCallActive(e){e&&this.overlay.setMode("avatar"),super.setCallActive(e),e?this.controlsContainer.style.display="none":this.controlsContainer.style.display="block"}}class Ae extends V{constructor(t,e,i,s="#6366f1",n="#a855f7",a){super(t,e,i,s,n,a),this.setupChat(),this.overlay.setMode("avatar")}injectVoiceTrigger(){const t=document.createElement("button");this.voiceTrigger=t,t.className="voice-btn-simple",t.style.overflow="hidden",t.style.padding="0",t.style.border="1.5px solid #e5e7eb",t.innerHTML=`
1076
+ `}}class O{constructor(t,e,i="#6366f1",s="#a855f7",n){o(this,"element");o(this,"overlay");o(this,"onStartCall");o(this,"onHangup");o(this,"primaryColor");o(this,"secondaryColor");o(this,"onCallEnded");this.onStartCall=t,this.onHangup=e,this.primaryColor=i,this.secondaryColor=s,this.onCallEnded=n,this.element=document.createElement("div"),this.element.style.height="100%",this.element.style.position="relative"}initOverlay(){this.overlay=new j(()=>this.onHangup(),this.primaryColor,this.secondaryColor,this.onCallEnded),this.element.appendChild(this.overlay.getElement())}getElement(){return this.element}setCallActive(t){t?this.overlay.show():this.overlay.hide()}setStatus(t){this.overlay.setStatus(t)}setTranscription(t,e){this.overlay.setTranscription(t,e)}setVideoTrack(t){this.overlay.setVideoTrack(t)}}class oe extends O{constructor(e,i,s="#6366f1",n="#a855f7",a){super(e,i,s,n,a);o(this,"voiceOrb");this.element.style.background="#f9fafb",this.voiceOrb=new ne(()=>this.onStartCall()),this.element.appendChild(this.voiceOrb.getElement()),this.initOverlay()}}class ae{constructor(t){o(this,"element");o(this,"chatWindow");this.onSendMessage=t,this.element=document.createElement("div"),this.element.style.flex="1",this.element.style.width="100%",this.element.style.minHeight="0",this.element.style.display="flex",this.element.style.flexDirection="column",this.chatWindow=new U(e=>this.onSendMessage(e)),this.element.appendChild(this.chatWindow.getElement())}getElement(){return this.element}getChatWindow(){return this.chatWindow}}class V{constructor(t,e,i,s="#6366f1",n="#a855f7",a){o(this,"element");o(this,"chatWindow");o(this,"overlay");o(this,"voiceTrigger");this.onSendMessage=t,this.onStartCall=e,this.onHangup=i,this.primaryColor=s,this.secondaryColor=n,this.onCallEnded=a,this.element=document.createElement("div"),this.element.style.flex="1",this.element.style.display="flex",this.element.style.flexDirection="column",this.element.style.minHeight="0",this.element.style.position="relative"}setupChat(){this.chatWindow=new U(e=>this.onSendMessage(e));const t=this.chatWindow.getElement();t.style.flex="1",this.element.appendChild(t),this.injectVoiceTrigger(),this.overlay=new j(()=>this.onHangup(),this.primaryColor,this.secondaryColor,this.onCallEnded),this.element.appendChild(this.overlay.getElement())}injectVoiceTrigger(){const t=document.createElement("button");this.voiceTrigger=t,t.className="voice-btn-simple",t.innerHTML=`<div class="voice-btn-icon">${u.audioLines}</div>`,t.onclick=()=>this.onStartCall();const e=this.chatWindow.getElement().querySelector(".chat-input-area");e?e.insertBefore(this.voiceTrigger,e.firstChild):console.warn("VaniraSDK: Failed to inject voice trigger",{inputArea:e})}getElement(){return this.element}getChatWindow(){return this.chatWindow}setCallActive(t){t?(this.overlay.show(),this.chatWindow&&(this.chatWindow.getElement().style.display="none")):(this.overlay.hide(),this.chatWindow&&(this.chatWindow.getElement().style.display="flex"))}setStatus(t){this.overlay.setStatus(t)}setTranscription(t,e){this.overlay.setTranscription(t,e)}setVideoTrack(t){this.overlay.setVideoTrack(t)}}class re extends V{constructor(t,e,i,s="#6366f1",n="#a855f7",a){super(t,e,i,s,n,a),this.setupChat()}}class le extends O{constructor(e,i,s="#6366f1",n="#a855f7",a){super(e,i,s,n,a);o(this,"avatarView");o(this,"startCallBtn");o(this,"controlsContainer");this.element.style.display="flex",this.element.style.flexDirection="column",this.avatarView=new se;const r=this.avatarView.getElement();r.style.width="100%",r.style.maxWidth="300px",r.style.aspectRatio="1/1",r.style.borderRadius="16px",r.style.overflow="hidden",r.style.margin="auto",r.style.position="relative",this.element.appendChild(r),this.controlsContainer=document.createElement("div"),this.controlsContainer.className="widget-body",this.controlsContainer.style.position="absolute",this.controlsContainer.style.bottom="20px",this.controlsContainer.style.width="100%",this.controlsContainer.style.zIndex="10";const l=document.createElement("div");l.className="controls",this.startCallBtn=document.createElement("button"),this.startCallBtn.className="control-btn primary",this.startCallBtn.innerHTML=`${u.phone} <span>Start Call</span>`,this.startCallBtn.onclick=()=>this.onStartCall(),l.appendChild(this.startCallBtn),this.controlsContainer.appendChild(l),this.element.appendChild(this.controlsContainer),this.initOverlay(),this.overlay.setMode("avatar")}getAvatarView(){return this.avatarView}setCallActive(e){e&&this.overlay.setMode("avatar"),super.setCallActive(e),e?this.controlsContainer.style.display="none":this.controlsContainer.style.display="block"}}class Ae extends V{constructor(t,e,i,s="#6366f1",n="#a855f7",a){super(t,e,i,s,n,a),this.setupChat(),this.overlay.setMode("avatar")}injectVoiceTrigger(){const t=document.createElement("button");this.voiceTrigger=t,t.className="voice-btn-simple",t.style.overflow="hidden",t.style.padding="0",t.style.border="1.5px solid #e5e7eb",t.innerHTML=`
1077
1077
  <video
1078
1078
  src="https://www.simli.com/jenna.mp4"
1079
1079
  autoplay loop muted pip="false" playsinline
@@ -1089,8 +1089,8 @@ overflow: hidden;
1089
1089
  ${ie}
1090
1090
  :host { ${te(this.primaryColor,this.secondaryColor)} }
1091
1091
  ${R.styles}
1092
- ${O.styles}
1092
+ ${W.styles}
1093
1093
  ${N.styles}
1094
1094
  ${this.gradient?`.widget-fab { background: ${this.gradient} !important; }`:""}
1095
- `,this.root.appendChild(s);const n=`vanira_pos_${this.widgetId||this.agentId}`,a=localStorage.getItem(n);let r=null;if(a)try{r=JSON.parse(a)}catch{}this.floatingButton=new R(()=>this.togglePanel(),(c,A)=>{var d,g;(d=this.floatingWelcomeChips)==null||d.updateCoordinates(c,A,A>window.innerHeight/2),this.isPanelOpen&&((g=this.panel)==null||g.updatePosition({left:`${Math.max(20,Math.min(c-170,window.innerWidth-420))}px`,top:A>window.innerHeight/2?"auto":`${A+80}px`,bottom:A>window.innerHeight/2?`${window.innerHeight-A+20}px`:"auto"}))},(c,A)=>{localStorage.setItem(n,JSON.stringify({x:c,y:A}))}),this.floatingButton.setIcon(this.getFabIcon()),r?this.floatingButton.updateCoordinates(r.x,r.y):this.floatingButton.setPosition(this.getPosStyle()),this.floatingWelcomeChips=new O(c=>this.handleFloatingChipClick(c)),r?this.floatingWelcomeChips.updateCoordinates(r.x,r.y,r.y>window.innerHeight/2):this.floatingWelcomeChips.setPosition(this.getPosStyle()),this.panel=new N(()=>this.closePanel(),this.getPanelTitle()),this.root.appendChild(this.floatingWelcomeChips.getElement()),this.root.appendChild(this.floatingButton.getElement()),this.root.appendChild(this.panel.getElement()),this.setupPanelContent(),this.chatWelcomeMessage&&!this.widgetMode.includes("chat")&&this.handleWelcomePayload(this.chatWelcomeMessage),this.initSessionManager()?this.widgetMode.includes("chat")&&this.initializeChatSession():this.showTabConflictBanner("conflict")}getFabIcon(){return this.widgetIcon&&T[this.widgetIcon]?T[this.widgetIcon]:this.widgetMode.includes("chat")?u.chat:u.voice_orb}getPanelTitle(){return"Assistant"}getPosStyle(){const e={"bottom-right":"bottom: 24px; right: 24px;","bottom-left":"bottom: 24px; left: 24px;","top-right":"top: 24px; right: 24px;","top-left":"top: 24px; left: 24px;"};return e[this.position]||e["bottom-right"]}setupPanelContent(){const e=(i,s)=>{var l,c;const n=(c=(l=this.currentView)==null?void 0:l.getChatWindow)==null?void 0:c.call(l);n&&n.addCallRecord(i,s);const a=`vanira_calls_${this.widgetId||this.agentId}`,r=JSON.parse(localStorage.getItem(a)||"[]");r.push({durationMs:i,startedAt:s}),r.length>50&&r.splice(0,r.length-50),localStorage.setItem(a,JSON.stringify(r))};switch(this.widgetMode){case"chat_only":this.currentView=new ae(i=>this.handleChatSend(i));break;case"chat_voice":this.currentView=new re(i=>this.handleChatSend(i),()=>this.create_call(),()=>this.end_call(),this.primaryColor,this.secondaryColor,e);break;case"avatar_only":this.currentView=new le(()=>this.create_call(),()=>this.end_call(),this.primaryColor,this.secondaryColor,e);break;case"chat_avatar":this.currentView=new Ae(i=>this.handleChatSend(i),()=>this.create_call(),()=>this.end_call(),this.primaryColor,this.secondaryColor,e);break;case"voice_only":default:this.currentView=new oe(()=>this.create_call(),()=>this.end_call(),this.primaryColor,this.secondaryColor,e);break}this.currentView&&this.panel&&this.panel.setContent(this.currentView.getElement())}async handleChatSend(e){var s,n,a,r,l;if(!e)return;this.sessionActive||((s=this.sessionManager)==null||s.forceClaimSession(),this.sessionActive=!0,this.widgetMode.includes("chat")&&await this.initializeChatSession(!1));const i=(a=(n=this.currentView)==null?void 0:n.getChatWindow)==null?void 0:a.call(n);if(i){this.chatId&&!this.eventSource&&(this.eventSource=v.listenForAdminReplies(this.chatId,this.prospectId,c=>{var A,d,g;(d=(A=this.currentView)==null?void 0:A.getChatWindow)==null||d.call(A).addMessage("assistant",c),(g=this.sessionManager)==null||g.pushMessage("assistant",c),this.playMessageSound("receive")})),i.addMessage("user",e),(r=this.sessionManager)==null||r.pushMessage("user",e),i.setTyping(!0),(l=this.sessionManager)==null||l.pushMessage("assistant","");try{let c=!1;await this.chatAdapter.sendMessage(e,this.agentId,this.prospectId,this.chatId,A=>{var d;c||(this.playMessageSound("receive"),c=!0),i.setTyping(!1),(A==null?void 0:A.type)==="button_list"&&((d=A.data)!=null&&d.buttons)&&(i.addButtons(A.data.buttons),this.welcomeChipsData=A.data.buttons,this.updateWelcomeChipsVisibility())},A=>{var d;c||(this.playMessageSound("receive"),c=!0),i.setTyping(!1),i.updateLastAssistantMessage(A),(d=this.sessionManager)==null||d.updateLastAssistantMessage(A)},A=>{var d;A&&(this.chatId=A,(d=this.sessionManager)==null||d.saveIds(this.prospectId,A))})}catch(c){i.setTyping(!1),console.error("[VaniraAI] Send message failed",c),i.addMessage("assistant","Error sending message.")}}}togglePanel(){this.isPanelOpen?this.closePanel():this.openPanel()}openPanel(){var i,s,n,a;this.isPanelOpen=!0,this.updateWelcomeChipsVisibility();const e=(i=this.floatingButton)==null?void 0:i.getElement().getBoundingClientRect();if(e){const r=e.top>window.innerHeight/2;(s=this.panel)==null||s.open({left:`${Math.max(20,Math.min(e.left-170,window.innerWidth-420))}px`,bottom:r?`${window.innerHeight-e.top+20}px`:void 0,top:r?void 0:`${e.top+80}px`})}else(n=this.panel)==null||n.open({bottom:this.position.includes("bottom")?"100px":void 0,top:this.position.includes("top")?"100px":void 0,right:this.position.includes("right")?"24px":void 0,left:this.position.includes("left")?"24px":void 0});(a=this.root)!=null&&a.host&&this.root.host.classList.add("vanira-panel-open")}closePanel(){var e,i;this.isPanelOpen=!1,this.updateWelcomeChipsVisibility(),(e=this.panel)==null||e.close(),(i=this.root)!=null&&i.host&&this.root.host.classList.remove("vanira-panel-open")}updateWelcomeChipsVisibility(){if(!this.floatingWelcomeChips)return;const e=!this.isPanelOpen&&this.welcomeChipsData.length>0;console.log("[VaniraAI] updateWelcomeChipsVisibility:",{visible:e,isPanelOpen:this.isPanelOpen,chipsCount:this.welcomeChipsData.length}),e?(this.floatingWelcomeChips.setChips(this.welcomeChipsData),this.floatingWelcomeChips.getElement().style.display="flex"):this.floatingWelcomeChips.getElement().style.display="none"}handleFloatingChipClick(e){this.openPanel(),this.handleChatSend(e)}};o(I,"audioContext",null);let P=I;class de{static getProvider(t){return new P(t)}}class X extends HTMLElement{constructor(){super();o(this,"shadow");o(this,"provider",null);o(this,"widgetId","");o(this,"agentId","");o(this,"pkKey","");o(this,"serverUrl","https://inboxapi.travelr.club");o(this,"position","bottom-right");o(this,"primaryColor","#000000");o(this,"secondaryColor","#000000");o(this,"gradient",null);o(this,"positionType","fixed");this.shadow=this.attachShadow({mode:"open"})}static get observedAttributes(){return["widget-id","agent-id","position","primary-color","secondary-color","server-url","gradient","position-type","pk-key"]}connectedCallback(){console.log("[VaniraAI Widget] Initializing..."),this.readAttributes();const e={widgetId:this.widgetId,agentId:this.agentId,pkKey:this.pkKey,serverUrl:this.serverUrl,position:this.position,primaryColor:this.primaryColor,secondaryColor:this.secondaryColor,gradient:this.gradient,positionType:this.positionType};this.provider=de.getProvider(e),this.provider&&this.provider.ui_renderer(this.shadow),this.widgetId&&!this.agentId&&this.initializeExpandedConfig()}readAttributes(){this.widgetId=this.getAttribute("widget-id")||"",this.agentId=this.getAttribute("agent-id")||"",this.pkKey=this.getAttribute("pk-key")||"",this.serverUrl=this.getAttribute("server-url")||"https://inboxapi.travelr.club",this.position=this.getAttribute("position")||"bottom-right",this.primaryColor=this.getAttribute("primary-color")||"#000000",this.secondaryColor=this.getAttribute("secondary-color")||this.primaryColor,this.gradient=this.getAttribute("gradient"),this.positionType=this.getAttribute("position-type")||"fixed"}async initializeExpandedConfig(){try{const e=await b.fetchWidgetConfig(this.widgetId,this.pkKey||void 0);this.provider&&await this.provider.initialize(e)}catch(e){console.error("[VaniraAI Widget] Config failed:",e)}}}customElements.get("vanira-convai")||customElements.define("vanira-convai",X),typeof window<"u"&&(window.VaniraConvAI=X,window.VaniraAI=G);const m=document.currentScript;if(m){const h=m.getAttribute("data-widget-id")||m.getAttribute("widget-id"),t=m.getAttribute("data-agent-id")||m.getAttribute("agent-id");if(h||t){const e=m.getAttribute("data-position")||"bottom-right",i=m.getAttribute("data-primary-color")||m.getAttribute("primary-color")||"#6366f1",s=m.getAttribute("data-secondary-color")||m.getAttribute("secondary-color"),n=m.getAttribute("data-gradient")||m.getAttribute("gradient"),a=m.getAttribute("data-server-url")||m.getAttribute("server-url"),r=m.getAttribute("data-pk-key")||m.getAttribute("pk-key"),l=document.createElement("vanira-convai");h&&l.setAttribute("widget-id",h),t&&l.setAttribute("agent-id",t),r&&l.setAttribute("pk-key",r),l.setAttribute("position",e),l.setAttribute("primary-color",i),s&&l.setAttribute("secondary-color",s),n&&l.setAttribute("gradient",n),a&&l.setAttribute("server-url",a),document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>document.body.appendChild(l)):document.body.appendChild(l),l.addEventListener("vaniraai:tool_call",c=>{const A=c.detail;console.log("[VaniraAI Widget] Tool call received by host page:",A.name,A.arguments),typeof window.__vaniraai_tool_handler=="function"&&window.__vaniraai_tool_handler(A,{sendResult:d=>{console.log("[VaniraAI] sendResult called:",d)}})})}}})();
1095
+ `,this.root.appendChild(s);const n=`vanira_pos_${this.widgetId||this.agentId}`,a=localStorage.getItem(n);let r=null;if(a)try{r=JSON.parse(a)}catch{}this.floatingButton=new R(()=>this.togglePanel(),(c,A)=>{var d,g;(d=this.floatingWelcomeChips)==null||d.updateCoordinates(c,A,A>window.innerHeight/2),this.isPanelOpen&&((g=this.panel)==null||g.updatePosition({left:`${Math.max(20,Math.min(c-170,window.innerWidth-420))}px`,top:A>window.innerHeight/2?"auto":`${A+80}px`,bottom:A>window.innerHeight/2?`${window.innerHeight-A+20}px`:"auto"}))},(c,A)=>{localStorage.setItem(n,JSON.stringify({x:c,y:A}))}),this.floatingButton.setIcon(this.getFabIcon()),r?this.floatingButton.updateCoordinates(r.x,r.y):this.floatingButton.setPosition(this.getPosStyle()),this.floatingWelcomeChips=new W(c=>this.handleFloatingChipClick(c)),r?this.floatingWelcomeChips.updateCoordinates(r.x,r.y,r.y>window.innerHeight/2):this.floatingWelcomeChips.setPosition(this.getPosStyle()),this.panel=new N(()=>this.closePanel(),this.getPanelTitle()),this.root.appendChild(this.floatingWelcomeChips.getElement()),this.root.appendChild(this.floatingButton.getElement()),this.root.appendChild(this.panel.getElement()),this.setupPanelContent(),this.chatWelcomeMessage&&!this.widgetMode.includes("chat")&&this.handleWelcomePayload(this.chatWelcomeMessage),this.initSessionManager()?this.widgetMode.includes("chat")&&this.initializeChatSession():this.showTabConflictBanner("conflict")}getFabIcon(){return this.widgetIcon&&T[this.widgetIcon]?T[this.widgetIcon]:this.widgetMode.includes("chat")?u.chat:u.voice_orb}getPanelTitle(){return"Assistant"}getPosStyle(){const e={"bottom-right":"bottom: 24px; right: 24px;","bottom-left":"bottom: 24px; left: 24px;","top-right":"top: 24px; right: 24px;","top-left":"top: 24px; left: 24px;"};return e[this.position]||e["bottom-right"]}setupPanelContent(){const e=(i,s)=>{var l,c;const n=(c=(l=this.currentView)==null?void 0:l.getChatWindow)==null?void 0:c.call(l);n&&n.addCallRecord(i,s);const a=`vanira_calls_${this.widgetId||this.agentId}`,r=JSON.parse(localStorage.getItem(a)||"[]");r.push({durationMs:i,startedAt:s}),r.length>50&&r.splice(0,r.length-50),localStorage.setItem(a,JSON.stringify(r))};switch(this.widgetMode){case"chat_only":this.currentView=new ae(i=>this.handleChatSend(i));break;case"chat_voice":this.currentView=new re(i=>this.handleChatSend(i),()=>this.create_call(),()=>this.end_call(),this.primaryColor,this.secondaryColor,e);break;case"avatar_only":this.currentView=new le(()=>this.create_call(),()=>this.end_call(),this.primaryColor,this.secondaryColor,e);break;case"chat_avatar":this.currentView=new Ae(i=>this.handleChatSend(i),()=>this.create_call(),()=>this.end_call(),this.primaryColor,this.secondaryColor,e);break;case"voice_only":default:this.currentView=new oe(()=>this.create_call(),()=>this.end_call(),this.primaryColor,this.secondaryColor,e);break}this.currentView&&this.panel&&this.panel.setContent(this.currentView.getElement())}async handleChatSend(e){var s,n,a,r,l;if(!e)return;this.sessionActive||((s=this.sessionManager)==null||s.forceClaimSession(),this.sessionActive=!0,this.widgetMode.includes("chat")&&await this.initializeChatSession(!1));const i=(a=(n=this.currentView)==null?void 0:n.getChatWindow)==null?void 0:a.call(n);if(i){this.chatId&&!this.eventSource&&(this.eventSource=v.listenForAdminReplies(this.chatId,this.prospectId,c=>{var A,d,g;(d=(A=this.currentView)==null?void 0:A.getChatWindow)==null||d.call(A).addMessage("assistant",c),(g=this.sessionManager)==null||g.pushMessage("assistant",c),this.playMessageSound("receive")})),i.addMessage("user",e),(r=this.sessionManager)==null||r.pushMessage("user",e),i.setTyping(!0),(l=this.sessionManager)==null||l.pushMessage("assistant","");try{let c=!1;await this.chatAdapter.sendMessage(e,this.agentId,this.prospectId,this.chatId,A=>{var d;c||(this.playMessageSound("receive"),c=!0),i.setTyping(!1),(A==null?void 0:A.type)==="button_list"&&((d=A.data)!=null&&d.buttons)&&(i.addButtons(A.data.buttons),this.welcomeChipsData=A.data.buttons,this.updateWelcomeChipsVisibility())},A=>{var d;c||(this.playMessageSound("receive"),c=!0),i.setTyping(!1),i.updateLastAssistantMessage(A),(d=this.sessionManager)==null||d.updateLastAssistantMessage(A)},A=>{var d;A&&(this.chatId=A,(d=this.sessionManager)==null||d.saveIds(this.prospectId,A))})}catch(c){i.setTyping(!1),console.error("[VaniraAI] Send message failed",c),i.addMessage("assistant","Error sending message.")}}}togglePanel(){this.isPanelOpen?this.closePanel():this.openPanel()}openPanel(){var i,s,n,a;this.isPanelOpen=!0,this.updateWelcomeChipsVisibility();const e=(i=this.floatingButton)==null?void 0:i.getElement().getBoundingClientRect();if(e){const r=e.top>window.innerHeight/2;(s=this.panel)==null||s.open({left:`${Math.max(20,Math.min(e.left-170,window.innerWidth-420))}px`,bottom:r?`${window.innerHeight-e.top+20}px`:void 0,top:r?void 0:`${e.top+80}px`})}else(n=this.panel)==null||n.open({bottom:this.position.includes("bottom")?"100px":void 0,top:this.position.includes("top")?"100px":void 0,right:this.position.includes("right")?"24px":void 0,left:this.position.includes("left")?"24px":void 0});(a=this.root)!=null&&a.host&&this.root.host.classList.add("vanira-panel-open")}closePanel(){var e,i;this.isPanelOpen=!1,this.updateWelcomeChipsVisibility(),(e=this.panel)==null||e.close(),(i=this.root)!=null&&i.host&&this.root.host.classList.remove("vanira-panel-open")}updateWelcomeChipsVisibility(){if(!this.floatingWelcomeChips)return;const e=!this.isPanelOpen&&this.welcomeChipsData.length>0;console.log("[VaniraAI] updateWelcomeChipsVisibility:",{visible:e,isPanelOpen:this.isPanelOpen,chipsCount:this.welcomeChipsData.length}),e?(this.floatingWelcomeChips.setChips(this.welcomeChipsData),this.floatingWelcomeChips.getElement().style.display="flex"):this.floatingWelcomeChips.getElement().style.display="none"}handleFloatingChipClick(e){this.openPanel(),this.handleChatSend(e)}};o(I,"audioContext",null);let P=I;class de{static getProvider(t){return new P(t)}}class X extends HTMLElement{constructor(){super();o(this,"shadow");o(this,"provider",null);o(this,"widgetId","");o(this,"agentId","");o(this,"pkKey","");o(this,"serverUrl","https://inboxapi.travelr.club");o(this,"position","bottom-right");o(this,"primaryColor","#000000");o(this,"secondaryColor","#000000");o(this,"gradient",null);o(this,"positionType","fixed");this.shadow=this.attachShadow({mode:"open"})}static get observedAttributes(){return["widget-id","agent-id","position","primary-color","secondary-color","server-url","gradient","position-type","pk-key"]}connectedCallback(){console.log("[VaniraAI Widget] Initializing..."),this.readAttributes();const e={widgetId:this.widgetId,agentId:this.agentId,pkKey:this.pkKey,serverUrl:this.serverUrl,position:this.position,primaryColor:this.primaryColor,secondaryColor:this.secondaryColor,gradient:this.gradient,positionType:this.positionType};this.provider=de.getProvider(e),this.provider&&this.provider.ui_renderer(this.shadow),this.widgetId&&!this.agentId&&this.initializeExpandedConfig()}readAttributes(){this.widgetId=this.getAttribute("widget-id")||"",this.agentId=this.getAttribute("agent-id")||"",this.pkKey=this.getAttribute("pk-key")||"",this.serverUrl=this.getAttribute("server-url")||"https://inboxapi.travelr.club",this.position=this.getAttribute("position")||"bottom-right",this.primaryColor=this.getAttribute("primary-color")||"#000000",this.secondaryColor=this.getAttribute("secondary-color")||this.primaryColor,this.gradient=this.getAttribute("gradient"),this.positionType=this.getAttribute("position-type")||"fixed"}async initializeExpandedConfig(){try{const e=await b.fetchWidgetConfig(this.widgetId,this.pkKey||void 0);this.provider&&await this.provider.initialize(e)}catch(e){console.error("[VaniraAI Widget] Config failed:",e)}}}customElements.get("vanira-convai")||customElements.define("vanira-convai",X),typeof window<"u"&&(window.VaniraConvAI=X,window.VaniraAI=G);const m=document.currentScript;if(m){const h=m.getAttribute("data-widget-id")||m.getAttribute("widget-id"),t=m.getAttribute("data-agent-id")||m.getAttribute("agent-id");if(h||t){const e=m.getAttribute("data-position")||"bottom-right",i=m.getAttribute("data-primary-color")||m.getAttribute("primary-color")||"#6366f1",s=m.getAttribute("data-secondary-color")||m.getAttribute("secondary-color"),n=m.getAttribute("data-gradient")||m.getAttribute("gradient"),a=m.getAttribute("data-server-url")||m.getAttribute("server-url"),r=m.getAttribute("data-pk-key")||m.getAttribute("pk-key"),l=document.createElement("vanira-convai");h&&l.setAttribute("widget-id",h),t&&l.setAttribute("agent-id",t),r&&l.setAttribute("pk-key",r),l.setAttribute("position",e),l.setAttribute("primary-color",i),s&&l.setAttribute("secondary-color",s),n&&l.setAttribute("gradient",n),a&&l.setAttribute("server-url",a),document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>document.body.appendChild(l)):document.body.appendChild(l),l.addEventListener("vaniraai:tool_call",c=>{const A=c.detail;console.log("[VaniraAI Widget] Tool call received by host page:",A.name,A.arguments),typeof window.__vaniraai_tool_handler=="function"&&window.__vaniraai_tool_handler(A,{sendResult:d=>{console.log("[VaniraAI] sendResult called:",d)}})})}}})();
1096
1096
  //# sourceMappingURL=vanira-sdk.js.map