mini-chat-bot-widget 0.8.0 ā 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chat-widget.esm.js +216 -11
- package/dist/chat-widget.esm.min.js +1 -1
- package/dist/chat-widget.umd.js +216 -11
- package/dist/chat-widget.umd.min.js +1 -1
- package/index.html +1 -1
- package/package.json +1 -1
- package/src/audio-chat-screen.js +196 -3
- package/src/chat-widget.js +14 -3
- package/src/text-chat-screen.js +184 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
function e(e,n,t){return(n=function(e){var n=function(e,n){if("object"!=typeof e||!e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var a=t.call(e,n);if("object"!=typeof a)return a;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===n?String:Number)(e)}(e,"string");return"symbol"==typeof n?n:n+""}(n))in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function n(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter(function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable})),t.push.apply(t,a)}return t}function t(t){for(var a=1;a<arguments.length;a++){var i=null!=arguments[a]?arguments[a]:{};a%2?n(Object(i),!0).forEach(function(n){e(t,n,i[n])}):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(i)):n(Object(i)).forEach(function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(i,e))})}return t}class a{constructor(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.placeholder=e.placeholder||"Type your message...",this.primaryColor=e.primaryColor||"#1a5c4b",this.title=e.title||"Chat Assistant",this.onMessage=e.onMessage||(()=>{}),this.onBack=e.onBack||(()=>{}),this.onOpenDrawer=e.onOpenDrawer||(()=>{}),this.onClose=e.onClose||(()=>{}),this.container=null,this.messages=e.messages,this.sendMessage=e.sendMessage||null,this.contentBlocks=e.contentBlocks||[],this.onContentBlocksChange=e.onContentBlocksChange||(()=>{}),this.navigateToAudioScreen=e.navigateToAudioScreen,this.SUPPORTED_FILE_TYPES=["image/jpeg","image/png","image/gif","image/webp"]}render(e){this.container=e,this._applyStyles(),e.innerHTML='\n <div class="text-chat-screen">\n <div class="chat-header">\n <div class="chat-header-content">\n <button class="chat-back" id="text-chat-menu">\n <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-menu-icon lucide-menu"><path d="M4 5h16"/><path d="M4 12h16"/><path d="M4 19h16"/></svg>\n </button>\n \n <div class="chat-header-text">\n <div class="chat-title">'.concat(this.title,'</div>\n </div>\n </div>\n <button class="chat-close" id="navigate-to-audio-screen">\n <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-mic-icon lucide-mic"><path d="M12 19v3"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><rect x="9" y="2" width="6" height="13" rx="3"/></svg>\n </button>\n ​ ​ ​\n <button class="chat-close" id="text-chat-close">\n <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <line x1="18" y1="6" x2="6" y2="18"></line>\n <line x1="6" y1="6" x2="18" y2="18"></line>\n </svg>\n </button>\n </div>\n <div class="chat-messages" id="chat-messages">\n <div class="chat-welcome">\n <div class="welcome-text">š Hello! I\'m your AI assistant. How can I help you today?</div>\n </div>\n </div>\n <div class="file-attachments-container" id="file-attachments-container" style="display: none;"></div>\n <div class="chat-input-wrapper">\n <div class="file-upload-controls">\n <input\n type="file"\n id="file-upload-input"\n accept="image/jpeg,image/png,image/gif,image/webp"\n style="display: none;"\n />\n <button id="file-upload-button" class="file-upload-button" title="Attach files">\n <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"></path>\n </svg>\n </button>\n </div>\n <input type="text" id="chat-input" placeholder="').concat(this.placeholder,'" autocomplete="off" />\n <button id="chat-send" disabled>\n <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <line x1="22" y1="2" x2="11" y2="13"></line>\n <polygon points="22 2 15 22 11 13 2 9 22 2"></polygon>\n </svg>\n </button>\n </div>\n </div>\n ');const n=e.querySelector("#text-chat-menu"),t=e.querySelector("#text-chat-close"),a=e.querySelector("#navigate-to-audio-screen");n&&n.addEventListener("click",()=>{this.onOpenDrawer?this.onOpenDrawer():this.onBack&&this.onBack()}),t&&t.addEventListener("click",()=>{this.onClose&&this.onClose()}),a&&a.addEventListener("click",()=>{this.navigateToAudioScreen&&this.navigateToAudioScreen()});const i=e.querySelector("#chat-input"),s=e.querySelector("#chat-send"),o=e.querySelector("#file-upload-input");e.querySelector("#file-upload-button").addEventListener("click",()=>{o.click()}),o.addEventListener("change",e=>{this.handleFileUpload(e)});const r=()=>{const e=i.value.trim().length>0,n=this.contentBlocks.length>0;s.disabled=!(e||n)};i.addEventListener("input",()=>{r()});const c=async()=>{const e=i.value.trim();if(e||0!==this.contentBlocks.length)if(this.addMessage(e||"š File attachments",!0),i.value="",s.disabled=!0,this.hideTypingIndicator(),this.sendMessage)try{await this.sendMessage(e,this.contentBlocks),this.contentBlocks=[],this.onContentBlocksChange(this.contentBlocks),this.renderFilePreview(),this.updateSendButton()}catch(e){console.error("Error sending message:",e),this.addMessage("Sorry, I encountered an error. Please try again.",!1)}finally{this.hideTypingIndicator()}else setTimeout(()=>{this.hideTypingIndicator(),this.handleUserMessage(e)},1e3+1e3*Math.random())};s.addEventListener("click",c),i.addEventListener("keypress",e=>{"Enter"!==e.key||s.disabled||c()}),setTimeout(()=>i.focus(),100),this.renderFilePreview(),this.messages&&this.messages.length>0&&setTimeout(()=>{this._syncMessages(this.messages)},50)}fileToContentBlock(e){return new Promise((n,t)=>{const a=new FileReader;a.onload=()=>{const i=a.result.split(",")[1];this.SUPPORTED_FILE_TYPES.includes(e.type)?n({type:"image",source_type:"base64",mime_type:e.type,data:i,metadata:{name:e.name,size:e.size}}):t(new Error("Unsupported file type: ".concat(e.type)))},a.onerror=()=>{t(new Error("Failed to read file: ".concat(e.name)))},a.readAsDataURL(e)})}isDuplicateFile(e,n){return!!this.SUPPORTED_FILE_TYPES.includes(e.type)&&n.some(n=>{var t;return"image"===n.type&&(null===(t=n.metadata)||void 0===t?void 0:t.name)===e.name&&n.mime_type===e.type})}formatFileSize(e){if(0===e)return"0 Bytes";const n=Math.floor(Math.log(e)/Math.log(1024));return parseFloat((e/Math.pow(1024,n)).toFixed(2))+" "+["Bytes","KB","MB","GB"][n]}getFileTypeDisplay(e){switch(e){case"image/jpeg":case"image/jpg":return"JPEG Image";case"image/png":return"PNG Image";case"image/gif":return"GIF Image";case"image/webp":return"WebP Image";default:return"Unknown File"}}async handleFileUpload(e){const n=e.target.files;if(!n)return;const t=Array.from(n),a=t.filter(e=>this.SUPPORTED_FILE_TYPES.includes(e.type));t.filter(e=>!this.SUPPORTED_FILE_TYPES.includes(e.type)).length>0&&console.warn("Invalid file type. Please upload a JPEG, PNG, GIF, or WEBP image.");const i=a[0];if(i)try{const e=await this.fileToContentBlock(i);this.contentBlocks=[e],this.onContentBlocksChange(this.contentBlocks),this.renderFilePreview(),this.updateSendButton()}catch(e){console.error("Failed to process files: ".concat(e.message))}e.target.value=""}removeBlock(e){this.contentBlocks=this.contentBlocks.filter((n,t)=>t!==e),this.onContentBlocksChange(this.contentBlocks),this.renderFilePreview(),this.updateSendButton()}updateSendButton(){if(!this.container)return;const e=this.container.querySelector("#chat-input"),n=this.container.querySelector("#chat-send");if(!e||!n)return;const t=e.value.trim().length>0,a=this.contentBlocks.length>0;n.disabled=!(t||a)}renderFilePreview(){if(!this.container)return;const e=this.container.querySelector("#file-attachments-container");if(e){if(!this.contentBlocks||0===this.contentBlocks.length)return e.innerHTML="",void(e.style.display="none");e.style.display="flex",e.innerHTML=this.contentBlocks.map((e,n)=>{var t,a,i;const s=(null===(t=e.metadata)||void 0===t?void 0:t.filename)||(null===(a=e.metadata)||void 0===a?void 0:a.name)||"file",o=this.formatFileSize((null===(i=e.metadata)||void 0===i?void 0:i.size)||0),r="image"===e.type,c=r?"data:".concat(e.mime_type,";base64,").concat(e.data):null;return'\n <div class="file-attachment '.concat(r?"has-thumbnail":"",'" data-index="').concat(n,'">\n ').concat(r?'\n <div class="file-thumbnail">\n <img src="'.concat(c,'" alt="').concat(s,'" class="file-thumbnail-image" />\n </div>\n '):'<div class="file-attachment-icon">š</div>','\n <div class="file-attachment-info">\n <div class="file-attachment-name" title="').concat(s,'">\n ').concat(s,'\n </div>\n <div class="file-attachment-size">').concat(o,'</div>\n </div>\n <button\n class="file-attachment-remove"\n data-index="').concat(n,'"\n title="Remove file"\n >\n ā\n </button>\n </div>\n ')}).join(""),e.querySelectorAll(".file-attachment-remove").forEach(e=>{e.addEventListener("click",n=>{n.stopPropagation();const t=parseInt(e.getAttribute("data-index"));this.removeBlock(t)})}),e.querySelectorAll(".file-thumbnail-image").forEach(e=>{e.addEventListener("click",e=>{e.stopPropagation()})})}}_formatTime(e){let n=e.getHours();const t=e.getMinutes(),a=n>=12?"PM":"AM";n%=12,n=n||12;return n.toString().padStart(2,"0")+":"+t.toString().padStart(2,"0")+" "+a}addMessage(e,n){let t=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;if(console.log("Is user",n),!this.container)return;const a=this.container.querySelector("#chat-messages");if(!a)return;const i=a.querySelector(".chat-welcome");i&&i.remove();const s=(null==t?void 0:t.id)||Date.now();console.log("Message ID",s);const o=a.querySelector('[data-message-id="'.concat(s,'"]'));if(o&&t){const n=o.querySelector(".message-bubble");return n&&(n.innerHTML=this._escapeHtml(t.content||e)),void(a.scrollTop=a.scrollHeight)}const r=document.createElement("div");r.className="chat-message ".concat(n?"user":"bot"),r.setAttribute("data-message-id",s);let c=e;t&&(t.isStreaming?c=t.content||"Thinking...":t.isError?(c=t.content||"Error occurred",r.classList.add("error")):c=t.content||e);let l="";t&&t.attachments&&t.attachments.length>0&&(l='\n <div class="message-attachments">\n '.concat(t.attachments.map((e,n)=>{var t,a,i;const s=(null===(t=e.metadata)||void 0===t?void 0:t.name)||(null===(a=e.metadata)||void 0===a?void 0:a.filename)||"Unknown file",o="image"===e.type,r=o&&e.data?"data:".concat(e.mime_type,";base64,").concat(e.data):null;return'\n <div class="message-attachment '.concat(o?"image":"pdf",'" data-attachment-index="').concat(n,'">\n <span class="message-attachment-icon">\n ').concat(o?"š¼ļø":"š",'\n </span>\n <div class="message-attachment-info">\n <div \n class="message-attachment-name ').concat(o?"clickable":"",'"\n ').concat(o&&r?'data-image-src="'.concat(r,'" data-image-alt="').concat(s,'"'):"",'\n style="cursor: ').concat(o?"pointer":"default",';"\n >\n ').concat(this._escapeHtml(s),'\n </div>\n <div class="message-attachment-size">\n ').concat(this.formatFileSize((null===(i=e.metadata)||void 0===i?void 0:i.size)||0)," ⢠").concat(this.getFileTypeDisplay(e.mime_type),"\n </div>\n </div>\n </div>\n ")}).join(""),"\n </div>\n "));const d=null!=t&&t.timestamp?new Date(t.timestamp):new Date,h=this._formatTime(d);r.innerHTML='\n <div class="message-content">\n '.concat(l,'\n <div class="message-bubble">\n ').concat(this._escapeHtml(c),'\n </div>\n <div class="message-time">').concat(h,"</div>\n </div>\n "),t&&t.attachments&&r.querySelectorAll(".message-attachment-name.clickable").forEach(e=>{e.addEventListener("click",n=>{n.stopPropagation();const t=e.getAttribute("data-image-src"),a=e.getAttribute("data-image-alt");t&&this.showExpandedImage(t,a)})}),a.appendChild(r),a.scrollTop=a.scrollHeight}_syncMessages(e){if(!this.container)return;const n=this.container.querySelector("#chat-messages");if(!n)return;if(e.length>0){const e=n.querySelector(".chat-welcome");e&&e.remove()}const t=n.querySelectorAll("[data-message-id]"),a=new Set(Array.from(t).map(e=>e.getAttribute("data-message-id")));e.forEach(e=>{const t=String(e.id);if(a.has(t)){const a=n.querySelector('[data-message-id="'.concat(t,'"]'));if(a){const n=a.querySelector(".message-bubble");n&&(n.innerHTML=this._escapeHtml(e.content||""));const t=a.querySelector(".message-content");if(t&&e.attachments&&e.attachments.length>0){let n='\n <div class="message-attachments">\n '.concat(e.attachments.map((e,n)=>{var t,a,i;const s=(null===(t=e.metadata)||void 0===t?void 0:t.name)||(null===(a=e.metadata)||void 0===a?void 0:a.filename)||"Unknown file",o="image"===e.type,r=o&&e.data?"data:".concat(e.mime_type,";base64,").concat(e.data):null;return'\n <div class="message-attachment '.concat(o?"image":"pdf",'" data-attachment-index="').concat(n,'">\n <span class="message-attachment-icon">\n ').concat(o?"š¼ļø":"š",'\n </span>\n <div class="message-attachment-info">\n <div \n class="message-attachment-name ').concat(o?"clickable":"",'"\n ').concat(o&&r?'data-image-src="'.concat(r,'" data-image-alt="').concat(s,'"'):"",'\n style="cursor: ').concat(o?"pointer":"default",';"\n >\n ').concat(this._escapeHtml(s),'\n </div>\n <div class="message-attachment-size">\n ').concat(this.formatFileSize((null===(i=e.metadata)||void 0===i?void 0:i.size)||0)," ⢠").concat(this.getFileTypeDisplay(e.mime_type),"\n </div>\n </div>\n </div>\n ")}).join(""),"\n </div>\n ");const a=t.querySelector(".message-attachments");a?a.outerHTML=n:t.insertAdjacentHTML("afterbegin",n),t.querySelectorAll(".message-attachment-name.clickable").forEach(e=>{const n=e.cloneNode(!0);e.parentNode.replaceChild(n,e),n.addEventListener("click",e=>{e.stopPropagation();const t=n.getAttribute("data-image-src"),a=n.getAttribute("data-image-alt");t&&this.showExpandedImage(t,a)})})}e.isStreaming?a.classList.add("streaming"):a.classList.remove("streaming"),e.isError&&a.classList.add("error")}}else this.addMessage(e.content||"","user"===e.sender,e)}),t.forEach(n=>{const t=n.getAttribute("data-message-id");e.some(e=>String(e.id)===t)||n.remove()}),n.scrollTop=n.scrollHeight}showTypingIndicator(){if(!this.container)return;const e=this.container.querySelector("#chat-messages");if(!e)return;const n=document.createElement("div");n.className="chat-message bot",n.id="typing-indicator",n.innerHTML='\n <div class="typing-indicator">\n <div class="typing-dot"></div>\n <div class="typing-dot"></div>\n <div class="typing-dot"></div>\n </div>\n ',e.appendChild(n),e.scrollTop=e.scrollHeight}hideTypingIndicator(){if(!this.container)return;const e=this.container.querySelector("#typing-indicator");e&&e.remove()}handleUserMessage(e){this.onMessage?this.onMessage(e,e=>{this.addMessage(e,!1)}):this.addMessage('You said: "'.concat(e,'"'),!1)}_escapeHtml(e){const n=document.createElement("div");return n.textContent=e,n.innerHTML}showExpandedImage(e,n){const t=document.querySelector(".expanded-image-modal");t&&t.remove();const a=document.createElement("div");a.className="expanded-image-modal",a.innerHTML='\n <div class="expanded-image-container">\n <button class="expanded-image-close" title="Close">ā</button>\n <img src="'.concat(e,'" alt="').concat(n||"Image",'" class="expanded-image" />\n <div class="expanded-image-caption">').concat(this._escapeHtml(n||"Image preview"),"</div>\n </div>\n ");const i=e=>{null==e||e.stopPropagation(),a.remove(),document.removeEventListener("mousedown",s)},s=e=>{e.target.closest(".expanded-image-container")||i(e)};a.querySelector(".expanded-image-close").addEventListener("click",i),a.addEventListener("click",e=>{e.target===a&&i(e)}),document.addEventListener("mousedown",s),document.body.appendChild(a)}_applyStyles(){if(document.getElementById("text-chat-screen-styles"))return;const e=document.createElement("style");e.id="text-chat-screen-styles",e.textContent="\n .text-chat-screen {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n \n }\n\n .text-chat-screen .chat-header {\n background: transparent;\n color: ".concat(this.primaryColor,";\n padding: 20px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n }\n\n .text-chat-screen .chat-header-content {\n display: flex;\n align-items: center;\n gap: 12px;\n flex: 1;\n }\n\n .text-chat-screen .chat-back {\n background: ").concat(this.primaryColor,";\n border: none;\n color: white;\n cursor: pointer;\n padding: 8px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s;\n margin-right: 8px;\n }\n\n \n\n .text-chat-screen .chat-avatar {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n background: rgba(255, 255, 255, 0.2);\n backdrop-filter: blur(10px);\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .text-chat-screen .chat-header-text {\n display: flex;\n flex-direction: column;\n gap: 2px;\n }\n\n .text-chat-screen .chat-title {\n font-weight: 600;\n font-size: 20px;\n }\n\n .text-chat-screen .chat-status {\n font-size: 12px;\n opacity: 0.9;\n display: flex;\n align-items: center;\n gap: 4px;\n }\n\n .text-chat-screen .chat-close {\n background: ").concat(this.primaryColor,";\n border: none;\n color: white;\n cursor: pointer;\n padding: 8px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s;\n }\n\n \n\n .text-chat-screen .chat-messages {\n flex: 1;\n padding: 20px;\n overflow-y: auto;\n background: linear-gradient(180deg, white 10%, #E1EFCC );\n display: flex;\n flex-direction: column;\n gap: 12px;\n }\n\n .text-chat-screen .chat-messages::-webkit-scrollbar {\n width: 6px;\n }\n\n .text-chat-screen .chat-messages::-webkit-scrollbar-track {\n background: transparent;\n }\n\n .text-chat-screen .chat-messages::-webkit-scrollbar-thumb {\n background: #cbd5e1;\n border-radius: 3px;\n }\n\n .text-chat-screen .chat-welcome {\n text-align: center;\n padding: 100px 20px;\n color: #64748b;\n \n }\n\n .text-chat-screen .chat-welcome .welcome-icon {\n font-size: 48px;\n margin-bottom: 12px;\n }\n\n .text-chat-screen .welcome-text {\n font-size: 15px;\n font-weight: 500;\n color: #475569;\n }\n\n .text-chat-screen .chat-message {\n display: flex;\n gap: 8px;\n animation: messageSlide 0.3s ease-out;\n }\n\n @keyframes messageSlide {\n from {\n opacity: 0;\n transform: translateY(10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n .text-chat-screen .chat-message.user {\n flex-direction: row-reverse;\n }\n\n .text-chat-screen .message-content {\n max-width: 75%;\n }\n\n .text-chat-screen .message-bubble {\n padding: 12px 16px;\n border-radius: 16px;\n font-size: 14px;\n line-height: 1.5;\n word-wrap: break-word;\n }\n\n .text-chat-screen .chat-message.user .message-bubble {\n background: #e9f5d7;\n color: ").concat(this.primaryColor,";\n border-bottom-right-radius: 4px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n }\n\n .text-chat-screen .chat-message.bot .message-bubble {\n background: white;\n color: #1e293b;\n border-bottom-left-radius: 4px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n }\n\n .text-chat-screen .message-time {\n font-size: 10px;\n color: #94a3b8;\n margin-top: 4px;\n text-align: right;\n }\n\n .text-chat-screen .typing-indicator {\n display: flex;\n gap: 4px;\n padding: 12px 16px;\n background: white;\n border-radius: 16px;\n border-bottom-left-radius: 4px;\n max-width: 60px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n }\n\n .text-chat-screen .typing-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: #94a3b8;\n animation: typing 1.4s infinite;\n }\n\n .text-chat-screen .typing-dot:nth-child(2) {\n animation-delay: 0.2s;\n }\n\n .text-chat-screen .typing-dot:nth-child(3) {\n animation-delay: 0.4s;\n }\n\n @keyframes typing {\n 0%, 60%, 100% {\n transform: translateY(0);\n opacity: 0.7;\n }\n 30% {\n transform: translateY(-10px);\n opacity: 1;\n }\n }\n\n .text-chat-screen .file-attachments-container {\n padding: 8px 12px;\n background: white;\n border-top: 1px solid #e2e8f0;\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n max-height: 120px;\n overflow-y: auto;\n }\n\n .text-chat-screen .file-attachments-container::-webkit-scrollbar {\n width: 4px;\n height: 4px;\n }\n\n .text-chat-screen .file-attachments-container::-webkit-scrollbar-track {\n background: transparent;\n }\n\n .text-chat-screen .file-attachments-container::-webkit-scrollbar-thumb {\n background: #cbd5e1;\n border-radius: 2px;\n }\n\n .text-chat-screen .file-attachment {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 10px;\n background: #f1f5f9;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n font-size: 12px;\n max-width: 200px;\n position: relative;\n }\n\n .text-chat-screen .file-attachment.has-thumbnail {\n padding: 4px;\n }\n\n .text-chat-screen .file-thumbnail {\n width: 40px;\n height: 40px;\n border-radius: 6px;\n overflow: hidden;\n flex-shrink: 0;\n background: #e2e8f0;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .text-chat-screen .file-thumbnail-image {\n width: 100%;\n height: 100%;\n object-fit: cover;\n cursor: pointer;\n }\n\n .text-chat-screen .file-attachment-icon {\n font-size: 24px;\n flex-shrink: 0;\n }\n\n .text-chat-screen .file-attachment-info {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n }\n\n .text-chat-screen .file-attachment-name {\n font-weight: 500;\n color: #1e293b;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 120px;\n }\n\n .text-chat-screen .file-attachment-size {\n font-size: 11px;\n color: #64748b;\n }\n\n .text-chat-screen .file-attachment-remove {\n background: transparent;\n border: none;\n color: #64748b;\n cursor: pointer;\n padding: 4px;\n border-radius: 4px;\n font-size: 16px;\n line-height: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s;\n flex-shrink: 0;\n }\n\n .text-chat-screen .file-attachment-remove:hover {\n background: #fee2e2;\n color: #dc2626;\n }\n\n .text-chat-screen .chat-input-wrapper {\n display: flex;\n padding: 10px;\n gap: 8px;\n background: white;\n border-top: 1px solid #e2e8f0;\n align-items: center;\n }\n\n .text-chat-screen .file-upload-controls {\n display: flex;\n align-items: center;\n }\n\n .text-chat-screen .file-upload-button {\n background: transparent;\n border: none;\n color: ").concat(this.primaryColor,";\n cursor: pointer;\n padding: 8px;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s;\n }\n\n .text-chat-screen .file-upload-button:hover {\n background: rgba(26, 92, 75, 0.1);\n }\n\n .text-chat-screen .file-upload-button:active {\n transform: scale(0.95);\n }\n\n .text-chat-screen #chat-input {\n flex: 1;\n border: 2px solid #e2e8f0;\n border-radius: 12px;\n padding: 12px 16px;\n font-size: 14px;\n outline: none;\n transition: all 0.2s;\n font-family: inherit;\n }\n\n .text-chat-screen #chat-input:focus {\n border-color: ").concat(this.primaryColor,";\n box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);\n }\n\n .text-chat-screen #chat-send {\n background: ").concat(this.primaryColor,";\n color: white;\n border: none;\n border-radius: 12px;\n padding: 12px 16px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s;\n }\n\n .text-chat-screen #chat-send:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .text-chat-screen #chat-send:not(:disabled):hover {\n transform: scale(1.05);\n box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3);\n }\n\n .text-chat-screen #chat-send:not(:disabled):active {\n transform: scale(0.95);\n }\n\n /* Message Attachments Styles */\n .text-chat-screen .message-attachments {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-bottom: 8px;\n }\n\n .text-chat-screen .message-attachment {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n background: #f1f5f9;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n font-size: 12px;\n max-width: 100%;\n }\n\n .text-chat-screen .message-attachment.image {\n background: #f8fafc;\n }\n\n .text-chat-screen .message-attachment.pdf {\n background: #fef2f2;\n }\n\n .text-chat-screen .message-attachment-icon {\n font-size: 20px;\n flex-shrink: 0;\n }\n\n .text-chat-screen .message-attachment-info {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n }\n\n .text-chat-screen .message-attachment-name {\n font-weight: 500;\n color: #1e293b;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .text-chat-screen .message-attachment-name.clickable:hover {\n color: ").concat(this.primaryColor,";\n text-decoration: underline;\n }\n\n .text-chat-screen .message-attachment-size {\n font-size: 11px;\n color: #64748b;\n }\n\n /* Expanded Image Modal Styles */\n .expanded-image-modal {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.8);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10000;\n animation: fadeIn 0.2s ease;\n }\n\n @keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n }\n\n .expanded-image-container {\n position: relative;\n max-width: 90%;\n max-height: 90vh;\n background: #fff;\n border-radius: 8px;\n overflow: hidden;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);\n animation: scaleIn 0.2s ease;\n display: flex;\n flex-direction: column;\n }\n\n @keyframes scaleIn {\n from {\n transform: scale(0.9);\n opacity: 0;\n }\n to {\n transform: scale(1);\n opacity: 1;\n }\n }\n\n .expanded-image-close {\n position: absolute;\n top: 12px;\n right: 12px;\n background: rgba(0, 0, 0, 0.6);\n border: none;\n color: white;\n width: 32px;\n height: 32px;\n border-radius: 50%;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 18px;\n z-index: 1;\n transition: all 0.2s;\n }\n\n .expanded-image-close:hover {\n background: rgba(0, 0, 0, 0.8);\n transform: scale(1.1);\n }\n\n .expanded-image {\n max-width: 100%;\n max-height: calc(90vh - 60px);\n object-fit: contain;\n display: block;\n }\n\n .expanded-image-caption {\n padding: 12px 16px;\n background: #fff;\n color: #1e293b;\n font-size: 14px;\n text-align: center;\n border-top: 1px solid #e2e8f0;\n }\n "),document.head.appendChild(e)}}class i{constructor(){this.apiKey="23588533c1-d990-4a7d-b052-d970c886147e",this.userId="749bd0b0c65e4d17a372be0ad92af981",this.callbackUrl="https://meity-auth.ulcacontrib.org/ulca/apis/v0/model/getModelsPipeline",this.inferenceUrl=null,this.inferenceHeaders={},this.asrServiceId={hi:"ai4bharat/conformer-hi-gpu--t4",en:"ai4bharat/whisper-medium-en--gpu--t4"},this.ttsServiceId={hi:"ai4bharat/indic-tts-coqui-indo_aryan-gpu--t4",en:"ai4bharat/indic-tts-coqui-misc-gpu--t4"},this.translationServiceId="ai4bharat/indictrans-v2-all-gpu--t4"}async initialize(){try{const e=await fetch(this.callbackUrl,{method:"POST",headers:{"Content-Type":"application/json",userID:this.userId,ulcaApiKey:this.apiKey},body:JSON.stringify({pipelineTasks:[{taskType:"asr"}],pipelineRequestConfig:{pipelineId:"64392f96daac500b55c543cd"}})}),n=await e.json();if(n.pipelineInferenceAPIEndPoint){this.inferenceUrl=n.pipelineInferenceAPIEndPoint.callbackUrl;const e=n.pipelineInferenceAPIEndPoint.inferenceApiKey.name,t=n.pipelineInferenceAPIEndPoint.inferenceApiKey.value;this.inferenceHeaders={"Content-Type":"application/json",[e]:t}}else this.inferenceUrl="https://dhruva-api.bhashini.gov.in/services/inference/pipeline",this.inferenceHeaders={"Content-Type":"application/json",userID:this.userId,ulcaApiKey:this.apiKey};return!0}catch(e){return console.error("Failed to initialize Bhashini:",e),this.inferenceUrl="https://dhruva-api.bhashini.gov.in/services/inference/pipeline",this.inferenceHeaders={"Content-Type":"application/json",userID:this.userId,ulcaApiKey:this.apiKey},!1}}async convertToWav(e){return new Promise((n,t)=>{const a=new(window.AudioContext||window.webkitAudioContext),i=new FileReader;i.onload=async e=>{try{const t=e.target.result,i=await a.decodeAudioData(t),s=new OfflineAudioContext(1,16e3*i.duration,16e3),o=s.createBufferSource();o.buffer=i,o.connect(s.destination),o.start();const r=await s.startRendering(),c=this.audioBufferToWav(r),l=new Blob([c],{type:"audio/wav"}),d=new FileReader;d.onloadend=()=>{const e=d.result.split(",")[1];n(e)},d.readAsDataURL(l)}catch(e){t(e)}},i.onerror=t,i.readAsArrayBuffer(e)})}audioBufferToWav(e){const n=e.length*e.numberOfChannels*2+44,t=new ArrayBuffer(n),a=new DataView(t),i=[];let s=0,o=0;const r=e=>{a.setUint16(o,e,!0),o+=2},c=e=>{a.setUint32(o,e,!0),o+=4};c(1179011410),c(n-8),c(1163280727),c(544501094),c(16),r(1),r(e.numberOfChannels),c(e.sampleRate),c(2*e.sampleRate*e.numberOfChannels),r(2*e.numberOfChannels),r(16),c(1635017060),c(n-o-4);for(let n=0;n<e.numberOfChannels;n++)i.push(e.getChannelData(n));for(;o<n;){for(let n=0;n<e.numberOfChannels;n++){let e=Math.max(-1,Math.min(1,i[n][s]));e=e<0?32768*e:32767*e,a.setInt16(o,e,!0),o+=2}s++}return t}async speechToText(e){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"auto",t=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"hi";this.inferenceUrl||await this.initialize();const a=[{taskType:"asr",config:{language:{sourceLanguage:n},serviceId:this.asrServiceId[n]||this.asrServiceId.hi,audioFormat:"wav",samplingRate:16e3}}];n!==t&&a.push({taskType:"translation",config:{sourceLanguage:"auto"===n?void 0:n,targetLanguage:t}});const i=await fetch(this.inferenceUrl,{method:"POST",headers:this.inferenceHeaders,body:JSON.stringify({pipelineTasks:a,inputData:{audio:[{audioContent:e}]}})});if(!i.ok)throw new Error("API error: ".concat(i.status," ").concat(i.statusText));const s=await i.json();return a.length>1?s.pipelineResponse[1].output[0].target:s.pipelineResponse[0].output[0].source}async textToSpeech(e){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"en",t=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"female";this.inferenceUrl||await this.initialize();const a=e.replace(/!/g,"."),i=await fetch(this.inferenceUrl,{method:"POST",headers:this.inferenceHeaders,body:JSON.stringify({pipelineTasks:[{taskType:"tts",config:{language:{sourceLanguage:n},serviceId:this.ttsServiceId[n]||this.ttsServiceId.en,samplingRate:8e3,gender:t}}],inputData:{input:[{source:a}]}})});if(!i.ok)throw new Error("TTS API error: ".concat(i.status," ").concat(i.statusText));return(await i.json()).pipelineResponse[0].audio[0].audioContent}async translateText(e,n,t){this.inferenceUrl||await this.initialize();const a=await fetch(this.inferenceUrl,{method:"POST",headers:this.inferenceHeaders,body:JSON.stringify({pipelineTasks:[{taskType:"translation",config:{language:{sourceLanguage:n,targetLanguage:t},serviceId:this.translationServiceId}}],inputData:{input:[{source:e}]}})});if(!a.ok)throw new Error("Translation API error: ".concat(a.status," ").concat(a.statusText));return(await a.json()).pipelineResponse[0].output[0].target}async speechToEnglish(e){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"hi";const t=await this.speechToText(e,n);if("en"===n)return{transcription:t,translation:t};return{transcription:t,translation:await this.translateText(t,n,"en")}}async speechToHindi(e){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"en";const t=await this.speechToText(e,n);if("hi"===n)return{transcription:t,translation:t};return{transcription:t,translation:await this.translateText(t,n,"hi")}}async transcribeSpeechToEnglish(e){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"hi";const t=await this.speechToText(e,n);if("en"===n)return{transcription:t,translation:t};return{transcription:t,translation:await this.translateText(t,n,"en")}}}class s{constructor(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.primaryColor=e.primaryColor||"#1a5c4b",this.title=e.title||"Chat Assistant",this.onRecordStart=e.onRecordStart||(()=>{}),this.onRecordStop=e.onRecordStop||(()=>{}),this.onBack=e.onBack||(()=>{}),this.onOpenDrawer=e.onOpenDrawer||(()=>{}),this.onClose=e.onClose||(()=>{}),this.navigateToTextScreen=e.navigateToTextScreen,this.sendMessage=e.sendMessage||null,this.selectedLanguage=e.selectedLanguage||"en",this.container=null,this.messages=e.messages||[],this.bhashini=new i,this.mediaRecorder=null,this.audioChunks=[],this.isRecording=!1,this.playedMessageIds=new Set,this.audioQueue=[],this.isPlaying=!1,this.contentBlocks=[],this.SUPPORTED_FILE_TYPES=["image/jpeg","image/png","image/gif","image/webp"]}render(e){this.container=e,this._applyStyles(),e.innerHTML='\n <div class="audio-chat-screen">\n <div class="chat-header">\n <div class="chat-header-content">\n <button class="chat-back" id="audio-chat-menu">\n <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-menu-icon lucide-menu"><path d="M4 5h16"/><path d="M4 12h16"/><path d="M4 19h16"/></svg>\n </button>\n \n <div class="chat-header-text">\n <div class="chat-title">'.concat(this.title,'</div>\n </div>\n </div>\n <button class="chat-close" id="navigate-to-text-screen">\n <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-message-square-text-icon lucide-message-square-text"><path d="M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z"/><path d="M7 11h10"/><path d="M7 15h6"/><path d="M7 7h8"/></svg>\n </button>\n ​ ​ ​\n <button class="chat-close" id="audio-chat-close">\n <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <line x1="18" y1="6" x2="6" y2="18"></line>\n <line x1="6" y1="6" x2="18" y2="18"></line>\n </svg>\n </button>\n </div>\n \n \n <div class="chat-messages" id="chat-messages">\n <div class="chat-welcome">\n <div class="welcome-text">š Hello! I\'m your AI assistant. How can I help you today?</div>\n </div>\n </div> \n \n \n <div class="file-attachments-container" id="file-attachments-container" style="display: none;"></div>\n <div class="bottom-inputs">\n <button id="record-button">\n <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-mic-icon lucide-mic"><path d="M12 19v3"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><rect x="9" y="2" width="6" height="13" rx="3"/></svg>\n </button>\n ​ ​ ​​ ​ ​\n <input\n type="file"\n id="file-upload-input"\n accept="image/jpeg,image/png,image/gif,image/webp"\n style="display: none;"\n />\n <button id="attachment-button">\n <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-paperclip-icon lucide-paperclip"><path d="m16 6-8.414 8.586a2 2 0 0 0 2.829 2.829l8.414-8.586a4 4 0 1 0-5.657-5.657l-8.379 8.551a6 6 0 1 0 8.485 8.485l8.379-8.551"/></svg>\n </button>\n </div>\n \n \n </div>\n ');const n=e.querySelector("#audio-chat-menu"),t=e.querySelector("#audio-chat-close"),a=e.querySelector("#navigate-to-text-screen");n&&n.addEventListener("click",()=>{this.onOpenDrawer?this.onOpenDrawer():this.onBack&&this.onBack()}),t&&t.addEventListener("click",()=>{this.onClose&&this.onClose()}),a&&a.addEventListener("click",()=>{this.navigateToTextScreen&&this.navigateToTextScreen()});const i=e.querySelector("#record-button"),s=e.querySelector("#attachment-button");i&&i.addEventListener("click",()=>{this.toggleRecording(i)});const o=e.querySelector("#file-upload-input");s&&o&&(s.addEventListener("click",()=>{o.click()}),o.addEventListener("change",e=>{this.handleFileUpload(e)})),this.messages&&this.messages.length>0&&setTimeout(()=>{this._syncMessages(this.messages)},50)}fileToContentBlock(e){return new Promise((n,t)=>{const a=new FileReader;a.onload=()=>{const i=a.result.split(",")[1];this.SUPPORTED_FILE_TYPES.includes(e.type)?n({type:"image",source_type:"base64",mime_type:e.type,data:i,metadata:{name:e.name,size:e.size}}):t(new Error("Unsupported file type: ".concat(e.type)))},a.onerror=()=>{t(new Error("Failed to read file: ".concat(e.name)))},a.readAsDataURL(e)})}async handleFileUpload(e){const n=e.target.files;if(!n)return;const t=Array.from(n),a=t.filter(e=>this.SUPPORTED_FILE_TYPES.includes(e.type));if(0===a.length)return void(t.length>0&&console.warn("Invalid file type."));const i=a[0];try{const e=await this.fileToContentBlock(i);this.contentBlocks=[e],this.renderFilePreview()}catch(e){console.error("Error processing file:",e)}e.target.value=""}removeBlock(e){this.contentBlocks=[],this.renderFilePreview()}renderFilePreview(){if(!this.container)return;const e=this.container.querySelector("#file-attachments-container");if(e){if(!this.contentBlocks||0===this.contentBlocks.length)return e.innerHTML="",void(e.style.display="none");e.style.display="flex",e.innerHTML=this.contentBlocks.map((e,n)=>{var t,a,i;const s=(null===(t=e.metadata)||void 0===t?void 0:t.filename)||(null===(a=e.metadata)||void 0===a?void 0:a.name)||"file",o=this.formatFileSize((null===(i=e.metadata)||void 0===i?void 0:i.size)||0),r="image"===e.type,c=r?"data:".concat(e.mime_type,";base64,").concat(e.data):null;return'\n <div class="file-attachment '.concat(r?"has-thumbnail":"",'" data-index="').concat(n,'">\n <div class="file-thumbnail">\n <img src="').concat(c,'" alt="').concat(s,'" class="file-thumbnail-image" />\n </div>\n <div class="file-attachment-info">\n <div class="file-attachment-name" title="').concat(s,'">\n ').concat(s,'\n </div>\n <div class="file-attachment-size">').concat(o,'</div>\n </div>\n <button\n class="file-attachment-remove"\n data-index="').concat(n,'"\n title="Remove file"\n >\n ā\n </button>\n </div>\n ')}).join(""),e.querySelectorAll(".file-attachment-remove").forEach(e=>{e.addEventListener("click",n=>{n.stopPropagation();const t=parseInt(e.getAttribute("data-index"));this.removeBlock(t)})})}}async toggleRecording(e){this.isRecording?this.stopRecording(e):await this.startRecording(e)}async startRecording(e){try{const n=await navigator.mediaDevices.getUserMedia({audio:!0});this.mediaRecorder=new MediaRecorder(n),this.audioChunks=[],this.mediaRecorder.ondataavailable=e=>{this.audioChunks.push(e.data)},this.mediaRecorder.onstop=async()=>{const e=new Blob(this.audioChunks,{type:"audio/wav"});this.audioChunks=[],n.getTracks().forEach(e=>e.stop()),await this.processAudioInput(e)},this.mediaRecorder.start(),this.isRecording=!0,this.onRecordStart(),e.classList.add("recording"),e.innerHTML='\n <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-square-icon"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect></svg>\n ',this.stopTTS()}catch(e){console.error("Error accessing microphone:",e),alert("Could not access microphone. Please check permissions.")}}stopRecording(e){this.mediaRecorder&&this.isRecording&&(this.mediaRecorder.stop(),this.isRecording=!1,this.onRecordStop(),e.classList.remove("recording"),e.innerHTML='\n <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-mic-icon lucide-mic"><path d="M12 19v3"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><rect x="9" y="2" width="6" height="13" rx="3"/></svg>\n ')}async processAudioInput(e){try{const n=await this.bhashini.convertToWav(e),t=await this.bhashini.speechToText(n,this.selectedLanguage,this.selectedLanguage);t&&t.trim()&&this.sendMessage&&(await this.sendMessage(t,this.contentBlocks),this.contentBlocks=[],this.renderFilePreview())}catch(e){console.error("Error processing audio:",e),this.addMessage("Sorry, I couldn't understand that.",!1,{isError:!0})}}stopTTS(){this.currentAudio&&(this.currentAudio.pause(),this.currentAudio=null),this.audioQueue=[],this.isPlaying=!1}async playNextInQueue(){if(!(this.container&&this.container.querySelector(".audio-chat-screen")))return;if(console.log("Playing next in queue",this.audioQueue),this.isPlaying||0===this.audioQueue.length)return;this.isPlaying=!0;const e=this.audioQueue.shift();try{const n=await this.bhashini.textToSpeech(e,this.selectedLanguage);if(n){const e="data:audio/wav;base64,".concat(n);this.currentAudio=new Audio(e),this.currentAudio.onended=()=>{this.isPlaying=!1,this.playNextInQueue()},this.currentAudio.onerror=()=>{this.isPlaying=!1,this.playNextInQueue()},await this.currentAudio.play()}else this.isPlaying=!1,this.playNextInQueue()}catch(e){console.error("TTS Error:",e),this.isPlaying=!1,this.playNextInQueue()}}formatFileSize(e){if(0===e)return"0 Bytes";const n=Math.floor(Math.log(e)/Math.log(1024));return parseFloat((e/Math.pow(1024,n)).toFixed(2))+" "+["Bytes","KB","MB","GB"][n]}getFileTypeDisplay(e){switch(e){case"image/jpeg":case"image/jpg":return"JPEG Image";case"image/png":return"PNG Image";case"image/gif":return"GIF Image";case"image/webp":return"WebP Image";case"application/pdf":return"PDF Document";default:return"Unknown File"}}_formatTime(e){let n=e.getHours();const t=e.getMinutes(),a=n>=12?"PM":"AM";n%=12,n=n||12;return n.toString().padStart(2,"0")+":"+t.toString().padStart(2,"0")+" "+a}addMessage(e,n){let t=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;if(!this.container)return;const a=this.container.querySelector("#chat-messages");if(!a)return;const i=a.querySelector(".chat-welcome");i&&i.remove();const s=(null==t?void 0:t.id)||Date.now(),o=a.querySelector('[data-message-id="'.concat(s,'"]'));if(o&&t){const n=o.querySelector(".message-bubble");return n&&(n.innerHTML=this._escapeHtml(t.content||e)),void(a.scrollTop=a.scrollHeight)}const r=document.createElement("div");r.className="chat-message ".concat(n?"user":"bot"),r.setAttribute("data-message-id",s);let c=e;t&&(t.isStreaming?c=t.content||"Thinking...":t.isError?(c=t.content||"Error occurred",r.classList.add("error")):c=t.content||e);let l="";t&&t.attachments&&t.attachments.length>0&&(l='\n <div class="message-attachments">\n '.concat(t.attachments.map((e,n)=>{var t,a,i;const s=(null===(t=e.metadata)||void 0===t?void 0:t.name)||(null===(a=e.metadata)||void 0===a?void 0:a.filename)||"Unknown file",o="image"===e.type,r=o&&e.data?"data:".concat(e.mime_type,";base64,").concat(e.data):null;return'\n <div class="message-attachment '.concat(o?"image":"pdf",'" data-attachment-index="').concat(n,'">\n <span class="message-attachment-icon">\n ').concat(o?"š¼ļø":"š",'\n </span>\n <div class="message-attachment-info">\n <div \n class="message-attachment-name ').concat(o?"clickable":"",'"\n ').concat(o&&r?'data-image-src="'.concat(r,'" data-image-alt="').concat(s,'"'):"",'\n style="cursor: ').concat(o?"pointer":"default",';"\n >\n ').concat(this._escapeHtml(s),'\n </div>\n <div class="message-attachment-size">\n ').concat(this.formatFileSize((null===(i=e.metadata)||void 0===i?void 0:i.size)||0)," ⢠").concat(this.getFileTypeDisplay(e.mime_type),"\n </div>\n </div>\n </div>\n ")}).join(""),"\n </div>\n "));const d=null!=t&&t.timestamp?new Date(t.timestamp):new Date,h=this._formatTime(d);r.innerHTML='\n <div class="message-content">\n '.concat(l,'\n <div class="message-bubble">').concat(this._escapeHtml(c),'</div>\n <div class="message-time">').concat(h,"</div>\n </div>\n "),t&&t.attachments&&r.querySelectorAll(".message-attachment-name.clickable").forEach(e=>{e.addEventListener("click",n=>{n.stopPropagation();const t=e.getAttribute("data-image-src"),a=e.getAttribute("data-image-alt");t&&this.showExpandedImage(t,a)})}),a.appendChild(r),a.scrollTop=a.scrollHeight}_syncMessages(e){if(!this.container)return;const n=this.container.querySelector("#chat-messages");if(!n)return;if(e.length>0){const e=n.querySelector(".chat-welcome");e&&e.remove()}const t=n.querySelectorAll("[data-message-id]"),a=new Set(Array.from(t).map(e=>e.getAttribute("data-message-id")));e.forEach(e=>{const t=String(e.id);if("user"===e.sender||this.playedMessageIds.has(t)||e.isStreaming||e.isProcessing||!e.content||(this.playedMessageIds.add(t),this.audioQueue.push(e.content),this.playNextInQueue()),a.has(t)){const a=n.querySelector('[data-message-id="'.concat(t,'"]'));if(a){const n=a.querySelector(".message-bubble");n&&(n.innerHTML=this._escapeHtml(e.content||""));const t=a.querySelector(".message-content");if(t&&e.attachments&&e.attachments.length>0){let n='\n <div class="message-attachments">\n '.concat(e.attachments.map((e,n)=>{var t,a,i;const s=(null===(t=e.metadata)||void 0===t?void 0:t.name)||(null===(a=e.metadata)||void 0===a?void 0:a.filename)||"Unknown file",o="image"===e.type,r=o&&e.data?"data:".concat(e.mime_type,";base64,").concat(e.data):null;return'\n <div class="message-attachment '.concat(o?"image":"pdf",'" data-attachment-index="').concat(n,'">\n <span class="message-attachment-icon">\n ').concat(o?"š¼ļø":"š",'\n </span>\n <div class="message-attachment-info">\n <div \n class="message-attachment-name ').concat(o?"clickable":"",'"\n ').concat(o&&r?'data-image-src="'.concat(r,'" data-image-alt="').concat(s,'"'):"",'\n style="cursor: ').concat(o?"pointer":"default",';"\n >\n ').concat(this._escapeHtml(s),'\n </div>\n <div class="message-attachment-size">\n ').concat(this.formatFileSize((null===(i=e.metadata)||void 0===i?void 0:i.size)||0)," ⢠").concat(this.getFileTypeDisplay(e.mime_type),"\n </div>\n </div>\n </div>\n ")}).join(""),"\n </div>\n ");const a=t.querySelector(".message-attachments");a?a.outerHTML=n:t.insertAdjacentHTML("afterbegin",n),t.querySelectorAll(".message-attachment-name.clickable").forEach(e=>{const n=e.cloneNode(!0);e.parentNode.replaceChild(n,e),n.addEventListener("click",e=>{e.stopPropagation();const t=n.getAttribute("data-image-src"),a=n.getAttribute("data-image-alt");t&&this.showExpandedImage(t,a)})})}e.isStreaming?a.classList.add("streaming"):a.classList.remove("streaming"),e.isError&&a.classList.add("error")}}else this.addMessage(e.content||"","user"===e.sender,e)}),t.forEach(n=>{const t=n.getAttribute("data-message-id");e.some(e=>String(e.id)===t)||n.remove()}),n.scrollTop=n.scrollHeight}_escapeHtml(e){const n=document.createElement("div");return n.textContent=e,n.innerHTML}showExpandedImage(e,n){const t=document.querySelector(".expanded-image-modal");t&&t.remove();const a=document.createElement("div");a.className="expanded-image-modal",a.innerHTML='\n <div class="expanded-image-container">\n <button class="expanded-image-close" title="Close">ā</button>\n <img src="'.concat(e,'" alt="').concat(n||"Image",'" class="expanded-image" />\n <div class="expanded-image-caption">').concat(this._escapeHtml(n||"Image preview"),"</div>\n </div>\n ");const i=e=>{e&&e.stopPropagation(),a.remove(),document.removeEventListener("mousedown",s)},s=e=>{e.target.closest(".expanded-image-container")||i(e)};a.querySelector(".expanded-image-close").addEventListener("click",i),a.addEventListener("click",e=>{e.target===a&&i(e)}),document.addEventListener("mousedown",s),document.body.appendChild(a)}_applyStyles(){if(document.getElementById("audio-chat-screen-styles"))return;const e=document.createElement("style");e.id="audio-chat-screen-styles",e.textContent="\n .audio-chat-screen {\n flex: 1;\n height: 100%;\n display: flex;\n flex-direction: column;\n position: relative;\n overflow: hidden;\n background: linear-gradient(180deg, white 10%, #E1EFCC );\n }\n\n .audio-chat-screen .chat-header {\n color: ".concat(this.primaryColor,";\n padding: 20px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n flex-shrink: 0;\n background: transparent;\n z-index: 20;\n }\n\n .audio-chat-screen .chat-header-content {\n display: flex;\n align-items: center;\n gap: 12px;\n flex: 1;\n }\n\n .audio-chat-screen .chat-back {\n background: ").concat(this.primaryColor,";\n border: none;\n color: white;\n cursor: pointer;\n padding: 8px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s;\n margin-right: 8px;\n }\n\n .bottom-inputs {\n width: 100%;\n padding: 20px;\n display: flex;\n justify-content: center;\n align-items: center;\n gap: 5px;\n z-index: 10;\n flex-shrink: 0;\n }\n\n .bottom-inputs button {\n border: none;\n border-radius: 9999px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: all 0.2s ease;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n }\n\n #record-button {\n width: 50px;\n height: 50px;\n background: ").concat(this.primaryColor,";\n color: #ffffff;\n }\n\n #record-button.recording {\n background: #ef4444;\n animation: pulse-ring 2s cubic-bezier(0.25, 0.46, 0.45, 0.94) infinite;\n }\n\n @keyframes pulse-ring {\n 0% {\n box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.7);\n }\n 70% {\n box-shadow: 0 0 0 10px rgba(239, 68, 68, 0);\n }\n 100% {\n box-shadow: 0 0 0 0 rgba(239, 68, 68, 0);\n }\n }\n\n #record-button:hover {\n transform: translateY(-2px) scale(1.03);\n box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);\n }\n\n #record-button:active {\n transform: translateY(0) scale(0.97);\n box-shadow: 0 3px 8px rgba(0, 0, 0, 0.15);\n }\n\n #attachment-button {\n width: 50px;\n height: 50px;\n background: #ffffff;\n color: ").concat(this.primaryColor,";\n border: 1px solid rgba(148, 163, 184, 0.5);\n }\n\n #attachment-button:hover {\n transform: translateY(-2px) scale(1.03);\n box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);\n }\n\n #attachment-button:active {\n transform: translateY(1px);\n box-shadow: 0 3px 8px rgba(15, 23, 42, 0.15);\n }\n .audio-chat-screen .chat-avatar {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n background: rgba(255, 255, 255, 0.2);\n backdrop-filter: blur(10px);\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .audio-chat-screen .chat-header-text {\n display: flex;\n flex-direction: column;\n gap: 2px;\n }\n\n .audio-chat-screen .chat-title {\n font-weight: 600;\n font-size: 20px;\n }\n\n .audio-chat-screen .chat-status {\n font-size: 12px;\n opacity: 0.9;\n display: flex;\n align-items: center;\n gap: 4px;\n }\n\n .audio-chat-screen .chat-close {\n background: ").concat(this.primaryColor,";\n border: none;\n color: white;\n cursor: pointer;\n padding: 8px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s;\n }\n\n\n .audio-chat-screen .audio-chat-content {\n flex: 1;\n height:100%;\n display: flex;\n flex-direction: column;\n padding: 20px;\n gap: 20px;\n }\n\n .audio-chat-screen .audio-status {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n background: white;\n border-radius: 16px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n }\n\n .audio-chat-screen .audio-status-icon {\n font-size: 48px;\n margin-bottom: 12px;\n transition: transform 0.3s;\n }\n\n .audio-chat-screen .audio-status-text {\n font-size: 16px;\n font-weight: 500;\n color: #475569;\n }\n\n /* Message list styles mirrored from TextChatScreen */\n .audio-chat-screen .chat-messages {\n flex: 1;\n padding: 20px;\n overflow-y: auto;\n overflow-x: hidden; /* Prevent horizontal scroll */\n min-height: 0; /* Crucial for nested flex scrolling */\n background: transparent;\n display: flex;\n flex-direction: column;\n gap: 12px;\n }\n\n .audio-chat-screen .chat-messages::-webkit-scrollbar {\n width: 6px;\n }\n\n .audio-chat-screen .chat-messages::-webkit-scrollbar-track {\n background: transparent;\n }\n\n .audio-chat-screen .chat-messages::-webkit-scrollbar-thumb {\n background: #cbd5e1;\n border-radius: 3px;\n }\n\n .audio-chat-screen .file-attachments-container {\n padding: 8px 12px;\n background: transparent;\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n max-height: 120px;\n overflow-y: auto;\n position: relative;\n z-index: 5;\n }\n\n .audio-chat-screen .file-attachment {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 10px;\n background: #f1f5f9;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n font-size: 12px;\n max-width: 200px;\n }\n\n .audio-chat-screen .file-thumbnail {\n width: 40px;\n height: 40px;\n border-radius: 6px;\n overflow: hidden;\n flex-shrink: 0;\n background: #e2e8f0;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .audio-chat-screen .file-thumbnail-image {\n width: 100%;\n height: 100%;\n object-fit: cover;\n }\n\n .audio-chat-screen .file-attachment-info {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n }\n\n .audio-chat-screen .file-attachment-name {\n font-weight: 500;\n color: #1e293b;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 120px;\n }\n\n .audio-chat-screen .file-attachment-size {\n font-size: 11px;\n color: #64748b;\n }\n\n .audio-chat-screen .file-attachment-remove {\n background: transparent;\n border: none;\n color: #64748b;\n cursor: pointer;\n padding: 4px;\n border-radius: 4px;\n font-size: 16px;\n line-height: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s;\n flex-shrink: 0;\n }\n\n .audio-chat-screen .file-attachment-remove:hover {\n background: #fee2e2;\n color: #dc2626;\n }\n\n .audio-chat-screen .chat-welcome {\n text-align: center;\n padding: 100px 20px;\n color: #64748b;\n }\n\n .audio-chat-screen .chat-welcome .welcome-icon {\n font-size: 48px;\n margin-bottom: 12px;\n }\n\n .audio-chat-screen .welcome-text {\n font-size: 15px;\n font-weight: 500;\n color: #475569;\n }\n\n .audio-chat-screen .chat-message {\n display: flex;\n gap: 8px;\n animation: messageSlide 0.3s ease-out;\n }\n\n @keyframes messageSlide {\n from {\n opacity: 0;\n transform: translateY(10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n .audio-chat-screen .chat-message.user {\n flex-direction: row-reverse;\n }\n\n .audio-chat-screen .message-content {\n max-width: 75%;\n }\n\n .audio-chat-screen .message-bubble {\n padding: 12px 16px;\n border-radius: 16px;\n font-size: 14px;\n line-height: 1.5;\n word-wrap: break-word;\n }\n\n .audio-chat-screen .chat-message.user .message-bubble {\n background: #e9f5d7;\n color: ").concat(this.primaryColor,";\n border-bottom-right-radius: 4px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n }\n\n .audio-chat-screen .chat-message.bot .message-bubble {\n background: white;\n color: #1e293b;\n border-bottom-left-radius: 4px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n }\n\n .audio-chat-screen .message-time {\n font-size: 10px;\n color: #94a3b8;\n margin-top: 4px;\n text-align: right;\n }\n\n /* Message Attachments Styles (mirrored from TextChatScreen) */\n .audio-chat-screen .message-attachments {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-bottom: 8px;\n }\n\n .audio-chat-screen .message-attachment {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n background: #f1f5f9;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n font-size: 12px;\n max-width: 100%;\n }\n\n .audio-chat-screen .message-attachment.image {\n background: #f8fafc;\n }\n\n .audio-chat-screen .message-attachment.pdf {\n background: #fef2f2;\n }\n\n .audio-chat-screen .message-attachment-icon {\n font-size: 20px;\n flex-shrink: 0;\n }\n\n .audio-chat-screen .message-attachment-info {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n }\n\n .audio-chat-screen .message-attachment-name {\n font-weight: 500;\n color: #1e293b;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .audio-chat-screen .message-attachment-name.clickable:hover {\n color: ").concat(this.primaryColor,";\n text-decoration: underline;\n }\n\n .audio-chat-screen .message-attachment-size {\n font-size: 11px;\n color: #64748b;\n }\n\n .audio-chat-screen .audio-messages {\n flex: 1;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n gap: 12px;\n min-height: 200px;\n }\n\n .audio-chat-screen .audio-message {\n display: flex;\n gap: 8px;\n animation: messageSlide 0.3s ease-out;\n }\n\n .audio-chat-screen .audio-message.user {\n flex-direction: row-reverse;\n }\n\n .audio-chat-screen .audio-message-content {\n max-width: 75%;\n }\n\n .audio-chat-screen .audio-message-bubble {\n padding: 12px 16px;\n border-radius: 16px;\n font-size: 14px;\n line-height: 1.5;\n word-wrap: break-word;\n }\n\n .audio-chat-screen .audio-message.user .audio-message-bubble {\n background: ").concat(this.primaryColor,";\n color: white;\n border-bottom-right-radius: 4px;\n }\n\n .audio-chat-screen .audio-message.assistant .audio-message-bubble {\n background: white;\n color: #1e293b;\n border-bottom-left-radius: 4px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n }\n\n @keyframes messageSlide {\n from {\n opacity: 0;\n transform: translateY(10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n .audio-chat-screen .audio-messages::-webkit-scrollbar {\n width: 6px;\n }\n\n .audio-chat-screen .audio-messages::-webkit-scrollbar-track {\n background: transparent;\n }\n\n .audio-chat-screen .audio-messages::-webkit-scrollbar-thumb {\n background: #cbd5e1;\n border-radius: 3px;\n }\n\n .audio-chat-screen .audio-controls {\n position: absolute;\n left: 50%;\n bottom: 20px;\n transform: translateX(-50%);\n display: flex;\n justify-content: center;\n align-items: center;\n pointer-events: none; /* let only the button receive events */\n }\n\n .audio-chat-screen .audio-controls .audio-record-btn {\n pointer-events: auto;\n }\n\n .audio-chat-screen .audio-record-btn {\n width: 80px;\n height: 80px;\n border-radius: 50%;\n background: ").concat(this.primaryColor,";\n color: white;\n border: none;\n cursor: pointer;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 8px;\n transition: all 0.3s;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n }\n\n .audio-chat-screen .audio-record-btn:hover {\n transform: scale(1.05);\n box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);\n }\n\n .audio-chat-screen .audio-record-btn:active {\n transform: scale(0.95);\n }\n\n .audio-chat-screen .audio-record-btn.recording {\n background: #ef4444;\n animation: pulse-record 1.5s infinite;\n }\n\n @keyframes pulse-record {\n 0%, 100% {\n box-shadow: 0 4px 12px rgba(239, 68, 68, 0.4);\n }\n 50% {\n box-shadow: 0 4px 24px rgba(239, 68, 68, 0.6);\n }\n }\n\n .audio-chat-screen .audio-record-btn span {\n font-size: 11px;\n font-weight: 500;\n margin-top: 4px;\n }\n\n .audio-chat-screen .audio-record-btn svg {\n width: 32px;\n height: 32px;\n }\n\n @media (max-width: 768px) {\n .audio-chat-screen .audio-record-btn {\n width: 100px;\n height: 100px;\n }\n }\n\n /* Expanded Image Modal Styles */\n .expanded-image-modal {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.8);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10000;\n animation: fadeIn 0.2s ease;\n }\n\n @keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n }\n\n .expanded-image-container {\n position: relative;\n max-width: 90%;\n max-height: 90vh;\n background: #fff;\n border-radius: 8px;\n overflow: hidden;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);\n animation: scaleIn 0.2s ease;\n display: flex;\n flex-direction: column;\n }\n\n @keyframes scaleIn {\n from {\n transform: scale(0.9);\n opacity: 0;\n }\n to {\n transform: scale(1);\n opacity: 1;\n }\n }\n\n .expanded-image-close {\n position: absolute;\n top: 12px;\n right: 12px;\n background: rgba(0, 0, 0, 0.6);\n border: none;\n color: white;\n width: 32px;\n height: 32px;\n border-radius: 50%;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 18px;\n z-index: 1;\n transition: all 0.2s;\n }\n\n .expanded-image-close:hover {\n background: rgba(0, 0, 0, 0.8);\n transform: scale(1.1);\n }\n\n .expanded-image {\n max-width: 100%;\n max-height: calc(90vh - 60px);\n object-fit: contain;\n display: block;\n }\n\n .expanded-image-caption {\n padding: 12px 16px;\n background: #fff;\n color: #1e293b;\n font-size: 14px;\n text-align: center;\n border-top: 1px solid #e2e8f0;\n }\n "),document.head.appendChild(e)}}class o{constructor(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.title=e.title||"Chat Assistant",this.placeholder=e.placeholder||"Type your message...",this.primaryColor=e.primaryColor||"#1a5c4b",this.container=null,this.messages=[],this.isMinimized=!1,this.currentScreen="welcome",this.textChatScreen=null,this.audioChatScreen=null,this.langgraphUrl=e.langgraphUrl||"http://localhost:8080",this.authToken=e.authToken||null,this.threadId=e.threadId||null,this.assistantId=e.assistantId||null,this.selectedLanguage=e.selectedLanguage||"en",this.accessToken=e.accessToken||"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InhpZHdnbHl5emRqc2dyaW92bWdtIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NDczOTE5NjEsImV4cCI6MjA2Mjk2Nzk2MX0.jAdwoGNbwK",this.supabaseToken=e.supabaseToken||"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InhpZHdnbHl5emRqc2dyaW92bWdtIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NDczOTE5NjEsImV4cCI6MjA2Mjk2Nzk2MX0.jAdwoGNbwK",this.userInfo=e.userInfo||{},this._customGetHeaders=e.getHeaders,this.getHeaders=()=>{if(this._customGetHeaders)return this._customGetHeaders();const e=this.authToken||this.accessToken,n=this.supabaseToken||e;return t(t(t({"Content-Type":"application/json"},e&&{Authorization:"Bearer ".concat(e)}),n&&{"x-supabase-access-token":n}),{},{Origin:("undefined"!=typeof window?window.location.origin:"*")||"*"})},this.getLatestCheckpoint=e.getLatestCheckpoint||(async()=>null),this.updateThread=e.updateThread||(async()=>{}),this.getUserThreads=e.getUserThreads||(async e=>{let{userId:n,userUuid:t}=e;try{const e=new URLSearchParams;t&&e.append("user_uuid",t);const n="".concat(this.langgraphUrl,"/history?").concat(e.toString()),a=await fetch(n,{method:"GET",headers:this.getHeaders()});return a.ok?await a.json():{threads:[]}}catch(e){return console.error("Error fetching threads",e),{threads:[]}}}),this.setUserInfoFromDirectChatLogin=e.setUserInfoFromDirectChatLogin||(()=>{}),this.setUserThreads=e.setUserThreads||(()=>{}),this.setUserThreadsMetaData=e.setUserThreadsMetaData||(()=>{}),this.languageOptions=[{label:"Assamese",value:"as"},{label:"Bengali",value:"bn"},{label:"Dogri",value:"doi"},{label:"English",value:"en"},{label:"Gujarati",value:"gu"},{label:"Hindi",value:"hi"},{label:"Kannada",value:"kn"},{label:"Konkani",value:"gom"},{label:"Maithili",value:"mai"},{label:"Malayalam",value:"ml"},{label:"Marathi",value:"mr"},{label:"Oriya",value:"or"},{label:"Punjabi",value:"pa"},{label:"Sanskrit",value:"sa"},{label:"Sindhi",value:"sd"},{label:"Tamil",value:"ta"},{label:"Telugu",value:"te"},{label:"Urdu",value:"ur"}],this.isLoading=!1,this.isConnected=!1,this.initialized=!1,this.contentBlocks=[],this.playedAudioIds=new Set,this.currentInputAudio=null,this.submissionInProgress=!1,this.processingAudioId=null,this._init(),"undefined"!=typeof window&&setTimeout(()=>{this.initializeChat()},100)}_init(){this.container=document.createElement("div"),this.container.id="chat-widget-container",this.container.innerHTML='\n <div class="chat-widget-minimized" id="chat-toggle">\n <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>\n </svg>\n </div>\n <div class="chat-widget-expanded" id="chat-expanded">\n <div class="chat-screen-container" id="chat-screen-container">\n \x3c!-- Screens will be rendered here --\x3e\n </div>\n <div class="chat-drawer-overlay" id="chat-drawer-overlay">\n <div class="chat-drawer">\n <div class="drawer-header">\n <div class="drawer-title">Menu</div>\n </div>\n <div class="drawer-content">\n <button class="drawer-item" id="drawer-new-chat">\n New Chat\n </button> \n <div class="language-selector-container">\n <div class="custom-select" id="language-selector">\n <div class="select-trigger" id="language-trigger">\n <span id="selected-language-text">English</span>\n <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="chevron"><path d="m6 9 6 6 6-6"/></svg>\n </div>\n <div class="select-options" id="language-options"></div>\n </div>\n </div>\n <div class="drawer-divider" style="height: 1px; background: #e2e8f0; margin: 8px 0;"></div>\n \n <div id="drawer-threads" class="threads-container">\n \x3c!-- Threads will be rendered here --\x3e\n <div class="threads-loading">Loading history...</div>\n </div>\n </div>\n \n </div>\n <div class="drawer-backdrop" id="drawer-backdrop"></div>\n </div>\n </div>\n ',document.body.appendChild(this.container),this._applyStyles(),this._initScreens(),this._renderScreen(),this._populateLanguageOptions(),this._bindEvents()}_applyStyles(){const e=document.createElement("style");e.textContent="\n @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap');\n \n #chat-widget-container {\n position: fixed;\n bottom: 24px;\n right: 24px;\n z-index: 10000;\n font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n }\n.text-chat-screen {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n\n .chat-header {\n color: ".concat(this.primaryColor,";\n padding: 20px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n }\n\n .chat-header-content {\n display: flex;\n align-items: center;\n gap: 12px;\n flex: 1;\n }\n\n .chat-back {\n background: transparent;\n border: none;\n color: white;\n cursor: pointer;\n padding: 8px;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s;\n margin-right: 8px;\n }\n\n .chat-back:hover {\n background: rgba(255, 255, 255, 0.15);\n }\n\n .chat-avatar {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n background: rgba(255, 255, 255, 0.2);\n backdrop-filter: blur(10px);\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .chat-header-text {\n display: flex;\n flex-direction: column;\n gap: 2px;\n }\n \n .chat-title {\n font-weight: 600;\n font-size: 20px;\n }\n\n .chat-status {\n font-size: 12px;\n opacity: 0.9;\n display: flex;\n align-items: center;\n gap: 4px;\n }\n\n .chat-close {\n background: ").concat(this.primaryColor,";\n border: none;\n color: white;\n cursor: pointer;\n padding: 8px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s;\n }\n\n .chat-widget-minimized {\n width: 60px;\n height: 60px;\n border-radius: 50%;\n background: ").concat(this.primaryColor,";\n color: white;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n .chat-widget-minimized:hover {\n transform: scale(1.1);\n }\n\n @keyframes pulse {\n 0%, 100% { box-shadow: 0 8px 24px rgba(99, 102, 241, 0.4); }\n 50% { box-shadow: 0 8px 32px rgba(99, 102, 241, 0.6); }\n }\n\n .chat-widget-expanded {\n position: relative;\n width: 480px;\n height: 640px;\n background: white;\n border-radius: 16px;\n box-shadow: 0 20px 60px rgba(0, 0, 0, 0.15);\n display: none;\n flex-direction: column;\n overflow: hidden;\n animation: slideUp 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n @keyframes slideUp {\n from {\n opacity: 0;\n transform: translateY(20px) scale(0.95);\n }\n to {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n }\n\n .chat-widget-expanded.visible {\n display: flex;\n }\n\n .chat-screen-container {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n\n /* Welcome Screen Styles */\n .welcome-screen {\n flex: 1;\n height: 100%;\n display: flex;\n flex-direction: column;\n align-items: stretch;\n justify-content: start;\n background: linear-gradient(180deg, white 10%, #E1EFCC );\n padding: 0px;\n }\n\n .welcome-content {\n width: 80%;\n margin: auto;\n text-align: center;\n padding-top: 20px;\n }\n\n .welcome-icon {\n font-size: 64px;\n margin-bottom: 16px;\n animation: bounce 2s infinite;\n }\n\n @keyframes bounce {\n 0%, 100% { transform: translateY(0); }\n 50% { transform: translateY(-10px); }\n }\n\n .welcome-title {\n font-size: 24px;\n font-weight: 600;\n color: #1e293b;\n margin: 0 0 8px 0;\n }\n\n .welcome-subtitle {\n font-size: 14px;\n color: #64748b;\n margin: 0 0 32px 0;\n }\n\n .welcome-options {\n display: flex;\n flex-direction: column;\n gap: 12px;\n }\n\n .welcome-option-btn {\n background: white;\n border: 2px solid #e2e8f0;\n border-radius: 12px;\n padding: 16px;\n display: flex;\n align-items: center;\n gap: 12px;\n cursor: pointer;\n transition: all 0.2s;\n text-align: left;\n width: 100%;\n }\n\n .welcome-option-btn:hover {\n border-color: ").concat(this.primaryColor,";\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n transform: translateY(-2px);\n }\n\n .option-icon {\n font-size: 32px;\n flex-shrink: 0;\n }\n\n .option-content {\n flex: 1;\n }\n\n .option-title {\n font-size: 16px;\n font-weight: 600;\n color: #1e293b;\n margin-bottom: 4px;\n }\n\n .option-description {\n font-size: 13px;\n color: #64748b;\n }\n\n .welcome-option-btn svg {\n color: #94a3b8;\n flex-shrink: 0;\n }\n\n .welcome-option-btn:hover svg {\n color: ").concat(this.primaryColor,";\n }\n.gradient-sphere-welcome-screen {\n width: 200px !important;\n height: 200px !important;\n border-radius: 50%;\n background: linear-gradient(135deg, #0a0d120f 0%, #85bc31 50%, #d0f19e 100%)\n !important;\n position: relative;\n margin: 20px auto 30px auto;\n box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);\n animation: float 3s ease-in-out infinite;\n flex-shrink: 0;\n}\n\n.sphere-highlight {\n position: absolute;\n top: 20%;\n right: 20%;\n width: 35px;\n height: 35px;\n background: radial-gradient(\n circle,\n rgba(255, 255, 255, 0.8) 0%,\n transparent 70%\n );\n border-radius: 50%;\n filter: blur(1px);\n}\n\n@keyframes float {\n 0%,\n 100% {\n transform: translateY(0px);\n }\n 50% {\n transform: translateY(-10px);\n }\n}\n\n.welcome-text {\n max-width: 400px;\n margin-bottom: 30px;\n flex-shrink: 0;\n text-align: left;\n}\n\n.greeting {\n font-size: 24px;\n font-weight: 600;\n color: #1a5c4b;\n margin: 0 0 16px 0;\n}\n\n.intro {\n font-size: 18px;\n font-weight: 500;\n color: #1a5c4b;\n margin: 0 0 12px 0;\n line-height: 1.4;\n}\n\n\n.action-buttons {\n display: flex;\n align-items: center;\n gap: 16px;\n flex-shrink: 0;\n margin-top: auto;\n /* padding-top: 10px; */\n padding-bottom: 20px;\n justify-content: center;\n width: 100%;\n align-self: center;\n}\n\n.primary-button {\n background: #1a5c4b;\n display:flex;\n color: white;\n border: none;\n padding: 16px 32px;\n border-radius: 25px;\n font-size: 16px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.3s ease;\n box-shadow: 0 4px 12px rgba(26, 92, 75, 0.3);\n}\n\n.primary-button:hover {\n transform: translateY(-2px);\n box-shadow: 0 6px 16px rgba(26, 92, 75, 0.4);\n}\n\n @media (max-width: 768px) {\n #chat-widget-container {\n bottom: 16px;\n right: 16px;\n }\n\n .chat-widget-expanded {\n width: 100vw;\n height: 100vh;\n border-radius: 0;\n max-width: 100vw;\n max-height: 100vh;\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n }\n\n .chat-widget-expanded.visible {\n display: flex;\n }\n\n .welcome-content {\n max-width: 100%;\n padding-top: 40px;\n }\n\n .chat-drawer {\n width: 85% !important; /* Wider drawer on mobile */\n }\n }\n\n /* Drawer Styles */\n .chat-drawer-overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 2000;\n display: flex;\n pointer-events: none;\n visibility: hidden;\n }\n\n .chat-drawer-overlay.visible {\n pointer-events: auto;\n visibility: visible;\n }\n\n .chat-drawer {\n width: 65%;\n background: white;\n height: 100%;\n transform: translateX(-100%);\n transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n display: flex;\n flex-direction: column;\n z-index: 2002;\n box-shadow: 4px 0 24px rgba(0,0,0,0.1);\n }\n\n .chat-drawer-overlay.visible .chat-drawer {\n transform: translateX(0);\n }\n\n .drawer-backdrop {\n flex: 1;\n background: rgba(0, 0, 0, 0.5);\n opacity: 0;\n transition: opacity 0.3s ease;\n backdrop-filter: blur(2px);\n cursor: pointer;\n }\n\n .chat-drawer-overlay.visible .drawer-backdrop {\n opacity: 1;\n }\n\n .drawer-header {\n padding: 24px;\n border-bottom: 1px solid #f1f5f9;\n }\n\n .drawer-title {\n font-size: 20px;\n font-weight: 600;\n color: ").concat(this.primaryColor,";\n }\n\n .drawer-content {\n flex: 1;\n padding: 16px;\n display: flex;\n flex-direction: column;\n gap: 8px;\n overflow-y: auto;\n }\n\n .drawer-item {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 16px;\n background: transparent;\n border: none;\n border-radius: 8px;\n color: #475569;\n font-size: 15px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s;\n text-align: left;\n }\n\n .drawer-item:hover {\n background: #f1f5f9;\n color: ").concat(this.primaryColor,";\n }\n\n .drawer-item svg {\n opacity: 0.7;\n }\n\n .drawer-item:hover svg {\n opacity: 1;\n color: ").concat(this.primaryColor,";\n }\n\n .drawer-footer {\n padding: 16px 24px;\n border-top: 1px solid #f1f5f9;\n }\n\n .drawer-version {\n font-size: 12px;\n color: #94a3b8;\n text-align: center;\n }\n\n /* Language Selector Styles */\n .language-selector-container {\n margin-top: 8px;\n margin-bottom: 8px;\n }\n\n .language-label {\n font-size: 11px;\n font-weight: 600;\n color: #94a3b8;\n margin-bottom: 6px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n padding-left: 4px;\n }\n\n .custom-select {\n position: relative;\n width: 100%;\n user-select: none;\n }\n\n .select-trigger {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 10px 12px;\n background: #f8fafc;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s;\n font-size: 14px;\n color: #334155;\n }\n\n .select-trigger:hover {\n border-color: ").concat(this.primaryColor,";\n background: white;\n }\n\n .select-trigger.active {\n border-color: ").concat(this.primaryColor,";\n background: white;\n box-shadow: 0 0 0 2px rgba(26, 92, 75, 0.1);\n }\n\n .select-options {\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n right: 0;\n background: white;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);\n max-height: 200px;\n overflow-y: auto;\n z-index: 50;\n display: none;\n opacity: 0;\n transform: translateY(-10px);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n .select-options.open {\n display: block;\n opacity: 1;\n transform: translateY(0);\n }\n\n .select-option {\n padding: 10px 12px;\n font-size: 14px;\n color: #334155;\n cursor: pointer;\n transition: all 0.1s;\n }\n\n .select-option:hover {\n background: #f1f5f9;\n color: ").concat(this.primaryColor,";\n }\n\n .select-option.selected {\n background: rgba(26, 92, 75, 0.08);\n color: ").concat(this.primaryColor,";\n font-weight: 500;\n }\n \n .chevron {\n transition: transform 0.2s ease;\n color: #94a3b8;\n }\n \n .select-trigger.active .chevron {\n transform: rotate(180deg);\n color: ").concat(this.primaryColor,";\n }\n \n /* Thread List Styles */\n .threads-container {\n flex: 1;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n gap: 4px;\n padding-top: 8px;\n }\n \n .threads-loading {\n padding: 16px;\n text-align: center;\n color: #94a3b8;\n font-size: 13px;\n }\n \n .thread-item {\n display: flex;\n flex-direction: column;\n padding: 10px 12px;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s;\n text-align: left;\n border: none;\n background: transparent;\n width: 100%;\n color: #475569;\n }\n \n .thread-item:hover {\n background-color: #f1f5f9; /* action.hover */\n color: ").concat(this.primaryColor,";\n }\n \n .thread-item.selected {\n background-color: rgba(26, 92, 75, 0.08); /* action.selected */\n }\n \n .thread-content {\n font-size: 0.9rem;\n color: #334155;\n line-height: 1.3;\n margin-bottom: 4px;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n font-weight: 500;\n }\n \n .thread-date {\n font-size: 0.75rem;\n font-weight: 600;\n color: #94a3b8;\n }\n \n .no-history {\n padding: 16px;\n text-align: center;\n color: #94a3b8;\n font-size: 14px;\n }\n "),document.head.appendChild(e)}_renderScreen(){const e=this.container.querySelector("#chat-screen-container");switch(this.currentScreen){case"welcome":this._renderWelcomeScreen(e);break;case"text":this._renderTextChatScreen(e);break;case"audio":this._renderAudioChatScreen(e)}}_initScreens(){this.textChatScreen=new a({title:this.title,placeholder:this.placeholder,primaryColor:this.primaryColor,onMessage:(e,n)=>{this._handleUserMessage(e,n)},onBack:()=>{this.currentScreen="welcome",this._renderScreen()},onOpenDrawer:()=>{this._toggleDrawer(!0)},onClose:()=>{const e=this.container.querySelector("#chat-expanded"),n=this.container.querySelector("#chat-toggle");e.classList.remove("visible"),n.style.display="flex",this.currentScreen="welcome",this.messages=[],this.contentBlocks=[],this._initScreens()},messages:this.messages,sendMessage:(e,n)=>this.sendMessage(e,n),contentBlocks:this.contentBlocks,onContentBlocksChange:e=>{this.contentBlocks=e},navigateToAudioScreen:()=>{this._navigateToScreen("audio")}}),this.audioChatScreen=new s({title:this.title,primaryColor:this.primaryColor,onRecordStart:()=>{},onRecordStop:()=>{},onBack:()=>{this.currentScreen="welcome",this._renderScreen()},onOpenDrawer:()=>{this._toggleDrawer(!0)},onClose:()=>{const e=this.container.querySelector("#chat-expanded"),n=this.container.querySelector("#chat-toggle");e.classList.remove("visible"),n.style.display="flex",this.currentScreen="welcome",this.messages=[],this._initScreens()},messages:this.messages,sendMessage:(e,n)=>this.sendMessage(e,n),selectedLanguage:this.selectedLanguage,navigateToTextScreen:()=>{this._navigateToScreen("text")}})}_renderWelcomeScreen(e){e.innerHTML='\n <main class="welcome-screen">\n <div class="chat-header">\n <div class="chat-header-content visible">\n <div class="chat-header-text">\n <div class="chat-title">'.concat(this.title,'</div>\n </div>\n </div>\n <button class="chat-close" id="text-chat-close">\n <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <line x1="18" y1="6" x2="6" y2="18"></line>\n <line x1="6" y1="6" x2="18" y2="18"></line>\n </svg>\n </button>\n </div>\n <div >\n <div class="welcome-content">\n <div class="gradient-sphere-welcome-screen">\n <div class="sphere-highlight">\n </div>\n </div>\n \n <div class="welcome-text">\n <p class="greeting">Hello!</p>\n <p class="intro">\n We are your Krishi Vigyan SahayakāKVS, a companion to help with every farming question! Tell us, what do you want to know today?\n </p>\n </div>\n \n <div class="action-buttons">\n <button\n class="primary-button !rounded-full"\n id="welcome-audio-btn"\n >\n Let\'s talk ​ ​ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-mic-icon lucide-mic"><path d="M12 19v3"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><rect x="9" y="2" width="6" height="13" rx="3"/></svg>\n </button>\n </div>\n \n \n\n </div>\n </div>\n </main>\n ');const n=e.querySelector("#welcome-audio-btn"),t=e.querySelector("#text-chat-close");n.addEventListener("click",()=>this._navigateToScreen("audio")),t&&t.addEventListener("click",()=>{const e=this.container.querySelector("#chat-expanded"),n=this.container.querySelector("#chat-toggle");e.classList.remove("visible"),n.style.display="flex",this.currentScreen="welcome",this.messages=[],this._initScreens()})}_renderTextChatScreen(e){this.textChatScreen&&(this.textChatScreen.contentBlocks=this.contentBlocks,this.textChatScreen.messages=this.messages,this.textChatScreen.render(e))}_renderAudioChatScreen(e){this.audioChatScreen&&(this.audioChatScreen.messages=this.messages,this.audioChatScreen.render(e))}_navigateToScreen(e){this.currentScreen=e,this._renderScreen()}_populateLanguageOptions(){const e=this.container.querySelector("#language-options");e&&(e.innerHTML=this.languageOptions.map(e=>'\n <div class="select-option '.concat(e.value===this.selectedLanguage?"selected":"",'" data-value="').concat(e.value,'">\n ').concat(e.label,"\n </div>\n ")).join(""),this._updateSelectedLanguageDisplay())}_updateSelectedLanguageDisplay(){const e=this.container.querySelector("#selected-language-text");if(e){const n=this.languageOptions.find(e=>e.value===this.selectedLanguage);e.textContent=n?n.label:"English"}}_bindLanguageSelectorEvents(){const e=this.container.querySelector("#language-selector"),n=this.container.querySelector("#language-trigger"),t=this.container.querySelector("#language-options");if(n&&t){n.addEventListener("click",e=>{e.stopPropagation();t.classList.contains("open")?(t.classList.remove("open"),n.classList.remove("active")):(t.classList.add("open"),n.classList.add("active"))});t.querySelectorAll(".select-option").forEach(e=>{e.addEventListener("click",e=>{const a=e.currentTarget.dataset.value;this.selectedLanguage=a,this._updateSelectedLanguageDisplay(),t.querySelectorAll(".select-option").forEach(e=>e.classList.remove("selected")),e.currentTarget.classList.add("selected"),t.classList.remove("open"),n.classList.remove("active"),console.log("Language selected:",this.selectedLanguage)})}),document.addEventListener("click",a=>{e&&!e.contains(a.target)&&(t.classList.remove("open"),n.classList.remove("active"))})}}async _fetchThreads(){const e=this.container.querySelector("#drawer-threads");if(e){e.innerHTML='<div class="threads-loading">Loading history...</div>';try{const n=localStorage.getItem("DfsWeb.user-info"),t=n?JSON.parse(n):null;if(null==t||!t.uuid)return void(e.innerHTML='<div class="no-history">Please log in to view history</div>');console.log("USER ID",t.id,"USER UUID",t.uuid);const a=await this.getUserThreads({userId:t.id,userUuid:t.uuid});console.log("THREAD DATA",a);const i=(a.threads||[]).filter(e=>e.history&&e.history.length>0);this._renderThreadList(i)}catch(n){console.error("UNEXPECTED ERROR IN FETCHING THREADS",n.message),e.innerHTML='<div class="no-history">Failed to load history</div>'}}}_renderThreadList(e){const n=this.container.querySelector("#drawer-threads");n&&(0!==e.length?(n.innerHTML="",e.forEach(e=>{var t;const a=e.thread_id===this.threadId,i=document.createElement("div");i.className="thread-item ".concat(a?"selected":"");const s=(null===(t=e.history[0])||void 0===t||null===(t=t.values)||void 0===t||null===(t=t.messages[0])||void 0===t?void 0:t.content)||"New Chat";let o=s;if(Array.isArray(s)){const e=s.find(e=>"text"===e.type);o=e?e.text:"Multimedia Message"}else"object"==typeof s&&(o="Message");const r=new Date(e.created_at).toLocaleString();i.innerHTML='\n <div class="thread-content">'.concat(o,'</div>\n <div class="thread-date">').concat(r,"</div>\n "),i.addEventListener("click",()=>{this._handleThreadSelect(e.thread_id)}),n.appendChild(i)})):n.innerHTML='<div class="no-history">No history available</div>')}_handleThreadSelect(e){console.log("Select thread:",e),this.threadId=e,this._toggleDrawer(!1),this.currentScreen="text",this.messages=[],this.setIsLoading=!0,this.isLoading=!0,this._renderScreen(),this.loadHistory(e).then(()=>{this.isLoading=!1,this._renderScreen()})}_bindEvents(){const e=this.container.querySelector("#chat-toggle"),n=this.container.querySelector("#chat-expanded");e&&(e.style.display="flex"),e.addEventListener("click",()=>{console.log("Clicked"),e.style.display="none",n.classList.add("visible"),this.currentScreen="welcome",this._renderScreen()});const t=this.container.querySelector("#drawer-backdrop");t&&t.addEventListener("click",()=>{this._toggleDrawer(!1)});this.container.querySelectorAll(".drawer-item").forEach(e=>{e.addEventListener("click",e=>{this._toggleDrawer(!1);"drawer-new-chat"===e.currentTarget.id&&this._resetChat()})}),this._bindLanguageSelectorEvents()}_toggleDrawer(e){const n=this.container.querySelector("#chat-drawer-overlay");n&&(e?(n.classList.add("visible"),this._fetchThreads()):n.classList.remove("visible"))}_resetChat(){this.messages=[],this.threadId=null,this.contentBlocks=[],this._initScreens(),this._renderScreen()}_handleUserMessage(e,n){n&&n('You said: "'.concat(e,'"'))}_addMessageToArray(e){this.messages.push(e),this._notifyScreensUpdate()}_updateMessageInArray(e,n){const a=this.messages.findIndex(n=>n.id===e);-1!==a&&(this.messages[a]=t(t({},this.messages[a]),n),this._notifyScreensUpdate())}_notifyScreensUpdate(){this.textChatScreen&&this.textChatScreen.container&&this.textChatScreen._syncMessages(this.messages),this.audioChatScreen&&this.audioChatScreen.container&&this.audioChatScreen._syncMessages(this.messages)}async sendMessage(e){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[];if(!e.trim()&&0===n.length||this.isLoading)return;console.log("š¤ Sending text message - Language:",this.selectedLanguage,"Assistant ID:",this.assistantId||"Not available","Thread ID:",this.threadId||"Not available","Access token:",this.accessToken?"Present":"Empty - backend will handle");const t=[];if(e.trim()){const n=e;t.push({type:"text",text:n})}n.forEach(e=>{t.push(e)});const a={id:Date.now(),content:e.trim()||"š File attachments",sender:"user",timestamp:(new Date).toISOString(),attachments:n.length>0?n:null};console.log("USER MESSAGE",a),console.log("USER MESSAGE CONTENTBLOCKS",n),console.log("USER MESSAGE CONTENT",t),this._addMessageToArray(a),this.contentBlocks=[],this.textChatScreen&&(this.textChatScreen.contentBlocks=[],this.textChatScreen.renderFilePreview(),this.textChatScreen.updateSendButton()),this.playedAudioIds.clear(),this.currentInputAudio=null,this.submissionInProgress=!1,this.processingAudioId=null,this.isLoading=!0;try{await this.sendMessageWithStreaming(t)}catch(e){console.error("Error sending message:",e);const n={id:Date.now()+1,content:"Sorry, I encountered an error. Please try again.",sender:"assistant",timestamp:(new Date).toISOString(),isError:!0};this._addMessageToArray(n)}finally{this.isLoading=!1}}async sendMessageWithStreaming(e){console.log("USER MESSAGE STREAMING",e),console.log("š¤ Sending text message - Language:",this.selectedLanguage,"Access token:",this.accessToken?"Present":"Not found");const n={id:Date.now()+1,content:"",sender:"assistant",timestamp:(new Date).toISOString(),isStreaming:!0,isProcessing:!0,textSessionId:Date.now()+1,hasAudioResponse:!1,inputType:"text"};this._addMessageToArray(n);let a=null;try{var i;const g=await this.getLatestCheckpoint(this.threadId);console.log("š¤ Sending message to backend:",t({input:{messages:[{id:"msg-".concat(Date.now()),type:"human",content:e}],user_language:this.selectedLanguage,access_token:"[redacted]",user_info:JSON.stringify(this.userInfo)},config:{configurable:{}},metadata:{supabaseAccessToken:"[redacted]",user_language:this.selectedLanguage,input_type:"text",audio_content:null},stream_mode:["values","messages-tuple","custom"],stream_subgraphs:!0,assistant_id:this.assistantId,on_disconnect:"cancel"},g&&{checkpoint:g}));const m=await fetch("".concat(this.langgraphUrl,"/threads/").concat(this.threadId,"/runs/stream"),{method:"POST",headers:this.getHeaders(),body:JSON.stringify(t({input:{messages:[{id:"msg-".concat(Date.now()),type:"human",content:e}],user_language:this.selectedLanguage,access_token:this.accessToken,user_info:JSON.stringify(this.userInfo)},config:{configurable:{}},metadata:{supabaseAccessToken:this.supabaseToken,user_language:this.selectedLanguage},stream_mode:["values","messages-tuple","custom"],stream_subgraphs:!0,assistant_id:this.assistantId,on_disconnect:"cancel"},g&&{checkpoint:g}))});if(!m.ok)throw new Error("HTTP error! status: ".concat(m.status));const f=m.body.getReader(),x=new TextDecoder;let b="",y="",v="",w=-1;const k=Date.now();let S=null,_=null,I=!1,T=null,C=!1,E="",A=null,L=null;console.log("š Starting to process streaming response for requestId:",k);const M=e=>{if(!e)return 0;const n=String(e).toLowerCase();return n.includes("mdms_assistant")||n.includes("grievance_assistant")||n.includes("mandiprice_assistant")?0:n.includes("assistant")&&!n.includes("tools")?3:n.includes("response_processor")||n.includes("post_assistant")?2:n.includes("ui_action_mapper")?1:0};for(;;){const{done:e,value:i}=await f.read();if(e)break;b+=x.decode(i,{stream:!0});const u=b.split("\n");b=u.pop()||"";for(const e of u)if(""!==e.trim()){if(console.log("š Processing SSE line:",{line:e.substring(0,100)+(e.length>100?"...":""),requestId:k}),e.startsWith("data:"))try{const n=JSON.parse(e.slice(5).trim());n.run_id&&(console.log("š¢ Run ID:",n.run_id),a=n.run_id)}catch(n){console.error("Error parsing JSON:",n,e)}if(e.startsWith("event: "))S=e.slice(7).trim(),console.log("šÆ Event type:",S);else if(e.startsWith("data: ")){const i=e.slice(6).trim();if("[DONE]"===i){console.log("š Stream completed");break}try{const e=JSON.parse(i);var s;if(_=e,e.run_id&&(console.log("š¢ Capturing run_id from parsed data:",e.run_id),a=e.run_id),"end"===S)if(console.log("š Received event: end - finalizing message with run_id:",a),e.run_id&&(a=e.run_id,console.log("š¢ Updated run_id from end event:",a)),y&&y.length>0)this._updateMessageInArray(n.id,{content:y,additional_kwargs:A,isStreaming:!1,isProcessing:!1,hasAudioResponse:(null===(s=this.messages.find(e=>e.id===n.id))||void 0===s?void 0:s.hasAudioResponse)||!1,latestRunId:a}),C=!0,E=y;else a&&this._updateMessageInArray(n.id,{latestRunId:a,isStreaming:!1,isProcessing:!1});if(console.log("š Parsed SSE data:",{event:S,hasData:!!e,dataKeys:e?Object.keys(e):"no data",topLevelKeys:Object.keys(e),hasAudioContent:null!=e&&e.audio_content?"YES":"NO",hasResponseProcessor:null!=e&&e.response_processor?"YES":"NO",hasRunId:null!=e&&e.run_id?"YES":"NO",runId:(null==e?void 0:e.run_id)||"N/A",requestId:k}),e.smart_router&&e.smart_router.access_token&&e.smart_router.farmer_profile&&!0===e.smart_router.farmer_profile_fetched){var o,r;console.log("š Authentication data detected in smart_router:",{hasAccessToken:!!e.smart_router.access_token,mobileNumber:e.smart_router.mobile_number,userUuid:e.smart_router.userUuid,hasFarmerProfile:!!e.smart_router.farmer_profile,farmerId:null===(o=e.smart_router.farmer_profile)||void 0===o?void 0:o.individualId,farmerName:null===(r=e.smart_router.farmer_profile)||void 0===r?void 0:r.name,requestId:k});try{const n=e.smart_router,a=n.farmer_profile,i=n.access_token;localStorage.setItem("DfsWeb.access-token",i);let s={};a.user_details?(s=t({},a.user_details),s.name=a.name||s.name||"",s.uuid||(s.uuid=n.userUuid),s.mobileNumber||(s.mobileNumber=n.mobile_number||a.mobileNumber)):(s={id:null,uuid:n.userUuid,userName:n.mobile_number,name:a.name||"",mobileNumber:n.mobile_number||a.mobileNumber,emailId:a.email||null,locale:null,type:"CITIZEN",roles:[{name:"Citizen",code:"CITIZEN",tenantId:a.tenantId||"br"}],active:!0,tenantId:a.tenantId||"br",permanentCity:null},this.setUserInfoFromDirectChatLogin(s)),this.userInfo=s,this.accessToken=i,s.uuid&&(console.log("USER INFO FOR UPDATING THREAD",s),this.threadId&&this.updateThread(this.threadId,s.uuid).then(e=>{console.log("ā
Thread updated after authentication:",e)}).catch(e=>{console.error("ā Error updating thread after authentication:",e.message)}),this.getUserThreads({userId:s.id,userUuid:s.uuid}).then(e=>{console.log("ā
Thread data fetched after authentication:",e),this.setUserThreads(e.threads),this.setUserThreadsMetaData({threads_processed:e.threads_processed,total_history_items:e.total_history_items,total_threads:e.total_threads})}).catch(e=>{console.error("ā Error fetching threads after authentication:",e.message)}))}catch(e){console.error("ā Error processing authentication data:",e)}}let u=null,g=null;if(e.response_processor&&Array.isArray(e.response_processor.ui_actions)?g=e.response_processor.ui_actions:e.response_processor&&e.response_processor.messages&&Array.isArray(e.response_processor.messages)&&e.response_processor.messages.length>0&&e.response_processor.messages[0].additional_kwargs&&Array.isArray(e.response_processor.messages[0].additional_kwargs.ui_actions)?g=e.response_processor.messages[0].additional_kwargs.ui_actions:e.ui_action_mapper&&Array.isArray(e.ui_action_mapper.ui_actions)?(u=e.ui_action_mapper,g=u.ui_actions):e.mdms_ui_action_mapper&&Array.isArray(e.mdms_ui_action_mapper.ui_actions)&&(u=e.mdms_ui_action_mapper,g=u.ui_actions),g&&g.length>0){console.log("UI ACTIONS",g);const e=g[g.length-1];if(e.web&&e.web.link){var c,l,d,h,p;let n=null,a={};if(e.web.parameters)e.web.parameters.scrollTo&&(n=e.web.parameters.scrollTo),a=t({},e.web.parameters);else if(e.web.link&&e.web.link.includes("scrollTo=")){n=new URLSearchParams(e.web.link.split("?")[1]).get("scrollTo")}let i=e.web.link,s=e.message||"";const o=(null===(c=e.web.parameters)||void 0===c?void 0:c.schemeId)&&""!==e.web.parameters.schemeId;let r=null;r=!(null===(l=e.web.parameters)||void 0===l||!l.button_title)||!(null===(d=e.web.parameters)||void 0===d||!d.name),o||r||(i="/help",s="Please find more information about available schemes and services"),T={content:"",url:i&&!i.startsWith("http")?window.location.origin+i:i,originalUrl:i,uiActionType:e.ui_action,scrollToId:n,navigationParams:t(t({},a),r&&{name:(null===(h=e.web.parameters)||void 0===h?void 0:h.button_title)||(null===(p=e.web.parameters)||void 0===p?void 0:p.name)})}}}if(e.analytics_visualization_node&&e.analytics_visualization_node.messages){const n=e.analytics_visualization_node.messages;if(n.length>0){const e=n[n.length-1];if("string"==typeof e&&e.includes("additional_kwargs")){const n=e.indexOf("additional_kwargs=")+18,t=e.indexOf("} response_metadata");if(n<t){const a=e.substring(n,t+1);try{let e=a.replace(/'/g,'"').replace(/None/g,"null").replace(/True/g,"true").replace(/False/g,"false");const n=JSON.parse(e);if(n.chart_image_url){console.log("šÆ Found chart image URL:",n.chart_image_url),A=n;try{const e=String(n.chart_image_url).trim();e.startsWith("http")&&(L=e,console.log("š Stored chartUrlFromViz:",L))}catch(e){console.warn("Failed to store chart image URL:",e)}}else n.antv_chart_data&&(console.log("šÆ Found chart data (fallback):",n.antv_chart_data),A=n)}catch(e){console.warn("Failed to parse chart image additional_kwargs:",e)}}}if("string"==typeof e){const n=e.match(/content=['"]([^'"]+)['"]/);if(n&&n[1]){const e=n[1].trim();e.startsWith("http")&&(L=e,console.log("š Stored extracted chartUrlFromViz:",L))}}}}let m=null,f=null;if(Object.keys(e).forEach(n=>{if("audio_content"!==n&&"audio_processor"!==n&&"ui_action_mapper"!==n){const t=e[n];t&&Array.isArray(t.messages)&&t.messages.length>0&&(m=n,f=t.messages)}}),f&&f.length>0){let e=f[f.length-1],n="";if("string"==typeof e)if(e.startsWith("content='")&&e.includes("' additional_kwargs")){const t=e.indexOf("content='")+9,a=e.indexOf("' additional_kwargs");n=e.substring(t,a).replace(/\\n/g,"\n").replace(/\\t/g,"\t").replace(/\\"/g,'"').replace(/\\'/g,"'")}else if(e.startsWith('content="')&&e.includes('" additional_kwargs')){const t=e.indexOf('content="')+9,a=e.indexOf('" additional_kwargs');n=e.substring(t,a).replace(/\\n/g,"\n").replace(/\\t/g,"\t").replace(/\\"/g,'"').replace(/\\'/g,"'")}else{const t=e.match(/content='([^']+)'/),a=e.match(/content="([^"]+)"/);n=t?t[1]:a?a[1]:e}else if(e&&"object"==typeof e)if("string"==typeof e.content)n=e.content;else if(Array.isArray(e.content)&&e.content.length>0){n=e.content.map(e=>"string"==typeof e?e:"string"==typeof(null==e?void 0:e.text)?e.text:"string"==typeof(null==e?void 0:e.value)?e.value:"").filter(Boolean).join(" ").trim()}else n="";if("string"==typeof n&&n.trim().length>0){const e=n.trim().startsWith("{")||n.trim().startsWith("["),t=M(m);if(e&&t<2)console.log("āļø Skipping JSON-like content from ".concat(m));else{const e=8e3,a=n.length>e?n.slice(0,e)+"\n\n⦠(truncated)":n;y=a,(t>w||t===w&&a.length>v.length)&&(v=a,w=t),I=!0,console.log("š¢ Found content from ".concat(m,":"),a.substring(0,100)+"...")}}}if(e){const t=S||"values";if(console.log("šµ Processing data message:",{eventType:t,currentEvent:S,dataKeys:Object.keys(e),requestId:k}),e.audio_content&&"string"==typeof e.audio_content){console.log("šµ AUDIO CONTENT FOUND in text stream:",{audioContentLength:e.audio_content.length,audioContentPreview:e.audio_content.substring(0,20)+"..."});const t="text_response_".concat(k,"_").concat(e.audio_content.substring(0,30)),i=this.playedAudioIds.has(t);if(console.log("š Text stream audio content received:",{audioResponseId:t,requestId:k,alreadyPlayed:i,audioContentLength:e.audio_content.length}),i)console.log("āļø Skipping audio: already played");else if(this.playedAudioIds.add(t),console.log("š Setting audio content for message:",{targetMessageId:n.id,audioContentLength:e.audio_content.length,audioContentPreview:e.audio_content.substring(0,20)+"..."}),this._updateMessageInArray(n.id,{hasAudioResponse:!0,audioContent:e.audio_content,latestRunId:a}),console.log("ā
Stored audio response (text stream)"),this.playedAudioIds.size>10){const e=Array.from(this.playedAudioIds);this.playedAudioIds.clear(),e.slice(-5).forEach(e=>this.playedAudioIds.add(e))}}else console.log("ā No audio_content found in text stream data");if(e.response_processor&&e.response_processor.audio_content&&"string"==typeof e.response_processor.audio_content){console.log("š Found audio_content in response_processor:",{audioContentLength:e.response_processor.audio_content.length,audioContentPreview:e.response_processor.audio_content.substring(0,50)+"..."});const t="text_response_".concat(k,"_").concat(e.response_processor.audio_content.substring(0,30)),i=this.playedAudioIds.has(t);if(console.log("š Response processor audio content received:",{audioResponseId:t,requestId:k,alreadyPlayed:i,audioContentLength:e.response_processor.audio_content.length}),i)console.log("āļø Skipping response processor audio: already played");else if(this.playedAudioIds.add(t),console.log("š Setting response processor audio content for message:",{targetMessageId:n.id,audioContentLength:e.response_processor.audio_content.length,audioContentPreview:e.response_processor.audio_content.substring(0,20)+"..."}),this._updateMessageInArray(n.id,{latestRunId:a,hasAudioResponse:!0,audioContent:e.response_processor.audio_content}),console.log("ā
Found matching message, setting response processor audio content"),this.playedAudioIds.size>10){const e=Array.from(this.playedAudioIds);this.playedAudioIds.clear(),e.slice(-5).forEach(e=>this.playedAudioIds.add(e))}}}}catch(e){console.log("ā ļø Failed to parse streaming data:",e)}}}}console.log("š Finalizing assistant message:",n.id),await new Promise(e=>setTimeout(e,100));const P=this.messages.find(e=>e.id===n.id);if(console.log("š Current assistant message before finalization:",{messageId:n.id,hasAudioContent:!(null==P||!P.audioContent),hasAudioResponse:null==P?void 0:P.hasAudioResponse,audioContentLength:(null==P||null===(i=P.audioContent)||void 0===i?void 0:i.length)||0}),C&&E&&E.length>10)console.log("ā
Message already finalized on end event; skipping overwrite");else{const e=v&&v.length>5?v:y,t=L&&String(L).startsWith("http")?L:e;if(t&&t.length>10){var u;console.log("š Finalizing message with content:",{messageId:n.id,currentMessageLength:String(t).length,currentMessagePreview:String(t).substring(0,50)+"..."});const e=this.messages.find(e=>e.id===n.id);console.log("š Finalizing message:",{latestRunId:a,messageId:n.id,existingAudioContent:!(null==e||!e.audioContent),existingAudioResponse:null==e?void 0:e.hasAudioResponse,audioContentLength:(null==e||null===(u=e.audioContent)||void 0===u?void 0:u.length)||0}),this._updateMessageInArray(n.id,{latestRunId:a,content:t,additional_kwargs:A,isStreaming:!1,isProcessing:!1,hasAudioResponse:(null==e?void 0:e.hasAudioResponse)||!1,audioContent:(null==e?void 0:e.audioContent)||null})}else{console.log("š Finalizing message with friendly fallback");const e=this.messages.find(e=>e.id===n.id);this._updateMessageInArray(n.id,{content:"Processing your request...",latestRunId:a,additional_kwargs:A,isStreaming:!1,isProcessing:!1,hasAudioResponse:(null==e?void 0:e.hasAudioResponse)||!1,audioContent:(null==e?void 0:e.audioContent)||null})}}if(T){console.log("š Adding UI action message:",T);const e={id:Date.now()+2,content:"",sender:"assistant",timestamp:(new Date).toISOString(),isUiAction:!0,url:T.url,uiActionType:T.uiActionType,scrollToId:T.scrollToId,navigationParams:T.navigationParams,originalUrl:T.originalUrl,isScrollAction:"scroll"===T.uiActionType,isNavigateStateAction:"navigate-state"===T.uiActionType},n=this.messages[this.messages.length-1];if(n){const i=t(t({},n),{},{uiActionMessage:e,latestRunId:a});console.log("UPDATED LAST MESSAGE",i),this._updateMessageInArray(n.id,{uiActionMessage:e,latestRunId:a})}}}catch(e){console.error("ā Streaming error:",e);const t=this.messages.find(e=>e.id===n.id);this._updateMessageInArray(n.id,{isStreaming:!1,isProcessing:!1,isError:!0,content:"Error occurred while processing request",latestRunId:a||(null==t?void 0:t.latestRunId)})}}async fetchAssistantId(){try{console.log("š Fetching assistant ID from API...");const e=this.authToken||this.accessToken,n=this.supabaseToken||e,t=await fetch("".concat(this.langgraphUrl,"/assistants/search"),{method:"POST",headers:{"Content-Type":"application/json",Authorization:"Bearer ".concat(e),"x-supabase-access-token":n,Origin:window.location.origin||"*"},body:JSON.stringify({limit:100,offset:0})});if(!t.ok)return console.log("ā API call failed with status: ".concat(t.status," - backend may have rejected due to auth")),null;const a=await t.json();console.log("š Available assistants:",a),a.forEach((e,n)=>{console.log("Assistant ".concat(n,":"),{id:e.assistant_id,name:e.name,hasName:!!e.name,type:typeof e.name})});const i=a.filter(e=>e.name&&e.name.includes("Default"))[0];if(i)return console.log("ā
Found Default Assistant:",i.assistant_id),this.assistantId=i.assistant_id,i.assistant_id;{console.log("ā ļø Default Assistant not found in the list");const e=a.find(e=>e.name&&""!==e.name.trim());return e?(console.log("ā ļø Using first valid assistant as fallback:",e.assistant_id,"Name:",e.name),this.assistantId=e.assistant_id,e.assistant_id):(console.log("ā No assistants with valid names available"),null)}}catch(e){return console.error("ā Error fetching assistant ID:",e),console.log("š Error details:",{name:e.name,message:e.message,isNetworkError:"TypeError"===e.name}),null}}async loadHistory(e){try{const t=await fetch("".concat(this.langgraphUrl,"/threads/").concat(e,"/history"),{method:"POST",headers:this.getHeaders(),body:JSON.stringify({limit:10})});if(t.ok){var n;const e=await t.json();console.log("š Loaded history:",e);const a=e[0];if(null==a||null===(n=a.values)||void 0===n||!n.messages)return void console.log("No messages found in history");const i=[];a.values.messages.forEach((e,n)=>{if("human"===e.type){let t="",a=!1;if(Array.isArray(e.content)){const n=e.content.find(e=>"text"===e.type);e.content.find(e=>"audio"===e.type)?(t="š¤ Audio message",a=!0):n&&(t=n.text)}else t=e.content;i.push({id:"history-".concat(n,"-human"),content:t,sender:"user",timestamp:(new Date).toISOString(),isAudio:a})}else"ai"===e.type&&i.push({id:"history-".concat(n,"-ai"),content:e.content,sender:"assistant",timestamp:(new Date).toISOString()})}),i&&i.length>0&&(console.log("š Loading ".concat(i.length," messages from history")),i.forEach(e=>{this._addMessageToArray(e)}))}}catch(e){console.error("ā Failed to load history:",e)}}async initializeChat(){try{console.log("š Initializing chat...");const e=localStorage.getItem("DfsWeb.access-token");console.log("š Access token status:",e?"Present":"Empty - backend will handle"),console.log("š Making API call to /assistants/search...");const n=await this.fetchAssistantId();if(!n)return console.log("ā Failed to fetch assistant ID - backend may have rejected due to auth"),this.isConnected=!1,void(this.initialized=!0);console.log("ā
Assistant ID fetched successfully:",n);const t=localStorage.getItem("DfsWeb.user-info"),a=t?JSON.parse(t):null;console.log("š Making API call to /threads...");const i=await fetch("".concat(this.langgraphUrl,"/threads"),{method:"POST",headers:this.getHeaders(),body:JSON.stringify({metadata:{user_id:(null==a?void 0:a.id)||null,user_uuid:(null==a?void 0:a.uuid)||null}})});if(i.ok){const e=await i.json();this.threadId=e.thread_id,this.isConnected=!0,console.log("ā
Thread created:",e.thread_id,"\n",e),await this.loadHistory(e.thread_id)}else{console.log("Thread created NOT");const e=await i.text();console.error("ā Failed to create thread:",i.status,e),this.isConnected=!1}this.initialized=!0}catch(e){console.error("ā Thread creation error:",e),this.isConnected=!1,this.initialized=!0}}}export{o as default};
|
|
1
|
+
function e(e,n,t){return(n=function(e){var n=function(e,n){if("object"!=typeof e||!e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var a=t.call(e,n);if("object"!=typeof a)return a;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===n?String:Number)(e)}(e,"string");return"symbol"==typeof n?n:n+""}(n))in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function n(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter(function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable})),t.push.apply(t,a)}return t}function t(t){for(var a=1;a<arguments.length;a++){var s=null!=arguments[a]?arguments[a]:{};a%2?n(Object(s),!0).forEach(function(n){e(t,n,s[n])}):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(s)):n(Object(s)).forEach(function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(s,e))})}return t}class a{constructor(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.placeholder=e.placeholder||"Type your message...",this.primaryColor=e.primaryColor||"#1a5c4b",this.title=e.title||"Chat Assistant",this.onMessage=e.onMessage||(()=>{}),this.onBack=e.onBack||(()=>{}),this.onOpenDrawer=e.onOpenDrawer||(()=>{}),this.onClose=e.onClose||(()=>{}),this.container=null,this.messages=e.messages,this.sendMessage=e.sendMessage||null,this.contentBlocks=e.contentBlocks||[],this.onContentBlocksChange=e.onContentBlocksChange||(()=>{}),this.navigateToAudioScreen=e.navigateToAudioScreen,this.SUPPORTED_FILE_TYPES=["image/jpeg","image/png","image/gif","image/webp"]}render(e){this.container=e,this._applyStyles(),e.innerHTML='\n <div class="text-chat-screen">\n <div class="chat-header">\n <div class="chat-header-content">\n <button class="chat-back" id="text-chat-menu">\n <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-menu-icon lucide-menu"><path d="M4 5h16"/><path d="M4 12h16"/><path d="M4 19h16"/></svg>\n </button>\n \n <div class="chat-header-text">\n <div class="chat-title">'.concat(this.title,'</div>\n </div>\n </div>\n <button class="chat-close" id="navigate-to-audio-screen">\n <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-mic-icon lucide-mic"><path d="M12 19v3"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><rect x="9" y="2" width="6" height="13" rx="3"/></svg>\n </button>\n ​ ​ ​\n <button class="chat-close" id="text-chat-close">\n <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <line x1="18" y1="6" x2="6" y2="18"></line>\n <line x1="6" y1="6" x2="18" y2="18"></line>\n </svg>\n </button>\n </div>\n <div class="chat-messages" id="chat-messages">\n <div class="chat-welcome">\n <div class="welcome-text">š Hello! I\'m your AI assistant. How can I help you today?</div>\n </div>\n </div>\n <div class="file-attachments-container" id="file-attachments-container" style="display: none;"></div>\n <div class="chat-input-wrapper">\n <div class="file-upload-controls">\n <input\n type="file"\n id="file-upload-input"\n accept="image/jpeg,image/png,image/gif,image/webp"\n style="display: none;"\n />\n <button id="file-upload-button" class="file-upload-button" title="Attach files">\n <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"></path>\n </svg>\n </button>\n </div>\n <input type="text" id="chat-input" placeholder="').concat(this.placeholder,'" autocomplete="off" />\n <button id="chat-send" disabled>\n <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <line x1="22" y1="2" x2="11" y2="13"></line>\n <polygon points="22 2 15 22 11 13 2 9 22 2"></polygon>\n </svg>\n </button>\n </div>\n </div>\n ');const n=e.querySelector("#text-chat-menu"),t=e.querySelector("#text-chat-close"),a=e.querySelector("#navigate-to-audio-screen");n&&n.addEventListener("click",()=>{this.onOpenDrawer?this.onOpenDrawer():this.onBack&&this.onBack()}),t&&t.addEventListener("click",()=>{this.onClose&&this.onClose()}),a&&a.addEventListener("click",()=>{this.navigateToAudioScreen&&this.navigateToAudioScreen()});const s=e.querySelector("#chat-input"),i=e.querySelector("#chat-send"),o=e.querySelector("#file-upload-input");e.querySelector("#file-upload-button").addEventListener("click",()=>{o.click()}),o.addEventListener("change",e=>{this.handleFileUpload(e)});const r=()=>{const e=s.value.trim().length>0,n=this.contentBlocks.length>0;i.disabled=!(e||n)};s.addEventListener("input",()=>{r()});const c=async()=>{const e=s.value.trim();if(e||0!==this.contentBlocks.length)if(this.addMessage(e||"š File attachments",!0),s.value="",i.disabled=!0,this.hideTypingIndicator(),this.sendMessage)try{await this.sendMessage(e,this.contentBlocks),this.contentBlocks=[],this.onContentBlocksChange(this.contentBlocks),this.renderFilePreview(),this.updateSendButton()}catch(e){console.error("Error sending message:",e),this.addMessage("Sorry, I encountered an error. Please try again.",!1)}finally{this.hideTypingIndicator()}else setTimeout(()=>{this.hideTypingIndicator(),this.handleUserMessage(e)},1e3+1e3*Math.random())};i.addEventListener("click",c),s.addEventListener("keypress",e=>{"Enter"!==e.key||i.disabled||c()}),setTimeout(()=>s.focus(),100),this.renderFilePreview(),this.messages&&this.messages.length>0&&setTimeout(()=>{this._syncMessages(this.messages)},50)}fileToContentBlock(e){return new Promise((n,t)=>{const a=new FileReader;a.onload=()=>{const s=a.result.split(",")[1];this.SUPPORTED_FILE_TYPES.includes(e.type)?n({type:"image",source_type:"base64",mime_type:e.type,data:s,metadata:{name:e.name,size:e.size}}):t(new Error("Unsupported file type: ".concat(e.type)))},a.onerror=()=>{t(new Error("Failed to read file: ".concat(e.name)))},a.readAsDataURL(e)})}isDuplicateFile(e,n){return!!this.SUPPORTED_FILE_TYPES.includes(e.type)&&n.some(n=>{var t;return"image"===n.type&&(null===(t=n.metadata)||void 0===t?void 0:t.name)===e.name&&n.mime_type===e.type})}formatFileSize(e){if(0===e)return"0 Bytes";const n=Math.floor(Math.log(e)/Math.log(1024));return parseFloat((e/Math.pow(1024,n)).toFixed(2))+" "+["Bytes","KB","MB","GB"][n]}getFileTypeDisplay(e){switch(e){case"image/jpeg":case"image/jpg":return"JPEG Image";case"image/png":return"PNG Image";case"image/gif":return"GIF Image";case"image/webp":return"WebP Image";default:return"Unknown File"}}async handleFileUpload(e){const n=e.target.files;if(!n)return;const t=Array.from(n),a=t.filter(e=>this.SUPPORTED_FILE_TYPES.includes(e.type));t.filter(e=>!this.SUPPORTED_FILE_TYPES.includes(e.type)).length>0&&console.warn("Invalid file type. Please upload a JPEG, PNG, GIF, or WEBP image.");const s=a[0];if(s)try{const e=await this.fileToContentBlock(s);this.contentBlocks=[e],this.onContentBlocksChange(this.contentBlocks),this.renderFilePreview(),this.updateSendButton()}catch(e){console.error("Failed to process files: ".concat(e.message))}e.target.value=""}removeBlock(e){this.contentBlocks=this.contentBlocks.filter((n,t)=>t!==e),this.onContentBlocksChange(this.contentBlocks),this.renderFilePreview(),this.updateSendButton()}updateSendButton(){if(!this.container)return;const e=this.container.querySelector("#chat-input"),n=this.container.querySelector("#chat-send");if(!e||!n)return;const t=e.value.trim().length>0,a=this.contentBlocks.length>0;n.disabled=!(t||a)}renderFilePreview(){if(!this.container)return;const e=this.container.querySelector("#file-attachments-container");if(e){if(!this.contentBlocks||0===this.contentBlocks.length)return e.innerHTML="",void(e.style.display="none");e.style.display="flex",e.innerHTML=this.contentBlocks.map((e,n)=>{var t,a,s;const i=(null===(t=e.metadata)||void 0===t?void 0:t.filename)||(null===(a=e.metadata)||void 0===a?void 0:a.name)||"file",o=this.formatFileSize((null===(s=e.metadata)||void 0===s?void 0:s.size)||0),r="image"===e.type,c=r?"data:".concat(e.mime_type,";base64,").concat(e.data):null;return'\n <div class="file-attachment '.concat(r?"has-thumbnail":"",'" data-index="').concat(n,'">\n ').concat(r?'\n <div class="file-thumbnail">\n <img src="'.concat(c,'" alt="').concat(i,'" class="file-thumbnail-image" />\n </div>\n '):'<div class="file-attachment-icon">š</div>','\n <div class="file-attachment-info">\n <div class="file-attachment-name" title="').concat(i,'">\n ').concat(i,'\n </div>\n <div class="file-attachment-size">').concat(o,'</div>\n </div>\n <button\n class="file-attachment-remove"\n data-index="').concat(n,'"\n title="Remove file"\n >\n ā\n </button>\n </div>\n ')}).join(""),e.querySelectorAll(".file-attachment-remove").forEach(e=>{e.addEventListener("click",n=>{n.stopPropagation();const t=parseInt(e.getAttribute("data-index"));this.removeBlock(t)})}),e.querySelectorAll(".file-thumbnail-image").forEach(e=>{e.addEventListener("click",e=>{e.stopPropagation()})})}}_formatTime(e){let n=e.getHours();const t=e.getMinutes(),a=n>=12?"PM":"AM";n%=12,n=n||12;return n.toString().padStart(2,"0")+":"+t.toString().padStart(2,"0")+" "+a}addMessage(e,n){let t=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;if(console.log("Is user",n),!this.container)return;const a=this.container.querySelector("#chat-messages");if(!a)return;const s=a.querySelector(".chat-welcome");s&&s.remove();const i=(null==t?void 0:t.id)||Date.now();console.log("Message ID",i);const o=a.querySelector('[data-message-id="'.concat(i,'"]'));if(o&&t){const s=o.querySelector(".message-bubble");if(s){const a=t.content||e;s.innerHTML=n?this._escapeHtml(a):this._parseMarkdown(a)}return void(a.scrollTop=a.scrollHeight)}const r=document.createElement("div");r.className="chat-message ".concat(n?"user":"bot"),r.setAttribute("data-message-id",i);let c=e;t&&(t.isStreaming?c=t.content||"Thinking...":t.isError?(c=t.content||"Error occurred",r.classList.add("error")):c=t.content||e);let l="";t&&t.attachments&&t.attachments.length>0&&(l='\n <div class="message-attachments">\n '.concat(t.attachments.map((e,n)=>{var t,a,s;const i=(null===(t=e.metadata)||void 0===t?void 0:t.name)||(null===(a=e.metadata)||void 0===a?void 0:a.filename)||"Unknown file",o="image"===e.type,r=o&&e.data?"data:".concat(e.mime_type,";base64,").concat(e.data):null;return'\n <div class="message-attachment '.concat(o?"image":"pdf",'" data-attachment-index="').concat(n,'">\n <span class="message-attachment-icon">\n ').concat(o?"š¼ļø":"š",'\n </span>\n <div class="message-attachment-info">\n <div \n class="message-attachment-name ').concat(o?"clickable":"",'"\n ').concat(o&&r?'data-image-src="'.concat(r,'" data-image-alt="').concat(i,'"'):"",'\n style="cursor: ').concat(o?"pointer":"default",';"\n >\n ').concat(this._escapeHtml(i),'\n </div>\n <div class="message-attachment-size">\n ').concat(this.formatFileSize((null===(s=e.metadata)||void 0===s?void 0:s.size)||0)," ⢠").concat(this.getFileTypeDisplay(e.mime_type),"\n </div>\n </div>\n </div>\n ")}).join(""),"\n </div>\n "));const d=null!=t&&t.timestamp?new Date(t.timestamp):new Date,h=this._formatTime(d),g=n?this._escapeHtml(c):this._parseMarkdown(c);r.innerHTML='\n <div class="message-content">\n '.concat(l,'\n <div class="message-bubble">\n ').concat(g,'\n </div>\n <div class="message-time">').concat(h,"</div>\n </div>\n "),t&&t.attachments&&r.querySelectorAll(".message-attachment-name.clickable").forEach(e=>{e.addEventListener("click",n=>{n.stopPropagation();const t=e.getAttribute("data-image-src"),a=e.getAttribute("data-image-alt");t&&this.showExpandedImage(t,a)})}),a.appendChild(r),a.scrollTop=a.scrollHeight}_syncMessages(e){if(!this.container)return;const n=this.container.querySelector("#chat-messages");if(!n)return;if(e.length>0){const e=n.querySelector(".chat-welcome");e&&e.remove()}const t=n.querySelectorAll("[data-message-id]"),a=new Set(Array.from(t).map(e=>e.getAttribute("data-message-id")));e.forEach(e=>{const t=String(e.id);if(a.has(t)){const a=n.querySelector('[data-message-id="'.concat(t,'"]'));if(a){const n=a.querySelector(".message-bubble");if(n){const t=e.content||"",a="user"===e.sender;n.innerHTML=a?this._escapeHtml(t):this._parseMarkdown(t)}const t=a.querySelector(".message-content");if(t&&e.attachments&&e.attachments.length>0){let n='\n <div class="message-attachments">\n '.concat(e.attachments.map((e,n)=>{var t,a,s;const i=(null===(t=e.metadata)||void 0===t?void 0:t.name)||(null===(a=e.metadata)||void 0===a?void 0:a.filename)||"Unknown file",o="image"===e.type,r=o&&e.data?"data:".concat(e.mime_type,";base64,").concat(e.data):null;return'\n <div class="message-attachment '.concat(o?"image":"pdf",'" data-attachment-index="').concat(n,'">\n <span class="message-attachment-icon">\n ').concat(o?"š¼ļø":"š",'\n </span>\n <div class="message-attachment-info">\n <div \n class="message-attachment-name ').concat(o?"clickable":"",'"\n ').concat(o&&r?'data-image-src="'.concat(r,'" data-image-alt="').concat(i,'"'):"",'\n style="cursor: ').concat(o?"pointer":"default",';"\n >\n ').concat(this._escapeHtml(i),'\n </div>\n <div class="message-attachment-size">\n ').concat(this.formatFileSize((null===(s=e.metadata)||void 0===s?void 0:s.size)||0)," ⢠").concat(this.getFileTypeDisplay(e.mime_type),"\n </div>\n </div>\n </div>\n ")}).join(""),"\n </div>\n ");const a=t.querySelector(".message-attachments");a?a.outerHTML=n:t.insertAdjacentHTML("afterbegin",n),t.querySelectorAll(".message-attachment-name.clickable").forEach(e=>{const n=e.cloneNode(!0);e.parentNode.replaceChild(n,e),n.addEventListener("click",e=>{e.stopPropagation();const t=n.getAttribute("data-image-src"),a=n.getAttribute("data-image-alt");t&&this.showExpandedImage(t,a)})})}e.isStreaming?a.classList.add("streaming"):a.classList.remove("streaming"),e.isError&&a.classList.add("error")}}else this.addMessage(e.content||"","user"===e.sender,e)}),t.forEach(n=>{const t=n.getAttribute("data-message-id");e.some(e=>String(e.id)===t)||n.remove()}),n.scrollTop=n.scrollHeight}showTypingIndicator(){if(!this.container)return;const e=this.container.querySelector("#chat-messages");if(!e)return;const n=document.createElement("div");n.className="chat-message bot",n.id="typing-indicator",n.innerHTML='\n <div class="typing-indicator">\n <div class="typing-dot"></div>\n <div class="typing-dot"></div>\n <div class="typing-dot"></div>\n </div>\n ',e.appendChild(n),e.scrollTop=e.scrollHeight}hideTypingIndicator(){if(!this.container)return;const e=this.container.querySelector("#typing-indicator");e&&e.remove()}handleUserMessage(e){this.onMessage?this.onMessage(e,e=>{this.addMessage(e,!1)}):this.addMessage('You said: "'.concat(e,'"'),!1)}_escapeHtml(e){const n=document.createElement("div");return n.textContent=e,n.innerHTML}_parseMarkdown(e){if(!e||"string"!=typeof e)return"";let n=e;n=n.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">");const t=n.split("\n"),a=[];let s=!1;for(let e=0;e<t.length;e++){let n=t[e];const i=n.match(/^(#{1,6})\s+(.+)$/);if(i){s&&(a.push("</ul>"),s=!1);const e=i[1].length;let n=i[2];n=n.replace(/\*\*([^*]+)\*\*/g,"<strong>$1</strong>"),n=n.replace(/__([^_]+)__/g,"<strong>$1</strong>"),n=n.replace(/(^|[^*])\*([^*]+)\*([^*]|$)/g,"$1<em>$2</em>$3"),n=n.replace(/(^|[^_])_([^_]+)_([^_]|$)/g,"$1<em>$2</em>$3"),a.push("<h".concat(e,">").concat(n,"</h").concat(e,">"));continue}const o=n.match(/^[\s]*[-*]\s+(.+)$/);if(o){let e=o[1];e=e.replace(/\*\*([^*]+)\*\*/g,"<strong>$1</strong>"),e=e.replace(/__([^_]+)__/g,"<strong>$1</strong>"),e=e.replace(/(^|[^*])\*([^*]+)\*([^*]|$)/g,"$1<em>$2</em>$3"),e=e.replace(/(^|[^_])_([^_]+)_([^_]|$)/g,"$1<em>$2</em>$3"),s||(a.push("<ul>"),s=!0),a.push("<li>".concat(e,"</li>"))}else{if(s&&(a.push("</ul>"),s=!1),""===n.trim()){a.push("");continue}n=n.replace(/\*\*([^*]+)\*\*/g,"<strong>$1</strong>"),n=n.replace(/__([^_]+)__/g,"<strong>$1</strong>"),n=n.replace(/(^|[^*])\*([^*]+)\*([^*]|$)/g,"$1<em>$2</em>$3"),n=n.replace(/(^|[^_])_([^_]+)_([^_]|$)/g,"$1<em>$2</em>$3"),n=n.replace(/`([^`]+)`/g,"<code>$1</code>"),n=n.replace(/\[([^\]]+)\]\(([^)]+)\)/g,'<a href="$2" target="_blank" rel="noopener noreferrer">$1</a>'),a.push(n)}}return s&&a.push("</ul>"),n=a.join("<br>"),n}showExpandedImage(e,n){const t=document.querySelector(".expanded-image-modal");t&&t.remove();const a=document.createElement("div");a.className="expanded-image-modal",a.innerHTML='\n <div class="expanded-image-container">\n <button class="expanded-image-close" title="Close">ā</button>\n <img src="'.concat(e,'" alt="').concat(n||"Image",'" class="expanded-image" />\n <div class="expanded-image-caption">').concat(this._escapeHtml(n||"Image preview"),"</div>\n </div>\n ");const s=e=>{null==e||e.stopPropagation(),a.remove(),document.removeEventListener("mousedown",i)},i=e=>{e.target.closest(".expanded-image-container")||s(e)};a.querySelector(".expanded-image-close").addEventListener("click",s),a.addEventListener("click",e=>{e.target===a&&s(e)}),document.addEventListener("mousedown",i),document.body.appendChild(a)}_applyStyles(){if(document.getElementById("text-chat-screen-styles"))return;const e=document.createElement("style");e.id="text-chat-screen-styles",e.textContent="\n .text-chat-screen {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n \n }\n\n .text-chat-screen .chat-header {\n background: transparent;\n color: ".concat(this.primaryColor,";\n padding: 20px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n }\n\n .text-chat-screen .chat-header-content {\n display: flex;\n align-items: center;\n gap: 12px;\n flex: 1;\n }\n\n .text-chat-screen .chat-back {\n background: ").concat(this.primaryColor,";\n border: none;\n color: white;\n cursor: pointer;\n padding: 8px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s;\n margin-right: 8px;\n }\n\n \n\n .text-chat-screen .chat-avatar {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n background: rgba(255, 255, 255, 0.2);\n backdrop-filter: blur(10px);\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .text-chat-screen .chat-header-text {\n display: flex;\n flex-direction: column;\n gap: 2px;\n }\n\n .text-chat-screen .chat-title {\n font-weight: 600;\n font-size: 20px;\n }\n\n .text-chat-screen .chat-status {\n font-size: 12px;\n opacity: 0.9;\n display: flex;\n align-items: center;\n gap: 4px;\n }\n\n .text-chat-screen .chat-close {\n background: ").concat(this.primaryColor,";\n border: none;\n color: white;\n cursor: pointer;\n padding: 8px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s;\n }\n\n \n\n .text-chat-screen .chat-messages {\n flex: 1;\n padding: 20px;\n overflow-y: auto;\n background: linear-gradient(180deg, white 10%, #E1EFCC );\n display: flex;\n flex-direction: column;\n gap: 12px;\n }\n\n .text-chat-screen .chat-messages::-webkit-scrollbar {\n width: 6px;\n }\n\n .text-chat-screen .chat-messages::-webkit-scrollbar-track {\n background: transparent;\n }\n\n .text-chat-screen .chat-messages::-webkit-scrollbar-thumb {\n background: #cbd5e1;\n border-radius: 3px;\n }\n\n .text-chat-screen .chat-welcome {\n text-align: center;\n padding: 100px 20px;\n color: #64748b;\n \n }\n\n .text-chat-screen .chat-welcome .welcome-icon {\n font-size: 48px;\n margin-bottom: 12px;\n }\n\n .text-chat-screen .welcome-text {\n font-size: 15px;\n font-weight: 500;\n color: #475569;\n }\n\n .text-chat-screen .chat-message {\n display: flex;\n gap: 8px;\n animation: messageSlide 0.3s ease-out;\n }\n\n @keyframes messageSlide {\n from {\n opacity: 0;\n transform: translateY(10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n .text-chat-screen .chat-message.user {\n flex-direction: row-reverse;\n }\n\n .text-chat-screen .message-content {\n max-width: 75%;\n }\n\n .text-chat-screen .message-bubble {\n padding: 12px 16px;\n border-radius: 16px;\n font-size: 14px;\n line-height: 1.5;\n word-wrap: break-word;\n }\n\n .text-chat-screen .chat-message.user .message-bubble {\n background: #e9f5d7;\n color: ").concat(this.primaryColor,";\n border-bottom-right-radius: 4px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n }\n\n .text-chat-screen .chat-message.bot .message-bubble {\n background: white;\n color: #1e293b;\n border-bottom-left-radius: 4px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n }\n\n /* ============================================\n Text Chat Message Bubble Styles\n ============================================ */\n\n/* Typography - Bold */\n.text-chat-screen .message-bubble strong {\n font-weight: 600;\n color: inherit;\n}\n\n/* Typography - Italic */\n.text-chat-screen .message-bubble em {\n font-style: italic;\n}\n\n/* Lists */\n.text-chat-screen .message-bubble ul {\n margin: 0px 0;\n padding-left: 20px;\n list-style-type: disc;\n margin-bottom:0px;\n margin-top:5px;\n}\n\n.text-chat-screen .message-bubble li {\n margin: 0;\n line-height: 1.1;\n padding-left: 3px;\n}\n\n/* Headings - Shared Styles */\n.text-chat-screen .message-bubble h1,\n.text-chat-screen .message-bubble h2,\n.text-chat-screen .message-bubble h3,\n.text-chat-screen .message-bubble h4,\n.text-chat-screen .message-bubble h5,\n.text-chat-screen .message-bubble h6 {\n margin: 0px 0 0px 0;\n font-weight: 600;\n color: inherit;\n line-height: 1.3;\n}\n\n/* Heading Sizes */\n.text-chat-screen .message-bubble h1 { font-size: 1.5em; }\n.text-chat-screen .message-bubble h2 { font-size: 1.3em; }\n.text-chat-screen .message-bubble h3 { font-size: 1.15em; }\n.text-chat-screen .message-bubble h4 { font-size: 1.05em; }\n.text-chat-screen .message-bubble h5 { font-size: 1em; }\n.text-chat-screen .message-bubble h6 { font-size: 0.95em; }\n\n/* Inline Code */\n.text-chat-screen .message-bubble code {\n background: rgba(0, 0, 0, 0.05);\n padding: 2px 6px;\n border-radius: 4px;\n font-family: 'Courier New', Courier, monospace;\n font-size: 0.9em;\n}\n\n/* Links */\n.text-chat-screen .message-bubble a {\n color: ").concat(this.primaryColor,";\n text-decoration: underline;\n}\n\n.text-chat-screen .message-bubble a:hover {\n opacity: 0.8;\n}\n.text-chat-screen .message-bubble br {\n line-height: 0.1; /* Adjust between 0 and 1 */\n}\n\n .text-chat-screen .message-time {\n font-size: 10px;\n color: #94a3b8;\n margin-top: 4px;\n text-align: right;\n }\n\n .text-chat-screen .typing-indicator {\n display: flex;\n gap: 4px;\n padding: 12px 16px;\n background: white;\n border-radius: 16px;\n border-bottom-left-radius: 4px;\n max-width: 60px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n }\n\n .text-chat-screen .typing-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: #94a3b8;\n animation: typing 1.4s infinite;\n }\n\n .text-chat-screen .typing-dot:nth-child(2) {\n animation-delay: 0.2s;\n }\n\n .text-chat-screen .typing-dot:nth-child(3) {\n animation-delay: 0.4s;\n }\n\n @keyframes typing {\n 0%, 60%, 100% {\n transform: translateY(0);\n opacity: 0.7;\n }\n 30% {\n transform: translateY(-10px);\n opacity: 1;\n }\n }\n\n .text-chat-screen .file-attachments-container {\n padding: 8px 12px;\n background: white;\n border-top: 1px solid #e2e8f0;\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n max-height: 120px;\n overflow-y: auto;\n }\n\n .text-chat-screen .file-attachments-container::-webkit-scrollbar {\n width: 4px;\n height: 4px;\n }\n\n .text-chat-screen .file-attachments-container::-webkit-scrollbar-track {\n background: transparent;\n }\n\n .text-chat-screen .file-attachments-container::-webkit-scrollbar-thumb {\n background: #cbd5e1;\n border-radius: 2px;\n }\n\n .text-chat-screen .file-attachment {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 10px;\n background: #f1f5f9;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n font-size: 12px;\n max-width: 200px;\n position: relative;\n }\n\n .text-chat-screen .file-attachment.has-thumbnail {\n padding: 4px;\n }\n\n .text-chat-screen .file-thumbnail {\n width: 40px;\n height: 40px;\n border-radius: 6px;\n overflow: hidden;\n flex-shrink: 0;\n background: #e2e8f0;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .text-chat-screen .file-thumbnail-image {\n width: 100%;\n height: 100%;\n object-fit: cover;\n cursor: pointer;\n }\n\n .text-chat-screen .file-attachment-icon {\n font-size: 24px;\n flex-shrink: 0;\n }\n\n .text-chat-screen .file-attachment-info {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n }\n\n .text-chat-screen .file-attachment-name {\n font-weight: 500;\n color: #1e293b;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 120px;\n }\n\n .text-chat-screen .file-attachment-size {\n font-size: 11px;\n color: #64748b;\n }\n\n .text-chat-screen .file-attachment-remove {\n background: transparent;\n border: none;\n color: #64748b;\n cursor: pointer;\n padding: 4px;\n border-radius: 4px;\n font-size: 16px;\n line-height: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s;\n flex-shrink: 0;\n }\n\n .text-chat-screen .file-attachment-remove:hover {\n background: #fee2e2;\n color: #dc2626;\n }\n\n .text-chat-screen .chat-input-wrapper {\n display: flex;\n padding: 10px;\n gap: 8px;\n background: white;\n border-top: 1px solid #e2e8f0;\n align-items: center;\n }\n\n .text-chat-screen .file-upload-controls {\n display: flex;\n align-items: center;\n }\n\n .text-chat-screen .file-upload-button {\n background: transparent;\n border: none;\n color: ").concat(this.primaryColor,";\n cursor: pointer;\n padding: 8px;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s;\n }\n\n .text-chat-screen .file-upload-button:hover {\n background: rgba(26, 92, 75, 0.1);\n }\n\n .text-chat-screen .file-upload-button:active {\n transform: scale(0.95);\n }\n\n .text-chat-screen #chat-input {\n flex: 1;\n border: 2px solid #e2e8f0;\n border-radius: 12px;\n padding: 12px 16px;\n font-size: 14px;\n outline: none;\n transition: all 0.2s;\n font-family: inherit;\n }\n\n .text-chat-screen #chat-input:focus {\n border-color: ").concat(this.primaryColor,";\n box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);\n }\n\n .text-chat-screen #chat-send {\n background: ").concat(this.primaryColor,";\n color: white;\n border: none;\n border-radius: 12px;\n padding: 12px 16px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s;\n }\n\n .text-chat-screen #chat-send:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .text-chat-screen #chat-send:not(:disabled):hover {\n transform: scale(1.05);\n box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3);\n }\n\n .text-chat-screen #chat-send:not(:disabled):active {\n transform: scale(0.95);\n }\n\n /* Message Attachments Styles */\n .text-chat-screen .message-attachments {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-bottom: 8px;\n }\n\n .text-chat-screen .message-attachment {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n background: #f1f5f9;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n font-size: 12px;\n max-width: 100%;\n }\n\n .text-chat-screen .message-attachment.image {\n background: #f8fafc;\n }\n\n .text-chat-screen .message-attachment.pdf {\n background: #fef2f2;\n }\n\n .text-chat-screen .message-attachment-icon {\n font-size: 20px;\n flex-shrink: 0;\n }\n\n .text-chat-screen .message-attachment-info {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n }\n\n .text-chat-screen .message-attachment-name {\n font-weight: 500;\n color: #1e293b;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .text-chat-screen .message-attachment-name.clickable:hover {\n color: ").concat(this.primaryColor,";\n text-decoration: underline;\n }\n\n .text-chat-screen .message-attachment-size {\n font-size: 11px;\n color: #64748b;\n }\n\n /* Expanded Image Modal Styles */\n .expanded-image-modal {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.8);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10000;\n animation: fadeIn 0.2s ease;\n }\n\n @keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n }\n\n .expanded-image-container {\n position: relative;\n max-width: 90%;\n max-height: 90vh;\n background: #fff;\n border-radius: 8px;\n overflow: hidden;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);\n animation: scaleIn 0.2s ease;\n display: flex;\n flex-direction: column;\n }\n\n @keyframes scaleIn {\n from {\n transform: scale(0.9);\n opacity: 0;\n }\n to {\n transform: scale(1);\n opacity: 1;\n }\n }\n\n .expanded-image-close {\n position: absolute;\n top: 12px;\n right: 12px;\n background: rgba(0, 0, 0, 0.6);\n border: none;\n color: white;\n width: 32px;\n height: 32px;\n border-radius: 50%;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 18px;\n z-index: 1;\n transition: all 0.2s;\n }\n\n .expanded-image-close:hover {\n background: rgba(0, 0, 0, 0.8);\n transform: scale(1.1);\n }\n\n .expanded-image {\n max-width: 100%;\n max-height: calc(90vh - 60px);\n object-fit: contain;\n display: block;\n }\n\n .expanded-image-caption {\n padding: 12px 16px;\n background: #fff;\n color: #1e293b;\n font-size: 14px;\n text-align: center;\n border-top: 1px solid #e2e8f0;\n }\n "),document.head.appendChild(e)}}class s{constructor(){this.apiKey="23588533c1-d990-4a7d-b052-d970c886147e",this.userId="749bd0b0c65e4d17a372be0ad92af981",this.callbackUrl="https://meity-auth.ulcacontrib.org/ulca/apis/v0/model/getModelsPipeline",this.inferenceUrl=null,this.inferenceHeaders={},this.asrServiceId={hi:"ai4bharat/conformer-hi-gpu--t4",en:"ai4bharat/whisper-medium-en--gpu--t4"},this.ttsServiceId={hi:"ai4bharat/indic-tts-coqui-indo_aryan-gpu--t4",en:"ai4bharat/indic-tts-coqui-misc-gpu--t4"},this.translationServiceId="ai4bharat/indictrans-v2-all-gpu--t4"}async initialize(){try{const e=await fetch(this.callbackUrl,{method:"POST",headers:{"Content-Type":"application/json",userID:this.userId,ulcaApiKey:this.apiKey},body:JSON.stringify({pipelineTasks:[{taskType:"asr"}],pipelineRequestConfig:{pipelineId:"64392f96daac500b55c543cd"}})}),n=await e.json();if(n.pipelineInferenceAPIEndPoint){this.inferenceUrl=n.pipelineInferenceAPIEndPoint.callbackUrl;const e=n.pipelineInferenceAPIEndPoint.inferenceApiKey.name,t=n.pipelineInferenceAPIEndPoint.inferenceApiKey.value;this.inferenceHeaders={"Content-Type":"application/json",[e]:t}}else this.inferenceUrl="https://dhruva-api.bhashini.gov.in/services/inference/pipeline",this.inferenceHeaders={"Content-Type":"application/json",userID:this.userId,ulcaApiKey:this.apiKey};return!0}catch(e){return console.error("Failed to initialize Bhashini:",e),this.inferenceUrl="https://dhruva-api.bhashini.gov.in/services/inference/pipeline",this.inferenceHeaders={"Content-Type":"application/json",userID:this.userId,ulcaApiKey:this.apiKey},!1}}async convertToWav(e){return new Promise((n,t)=>{const a=new(window.AudioContext||window.webkitAudioContext),s=new FileReader;s.onload=async e=>{try{const t=e.target.result,s=await a.decodeAudioData(t),i=new OfflineAudioContext(1,16e3*s.duration,16e3),o=i.createBufferSource();o.buffer=s,o.connect(i.destination),o.start();const r=await i.startRendering(),c=this.audioBufferToWav(r),l=new Blob([c],{type:"audio/wav"}),d=new FileReader;d.onloadend=()=>{const e=d.result.split(",")[1];n(e)},d.readAsDataURL(l)}catch(e){t(e)}},s.onerror=t,s.readAsArrayBuffer(e)})}audioBufferToWav(e){const n=e.length*e.numberOfChannels*2+44,t=new ArrayBuffer(n),a=new DataView(t),s=[];let i=0,o=0;const r=e=>{a.setUint16(o,e,!0),o+=2},c=e=>{a.setUint32(o,e,!0),o+=4};c(1179011410),c(n-8),c(1163280727),c(544501094),c(16),r(1),r(e.numberOfChannels),c(e.sampleRate),c(2*e.sampleRate*e.numberOfChannels),r(2*e.numberOfChannels),r(16),c(1635017060),c(n-o-4);for(let n=0;n<e.numberOfChannels;n++)s.push(e.getChannelData(n));for(;o<n;){for(let n=0;n<e.numberOfChannels;n++){let e=Math.max(-1,Math.min(1,s[n][i]));e=e<0?32768*e:32767*e,a.setInt16(o,e,!0),o+=2}i++}return t}async speechToText(e){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"auto",t=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"hi";this.inferenceUrl||await this.initialize();const a=[{taskType:"asr",config:{language:{sourceLanguage:n},serviceId:this.asrServiceId[n]||this.asrServiceId.hi,audioFormat:"wav",samplingRate:16e3}}];n!==t&&a.push({taskType:"translation",config:{sourceLanguage:"auto"===n?void 0:n,targetLanguage:t}});const s=await fetch(this.inferenceUrl,{method:"POST",headers:this.inferenceHeaders,body:JSON.stringify({pipelineTasks:a,inputData:{audio:[{audioContent:e}]}})});if(!s.ok)throw new Error("API error: ".concat(s.status," ").concat(s.statusText));const i=await s.json();return a.length>1?i.pipelineResponse[1].output[0].target:i.pipelineResponse[0].output[0].source}async textToSpeech(e){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"en",t=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"female";this.inferenceUrl||await this.initialize();const a=e.replace(/!/g,"."),s=await fetch(this.inferenceUrl,{method:"POST",headers:this.inferenceHeaders,body:JSON.stringify({pipelineTasks:[{taskType:"tts",config:{language:{sourceLanguage:n},serviceId:this.ttsServiceId[n]||this.ttsServiceId.en,samplingRate:8e3,gender:t}}],inputData:{input:[{source:a}]}})});if(!s.ok)throw new Error("TTS API error: ".concat(s.status," ").concat(s.statusText));return(await s.json()).pipelineResponse[0].audio[0].audioContent}async translateText(e,n,t){this.inferenceUrl||await this.initialize();const a=await fetch(this.inferenceUrl,{method:"POST",headers:this.inferenceHeaders,body:JSON.stringify({pipelineTasks:[{taskType:"translation",config:{language:{sourceLanguage:n,targetLanguage:t},serviceId:this.translationServiceId}}],inputData:{input:[{source:e}]}})});if(!a.ok)throw new Error("Translation API error: ".concat(a.status," ").concat(a.statusText));return(await a.json()).pipelineResponse[0].output[0].target}async speechToEnglish(e){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"hi";const t=await this.speechToText(e,n);if("en"===n)return{transcription:t,translation:t};return{transcription:t,translation:await this.translateText(t,n,"en")}}async speechToHindi(e){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"en";const t=await this.speechToText(e,n);if("hi"===n)return{transcription:t,translation:t};return{transcription:t,translation:await this.translateText(t,n,"hi")}}async transcribeSpeechToEnglish(e){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"hi";const t=await this.speechToText(e,n);if("en"===n)return{transcription:t,translation:t};return{transcription:t,translation:await this.translateText(t,n,"en")}}}class i{constructor(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.primaryColor=e.primaryColor||"#1a5c4b",this.title=e.title||"Chat Assistant",this.onRecordStart=e.onRecordStart||(()=>{}),this.onRecordStop=e.onRecordStop||(()=>{}),this.onBack=e.onBack||(()=>{}),this.onOpenDrawer=e.onOpenDrawer||(()=>{}),this.onClose=e.onClose||(()=>{}),this.navigateToTextScreen=e.navigateToTextScreen,this.sendMessage=e.sendMessage||null,this.selectedLanguage=e.selectedLanguage||"en",this.container=null,this.messages=e.messages||[],this.bhashini=new s,this.mediaRecorder=null,this.audioChunks=[],this.isRecording=!1,this.playedMessageIds=new Set,this.audioQueue=[],this.isPlaying=!1,this.contentBlocks=[],this.SUPPORTED_FILE_TYPES=["image/jpeg","image/png","image/gif","image/webp"]}render(e){this.container=e,this._applyStyles(),e.innerHTML='\n <div class="audio-chat-screen">\n <div class="chat-header">\n <div class="chat-header-content">\n <button class="chat-back" id="audio-chat-menu">\n <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-menu-icon lucide-menu"><path d="M4 5h16"/><path d="M4 12h16"/><path d="M4 19h16"/></svg>\n </button>\n \n <div class="chat-header-text">\n <div class="chat-title">'.concat(this.title,'</div>\n </div>\n </div>\n <button class="chat-close" id="navigate-to-text-screen">\n <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-message-square-text-icon lucide-message-square-text"><path d="M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z"/><path d="M7 11h10"/><path d="M7 15h6"/><path d="M7 7h8"/></svg>\n </button>\n ​ ​ ​\n <button class="chat-close" id="audio-chat-close">\n <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <line x1="18" y1="6" x2="6" y2="18"></line>\n <line x1="6" y1="6" x2="18" y2="18"></line>\n </svg>\n </button>\n </div>\n \n \n <div class="chat-messages" id="chat-messages">\n <div class="chat-welcome">\n <div class="welcome-text">š Hello! I\'m your AI assistant. How can I help you today?</div>\n </div>\n </div> \n \n \n <div class="file-attachments-container" id="file-attachments-container" style="display: none;"></div>\n <div class="bottom-inputs">\n <button id="record-button">\n <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-mic-icon lucide-mic"><path d="M12 19v3"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><rect x="9" y="2" width="6" height="13" rx="3"/></svg>\n </button>\n ​ ​ ​​ ​ ​\n <input\n type="file"\n id="file-upload-input"\n accept="image/jpeg,image/png,image/gif,image/webp"\n style="display: none;"\n />\n <button id="attachment-button">\n <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-paperclip-icon lucide-paperclip"><path d="m16 6-8.414 8.586a2 2 0 0 0 2.829 2.829l8.414-8.586a4 4 0 1 0-5.657-5.657l-8.379 8.551a6 6 0 1 0 8.485 8.485l8.379-8.551"/></svg>\n </button>\n </div>\n \n \n </div>\n ');const n=e.querySelector("#audio-chat-menu"),t=e.querySelector("#audio-chat-close"),a=e.querySelector("#navigate-to-text-screen");n&&n.addEventListener("click",()=>{this.onOpenDrawer?this.onOpenDrawer():this.onBack&&this.onBack()}),t&&t.addEventListener("click",()=>{this.onClose&&this.onClose()}),a&&a.addEventListener("click",()=>{this.navigateToTextScreen&&this.navigateToTextScreen()});const s=e.querySelector("#record-button"),i=e.querySelector("#attachment-button");s&&s.addEventListener("click",()=>{this.toggleRecording(s)});const o=e.querySelector("#file-upload-input");i&&o&&(i.addEventListener("click",()=>{o.click()}),o.addEventListener("change",e=>{this.handleFileUpload(e)})),this.messages&&this.messages.length>0&&setTimeout(()=>{this._syncMessages(this.messages)},50)}fileToContentBlock(e){return new Promise((n,t)=>{const a=new FileReader;a.onload=()=>{const s=a.result.split(",")[1];this.SUPPORTED_FILE_TYPES.includes(e.type)?n({type:"image",source_type:"base64",mime_type:e.type,data:s,metadata:{name:e.name,size:e.size}}):t(new Error("Unsupported file type: ".concat(e.type)))},a.onerror=()=>{t(new Error("Failed to read file: ".concat(e.name)))},a.readAsDataURL(e)})}async handleFileUpload(e){const n=e.target.files;if(!n)return;const t=Array.from(n),a=t.filter(e=>this.SUPPORTED_FILE_TYPES.includes(e.type));if(0===a.length)return void(t.length>0&&console.warn("Invalid file type."));const s=a[0];try{const e=await this.fileToContentBlock(s);this.contentBlocks=[e],this.renderFilePreview()}catch(e){console.error("Error processing file:",e)}e.target.value=""}removeBlock(e){this.contentBlocks=[],this.renderFilePreview()}renderFilePreview(){if(!this.container)return;const e=this.container.querySelector("#file-attachments-container");if(e){if(!this.contentBlocks||0===this.contentBlocks.length)return e.innerHTML="",void(e.style.display="none");e.style.display="flex",e.innerHTML=this.contentBlocks.map((e,n)=>{var t,a,s;const i=(null===(t=e.metadata)||void 0===t?void 0:t.filename)||(null===(a=e.metadata)||void 0===a?void 0:a.name)||"file",o=this.formatFileSize((null===(s=e.metadata)||void 0===s?void 0:s.size)||0),r="image"===e.type,c=r?"data:".concat(e.mime_type,";base64,").concat(e.data):null;return'\n <div class="file-attachment '.concat(r?"has-thumbnail":"",'" data-index="').concat(n,'">\n <div class="file-thumbnail">\n <img src="').concat(c,'" alt="').concat(i,'" class="file-thumbnail-image" />\n </div>\n <div class="file-attachment-info">\n <div class="file-attachment-name" title="').concat(i,'">\n ').concat(i,'\n </div>\n <div class="file-attachment-size">').concat(o,'</div>\n </div>\n <button\n class="file-attachment-remove"\n data-index="').concat(n,'"\n title="Remove file"\n >\n ā\n </button>\n </div>\n ')}).join(""),e.querySelectorAll(".file-attachment-remove").forEach(e=>{e.addEventListener("click",n=>{n.stopPropagation();const t=parseInt(e.getAttribute("data-index"));this.removeBlock(t)})})}}async toggleRecording(e){this.isRecording?this.stopRecording(e):await this.startRecording(e)}async startRecording(e){try{const n=await navigator.mediaDevices.getUserMedia({audio:!0});this.mediaRecorder=new MediaRecorder(n),this.audioChunks=[],this.mediaRecorder.ondataavailable=e=>{this.audioChunks.push(e.data)},this.mediaRecorder.onstop=async()=>{const e=new Blob(this.audioChunks,{type:"audio/wav"});this.audioChunks=[],n.getTracks().forEach(e=>e.stop()),await this.processAudioInput(e)},this.mediaRecorder.start(),this.isRecording=!0,this.onRecordStart(),e.classList.add("recording"),e.innerHTML='\n <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-square-icon"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect></svg>\n ',this.stopTTS()}catch(e){console.error("Error accessing microphone:",e),alert("Could not access microphone. Please check permissions.")}}stopRecording(e){this.mediaRecorder&&this.isRecording&&(this.mediaRecorder.stop(),this.isRecording=!1,this.onRecordStop(),e.classList.remove("recording"),e.innerHTML='\n <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-mic-icon lucide-mic"><path d="M12 19v3"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><rect x="9" y="2" width="6" height="13" rx="3"/></svg>\n ')}async processAudioInput(e){try{const n=await this.bhashini.convertToWav(e),t=await this.bhashini.speechToText(n,this.selectedLanguage,this.selectedLanguage);t&&t.trim()&&this.sendMessage&&(await this.sendMessage(t,this.contentBlocks),this.contentBlocks=[],this.renderFilePreview())}catch(e){console.error("Error processing audio:",e),this.addMessage("Sorry, I couldn't understand that.",!1,{isError:!0})}}stopTTS(){this.currentAudio&&(this.currentAudio.pause(),this.currentAudio=null),this.audioQueue=[],this.isPlaying=!1}async playNextInQueue(){if(!(this.container&&this.container.querySelector(".audio-chat-screen")))return;if(console.log("Playing next in queue",this.audioQueue),this.isPlaying||0===this.audioQueue.length)return;this.isPlaying=!0;const e=this.audioQueue.shift();try{console.log("TTS Language:",this.selectedLanguage);const n=await this.bhashini.textToSpeech(e,this.selectedLanguage);if(n){const e="data:audio/wav;base64,".concat(n);this.currentAudio=new Audio(e),this.currentAudio.onended=()=>{this.isPlaying=!1,this.playNextInQueue()},this.currentAudio.onerror=()=>{this.isPlaying=!1,this.playNextInQueue()},await this.currentAudio.play()}else this.isPlaying=!1,this.playNextInQueue()}catch(e){console.error("TTS Error:",e),this.isPlaying=!1,this.playNextInQueue()}}formatFileSize(e){if(0===e)return"0 Bytes";const n=Math.floor(Math.log(e)/Math.log(1024));return parseFloat((e/Math.pow(1024,n)).toFixed(2))+" "+["Bytes","KB","MB","GB"][n]}getFileTypeDisplay(e){switch(e){case"image/jpeg":case"image/jpg":return"JPEG Image";case"image/png":return"PNG Image";case"image/gif":return"GIF Image";case"image/webp":return"WebP Image";case"application/pdf":return"PDF Document";default:return"Unknown File"}}_formatTime(e){let n=e.getHours();const t=e.getMinutes(),a=n>=12?"PM":"AM";n%=12,n=n||12;return n.toString().padStart(2,"0")+":"+t.toString().padStart(2,"0")+" "+a}addMessage(e,n){let t=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;if(!this.container)return;const a=this.container.querySelector("#chat-messages");if(!a)return;const s=a.querySelector(".chat-welcome");s&&s.remove();const i=(null==t?void 0:t.id)||Date.now(),o=a.querySelector('[data-message-id="'.concat(i,'"]'));if(o&&t){const s=o.querySelector(".message-bubble");if(s){const a=t.content||e;s.innerHTML=n?this._escapeHtml(a):this._parseMarkdown(a)}return void(a.scrollTop=a.scrollHeight)}const r=document.createElement("div");r.className="chat-message ".concat(n?"user":"bot"),r.setAttribute("data-message-id",i);let c=e;t&&(t.isStreaming?c=t.content||"Thinking...":t.isError?(c=t.content||"Error occurred",r.classList.add("error")):c=t.content||e);let l="";t&&t.attachments&&t.attachments.length>0&&(l='\n <div class="message-attachments">\n '.concat(t.attachments.map((e,n)=>{var t,a,s;const i=(null===(t=e.metadata)||void 0===t?void 0:t.name)||(null===(a=e.metadata)||void 0===a?void 0:a.filename)||"Unknown file",o="image"===e.type,r=o&&e.data?"data:".concat(e.mime_type,";base64,").concat(e.data):null;return'\n <div class="message-attachment '.concat(o?"image":"pdf",'" data-attachment-index="').concat(n,'">\n <span class="message-attachment-icon">\n ').concat(o?"š¼ļø":"š",'\n </span>\n <div class="message-attachment-info">\n <div \n class="message-attachment-name ').concat(o?"clickable":"",'"\n ').concat(o&&r?'data-image-src="'.concat(r,'" data-image-alt="').concat(i,'"'):"",'\n style="cursor: ').concat(o?"pointer":"default",';"\n >\n ').concat(this._escapeHtml(i),'\n </div>\n <div class="message-attachment-size">\n ').concat(this.formatFileSize((null===(s=e.metadata)||void 0===s?void 0:s.size)||0)," ⢠").concat(this.getFileTypeDisplay(e.mime_type),"\n </div>\n </div>\n </div>\n ")}).join(""),"\n </div>\n "));const d=null!=t&&t.timestamp?new Date(t.timestamp):new Date,h=this._formatTime(d),g=n?this._escapeHtml(c):this._parseMarkdown(c);r.innerHTML='\n <div class="message-content">\n '.concat(l,'\n <div class="message-bubble">').concat(g,'</div>\n <div class="message-time">').concat(h,"</div>\n </div>\n "),t&&t.attachments&&r.querySelectorAll(".message-attachment-name.clickable").forEach(e=>{e.addEventListener("click",n=>{n.stopPropagation();const t=e.getAttribute("data-image-src"),a=e.getAttribute("data-image-alt");t&&this.showExpandedImage(t,a)})}),a.appendChild(r),a.scrollTop=a.scrollHeight}_syncMessages(e){if(!this.container)return;const n=this.container.querySelector("#chat-messages");if(!n)return;if(e.length>0){const e=n.querySelector(".chat-welcome");e&&e.remove()}const t=n.querySelectorAll("[data-message-id]"),a=new Set(Array.from(t).map(e=>e.getAttribute("data-message-id")));e.forEach(e=>{const t=String(e.id);if("user"===e.sender||this.playedMessageIds.has(t)||e.isStreaming||e.isProcessing||!e.content||(this.playedMessageIds.add(t),this.audioQueue.push(e.content),this.playNextInQueue()),a.has(t)){const a=n.querySelector('[data-message-id="'.concat(t,'"]'));if(a){const n=a.querySelector(".message-bubble");if(n){const t=e.content||"",a="user"===e.sender;n.innerHTML=a?this._escapeHtml(t):this._parseMarkdown(t)}const t=a.querySelector(".message-content");if(t&&e.attachments&&e.attachments.length>0){let n='\n <div class="message-attachments">\n '.concat(e.attachments.map((e,n)=>{var t,a,s;const i=(null===(t=e.metadata)||void 0===t?void 0:t.name)||(null===(a=e.metadata)||void 0===a?void 0:a.filename)||"Unknown file",o="image"===e.type,r=o&&e.data?"data:".concat(e.mime_type,";base64,").concat(e.data):null;return'\n <div class="message-attachment '.concat(o?"image":"pdf",'" data-attachment-index="').concat(n,'">\n <span class="message-attachment-icon">\n ').concat(o?"š¼ļø":"š",'\n </span>\n <div class="message-attachment-info">\n <div \n class="message-attachment-name ').concat(o?"clickable":"",'"\n ').concat(o&&r?'data-image-src="'.concat(r,'" data-image-alt="').concat(i,'"'):"",'\n style="cursor: ').concat(o?"pointer":"default",';"\n >\n ').concat(this._escapeHtml(i),'\n </div>\n <div class="message-attachment-size">\n ').concat(this.formatFileSize((null===(s=e.metadata)||void 0===s?void 0:s.size)||0)," ⢠").concat(this.getFileTypeDisplay(e.mime_type),"\n </div>\n </div>\n </div>\n ")}).join(""),"\n </div>\n ");const a=t.querySelector(".message-attachments");a?a.outerHTML=n:t.insertAdjacentHTML("afterbegin",n),t.querySelectorAll(".message-attachment-name.clickable").forEach(e=>{const n=e.cloneNode(!0);e.parentNode.replaceChild(n,e),n.addEventListener("click",e=>{e.stopPropagation();const t=n.getAttribute("data-image-src"),a=n.getAttribute("data-image-alt");t&&this.showExpandedImage(t,a)})})}e.isStreaming?a.classList.add("streaming"):a.classList.remove("streaming"),e.isError&&a.classList.add("error")}}else this.addMessage(e.content||"","user"===e.sender,e)}),t.forEach(n=>{const t=n.getAttribute("data-message-id");e.some(e=>String(e.id)===t)||n.remove()}),n.scrollTop=n.scrollHeight}_escapeHtml(e){const n=document.createElement("div");return n.textContent=e,n.innerHTML}_parseMarkdown(e){if(!e||"string"!=typeof e)return"";let n=e;n=n.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">");const t=n.split("\n"),a=[];let s=!1;for(let e=0;e<t.length;e++){let n=t[e];const i=n.match(/^(#{1,6})\s+(.+)$/);if(i){s&&(a.push("</ul>"),s=!1);const e=i[1].length;let n=i[2];n=n.replace(/\*\*([^*]+)\*\*/g,"<strong>$1</strong>"),n=n.replace(/__([^_]+)__/g,"<strong>$1</strong>"),n=n.replace(/(^|[^*])\*([^*]+)\*([^*]|$)/g,"$1<em>$2</em>$3"),n=n.replace(/(^|[^_])_([^_]+)_([^_]|$)/g,"$1<em>$2</em>$3"),a.push("<h".concat(e,">").concat(n,"</h").concat(e,">"));continue}const o=n.match(/^[\s]*[-*]\s+(.+)$/);if(o){let e=o[1];e=e.replace(/\*\*([^*]+)\*\*/g,"<strong>$1</strong>"),e=e.replace(/__([^_]+)__/g,"<strong>$1</strong>"),e=e.replace(/(^|[^*])\*([^*]+)\*([^*]|$)/g,"$1<em>$2</em>$3"),e=e.replace(/(^|[^_])_([^_]+)_([^_]|$)/g,"$1<em>$2</em>$3"),s||(a.push("<ul>"),s=!0),a.push("<li>".concat(e,"</li>"))}else{if(s&&(a.push("</ul>"),s=!1),""===n.trim()){a.push("");continue}n=n.replace(/\*\*([^*]+)\*\*/g,"<strong>$1</strong>"),n=n.replace(/__([^_]+)__/g,"<strong>$1</strong>"),n=n.replace(/(^|[^*])\*([^*]+)\*([^*]|$)/g,"$1<em>$2</em>$3"),n=n.replace(/(^|[^_])_([^_]+)_([^_]|$)/g,"$1<em>$2</em>$3"),n=n.replace(/`([^`]+)`/g,"<code>$1</code>"),n=n.replace(/\[([^\]]+)\]\(([^)]+)\)/g,'<a href="$2" target="_blank" rel="noopener noreferrer">$1</a>'),a.push(n)}}return s&&a.push("</ul>"),n=a.join("<br>"),n}showExpandedImage(e,n){const t=document.querySelector(".expanded-image-modal");t&&t.remove();const a=document.createElement("div");a.className="expanded-image-modal",a.innerHTML='\n <div class="expanded-image-container">\n <button class="expanded-image-close" title="Close">ā</button>\n <img src="'.concat(e,'" alt="').concat(n||"Image",'" class="expanded-image" />\n <div class="expanded-image-caption">').concat(this._escapeHtml(n||"Image preview"),"</div>\n </div>\n ");const s=e=>{e&&e.stopPropagation(),a.remove(),document.removeEventListener("mousedown",i)},i=e=>{e.target.closest(".expanded-image-container")||s(e)};a.querySelector(".expanded-image-close").addEventListener("click",s),a.addEventListener("click",e=>{e.target===a&&s(e)}),document.addEventListener("mousedown",i),document.body.appendChild(a)}_applyStyles(){if(document.getElementById("audio-chat-screen-styles"))return;const e=document.createElement("style");e.id="audio-chat-screen-styles",e.textContent="\n .audio-chat-screen {\n flex: 1;\n height: 100%;\n display: flex;\n flex-direction: column;\n position: relative;\n overflow: hidden;\n background: linear-gradient(180deg, white 10%, #E1EFCC );\n }\n\n .audio-chat-screen .chat-header {\n color: ".concat(this.primaryColor,";\n padding: 20px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n flex-shrink: 0;\n background: transparent;\n z-index: 20;\n }\n\n .audio-chat-screen .chat-header-content {\n display: flex;\n align-items: center;\n gap: 12px;\n flex: 1;\n }\n\n .audio-chat-screen .chat-back {\n background: ").concat(this.primaryColor,";\n border: none;\n color: white;\n cursor: pointer;\n padding: 8px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s;\n margin-right: 8px;\n }\n\n .bottom-inputs {\n width: 100%;\n padding: 20px;\n display: flex;\n justify-content: center;\n align-items: center;\n gap: 5px;\n z-index: 10;\n flex-shrink: 0;\n }\n\n .bottom-inputs button {\n border: none;\n border-radius: 9999px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: all 0.2s ease;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n }\n\n #record-button {\n width: 50px;\n height: 50px;\n background: ").concat(this.primaryColor,";\n color: #ffffff;\n }\n\n #record-button.recording {\n background: #ef4444;\n animation: pulse-ring 2s cubic-bezier(0.25, 0.46, 0.45, 0.94) infinite;\n }\n\n @keyframes pulse-ring {\n 0% {\n box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.7);\n }\n 70% {\n box-shadow: 0 0 0 10px rgba(239, 68, 68, 0);\n }\n 100% {\n box-shadow: 0 0 0 0 rgba(239, 68, 68, 0);\n }\n }\n\n #record-button:hover {\n transform: translateY(-2px) scale(1.03);\n box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);\n }\n\n #record-button:active {\n transform: translateY(0) scale(0.97);\n box-shadow: 0 3px 8px rgba(0, 0, 0, 0.15);\n }\n\n #attachment-button {\n width: 50px;\n height: 50px;\n background: #ffffff;\n color: ").concat(this.primaryColor,";\n border: 1px solid rgba(148, 163, 184, 0.5);\n }\n\n #attachment-button:hover {\n transform: translateY(-2px) scale(1.03);\n box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);\n }\n\n #attachment-button:active {\n transform: translateY(1px);\n box-shadow: 0 3px 8px rgba(15, 23, 42, 0.15);\n }\n .audio-chat-screen .chat-avatar {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n background: rgba(255, 255, 255, 0.2);\n backdrop-filter: blur(10px);\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .audio-chat-screen .chat-header-text {\n display: flex;\n flex-direction: column;\n gap: 2px;\n }\n\n .audio-chat-screen .chat-title {\n font-weight: 600;\n font-size: 20px;\n }\n\n .audio-chat-screen .chat-status {\n font-size: 12px;\n opacity: 0.9;\n display: flex;\n align-items: center;\n gap: 4px;\n }\n\n .audio-chat-screen .chat-close {\n background: ").concat(this.primaryColor,";\n border: none;\n color: white;\n cursor: pointer;\n padding: 8px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s;\n }\n\n\n .audio-chat-screen .audio-chat-content {\n flex: 1;\n height:100%;\n display: flex;\n flex-direction: column;\n padding: 20px;\n gap: 20px;\n }\n\n .audio-chat-screen .audio-status {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n background: white;\n border-radius: 16px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n }\n\n .audio-chat-screen .audio-status-icon {\n font-size: 48px;\n margin-bottom: 12px;\n transition: transform 0.3s;\n }\n\n .audio-chat-screen .audio-status-text {\n font-size: 16px;\n font-weight: 500;\n color: #475569;\n }\n\n /* Message list styles mirrored from TextChatScreen */\n .audio-chat-screen .chat-messages {\n flex: 1;\n padding: 20px;\n overflow-y: auto;\n overflow-x: hidden; /* Prevent horizontal scroll */\n min-height: 0; /* Crucial for nested flex scrolling */\n background: transparent;\n display: flex;\n flex-direction: column;\n gap: 12px;\n }\n\n .audio-chat-screen .chat-messages::-webkit-scrollbar {\n width: 6px;\n }\n\n .audio-chat-screen .chat-messages::-webkit-scrollbar-track {\n background: transparent;\n }\n\n .audio-chat-screen .chat-messages::-webkit-scrollbar-thumb {\n background: #cbd5e1;\n border-radius: 3px;\n }\n\n .audio-chat-screen .file-attachments-container {\n padding: 8px 12px;\n background: transparent;\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n max-height: 120px;\n overflow-y: auto;\n position: relative;\n z-index: 5;\n }\n\n .audio-chat-screen .file-attachment {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 10px;\n background: #f1f5f9;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n font-size: 12px;\n max-width: 200px;\n }\n\n .audio-chat-screen .file-thumbnail {\n width: 40px;\n height: 40px;\n border-radius: 6px;\n overflow: hidden;\n flex-shrink: 0;\n background: #e2e8f0;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .audio-chat-screen .file-thumbnail-image {\n width: 100%;\n height: 100%;\n object-fit: cover;\n }\n\n .audio-chat-screen .file-attachment-info {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n }\n\n .audio-chat-screen .file-attachment-name {\n font-weight: 500;\n color: #1e293b;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 120px;\n }\n\n .audio-chat-screen .file-attachment-size {\n font-size: 11px;\n color: #64748b;\n }\n\n .audio-chat-screen .file-attachment-remove {\n background: transparent;\n border: none;\n color: #64748b;\n cursor: pointer;\n padding: 4px;\n border-radius: 4px;\n font-size: 16px;\n line-height: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s;\n flex-shrink: 0;\n }\n\n .audio-chat-screen .file-attachment-remove:hover {\n background: #fee2e2;\n color: #dc2626;\n }\n\n .audio-chat-screen .chat-welcome {\n text-align: center;\n padding: 100px 20px;\n color: #64748b;\n }\n\n .audio-chat-screen .chat-welcome .welcome-icon {\n font-size: 48px;\n margin-bottom: 12px;\n }\n\n .audio-chat-screen .welcome-text {\n font-size: 15px;\n font-weight: 500;\n color: #475569;\n }\n\n .audio-chat-screen .chat-message {\n display: flex;\n gap: 8px;\n animation: messageSlide 0.3s ease-out;\n }\n\n @keyframes messageSlide {\n from {\n opacity: 0;\n transform: translateY(10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n .audio-chat-screen .chat-message.user {\n flex-direction: row-reverse;\n }\n\n .audio-chat-screen .message-content {\n max-width: 75%;\n }\n\n .audio-chat-screen .message-bubble {\n padding: 12px 16px;\n border-radius: 16px;\n font-size: 14px;\n line-height: 1.5;\n word-wrap: break-word;\n }\n\n .audio-chat-screen .chat-message.user .message-bubble {\n background: #e9f5d7;\n color: ").concat(this.primaryColor,";\n border-bottom-right-radius: 4px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n }\n\n .audio-chat-screen .chat-message.bot .message-bubble {\n background: white;\n color: #1e293b;\n border-bottom-left-radius: 4px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n }\n\n /* Markdown styles */\n .audio-chat-screen .message-bubble strong {\n font-weight: 600;\n color: inherit;\n }\n\n .audio-chat-screen .message-bubble em {\n font-style: italic;\n }\n\n .audio-chat-screen .message-bubble ul {\n margin: 0px 0;\n padding-left: 20px;\n list-style-type: disc;\n margin-bottom:0px;\n margin-top:5px;\n }\n\n .audio-chat-screen .message-bubble li {\n margin: 0;\n line-height: 1.1;\n padding-left: 3px;\n }\n\n .audio-chat-screen .message-bubble h1,\n .audio-chat-screen .message-bubble h2,\n .audio-chat-screen .message-bubble h3,\n .audio-chat-screen .message-bubble h4,\n .audio-chat-screen .message-bubble h5,\n .audio-chat-screen .message-bubble h6 {\n margin: 0px 0 0px 0;\n font-weight: 600;\n color: inherit;\n line-height: 1.3;\n }\n\n .audio-chat-screen .message-bubble h1 {\n font-size: 1.5em;\n }\n\n .audio-chat-screen .message-bubble h2 {\n font-size: 1.3em;\n }\n\n .audio-chat-screen .message-bubble h3 {\n font-size: 1.15em;\n }\n\n .audio-chat-screen .message-bubble h4 {\n font-size: 1.05em;\n }\n\n .audio-chat-screen .message-bubble h5 {\n font-size: 1em;\n }\n\n .audio-chat-screen .message-bubble h6 {\n font-size: 0.95em;\n }\n\n .audio-chat-screen .message-bubble code {\n background: rgba(0, 0, 0, 0.05);\n padding: 2px 6px;\n border-radius: 4px;\n font-family: 'Courier New', Courier, monospace;\n font-size: 0.9em;\n }\n\n .audio-chat-screen .message-bubble a {\n color: ").concat(this.primaryColor,";\n text-decoration: underline;\n }\n\n .audio-chat-screen .message-bubble a:hover {\n opacity: 0.8;\n }\n \n .audio-chat-screen .message-bubble br {\n line-height: 0.1; /* Adjust between 0 and 1 */\n}\n\n\n .audio-chat-screen .message-time {\n font-size: 10px;\n color: #94a3b8;\n margin-top: 4px;\n text-align: right;\n }\n\n /* Message Attachments Styles (mirrored from TextChatScreen) */\n .audio-chat-screen .message-attachments {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-bottom: 8px;\n }\n\n .audio-chat-screen .message-attachment {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n background: #f1f5f9;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n font-size: 12px;\n max-width: 100%;\n }\n\n .audio-chat-screen .message-attachment.image {\n background: #f8fafc;\n }\n\n .audio-chat-screen .message-attachment.pdf {\n background: #fef2f2;\n }\n\n .audio-chat-screen .message-attachment-icon {\n font-size: 20px;\n flex-shrink: 0;\n }\n\n .audio-chat-screen .message-attachment-info {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n }\n\n .audio-chat-screen .message-attachment-name {\n font-weight: 500;\n color: #1e293b;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .audio-chat-screen .message-attachment-name.clickable:hover {\n color: ").concat(this.primaryColor,";\n text-decoration: underline;\n }\n\n .audio-chat-screen .message-attachment-size {\n font-size: 11px;\n color: #64748b;\n }\n\n .audio-chat-screen .audio-messages {\n flex: 1;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n gap: 12px;\n min-height: 200px;\n }\n\n .audio-chat-screen .audio-message {\n display: flex;\n gap: 8px;\n animation: messageSlide 0.3s ease-out;\n }\n\n .audio-chat-screen .audio-message.user {\n flex-direction: row-reverse;\n }\n\n .audio-chat-screen .audio-message-content {\n max-width: 75%;\n }\n\n .audio-chat-screen .audio-message-bubble {\n padding: 12px 16px;\n border-radius: 16px;\n font-size: 14px;\n line-height: 1.5;\n word-wrap: break-word;\n }\n\n .audio-chat-screen .audio-message.user .audio-message-bubble {\n background: ").concat(this.primaryColor,";\n color: white;\n border-bottom-right-radius: 4px;\n }\n\n .audio-chat-screen .audio-message.assistant .audio-message-bubble {\n background: white;\n color: #1e293b;\n border-bottom-left-radius: 4px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n }\n\n @keyframes messageSlide {\n from {\n opacity: 0;\n transform: translateY(10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n .audio-chat-screen .audio-messages::-webkit-scrollbar {\n width: 6px;\n }\n\n .audio-chat-screen .audio-messages::-webkit-scrollbar-track {\n background: transparent;\n }\n\n .audio-chat-screen .audio-messages::-webkit-scrollbar-thumb {\n background: #cbd5e1;\n border-radius: 3px;\n }\n\n .audio-chat-screen .audio-controls {\n position: absolute;\n left: 50%;\n bottom: 20px;\n transform: translateX(-50%);\n display: flex;\n justify-content: center;\n align-items: center;\n pointer-events: none; /* let only the button receive events */\n }\n\n .audio-chat-screen .audio-controls .audio-record-btn {\n pointer-events: auto;\n }\n\n .audio-chat-screen .audio-record-btn {\n width: 80px;\n height: 80px;\n border-radius: 50%;\n background: ").concat(this.primaryColor,";\n color: white;\n border: none;\n cursor: pointer;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 8px;\n transition: all 0.3s;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n }\n\n .audio-chat-screen .audio-record-btn:hover {\n transform: scale(1.05);\n box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);\n }\n\n .audio-chat-screen .audio-record-btn:active {\n transform: scale(0.95);\n }\n\n .audio-chat-screen .audio-record-btn.recording {\n background: #ef4444;\n animation: pulse-record 1.5s infinite;\n }\n\n @keyframes pulse-record {\n 0%, 100% {\n box-shadow: 0 4px 12px rgba(239, 68, 68, 0.4);\n }\n 50% {\n box-shadow: 0 4px 24px rgba(239, 68, 68, 0.6);\n }\n }\n\n .audio-chat-screen .audio-record-btn span {\n font-size: 11px;\n font-weight: 500;\n margin-top: 4px;\n }\n\n .audio-chat-screen .audio-record-btn svg {\n width: 32px;\n height: 32px;\n }\n\n @media (max-width: 768px) {\n .audio-chat-screen .audio-record-btn {\n width: 100px;\n height: 100px;\n }\n }\n\n /* Expanded Image Modal Styles */\n .expanded-image-modal {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.8);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10000;\n animation: fadeIn 0.2s ease;\n }\n\n @keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n }\n\n .expanded-image-container {\n position: relative;\n max-width: 90%;\n max-height: 90vh;\n background: #fff;\n border-radius: 8px;\n overflow: hidden;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);\n animation: scaleIn 0.2s ease;\n display: flex;\n flex-direction: column;\n }\n\n @keyframes scaleIn {\n from {\n transform: scale(0.9);\n opacity: 0;\n }\n to {\n transform: scale(1);\n opacity: 1;\n }\n }\n\n .expanded-image-close {\n position: absolute;\n top: 12px;\n right: 12px;\n background: rgba(0, 0, 0, 0.6);\n border: none;\n color: white;\n width: 32px;\n height: 32px;\n border-radius: 50%;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 18px;\n z-index: 1;\n transition: all 0.2s;\n }\n\n .expanded-image-close:hover {\n background: rgba(0, 0, 0, 0.8);\n transform: scale(1.1);\n }\n\n .expanded-image {\n max-width: 100%;\n max-height: calc(90vh - 60px);\n object-fit: contain;\n display: block;\n }\n\n .expanded-image-caption {\n padding: 12px 16px;\n background: #fff;\n color: #1e293b;\n font-size: 14px;\n text-align: center;\n border-top: 1px solid #e2e8f0;\n }\n "),document.head.appendChild(e)}}class o{constructor(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.title=e.title||"Chat Assistant",this.placeholder=e.placeholder||"Type your message...",this.primaryColor=e.primaryColor||"#1a5c4b",this.container=null,this.messages=[],this.isMinimized=!1,this.currentScreen="welcome",this.textChatScreen=null,this.audioChatScreen=null,this.langgraphUrl=e.langgraphUrl||"http://localhost:8080",this.authToken=e.authToken||null,this.threadId=e.threadId||null,this.assistantId=e.assistantId||null,this.selectedLanguage=e.selectedLanguage||"en",this.accessToken=e.accessToken||"",this.supabaseToken=e.supabaseToken||"",this.userInfo=e.userInfo||{},this.mcpServerUrl=e.mcpServerUrl||"http://localhost:8010/mcp",this._customGetHeaders=e.getHeaders,this.getHeaders=()=>{if(this._customGetHeaders)return this._customGetHeaders();const e=this.authToken||this.accessToken,n=this.supabaseToken||e;return t(t(t({"Content-Type":"application/json"},e&&{Authorization:"Bearer ".concat(e)}),n&&{"x-supabase-access-token":n}),{},{Origin:("undefined"!=typeof window?window.location.origin:"*")||"*"})},this.getLatestCheckpoint=e.getLatestCheckpoint||(async()=>null),this.updateThread=e.updateThread||(async()=>{}),this.getUserThreads=e.getUserThreads||(async e=>{let{userId:n,userUuid:t}=e;try{const e=new URLSearchParams;t&&e.append("user_uuid",t);const n="".concat(this.langgraphUrl,"/history?").concat(e.toString()),a=await fetch(n,{method:"GET",headers:this.getHeaders()});return a.ok?await a.json():{threads:[]}}catch(e){return console.error("Error fetching threads",e),{threads:[]}}}),this.setUserInfoFromDirectChatLogin=e.setUserInfoFromDirectChatLogin||(()=>{}),this.setUserThreads=e.setUserThreads||(()=>{}),this.setUserThreadsMetaData=e.setUserThreadsMetaData||(()=>{}),this.languageOptions=[{label:"Assamese",value:"as"},{label:"Bengali",value:"bn"},{label:"Dogri",value:"doi"},{label:"English",value:"en"},{label:"Gujarati",value:"gu"},{label:"Hindi",value:"hi"},{label:"Kannada",value:"kn"},{label:"Konkani",value:"gom"},{label:"Maithili",value:"mai"},{label:"Malayalam",value:"ml"},{label:"Marathi",value:"mr"},{label:"Oriya",value:"or"},{label:"Punjabi",value:"pa"},{label:"Sanskrit",value:"sa"},{label:"Sindhi",value:"sd"},{label:"Tamil",value:"ta"},{label:"Telugu",value:"te"},{label:"Urdu",value:"ur"}],this.isLoading=!1,this.isConnected=!1,this.initialized=!1,this.contentBlocks=[],this.playedAudioIds=new Set,this.currentInputAudio=null,this.submissionInProgress=!1,this.processingAudioId=null,this._init(),"undefined"!=typeof window&&setTimeout(()=>{this.initializeChat()},100)}_init(){this.container=document.createElement("div"),this.container.id="chat-widget-container",this.container.innerHTML='\n <div class="chat-widget-minimized" id="chat-toggle">\n <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>\n </svg>\n </div>\n <div class="chat-widget-expanded" id="chat-expanded">\n <div class="chat-screen-container" id="chat-screen-container">\n \x3c!-- Screens will be rendered here --\x3e\n </div>\n <div class="chat-drawer-overlay" id="chat-drawer-overlay">\n <div class="chat-drawer">\n <div class="drawer-header">\n <div class="drawer-title">Menu</div>\n </div>\n <div class="drawer-content">\n <button class="drawer-item" id="drawer-new-chat">\n New Chat\n </button> \n <div class="language-selector-container">\n <div class="custom-select" id="language-selector">\n <div class="select-trigger" id="language-trigger">\n <span id="selected-language-text">English</span>\n <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="chevron"><path d="m6 9 6 6 6-6"/></svg>\n </div>\n <div class="select-options" id="language-options"></div>\n </div>\n </div>\n <div class="drawer-divider" style="height: 1px; background: #e2e8f0; margin: 8px 0;"></div>\n \n <div id="drawer-threads" class="threads-container">\n \x3c!-- Threads will be rendered here --\x3e\n <div class="threads-loading">Loading history...</div>\n </div>\n </div>\n \n </div>\n <div class="drawer-backdrop" id="drawer-backdrop"></div>\n </div>\n </div>\n ',document.body.appendChild(this.container),this._applyStyles(),this._initScreens(),this._renderScreen(),this._populateLanguageOptions(),this._bindEvents()}_applyStyles(){const e=document.createElement("style");e.textContent="\n @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap');\n \n #chat-widget-container {\n position: fixed;\n bottom: 24px;\n right: 24px;\n z-index: 10000;\n font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n }\n.text-chat-screen {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n\n .chat-header {\n color: ".concat(this.primaryColor,";\n padding: 20px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n }\n\n .chat-header-content {\n display: flex;\n align-items: center;\n gap: 12px;\n flex: 1;\n }\n\n .chat-back {\n background: transparent;\n border: none;\n color: white;\n cursor: pointer;\n padding: 8px;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s;\n margin-right: 8px;\n }\n\n .chat-back:hover {\n background: rgba(255, 255, 255, 0.15);\n }\n\n .chat-avatar {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n background: rgba(255, 255, 255, 0.2);\n backdrop-filter: blur(10px);\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .chat-header-text {\n display: flex;\n flex-direction: column;\n gap: 2px;\n }\n \n .chat-title {\n font-weight: 600;\n font-size: 20px;\n }\n\n .chat-status {\n font-size: 12px;\n opacity: 0.9;\n display: flex;\n align-items: center;\n gap: 4px;\n }\n\n .chat-close {\n background: ").concat(this.primaryColor,";\n border: none;\n color: white;\n cursor: pointer;\n padding: 8px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s;\n }\n\n .chat-widget-minimized {\n width: 60px;\n height: 60px;\n border-radius: 50%;\n background: ").concat(this.primaryColor,";\n color: white;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n .chat-widget-minimized:hover {\n transform: scale(1.1);\n }\n\n @keyframes pulse {\n 0%, 100% { box-shadow: 0 8px 24px rgba(99, 102, 241, 0.4); }\n 50% { box-shadow: 0 8px 32px rgba(99, 102, 241, 0.6); }\n }\n\n .chat-widget-expanded {\n position: relative;\n width: 480px;\n height: 640px;\n background: white;\n border-radius: 16px;\n box-shadow: 0 20px 60px rgba(0, 0, 0, 0.15);\n display: none;\n flex-direction: column;\n overflow: hidden;\n animation: slideUp 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n @keyframes slideUp {\n from {\n opacity: 0;\n transform: translateY(20px) scale(0.95);\n }\n to {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n }\n\n .chat-widget-expanded.visible {\n display: flex;\n }\n\n .chat-screen-container {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n\n /* Welcome Screen Styles */\n .welcome-screen {\n flex: 1;\n height: 100%;\n display: flex;\n flex-direction: column;\n align-items: stretch;\n justify-content: start;\n background: linear-gradient(180deg, white 10%, #E1EFCC );\n padding: 0px;\n }\n\n .welcome-content {\n width: 80%;\n margin: auto;\n text-align: center;\n padding-top: 20px;\n }\n\n .welcome-icon {\n font-size: 64px;\n margin-bottom: 16px;\n animation: bounce 2s infinite;\n }\n\n @keyframes bounce {\n 0%, 100% { transform: translateY(0); }\n 50% { transform: translateY(-10px); }\n }\n\n .welcome-title {\n font-size: 24px;\n font-weight: 600;\n color: #1e293b;\n margin: 0 0 8px 0;\n }\n\n .welcome-subtitle {\n font-size: 14px;\n color: #64748b;\n margin: 0 0 32px 0;\n }\n\n .welcome-options {\n display: flex;\n flex-direction: column;\n gap: 12px;\n }\n\n .welcome-option-btn {\n background: white;\n border: 2px solid #e2e8f0;\n border-radius: 12px;\n padding: 16px;\n display: flex;\n align-items: center;\n gap: 12px;\n cursor: pointer;\n transition: all 0.2s;\n text-align: left;\n width: 100%;\n }\n\n .welcome-option-btn:hover {\n border-color: ").concat(this.primaryColor,";\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n transform: translateY(-2px);\n }\n\n .option-icon {\n font-size: 32px;\n flex-shrink: 0;\n }\n\n .option-content {\n flex: 1;\n }\n\n .option-title {\n font-size: 16px;\n font-weight: 600;\n color: #1e293b;\n margin-bottom: 4px;\n }\n\n .option-description {\n font-size: 13px;\n color: #64748b;\n }\n\n .welcome-option-btn svg {\n color: #94a3b8;\n flex-shrink: 0;\n }\n\n .welcome-option-btn:hover svg {\n color: ").concat(this.primaryColor,";\n }\n.gradient-sphere-welcome-screen {\n width: 200px !important;\n height: 200px !important;\n border-radius: 50%;\n background: linear-gradient(135deg, #0a0d120f 0%, #85bc31 50%, #d0f19e 100%)\n !important;\n position: relative;\n margin: 20px auto 30px auto;\n box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);\n animation: float 3s ease-in-out infinite;\n flex-shrink: 0;\n}\n\n.sphere-highlight {\n position: absolute;\n top: 20%;\n right: 20%;\n width: 35px;\n height: 35px;\n background: radial-gradient(\n circle,\n rgba(255, 255, 255, 0.8) 0%,\n transparent 70%\n );\n border-radius: 50%;\n filter: blur(1px);\n}\n\n@keyframes float {\n 0%,\n 100% {\n transform: translateY(0px);\n }\n 50% {\n transform: translateY(-10px);\n }\n}\n\n.welcome-text {\n max-width: 400px;\n margin-bottom: 30px;\n flex-shrink: 0;\n text-align: left;\n}\n\n.greeting {\n font-size: 24px;\n font-weight: 600;\n color: #1a5c4b;\n margin: 0 0 16px 0;\n}\n\n.intro {\n font-size: 18px;\n font-weight: 500;\n color: #1a5c4b;\n margin: 0 0 12px 0;\n line-height: 1.4;\n}\n\n\n.action-buttons {\n display: flex;\n align-items: center;\n gap: 16px;\n flex-shrink: 0;\n margin-top: auto;\n /* padding-top: 10px; */\n padding-bottom: 20px;\n justify-content: center;\n width: 100%;\n align-self: center;\n}\n\n.primary-button {\n background: #1a5c4b;\n display:flex;\n color: white;\n border: none;\n padding: 16px 32px;\n border-radius: 25px;\n font-size: 16px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.3s ease;\n box-shadow: 0 4px 12px rgba(26, 92, 75, 0.3);\n}\n\n.primary-button:hover {\n transform: translateY(-2px);\n box-shadow: 0 6px 16px rgba(26, 92, 75, 0.4);\n}\n\n @media (max-width: 768px) {\n #chat-widget-container {\n bottom: 16px;\n right: 16px;\n }\n\n .chat-widget-expanded {\n width: 100vw;\n height: 100vh;\n border-radius: 0;\n max-width: 100vw;\n max-height: 100vh;\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n }\n\n .chat-widget-expanded.visible {\n display: flex;\n }\n\n .welcome-content {\n max-width: 100%;\n padding-top: 40px;\n }\n\n .chat-drawer {\n width: 85% !important; /* Wider drawer on mobile */\n }\n }\n\n /* Drawer Styles */\n .chat-drawer-overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 2000;\n display: flex;\n pointer-events: none;\n visibility: hidden;\n }\n\n .chat-drawer-overlay.visible {\n pointer-events: auto;\n visibility: visible;\n }\n\n .chat-drawer {\n width: 65%;\n background: white;\n height: 100%;\n transform: translateX(-100%);\n transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n display: flex;\n flex-direction: column;\n z-index: 2002;\n box-shadow: 4px 0 24px rgba(0,0,0,0.1);\n }\n\n .chat-drawer-overlay.visible .chat-drawer {\n transform: translateX(0);\n }\n\n .drawer-backdrop {\n flex: 1;\n background: rgba(0, 0, 0, 0.5);\n opacity: 0;\n transition: opacity 0.3s ease;\n backdrop-filter: blur(2px);\n cursor: pointer;\n }\n\n .chat-drawer-overlay.visible .drawer-backdrop {\n opacity: 1;\n }\n\n .drawer-header {\n padding: 24px;\n border-bottom: 1px solid #f1f5f9;\n }\n\n .drawer-title {\n font-size: 20px;\n font-weight: 600;\n color: ").concat(this.primaryColor,";\n }\n\n .drawer-content {\n flex: 1;\n padding: 16px;\n display: flex;\n flex-direction: column;\n gap: 8px;\n overflow-y: auto;\n }\n\n .drawer-item {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 16px;\n background: transparent;\n border: none;\n border-radius: 8px;\n color: #475569;\n font-size: 15px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s;\n text-align: left;\n }\n\n .drawer-item:hover {\n background: #f1f5f9;\n color: ").concat(this.primaryColor,";\n }\n\n .drawer-item svg {\n opacity: 0.7;\n }\n\n .drawer-item:hover svg {\n opacity: 1;\n color: ").concat(this.primaryColor,";\n }\n\n .drawer-footer {\n padding: 16px 24px;\n border-top: 1px solid #f1f5f9;\n }\n\n .drawer-version {\n font-size: 12px;\n color: #94a3b8;\n text-align: center;\n }\n\n /* Language Selector Styles */\n .language-selector-container {\n margin-top: 8px;\n margin-bottom: 8px;\n }\n\n .language-label {\n font-size: 11px;\n font-weight: 600;\n color: #94a3b8;\n margin-bottom: 6px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n padding-left: 4px;\n }\n\n .custom-select {\n position: relative;\n width: 100%;\n user-select: none;\n }\n\n .select-trigger {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 10px 12px;\n background: #f8fafc;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s;\n font-size: 14px;\n color: #334155;\n }\n\n .select-trigger:hover {\n border-color: ").concat(this.primaryColor,";\n background: white;\n }\n\n .select-trigger.active {\n border-color: ").concat(this.primaryColor,";\n background: white;\n box-shadow: 0 0 0 2px rgba(26, 92, 75, 0.1);\n }\n\n .select-options {\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n right: 0;\n background: white;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);\n max-height: 200px;\n overflow-y: auto;\n z-index: 50;\n display: none;\n opacity: 0;\n transform: translateY(-10px);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n .select-options.open {\n display: block;\n opacity: 1;\n transform: translateY(0);\n }\n\n .select-option {\n padding: 10px 12px;\n font-size: 14px;\n color: #334155;\n cursor: pointer;\n transition: all 0.1s;\n }\n\n .select-option:hover {\n background: #f1f5f9;\n color: ").concat(this.primaryColor,";\n }\n\n .select-option.selected {\n background: rgba(26, 92, 75, 0.08);\n color: ").concat(this.primaryColor,";\n font-weight: 500;\n }\n \n .chevron {\n transition: transform 0.2s ease;\n color: #94a3b8;\n }\n \n .select-trigger.active .chevron {\n transform: rotate(180deg);\n color: ").concat(this.primaryColor,";\n }\n \n /* Thread List Styles */\n .threads-container {\n flex: 1;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n gap: 4px;\n padding-top: 8px;\n }\n \n .threads-loading {\n padding: 16px;\n text-align: center;\n color: #94a3b8;\n font-size: 13px;\n }\n \n .thread-item {\n display: flex;\n flex-direction: column;\n padding: 10px 12px;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s;\n text-align: left;\n border: none;\n background: transparent;\n width: 100%;\n color: #475569;\n }\n \n .thread-item:hover {\n background-color: #f1f5f9; /* action.hover */\n color: ").concat(this.primaryColor,";\n }\n \n .thread-item.selected {\n background-color: rgba(26, 92, 75, 0.08); /* action.selected */\n }\n \n .thread-content {\n font-size: 0.9rem;\n color: #334155;\n line-height: 1.3;\n margin-bottom: 4px;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n font-weight: 500;\n }\n \n .thread-date {\n font-size: 0.75rem;\n font-weight: 600;\n color: #94a3b8;\n }\n \n .no-history {\n padding: 16px;\n text-align: center;\n color: #94a3b8;\n font-size: 14px;\n }\n "),document.head.appendChild(e)}_renderScreen(){const e=this.container.querySelector("#chat-screen-container");switch(this.currentScreen){case"welcome":this._renderWelcomeScreen(e);break;case"text":this._renderTextChatScreen(e);break;case"audio":this._renderAudioChatScreen(e)}}_initScreens(){this.textChatScreen=new a({title:this.title,placeholder:this.placeholder,primaryColor:this.primaryColor,onMessage:(e,n)=>{this._handleUserMessage(e,n)},onBack:()=>{this.currentScreen="welcome",this._renderScreen()},onOpenDrawer:()=>{this._toggleDrawer(!0)},onClose:()=>{const e=this.container.querySelector("#chat-expanded"),n=this.container.querySelector("#chat-toggle");e.classList.remove("visible"),n.style.display="flex",this.currentScreen="welcome",this.messages=[],this.contentBlocks=[],this._initScreens()},messages:this.messages,sendMessage:(e,n)=>this.sendMessage(e,n),contentBlocks:this.contentBlocks,onContentBlocksChange:e=>{this.contentBlocks=e},navigateToAudioScreen:()=>{this._navigateToScreen("audio")}}),this.audioChatScreen=new i({title:this.title,primaryColor:this.primaryColor,onRecordStart:()=>{},onRecordStop:()=>{},onBack:()=>{this.currentScreen="welcome",this._renderScreen()},onOpenDrawer:()=>{this._toggleDrawer(!0)},onClose:()=>{const e=this.container.querySelector("#chat-expanded"),n=this.container.querySelector("#chat-toggle");e.classList.remove("visible"),n.style.display="flex",this.currentScreen="welcome",this.messages=[],this._initScreens()},messages:this.messages,sendMessage:(e,n)=>this.sendMessage(e,n),selectedLanguage:this.selectedLanguage,navigateToTextScreen:()=>{this._navigateToScreen("text")}})}_renderWelcomeScreen(e){e.innerHTML='\n <main class="welcome-screen">\n <div class="chat-header">\n <div class="chat-header-content visible">\n <div class="chat-header-text">\n <div class="chat-title">'.concat(this.title,'</div>\n </div>\n </div>\n <button class="chat-close" id="text-chat-close">\n <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <line x1="18" y1="6" x2="6" y2="18"></line>\n <line x1="6" y1="6" x2="18" y2="18"></line>\n </svg>\n </button>\n </div>\n <div >\n <div class="welcome-content">\n <div class="gradient-sphere-welcome-screen">\n <div class="sphere-highlight">\n </div>\n </div>\n \n <div class="welcome-text">\n <p class="greeting">Hello!</p>\n <p class="intro">\n This is PUCAR agent how can I help you today.\n </p>\n </div>\n \n <div class="action-buttons">\n <button\n class="primary-button !rounded-full"\n id="welcome-audio-btn"\n >\n Let\'s talk ​ ​ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-mic-icon lucide-mic"><path d="M12 19v3"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><rect x="9" y="2" width="6" height="13" rx="3"/></svg>\n </button>\n </div>\n \n \n\n </div>\n </div>\n </main>\n ');const n=e.querySelector("#welcome-audio-btn"),t=e.querySelector("#text-chat-close");n.addEventListener("click",()=>this._navigateToScreen("audio")),t&&t.addEventListener("click",()=>{const e=this.container.querySelector("#chat-expanded"),n=this.container.querySelector("#chat-toggle");e.classList.remove("visible"),n.style.display="flex",this.currentScreen="welcome",this.messages=[],this._initScreens()})}_renderTextChatScreen(e){this.textChatScreen&&(this.textChatScreen.contentBlocks=this.contentBlocks,this.textChatScreen.messages=this.messages,this.textChatScreen.render(e))}_renderAudioChatScreen(e){this.audioChatScreen&&(this.audioChatScreen.messages=this.messages,this.audioChatScreen.render(e))}_navigateToScreen(e){this.currentScreen=e,this._renderScreen()}_populateLanguageOptions(){const e=this.container.querySelector("#language-options");e&&(e.innerHTML=this.languageOptions.map(e=>'\n <div class="select-option '.concat(e.value===this.selectedLanguage?"selected":"",'" data-value="').concat(e.value,'">\n ').concat(e.label,"\n </div>\n ")).join(""),this._updateSelectedLanguageDisplay())}_updateSelectedLanguageDisplay(){const e=this.container.querySelector("#selected-language-text");if(e){const n=this.languageOptions.find(e=>e.value===this.selectedLanguage);e.textContent=n?n.label:"English"}}_bindLanguageSelectorEvents(){const e=this.container.querySelector("#language-selector"),n=this.container.querySelector("#language-trigger"),t=this.container.querySelector("#language-options");if(n&&t){n.addEventListener("click",e=>{e.stopPropagation();t.classList.contains("open")?(t.classList.remove("open"),n.classList.remove("active")):(t.classList.add("open"),n.classList.add("active"))});t.querySelectorAll(".select-option").forEach(e=>{e.addEventListener("click",e=>{const a=e.currentTarget.dataset.value;this.selectedLanguage=a,this.audioChatScreen&&(this.audioChatScreen.selectedLanguage=a),this._updateSelectedLanguageDisplay(),t.querySelectorAll(".select-option").forEach(e=>e.classList.remove("selected")),e.currentTarget.classList.add("selected"),t.classList.remove("open"),n.classList.remove("active"),console.log("Language selected:",this.selectedLanguage)})}),document.addEventListener("click",a=>{e&&!e.contains(a.target)&&(t.classList.remove("open"),n.classList.remove("active"))})}}async _fetchThreads(){const e=this.container.querySelector("#drawer-threads");if(e){e.innerHTML='<div class="threads-loading">Loading history...</div>';try{const n=localStorage.getItem("DfsWeb.user-info"),t=n?JSON.parse(n):null;if(null==t||!t.uuid)return void(e.innerHTML='<div class="no-history">Please log in to view history</div>');console.log("USER ID",t.id,"USER UUID",t.uuid);const a=await this.getUserThreads({userId:t.id,userUuid:t.uuid});console.log("THREAD DATA",a);const s=(a.threads||[]).filter(e=>e.history&&e.history.length>0);this._renderThreadList(s)}catch(n){console.error("UNEXPECTED ERROR IN FETCHING THREADS",n.message),e.innerHTML='<div class="no-history">Failed to load history</div>'}}}_renderThreadList(e){const n=this.container.querySelector("#drawer-threads");n&&(0!==e.length?(n.innerHTML="",e.forEach(e=>{var t;const a=e.thread_id===this.threadId,s=document.createElement("div");s.className="thread-item ".concat(a?"selected":"");const i=(null===(t=e.history[0])||void 0===t||null===(t=t.values)||void 0===t||null===(t=t.messages[0])||void 0===t?void 0:t.content)||"New Chat";let o=i;if(Array.isArray(i)){const e=i.find(e=>"text"===e.type);o=e?e.text:"Multimedia Message"}else"object"==typeof i&&(o="Message");const r=new Date(e.created_at).toLocaleString();s.innerHTML='\n <div class="thread-content">'.concat(o,'</div>\n <div class="thread-date">').concat(r,"</div>\n "),s.addEventListener("click",()=>{this._handleThreadSelect(e.thread_id)}),n.appendChild(s)})):n.innerHTML='<div class="no-history">No history available</div>')}_handleThreadSelect(e){console.log("Select thread:",e),this.threadId=e,this._toggleDrawer(!1),this.currentScreen="text",this.messages=[],this.setIsLoading=!0,this.isLoading=!0,this._renderScreen(),this.loadHistory(e).then(()=>{this.isLoading=!1,this._renderScreen()})}_bindEvents(){const e=this.container.querySelector("#chat-toggle"),n=this.container.querySelector("#chat-expanded");e&&(e.style.display="flex"),e.addEventListener("click",()=>{console.log("Clicked"),e.style.display="none",n.classList.add("visible"),this.currentScreen="welcome",this._renderScreen()});const t=this.container.querySelector("#drawer-backdrop");t&&t.addEventListener("click",()=>{this._toggleDrawer(!1)});this.container.querySelectorAll(".drawer-item").forEach(e=>{e.addEventListener("click",e=>{this._toggleDrawer(!1);"drawer-new-chat"===e.currentTarget.id&&this._resetChat()})}),this._bindLanguageSelectorEvents()}_toggleDrawer(e){const n=this.container.querySelector("#chat-drawer-overlay");n&&(e?(n.classList.add("visible"),this._fetchThreads()):n.classList.remove("visible"))}_resetChat(){this.messages=[],this.threadId=null,this.contentBlocks=[],this._initScreens(),this._renderScreen()}_handleUserMessage(e,n){n&&n('You said: "'.concat(e,'"'))}_addMessageToArray(e){this.messages.push(e),this._notifyScreensUpdate()}_updateMessageInArray(e,n){const a=this.messages.findIndex(n=>n.id===e);-1!==a&&(this.messages[a]=t(t({},this.messages[a]),n),this._notifyScreensUpdate())}_notifyScreensUpdate(){this.textChatScreen&&this.textChatScreen.container&&this.textChatScreen._syncMessages(this.messages),this.audioChatScreen&&this.audioChatScreen.container&&this.audioChatScreen._syncMessages(this.messages)}async sendMessage(e){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[];if(!e.trim()&&0===n.length||this.isLoading)return;console.log("š¤ Sending text message - Language:",this.selectedLanguage,"Assistant ID:",this.assistantId||"Not available","Thread ID:",this.threadId||"Not available","Access token:",this.accessToken?"Present":"Empty - backend will handle");const t=[];if(e.trim()){const n=e;t.push({type:"text",text:n})}n.forEach(e=>{t.push(e)});const a={id:Date.now(),content:e.trim()||"š File attachments",sender:"user",timestamp:(new Date).toISOString(),attachments:n.length>0?n:null};console.log("USER MESSAGE",a),console.log("USER MESSAGE CONTENTBLOCKS",n),console.log("USER MESSAGE CONTENT",t),this._addMessageToArray(a),this.contentBlocks=[],this.textChatScreen&&(this.textChatScreen.contentBlocks=[],this.textChatScreen.renderFilePreview(),this.textChatScreen.updateSendButton()),this.playedAudioIds.clear(),this.currentInputAudio=null,this.submissionInProgress=!1,this.processingAudioId=null,this.isLoading=!0;try{await this.sendMessageWithStreaming(t)}catch(e){console.error("Error sending message:",e);const n={id:Date.now()+1,content:"Sorry, I encountered an error. Please try again.",sender:"assistant",timestamp:(new Date).toISOString(),isError:!0};this._addMessageToArray(n)}finally{this.isLoading=!1}}async sendMessageWithStreaming(e){console.log("USER MESSAGE STREAMING",e),console.log("š¤ Sending text message - Language:",this.selectedLanguage,"Access token:",this.accessToken?"Present":"Not found");const n={id:Date.now()+1,content:"",sender:"assistant",timestamp:(new Date).toISOString(),isStreaming:!0,isProcessing:!0,textSessionId:Date.now()+1,hasAudioResponse:!1,inputType:"text"};this._addMessageToArray(n);let a=null;try{var s;const u=await this.getLatestCheckpoint(this.threadId);console.log("š¤ Sending message to backend:",t({input:{messages:[{id:"msg-".concat(Date.now()),type:"human",content:e}],user_language:this.selectedLanguage,access_token:"[redacted]",user_info:JSON.stringify(this.userInfo)},config:{configurable:{}},metadata:{supabaseAccessToken:"[redacted]",user_language:this.selectedLanguage,input_type:"text",audio_content:null},stream_mode:["values","messages-tuple","custom"],stream_subgraphs:!0,assistant_id:this.assistantId,on_disconnect:"cancel"},u&&{checkpoint:u}));const m=await fetch("".concat(this.langgraphUrl,"/threads/").concat(this.threadId,"/runs/stream"),{method:"POST",headers:this.getHeaders(),body:JSON.stringify(t({input:{messages:[{id:"msg-".concat(Date.now()),type:"human",content:e}],user_language:this.selectedLanguage,access_token:this.accessToken,user_info:JSON.stringify(this.userInfo)},config:{configurable:{}},metadata:{supabaseAccessToken:this.supabaseToken,user_language:this.selectedLanguage},stream_mode:["values","messages-tuple","custom"],stream_subgraphs:!0,assistant_id:this.assistantId,on_disconnect:"cancel"},u&&{checkpoint:u}))});if(!m.ok)throw new Error("HTTP error! status: ".concat(m.status));const f=m.body.getReader(),x=new TextDecoder;let b="",y="",v="",w=-1;const k=Date.now();let _=null,S=null,T=!1,I=null,C=!1,E="",A=null,L=null;console.log("š Starting to process streaming response for requestId:",k);const M=e=>{if(!e)return 0;const n=String(e).toLowerCase();return n.includes("mdms_assistant")||n.includes("grievance_assistant")||n.includes("mandiprice_assistant")?0:n.includes("assistant")&&!n.includes("tools")?3:n.includes("response_processor")||n.includes("post_assistant")?2:n.includes("ui_action_mapper")?1:0};for(;;){const{done:e,value:s}=await f.read();if(e)break;b+=x.decode(s,{stream:!0});const p=b.split("\n");b=p.pop()||"";for(const e of p)if(""!==e.trim()){if(console.log("š Processing SSE line:",{line:e.substring(0,100)+(e.length>100?"...":""),requestId:k}),e.startsWith("data:"))try{const n=JSON.parse(e.slice(5).trim());n.run_id&&(console.log("š¢ Run ID:",n.run_id),a=n.run_id)}catch(n){console.error("Error parsing JSON:",n,e)}if(e.startsWith("event: "))_=e.slice(7).trim(),console.log("šÆ Event type:",_);else if(e.startsWith("data: ")){const s=e.slice(6).trim();if("[DONE]"===s){console.log("š Stream completed");break}try{const e=JSON.parse(s);var i;if(S=e,e.run_id&&(console.log("š¢ Capturing run_id from parsed data:",e.run_id),a=e.run_id),"end"===_)if(console.log("š Received event: end - finalizing message with run_id:",a),e.run_id&&(a=e.run_id,console.log("š¢ Updated run_id from end event:",a)),y&&y.length>0)this._updateMessageInArray(n.id,{content:y,additional_kwargs:A,isStreaming:!1,isProcessing:!1,hasAudioResponse:(null===(i=this.messages.find(e=>e.id===n.id))||void 0===i?void 0:i.hasAudioResponse)||!1,latestRunId:a}),C=!0,E=y;else a&&this._updateMessageInArray(n.id,{latestRunId:a,isStreaming:!1,isProcessing:!1});if(console.log("š Parsed SSE data:",{event:_,hasData:!!e,dataKeys:e?Object.keys(e):"no data",topLevelKeys:Object.keys(e),hasAudioContent:null!=e&&e.audio_content?"YES":"NO",hasResponseProcessor:null!=e&&e.response_processor?"YES":"NO",hasRunId:null!=e&&e.run_id?"YES":"NO",runId:(null==e?void 0:e.run_id)||"N/A",requestId:k}),e.smart_router&&e.smart_router.access_token&&e.smart_router.farmer_profile&&!0===e.smart_router.farmer_profile_fetched){var o,r;console.log("š Authentication data detected in smart_router:",{hasAccessToken:!!e.smart_router.access_token,mobileNumber:e.smart_router.mobile_number,userUuid:e.smart_router.userUuid,hasFarmerProfile:!!e.smart_router.farmer_profile,farmerId:null===(o=e.smart_router.farmer_profile)||void 0===o?void 0:o.individualId,farmerName:null===(r=e.smart_router.farmer_profile)||void 0===r?void 0:r.name,requestId:k});try{const n=e.smart_router,a=n.farmer_profile,s=n.access_token;localStorage.setItem("DfsWeb.access-token",s);let i={};a.user_details?(i=t({},a.user_details),i.name=a.name||i.name||"",i.uuid||(i.uuid=n.userUuid),i.mobileNumber||(i.mobileNumber=n.mobile_number||a.mobileNumber)):(i={id:null,uuid:n.userUuid,userName:n.mobile_number,name:a.name||"",mobileNumber:n.mobile_number||a.mobileNumber,emailId:a.email||null,locale:null,type:"CITIZEN",roles:[{name:"Citizen",code:"CITIZEN",tenantId:a.tenantId||"br"}],active:!0,tenantId:a.tenantId||"br",permanentCity:null},this.setUserInfoFromDirectChatLogin(i)),this.userInfo=i,this.accessToken=s,i.uuid&&(console.log("USER INFO FOR UPDATING THREAD",i),this.threadId&&this.updateThread(this.threadId,i.uuid).then(e=>{console.log("ā
Thread updated after authentication:",e)}).catch(e=>{console.error("ā Error updating thread after authentication:",e.message)}),this.getUserThreads({userId:i.id,userUuid:i.uuid}).then(e=>{console.log("ā
Thread data fetched after authentication:",e),this.setUserThreads(e.threads),this.setUserThreadsMetaData({threads_processed:e.threads_processed,total_history_items:e.total_history_items,total_threads:e.total_threads})}).catch(e=>{console.error("ā Error fetching threads after authentication:",e.message)}))}catch(e){console.error("ā Error processing authentication data:",e)}}let p=null,u=null;if(e.response_processor&&Array.isArray(e.response_processor.ui_actions)?u=e.response_processor.ui_actions:e.response_processor&&e.response_processor.messages&&Array.isArray(e.response_processor.messages)&&e.response_processor.messages.length>0&&e.response_processor.messages[0].additional_kwargs&&Array.isArray(e.response_processor.messages[0].additional_kwargs.ui_actions)?u=e.response_processor.messages[0].additional_kwargs.ui_actions:e.ui_action_mapper&&Array.isArray(e.ui_action_mapper.ui_actions)?(p=e.ui_action_mapper,u=p.ui_actions):e.mdms_ui_action_mapper&&Array.isArray(e.mdms_ui_action_mapper.ui_actions)&&(p=e.mdms_ui_action_mapper,u=p.ui_actions),u&&u.length>0){console.log("UI ACTIONS",u);const e=u[u.length-1];if(e.web&&e.web.link){var c,l,d,h,g;let n=null,a={};if(e.web.parameters)e.web.parameters.scrollTo&&(n=e.web.parameters.scrollTo),a=t({},e.web.parameters);else if(e.web.link&&e.web.link.includes("scrollTo=")){n=new URLSearchParams(e.web.link.split("?")[1]).get("scrollTo")}let s=e.web.link,i=e.message||"";const o=(null===(c=e.web.parameters)||void 0===c?void 0:c.schemeId)&&""!==e.web.parameters.schemeId;let r=null;r=!(null===(l=e.web.parameters)||void 0===l||!l.button_title)||!(null===(d=e.web.parameters)||void 0===d||!d.name),o||r||(s="/help",i="Please find more information about available schemes and services"),I={content:"",url:s&&!s.startsWith("http")?window.location.origin+s:s,originalUrl:s,uiActionType:e.ui_action,scrollToId:n,navigationParams:t(t({},a),r&&{name:(null===(h=e.web.parameters)||void 0===h?void 0:h.button_title)||(null===(g=e.web.parameters)||void 0===g?void 0:g.name)})}}}if(e.analytics_visualization_node&&e.analytics_visualization_node.messages){const n=e.analytics_visualization_node.messages;if(n.length>0){const e=n[n.length-1];if("string"==typeof e&&e.includes("additional_kwargs")){const n=e.indexOf("additional_kwargs=")+18,t=e.indexOf("} response_metadata");if(n<t){const a=e.substring(n,t+1);try{let e=a.replace(/'/g,'"').replace(/None/g,"null").replace(/True/g,"true").replace(/False/g,"false");const n=JSON.parse(e);if(n.chart_image_url){console.log("šÆ Found chart image URL:",n.chart_image_url),A=n;try{const e=String(n.chart_image_url).trim();e.startsWith("http")&&(L=e,console.log("š Stored chartUrlFromViz:",L))}catch(e){console.warn("Failed to store chart image URL:",e)}}else n.antv_chart_data&&(console.log("šÆ Found chart data (fallback):",n.antv_chart_data),A=n)}catch(e){console.warn("Failed to parse chart image additional_kwargs:",e)}}}if("string"==typeof e){const n=e.match(/content=['"]([^'"]+)['"]/);if(n&&n[1]){const e=n[1].trim();e.startsWith("http")&&(L=e,console.log("š Stored extracted chartUrlFromViz:",L))}}}}let m=null,f=null;if(Object.keys(e).forEach(n=>{if("audio_content"!==n&&"audio_processor"!==n&&"ui_action_mapper"!==n){const t=e[n];t&&Array.isArray(t.messages)&&t.messages.length>0&&(m=n,f=t.messages)}}),f&&f.length>0){let e=f[f.length-1],n="";if("string"==typeof e)if(e.startsWith("content='")&&e.includes("' additional_kwargs")){const t=e.indexOf("content='")+9,a=e.indexOf("' additional_kwargs");n=e.substring(t,a).replace(/\\n/g,"\n").replace(/\\t/g,"\t").replace(/\\"/g,'"').replace(/\\'/g,"'")}else if(e.startsWith('content="')&&e.includes('" additional_kwargs')){const t=e.indexOf('content="')+9,a=e.indexOf('" additional_kwargs');n=e.substring(t,a).replace(/\\n/g,"\n").replace(/\\t/g,"\t").replace(/\\"/g,'"').replace(/\\'/g,"'")}else{const t=e.match(/content='([^']+)'/),a=e.match(/content="([^"]+)"/);n=t?t[1]:a?a[1]:e}else if(e&&"object"==typeof e)if("string"==typeof e.content)n=e.content;else if(Array.isArray(e.content)&&e.content.length>0){n=e.content.map(e=>"string"==typeof e?e:"string"==typeof(null==e?void 0:e.text)?e.text:"string"==typeof(null==e?void 0:e.value)?e.value:"").filter(Boolean).join(" ").trim()}else n="";if("string"==typeof n&&n.trim().length>0){const e=n.trim().startsWith("{")||n.trim().startsWith("["),t=M(m);if(e&&t<2)console.log("āļø Skipping JSON-like content from ".concat(m));else{const e=8e3,a=n.length>e?n.slice(0,e)+"\n\n⦠(truncated)":n;y=a,(t>w||t===w&&a.length>v.length)&&(v=a,w=t),T=!0,console.log("š¢ Found content from ".concat(m,":"),a.substring(0,100)+"...")}}}if(e){const t=_||"values";if(console.log("šµ Processing data message:",{eventType:t,currentEvent:_,dataKeys:Object.keys(e),requestId:k}),e.audio_content&&"string"==typeof e.audio_content){console.log("šµ AUDIO CONTENT FOUND in text stream:",{audioContentLength:e.audio_content.length,audioContentPreview:e.audio_content.substring(0,20)+"..."});const t="text_response_".concat(k,"_").concat(e.audio_content.substring(0,30)),s=this.playedAudioIds.has(t);if(console.log("š Text stream audio content received:",{audioResponseId:t,requestId:k,alreadyPlayed:s,audioContentLength:e.audio_content.length}),s)console.log("āļø Skipping audio: already played");else if(this.playedAudioIds.add(t),console.log("š Setting audio content for message:",{targetMessageId:n.id,audioContentLength:e.audio_content.length,audioContentPreview:e.audio_content.substring(0,20)+"..."}),this._updateMessageInArray(n.id,{hasAudioResponse:!0,audioContent:e.audio_content,latestRunId:a}),console.log("ā
Stored audio response (text stream)"),this.playedAudioIds.size>10){const e=Array.from(this.playedAudioIds);this.playedAudioIds.clear(),e.slice(-5).forEach(e=>this.playedAudioIds.add(e))}}else console.log("ā No audio_content found in text stream data");if(e.response_processor&&e.response_processor.audio_content&&"string"==typeof e.response_processor.audio_content){console.log("š Found audio_content in response_processor:",{audioContentLength:e.response_processor.audio_content.length,audioContentPreview:e.response_processor.audio_content.substring(0,50)+"..."});const t="text_response_".concat(k,"_").concat(e.response_processor.audio_content.substring(0,30)),s=this.playedAudioIds.has(t);if(console.log("š Response processor audio content received:",{audioResponseId:t,requestId:k,alreadyPlayed:s,audioContentLength:e.response_processor.audio_content.length}),s)console.log("āļø Skipping response processor audio: already played");else if(this.playedAudioIds.add(t),console.log("š Setting response processor audio content for message:",{targetMessageId:n.id,audioContentLength:e.response_processor.audio_content.length,audioContentPreview:e.response_processor.audio_content.substring(0,20)+"..."}),this._updateMessageInArray(n.id,{latestRunId:a,hasAudioResponse:!0,audioContent:e.response_processor.audio_content}),console.log("ā
Found matching message, setting response processor audio content"),this.playedAudioIds.size>10){const e=Array.from(this.playedAudioIds);this.playedAudioIds.clear(),e.slice(-5).forEach(e=>this.playedAudioIds.add(e))}}}}catch(e){console.log("ā ļø Failed to parse streaming data:",e)}}}}console.log("š Finalizing assistant message:",n.id),await new Promise(e=>setTimeout(e,100));const z=this.messages.find(e=>e.id===n.id);if(console.log("š Current assistant message before finalization:",{messageId:n.id,hasAudioContent:!(null==z||!z.audioContent),hasAudioResponse:null==z?void 0:z.hasAudioResponse,audioContentLength:(null==z||null===(s=z.audioContent)||void 0===s?void 0:s.length)||0}),C&&E&&E.length>10)console.log("ā
Message already finalized on end event; skipping overwrite");else{const e=v&&v.length>5?v:y,t=L&&String(L).startsWith("http")?L:e;if(t&&t.length>10){var p;console.log("š Finalizing message with content:",{messageId:n.id,currentMessageLength:String(t).length,currentMessagePreview:String(t).substring(0,50)+"..."});const e=this.messages.find(e=>e.id===n.id);console.log("š Finalizing message:",{latestRunId:a,messageId:n.id,existingAudioContent:!(null==e||!e.audioContent),existingAudioResponse:null==e?void 0:e.hasAudioResponse,audioContentLength:(null==e||null===(p=e.audioContent)||void 0===p?void 0:p.length)||0}),this._updateMessageInArray(n.id,{latestRunId:a,content:t,additional_kwargs:A,isStreaming:!1,isProcessing:!1,hasAudioResponse:(null==e?void 0:e.hasAudioResponse)||!1,audioContent:(null==e?void 0:e.audioContent)||null})}else{console.log("š Finalizing message with friendly fallback");const e=this.messages.find(e=>e.id===n.id);this._updateMessageInArray(n.id,{content:"Processing your request...",latestRunId:a,additional_kwargs:A,isStreaming:!1,isProcessing:!1,hasAudioResponse:(null==e?void 0:e.hasAudioResponse)||!1,audioContent:(null==e?void 0:e.audioContent)||null})}}if(I){console.log("š Adding UI action message:",I);const e={id:Date.now()+2,content:"",sender:"assistant",timestamp:(new Date).toISOString(),isUiAction:!0,url:I.url,uiActionType:I.uiActionType,scrollToId:I.scrollToId,navigationParams:I.navigationParams,originalUrl:I.originalUrl,isScrollAction:"scroll"===I.uiActionType,isNavigateStateAction:"navigate-state"===I.uiActionType},n=this.messages[this.messages.length-1];if(n){const s=t(t({},n),{},{uiActionMessage:e,latestRunId:a});console.log("UPDATED LAST MESSAGE",s),this._updateMessageInArray(n.id,{uiActionMessage:e,latestRunId:a})}}}catch(e){console.error("ā Streaming error:",e);const t=this.messages.find(e=>e.id===n.id);this._updateMessageInArray(n.id,{isStreaming:!1,isProcessing:!1,isError:!0,content:"Error occurred while processing request",latestRunId:a||(null==t?void 0:t.latestRunId)})}}async fetchAssistantId(){try{console.log("š Fetching assistant ID from API...");const e=this.authToken||this.accessToken,n=this.supabaseToken||e,t=await fetch("".concat(this.langgraphUrl,"/assistants/search"),{method:"POST",headers:{"Content-Type":"application/json",Authorization:"Bearer ".concat(e),"x-supabase-access-token":n,Origin:window.location.origin||"*"},body:JSON.stringify({limit:100,offset:0})});if(!t.ok)return console.log("ā API call failed with status: ".concat(t.status," - backend may have rejected due to auth")),null;const a=await t.json();console.log("š Available assistants:",a),a.forEach((e,n)=>{console.log("Assistant ".concat(n,":"),{id:e.assistant_id,name:e.name,hasName:!!e.name,type:typeof e.name})});const s=a.filter(e=>e.name&&e.name.includes("Default"))[0];if(s)return console.log("ā
Found Default Assistant:",s.assistant_id),this.assistantId=s.assistant_id,s.assistant_id;{console.log("ā ļø Default Assistant not found in the list");const e=a.find(e=>e.name&&""!==e.name.trim());return e?(console.log("ā ļø Using first valid assistant as fallback:",e.assistant_id,"Name:",e.name),this.assistantId=e.assistant_id,e.assistant_id):(console.log("ā No assistants with valid names available"),null)}}catch(e){return console.error("ā Error fetching assistant ID:",e),console.log("š Error details:",{name:e.name,message:e.message,isNetworkError:"TypeError"===e.name}),null}}async loadHistory(e){try{const t=await fetch("".concat(this.langgraphUrl,"/threads/").concat(e,"/history"),{method:"POST",headers:this.getHeaders(),body:JSON.stringify({limit:10})});if(t.ok){var n;const e=await t.json();console.log("š Loaded history:",e);const a=e[0];if(null==a||null===(n=a.values)||void 0===n||!n.messages)return void console.log("No messages found in history");const s=[];a.values.messages.forEach((e,n)=>{if("human"===e.type){let t="",a=!1;if(Array.isArray(e.content)){const n=e.content.find(e=>"text"===e.type);e.content.find(e=>"audio"===e.type)?(t="š¤ Audio message",a=!0):n&&(t=n.text)}else t=e.content;s.push({id:"history-".concat(n,"-human"),content:t,sender:"user",timestamp:(new Date).toISOString(),isAudio:a})}else"ai"===e.type&&s.push({id:"history-".concat(n,"-ai"),content:e.content,sender:"assistant",timestamp:(new Date).toISOString()})}),s&&s.length>0&&(console.log("š Loading ".concat(s.length," messages from history")),s.forEach(e=>{this._addMessageToArray(e)}))}}catch(e){console.error("ā Failed to load history:",e)}}async initializeChat(){try{console.log("š Initializing chat...");const e=localStorage.getItem("DfsWeb.access-token");console.log("š Access token status:",e?"Present":"Empty - backend will handle"),console.log("š Making API call to /assistants/search...");const n=await this.fetchAssistantId();if(!n)return console.log("ā Failed to fetch assistant ID - backend may have rejected due to auth"),this.isConnected=!1,void(this.initialized=!0);console.log("ā
Assistant ID fetched successfully:",n);const t=localStorage.getItem("DfsWeb.user-info"),a=t?JSON.parse(t):null;console.log("š Making API call to /threads...");const s=await fetch("".concat(this.langgraphUrl,"/threads"),{method:"POST",headers:this.getHeaders(),body:JSON.stringify({metadata:{user_id:(null==a?void 0:a.id)||null,user_uuid:(null==a?void 0:a.uuid)||null}})});if(s.ok){const e=await s.json();this.threadId=e.thread_id,this.isConnected=!0,console.log("ā
Thread created:",e.thread_id,"\n",e),await this.loadHistory(e.thread_id)}else{console.log("Thread created NOT");const e=await s.text();console.error("ā Failed to create thread:",s.status,e),this.isConnected=!1}this.initialized=!0}catch(e){console.error("ā Thread creation error:",e),this.isConnected=!1,this.initialized=!0}}}export{o as default};
|