@crestapps/ai-chat-ui 2.0.0-preview.154 → 2.0.0-preview.162

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["ai-chat.js"],"names":["_excluded","_regenerator","e","t","r","Symbol","n","iterator","o","toStringTag","i","c","prototype","Generator","u","Object","create","_regeneratorDefine2","f","p","y","G","v","a","d","bind","length","l","TypeError","call","done","value","GeneratorFunction","GeneratorFunctionPrototype","getPrototypeOf","this","setPrototypeOf","__proto__","displayName","w","m","defineProperty","_invoke","enumerable","configurable","writable","asyncGeneratorStep","Promise","resolve","then","_asyncToGenerator","arguments","apply","_next","_throw","_toConsumableArray","_arrayWithoutHoles","_iterableToArray","_unsupportedIterableToArray","_nonIterableSpread","Array","from","isArray","_arrayLikeToArray","_objectWithoutProperties","_objectWithoutPropertiesLoose","getOwnPropertySymbols","indexOf","propertyIsEnumerable","hasOwnProperty","_createForOfIteratorHelper","_n","F","s","next","_slicedToArray","_arrayWithHoles","_iterableToArrayLimit","_nonIterableRest","toString","slice","constructor","name","test","push","_typeof","window","coreAIChatManager","defaultConfig","generatedImageAltText","generatedImageMaxWidth","downloadImageTitle","downloadChartTitle","downloadChartButtonText","userLabel","assistantLabel","thumbsUpTitle","thumbsDownTitle","copyTitle","copiedTitle","codeCopiedText","copyResetDelayMs","widget","chatWidgetContainer","chatWidgetStateName","chatHistorySection","showHistoryButton","closeHistoryButton","newChatButton","toggleButtonSelector","resetSizeButtonSelector","dragHandleSelector","enableDragging","enableResizing","persistLayout","defaultWidth","defaultHeight","minWidth","minHeight","messageTemplate","indicatorTemplate","sanitizeUrl","url","trimmed","trim","escapeHtmlEntities","text","span","document","createElement","textContent","innerHTML","refreshFontAwesomeIcons","root","fontAwesome","FontAwesome","nodeType","selector","matches","querySelector","containsFontAwesomePlaceholders","dom","i2svg","node","observeFontAwesomeIcons","MutationObserver","observer","mutations","forEach","mutation","addedNodes","observe","childList","subtree","normalizeReference","reference","_ref","_normalized$index","_ref2","_normalized$text","_ref3","_normalized$title","_ref4","_normalized$link","_ref5","_normalized$reference","_normalized$isGenerat","normalized","assign","index","Index","Text","title","Title","link","Link","referenceType","ReferenceType","isGenerated","IsGenerated","isDownloadCitationReference","toLowerCase","normalizeReferences","references","_i","_Object$entries","entries","_normalizeReference","_Object$entries$_i","key","getCitationLabel","updateMessagePresentation","message","messageReferences","rawContent","content","citationDisplay","processedContent","referenceEntries","citations","citedRefs","filter","_ref6","includes","generatedRefs","_ref8","_ref9","sort","_ref0","_ref1","b","_ref12","_ref13","_step","displayIndex","_iterator","_step$value","placeholder","concat","replaceAll","referenceKey","label","isDownload","err","_i2","_citations","citation","_step2","_iterator2","_step2$value","map","_ref16","buildCitationDisplay","displayContent","citationReferences","copyContent","_step3","_iterator3","_step4","_iterator4","trimEnd","buildCopyContent","htmlContent","parseMarkdownContent","renderer","marked","Renderer","data","href","code","lang","highlighted","hljs","getLanguage","highlight","language","_","highlightAuto","langDisplay","image","src","alt","maxWidth","chartCounter","_pendingCharts","renderChartsInMessage","charts","requestAnimationFrame","_step5","_iterator5","renderChartOnCanvas","chartId","config","canvas","getElementById","Chart","console","warn","offsetParent","__chartConfigs","_cfg$options","_cfg$options2","_cfg$options2$aspectR","_chartInstance","destroy","cfg","JSON","parse","options","responsive","maintainAspectRatio","aspectRatio","error","html","DOMPurify","sanitize","ADD_TAGS","ADD_ATTR","compactObject","source","fromEntries","_ref17","undefined","use","extensions","level","start","idx","tokenizer","extracted","token","jsonStart","depth","inString","escape","ch","jsonEnd","closeBracketIndex","startIndex","endIndex","json","substring","tryExtractChartMarker","type","raw","renderPendingCharts","configs","_i3","_Object$keys","keys","initialize","instanceConfig","normalizedInstanceConfig","normalizedWidgetConfig","template","encodedAssistantLabel","replace","resolveIndicatorTemplate","hasWidgetConfig","widgetBehavior","coreAIChatWidgetBehavior","signalRHubUrl","appElementSelector","chatContainerElementSelector","inputElementSelector","sendButtonElementSelector","appDefinition","inputElement","buttonElement","chatContainer","isSessionStarted","isPlaceholderVisible","isStreaming","isNavigatingAway","autoScroll","stream","messages","notifications","prompt","documents","existingDocuments","isUploading","isDocumentOperationPending","documentOperationQueue","uploadErrors","isDragOver","documentBar","metricsEnabled","isRecording","mediaRecorder","preRecordingPrompt","micButton","speechToTextEnabled","chatMode","textToSpeechEnabled","ttsVoiceName","audioChunks","audioPlayQueue","isPlayingAudio","currentAudioElement","currentAudioUrl","ttsButton","ttsPlayingMessageIndex","ttsAudioCache","ttsInstanceId","Math","random","singleResponseMode","conversationModeEnabled","conversationButton","isConversationMode","notificationDismissTimers","pendingSessionPromise","pendingSessionResolver","pendingSessionRejector","pendingSessionTimeoutId","copiedMessageIndex","copyResetTimeoutId","activeCopyButton","computed","lastAssistantIndex","role","methods","handleBeforeUnload","handleDragOver","sessionDocumentsEnabled","preventDefault","stopPropagation","inputArea","closest","classList","add","handleDragLeave","remove","handleDrop","dataTransfer","files","uploadFiles","triggerFileInput","fileInput","click","handleFileInputChange","target","queueDocumentOperation","operation","self","nextOperation","_callee","_context","_this","_callee3","filesToUpload","_context3","uploadDocumentUrl","_callee2","sessionId","profileId","formData","response","errorText","uploadError","result","_t","_t2","_context2","getSessionId","getProfileId","ensureSessionForDocuments","fileName","renderDocumentBar","FormData","append","fetch","method","body","ok","extractReadableErrorMessage","initializeSession","uploaded","failed","reloadCurrentSession","removeDocument","doc","_this2","_callee5","_context5","removeDocumentUrl","_callee4","removeError","_t3","_context4","headers","stringify","itemId","documentId","splice","status","formatFileSize","bytes","toFixed","escapeHtml","failedItem","failedName","errorMsg","supportedExtensionsText","replaceChildren","RETURN_DOM_FRAGMENT","closeButtons","querySelectorAll","j","addEventListener","docToRemove","parseInt","getAttribute","errorCloseButtons","addBtn","div","fallbackMessage","startsWith","parsed","detail","normalizeAssistantAppearance","appearance","icon","cssClass","disableStreamingAnimation","getAssistantLabel","getAssistantRoleClasses","classes","getAssistantIconClasses","shouldAnimateAssistantIcon","getAssistantIcon","startConnection","_this3","_callee6","_t4","_context6","connection","signalR","HubConnectionBuilder","withUrl","withAutomaticReconnect","build","serverTimeoutInMilliseconds","keepAliveIntervalInMilliseconds","on","_data$messages","msg","addMessage","$nextTick","refreshAllFeedbackIcons","initialPrompt","stopRecording","rejectPendingSessionRequest","hideTypingIndicator","handleReceiveError","getErrorMessage","reason","messageId","userRating","find","id","isFinal","_conversationPartialTranscript","_conversationPartialMessage","hidePlaceholder","isPartial","scrollToBottom","_audioInputSent","dispatchEvent","Event","stopAudio","_conversationAssistantMessage","oldMsg","escaped","responseId","msgIndex","newMessage","base64Audio","contentType","binaryString","atob","Uint8Array","charCodeAt","playCollectedAudio","notification","receiveNotification","updateNotification","notificationType","removeNotification","onreconnecting","onreconnected","info","onclose","addMessageInternal","_this4","fireEvent","CustomEvent","_message$rawContent","_this5","addMessages","_this6","showPlaceholder","isOrchestratorAvailable","applyOrchestratorAvailability","unavailableMessage","orchestratorUnavailableMessage","disabled","micButtonElement","style","display","conversationButtonElement","event","isIndicator","sendMessage","trimmedPrompt","streamMessage","startRecording","_this7","navigator","mediaDevices","getUserMedia","audio","echoCancellation","noiseSuppression","autoGainControl","mimeType","MediaRecorder","isTypeSupported","audioBitsPerSecond","subject","Subject","pendingChunk","size","_callee7","uint8Array","base64","_context7","arrayBuffer","reduce","str","byte","String","fromCharCode","btoa","getTracks","track","stop","complete","documentElement","send","updateMicButton","toggleRecording","sessionProfileId","_this8","dispose","streamingStarted","showTypingIndicator","lastResponseId","messageIndex","currentSessionId","subscribe","chunk","_i4","_Object$entries2","_normalizeReference2","_Object$entries2$_i","_this8$stream","processReferences","streamingFinished","synthesizeSpeech","_this8$stream2","getServiceDownMessage","_this9","_ref23","_message$rawContent2","stopIcon","setAttribute","startIcon","removeAttribute","focus","icons","handleExternalTtsStop","_e$detail","sourceId","updateTtsPlaybackButtons","_this0","button","isPlaying","Number","toggle","updateCopyButtons","_this1","isCopied","iconHtml","setCopyButtonState","cacheIndex","_this10","_ttsCacheIndex","invoke","toggleMessageTts","_this11","playAudioBlob","_this12","_step6","totalLength","sum","combined","offset","_iterator6","set","blob","Blob","_this13","URL","createObjectURL","Audio","revokeObjectURL","playNextInQueue","play","_this14","nextBlob","shift","conversationModeOnAudioEnded","_this15","pause","currentTime","toggleConversationMode","stopConversationMode","startConversationMode","_this16","updateConversationButton","_conversationSubject","_conversationStream","AudioCtx","AudioContext","webkitAudioContext","_conversationAudioCtx","_conversationAnalyser","createAnalyser","fftSize","createMediaStreamSource","connect","analyser","freqData","frequencyBinCount","getByteFrequencyData","k","_callee8","_context8","close","dismissible","autoDismissMs","endHtml","blur","startHtml","conversationModeSendPrompt","generatePrompt","element","templateProfileId","createSessionUrl","baseUrl","param","fullUrl","location","origin","searchParams","originalLength","_this17","clearNotificationDismiss","existingIndex","findIndex","scheduleNotificationDismiss","_this18","setTimeout","timerId","clearTimeout","dismissNotification","handleNotificationAction","actionName","_this19","scrollTop","scrollHeight","clientHeight","handleUserInput","setSessionId","resetSession","sessionRating","onSessionReset","startNewSession","requestNewSession","_this20","_callee9","_context9","_this21","reject","resolvePendingSessionRequest","clearPendingSessionRequest","initializeApp","_this22","placeholderElementSelector","loadSession","documentBarSelector","className","multiple","allowedExtensions","accept","parentElement","appendChild","atBottom","shiftKey","lastMsg","pop","promptGenerators","getElementsByClassName","chatSessions","showChatScreen","initialMessages","btn","block","codeEl","clipboard","writeText","copiedText","micButtonElementSelector","conversationButtonElementSelector","force","onSessionInitialized","sessionUrlTemplate","history","replaceState","sessionUrl","encodeURIComponent","resolveSessionId","clearCopiedMessageState","copyResponse","_ref25","_message$copyContent","_event$target","_event$target$closest","_this23","currentTarget","updateFeedbackIcons","container","upBtn","downBtn","upClass","upIcon","fontSize","downClass","downIcon","containers","$el","msgId","rateMessage","isPositive","newRating","feedbackContainer","btnClass","offsetWidth","onEnd","removeEventListener","watch","handler","onDocumentsChanged","deep","_this24","active","mounted","_this25","_callee0","_context0","onMounted","fontAwesomeObserver","beforeUnmount","disconnect","onBeforeUnmount","app","Vue","createApp","mount","attach","autoInitializeSelector","getAttributeValue","attributeName","parseJsonAttribute","description","rawValue","buildConfigFromDataAttributes","_parseJsonAttribute","_parseJsonAttribute2","settings","hasAttribute","allowWidgetHost","booleanAttributes","parseBooleanAttributeValue","buildConfigFromElement","jsonConfig","attributeConfig","initializeFromElement","dataset","coreAiChatInitialized","__coreAIChatApp","scanForAutoInitialization","startAutoInitialization","readyState","once","download","toDataURL","img","res","removeChild"],"mappings":"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","file":"ai-chat.min.js","sourcesContent":["window.coreAIChatManager = function () {\n\n // Defaults (can be overridden by instanceConfig)\n var defaultConfig = {\n // UI defaults for generated media\n generatedImageAltText: 'Generated Image',\n generatedImageMaxWidth: 400,\n downloadImageTitle: 'Download image',\n downloadChartTitle: 'Download chart as image',\n downloadChartButtonText: 'Download',\n userLabel: 'You',\n assistantLabel: 'Assistant',\n thumbsUpTitle: 'Thumbs up',\n thumbsDownTitle: 'Thumbs down',\n copyTitle: 'Click here to copy response to clipboard.',\n copiedTitle: 'Response copied to clipboard.',\n codeCopiedText: 'Copied!',\n copyResetDelayMs: 2000,\n widget: {\n chatWidgetContainer: null,\n chatWidgetStateName: null,\n chatHistorySection: null,\n showHistoryButton: null,\n closeHistoryButton: null,\n newChatButton: null,\n toggleButtonSelector: null,\n resetSizeButtonSelector: null,\n dragHandleSelector: '.ai-chat-widget-header',\n enableDragging: true,\n enableResizing: true,\n persistLayout: true,\n defaultWidth: null,\n defaultHeight: null,\n minWidth: 320,\n minHeight: 420\n },\n messageTemplate: `\n <div class=\"ai-chat-messages\">\n <div v-for=\"(message, index) in messages\" :key=\"'msg-' + index\" class=\"ai-chat-message-item\">\n <div>\n <div v-if=\"message.role === 'user'\" class=\"ai-chat-message-heading ai-chat-message-heading-user\">\n <span class=\"ai-chat-msg-role ai-chat-msg-role-user\">{{ userLabel }}</span>\n </div>\n <div v-else-if=\"message.role !== 'indicator'\" class=\"ai-chat-message-heading ai-chat-message-heading-assistant\">\n <div :class=\"getAssistantRoleClasses(message)\">\n <span :class=\"getAssistantIconClasses(message, index)\"><i :class=\"getAssistantIcon(message)\"></i></span>\n <span class=\"ai-chat-message-role-label\">{{ getAssistantLabel(message) }}</span>\n </div>\n </div>\n <div class=\"ai-chat-message-body lh-base\">\n <h4 v-if=\"message.title\">{{ message.title }}</h4>\n <div v-html=\"message.htmlContent\"></div>\n <ol v-if=\"message.citationReferences && message.citationReferences.length\" class=\"ai-chat-citation-list\">\n <li v-for=\"citation in message.citationReferences\" :key=\"'citation-' + (citation.referenceKey || citation.displayIndex)\" class=\"ai-chat-citation-item\">\n <a v-if=\"citation.link\" :href=\"citation.link\" :target=\"citation.isDownload ? null : '_blank'\" :rel=\"citation.isDownload ? null : 'noopener noreferrer'\">{{ citation.label }}</a>\n <span v-else>{{ citation.label }}</span>\n </li>\n </ol>\n <span class=\"message-buttons-container\" v-if=\"!isIndicator(message)\">\n <template v-if=\"metricsEnabled && message.role === 'assistant'\">\n <span class=\"ai-chat-message-assistant-feedback\" :data-message-id=\"message.id\">\n <button type=\"button\" class=\"btn btn-sm btn-link text-success p-0 me-2 button-message-toolbox rate-up-btn\" @click=\"rateMessage(message, true, $event)\" :title=\"thumbsUpTitle\">\n <i class=\"fa-regular fa-thumbs-up\"></i>\n </button>\n <button type=\"button\" class=\"btn btn-sm btn-link text-danger p-0 me-2 button-message-toolbox rate-down-btn\" @click=\"rateMessage(message, false, $event)\" :title=\"thumbsDownTitle\">\n <i class=\"fa-regular fa-thumbs-down\"></i>\n </button>\n </span>\n </template>\n <button type=\"button\" v-if=\"textToSpeechEnabled && !isConversationMode && message.role === 'assistant' && !message.isStreaming\" class=\"btn btn-sm btn-link text-secondary p-0 me-1 button-message-toolbox\" :class=\"{ 'tts-playing': ttsPlayingMessageIndex === index }\" :data-tts-message-index=\"index\" @click=\"toggleMessageTts(message, index)\" :title=\"ttsPlayingMessageIndex === index ? 'Pause audio' : 'Read aloud'\">\n <span :class=\"ttsPlayingMessageIndex === index ? 'fa-solid fa-circle-pause' : 'fa-solid fa-circle-play'\"></span>\n </button>\n <button type=\"button\" class=\"btn btn-sm btn-link p-0 button-message-toolbox ai-response-copy-btn\" :class=\"copiedMessageIndex === index ? 'text-success' : 'text-secondary'\" :data-copy-message-index=\"index\" @click=\"copyResponse(message, index, $event)\" :title=\"copiedMessageIndex === index ? copiedTitle : copyTitle\">\n <i :class=\"copiedMessageIndex === index ? 'fa-solid fa-check' : 'fa-solid fa-copy'\"></i>\n </button>\n </span>\n </div>\n </div>\n </div>\n <div v-for=\"notification in notifications\" :key=\"'notif-' + notification.type\" class=\"ai-chat-notification\" :class=\"'ai-chat-notification-' + (notification.type || 'info') + ' ' + (notification.cssClass || '')\">\n <div class=\"ai-chat-notification-content\">\n <i v-if=\"notification.icon\" :class=\"notification.icon\" class=\"ai-chat-notification-icon\"></i>\n <span class=\"ai-chat-notification-text\">{{ notification.content }}</span>\n <button type=\"button\" v-if=\"notification.dismissible\" class=\"btn btn-sm btn-link p-0 ms-2 ai-chat-notification-dismiss\" @click=\"dismissNotification(notification.type)\" title=\"Dismiss\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n <div v-if=\"notification.actions && notification.actions.length\" class=\"ai-chat-notification-actions\">\n <button type=\"button\" v-for=\"action in notification.actions\" :key=\"action.name\" class=\"btn btn-sm\" :class=\"action.cssClass || 'btn-outline-secondary'\" @click=\"handleNotificationAction(notification.type, action.name)\">\n <i v-if=\"action.icon\" :class=\"action.icon\" class=\"me-1\"></i>\n {{ action.label }}\n </button>\n </div>\n </div>\n </div>\n `,\n indicatorTemplate: `\n <div class=\"ai-chat-message-heading ai-chat-message-heading-assistant\">\n <div class=\"ai-chat-msg-role ai-chat-msg-role-assistant\">\n <span class=\"ai-streaming-icon\"><i class=\"fa fa-robot\" style=\"display: inline-block;\"></i></span>\n <span class=\"ai-chat-message-role-label\">Assistant</span>\n </div>\n </div>\n `\n };\n\n // Sanitize URLs to prevent javascript: protocol injection.\n function sanitizeUrl(url) {\n if (!url) return '';\n var trimmed = url.trim();\n if (/^javascript:/i.test(trimmed) || /^vbscript:/i.test(trimmed) || /^data:text\\/html/i.test(trimmed)) {\n return '';\n }\n return url;\n }\n\n // Safely HTML-encode a string using the DOM (avoids regex-based HTML filtering).\n function escapeHtmlEntities(text) {\n var span = document.createElement('span');\n span.textContent = text;\n return span.innerHTML;\n }\n\n function containsFontAwesomePlaceholders(root) {\n if (!root || root.nodeType !== 1) {\n return false;\n }\n\n var selector = 'i[class*=\"fa-\"],i.fa,i.fas,i.far,i.fab';\n if (typeof root.matches === 'function' && root.matches(selector)) {\n return true;\n }\n\n return typeof root.querySelector === 'function' && !!root.querySelector(selector);\n }\n\n function refreshFontAwesomeIcons(root) {\n var fontAwesome = window.FontAwesome;\n if (!containsFontAwesomePlaceholders(root) || !fontAwesome || !fontAwesome.dom || typeof fontAwesome.dom.i2svg !== 'function') {\n return;\n }\n\n fontAwesome.dom.i2svg({ node: root });\n }\n\n function observeFontAwesomeIcons(root) {\n if (!root || typeof MutationObserver === 'undefined') {\n return null;\n }\n\n var observer = new MutationObserver(function (mutations) {\n mutations.forEach(function (mutation) {\n mutation.addedNodes.forEach(function (node) {\n refreshFontAwesomeIcons(node);\n });\n });\n });\n\n observer.observe(root, {\n childList: true,\n subtree: true\n });\n\n return observer;\n }\n\n function parsePixelValue(value) {\n if (typeof value === 'number' && Number.isFinite(value)) {\n return value;\n }\n\n if (typeof value !== 'string') {\n return null;\n }\n\n var parsed = parseFloat(value);\n return Number.isFinite(parsed) ? parsed : null;\n }\n\n function clamp(value, min, max) {\n return Math.min(Math.max(value, min), max);\n }\n\n function normalizeReference(reference) {\n if (!reference || typeof reference !== 'object') {\n return null;\n }\n\n const normalized = Object.assign({}, reference);\n normalized.index = normalized.index ?? normalized.Index ?? 0;\n normalized.text = normalized.text ?? normalized.Text ?? null;\n normalized.title = normalized.title ?? normalized.Title ?? null;\n normalized.link = sanitizeUrl(normalized.link ?? normalized.Link ?? null);\n normalized.referenceType = normalized.referenceType ?? normalized.ReferenceType ?? null;\n normalized.isGenerated = (normalized.isGenerated ?? normalized.IsGenerated) === true;\n\n return normalized;\n }\n\n function isDownloadCitationReference(reference) {\n if (!reference || typeof reference !== 'object') {\n return false;\n }\n\n if (typeof reference.referenceType === 'string' && reference.referenceType.toLowerCase() === 'document') {\n return true;\n }\n\n if (typeof reference.link === 'string' && /\\/ai\\/documents\\/.+\\/download(?:$|\\?)/i.test(reference.link)) {\n return true;\n }\n\n return false;\n }\n\n function normalizeReferences(references) {\n if (!references || typeof references !== 'object') {\n return {};\n }\n\n const normalized = {};\n\n for (const [key, value] of Object.entries(references)) {\n normalized[key] = normalizeReference(value) ?? {};\n }\n\n return normalized;\n }\n\n function getCitationLabel(reference, key) {\n return reference.title || reference.text || key;\n }\n\n function buildCitationDisplay(content, references) {\n let processedContent = (content || '').trim();\n const messageReferences = normalizeReferences(references);\n const referenceEntries = Object.entries(messageReferences);\n\n if (!referenceEntries.length) {\n return { content: processedContent, citations: [] };\n }\n\n const citedRefs = referenceEntries.filter(([key]) => processedContent.includes(key));\n const generatedRefs = referenceEntries.filter(([key, value]) => value.isGenerated && !processedContent.includes(key));\n\n if (!citedRefs.length && !generatedRefs.length) {\n return { content: processedContent, citations: [] };\n }\n\n citedRefs.sort(([, a], [, b]) => a.index - b.index);\n generatedRefs.sort(([, a], [, b]) => a.index - b.index);\n\n const citations = [];\n let displayIndex = 1;\n\n for (const [key, value] of citedRefs) {\n const placeholder = `__CITE_${displayIndex}_${value.index || displayIndex}__`;\n processedContent = processedContent.replaceAll(key, placeholder);\n citations.push({\n referenceKey: key,\n displayIndex: displayIndex,\n label: getCitationLabel(value, key),\n link: value.link || null,\n isDownload: isDownloadCitationReference(value),\n placeholder: placeholder,\n });\n\n displayIndex++;\n }\n\n for (const citation of citations) {\n processedContent = processedContent.replaceAll(citation.placeholder, `<sup>${citation.displayIndex}</sup>`);\n }\n\n processedContent = processedContent.replaceAll('</sup><sup>', '</sup><sup>,</sup><sup>');\n\n // Generated files (such as exported tabular data) are always offered as a download even when\n // the model does not cite them inline, so the user never loses access to the produced file.\n for (const [key, value] of generatedRefs) {\n citations.push({\n referenceKey: key,\n displayIndex: displayIndex,\n label: getCitationLabel(value, key),\n link: value.link || null,\n isDownload: true,\n placeholder: null,\n });\n\n displayIndex++;\n }\n\n return {\n content: processedContent,\n citations: citations.map(({ placeholder, ...citation }) => citation),\n };\n }\n\n function buildCopyContent(content, citations) {\n let copyContent = (content || '').trim();\n\n if (!copyContent || !Array.isArray(citations) || citations.length === 0) {\n return copyContent;\n }\n\n for (const citation of citations) {\n copyContent = copyContent.replaceAll(citation.referenceKey, `[${citation.displayIndex}]`);\n }\n\n copyContent += '\\n\\nReferences:\\n';\n\n for (const citation of citations) {\n copyContent += `${citation.displayIndex}. ${citation.label}`;\n\n if (citation.link) {\n copyContent += ` - ${citation.link}`;\n }\n\n copyContent += '\\n';\n }\n\n return copyContent.trimEnd();\n }\n\n function updateMessagePresentation(message, references) {\n const messageReferences = normalizeReferences(references ?? message.references);\n const rawContent = typeof message.rawContent === 'string'\n ? message.rawContent\n : typeof message.content === 'string'\n ? message.content\n : '';\n const citationDisplay = buildCitationDisplay(rawContent, messageReferences);\n\n message.rawContent = rawContent;\n message.content = rawContent;\n message.displayContent = citationDisplay.content;\n message.references = messageReferences;\n message.citationReferences = citationDisplay.citations;\n message.copyContent = buildCopyContent(rawContent, citationDisplay.citations);\n message.htmlContent = parseMarkdownContent(citationDisplay.content, message);\n\n return message;\n }\n\n const renderer = new marked.Renderer();\n\n // Modify the link rendering to open in a new tab\n renderer.link = function (data) {\n var href = sanitizeUrl(data.href);\n if (!href) return data.text || '';\n return `<a href=\"${href}\" target=\"_blank\" rel=\"noopener noreferrer\">${data.text}</a>`;\n };\n\n // Custom code block renderer with highlight.js integration and copy button.\n renderer.code = function (data) {\n var code = data.text || '';\n var lang = (data.lang || '').trim();\n var highlighted = code;\n\n if (typeof hljs !== 'undefined') {\n if (lang && hljs.getLanguage(lang)) {\n try {\n highlighted = hljs.highlight(code, { language: lang }).value;\n } catch (_) { }\n } else {\n try {\n highlighted = hljs.highlightAuto(code).value;\n } catch (_) { }\n }\n } else {\n highlighted = escapeHtmlEntities(code);\n }\n\n var langDisplay = lang ? escapeHtmlEntities(lang) : 'code';\n return `<div class=\"ai-code-block\"><div class=\"ai-code-header\"><span class=\"ai-code-lang\"><i class=\"fa-solid fa-code\"></i> ${langDisplay}</span><button type=\"button\" class=\"ai-code-copy-btn\" title=\"Copy code\"><i class=\"fa-regular fa-copy\"></i></button></div><pre><code class=\"hljs${lang ? ' language-' + lang : ''}\">${highlighted}</code></pre></div>`;\n };\n\n // Custom image renderer for generated images with thumbnail styling and download button.\n // Handles both URL and data-URI sources (data URIs are converted to blobs for download).\n renderer.image = function (data) {\n const src = sanitizeUrl(data.href);\n if (!src) return '';\n const alt = data.text || defaultConfig.generatedImageAltText;\n const maxWidth = defaultConfig.generatedImageMaxWidth;\n return `<div class=\"generated-image-container\">\n <img src=\"${src}\" alt=\"${alt}\" class=\"img-thumbnail\" style=\"max-width: ${maxWidth}px; height: auto;\" />\n <div class=\"mt-2\">\n <a href=\"${src}\" target=\"_blank\" download=\"${alt}\" title=\"${defaultConfig.downloadImageTitle}\" class=\"btn btn-sm btn-outline-secondary ai-download-image\">\n <i class=\"fa-solid fa-download\"></i>\n </a>\n </div>\n </div>`;\n };\n\n // Chart counter for unique IDs\n let chartCounter = 0;\n\n // Collector for charts discovered during marked parsing.\n let _pendingCharts = [];\n\n // Global chart config map: any page (e.g., Chat Interactions) that uses\n // the shared marked instance can call window.renderPendingCharts() after\n // its DOM update to render charts it didn't create itself.\n window.__chartConfigs = window.__chartConfigs || {};\n\n function createChartHtml(chartId) {\n return `<div class=\"chart-container\" style=\"position: relative; width: 100%; max-width: 560px; min-height: 420px;\">`\n + `<canvas id=\"${chartId}\"></canvas>`\n + `</div>`\n + `<div class=\"mt-2\">`\n + `<button type=\"button\" class=\"btn btn-sm btn-outline-secondary download-chart-btn\" data-chart-id=\"${chartId}\" title=\"${defaultConfig.downloadChartTitle}\">`\n + `<i class=\"fa-solid fa-download\"></i> ${defaultConfig.downloadChartButtonText}`\n + `</button>`\n + `</div>`;\n }\n\n // Register [chart:{...json...}] as a native marked block extension so the\n // markdown parser handles chart markers inline with surrounding text.\n marked.use({\n extensions: [{\n name: 'chart',\n level: 'block',\n start(src) {\n const idx = src.indexOf('[chart:');\n return idx >= 0 ? idx : undefined;\n },\n tokenizer(src) {\n const extracted = tryExtractChartMarker(src);\n if (!extracted || extracted.startIndex !== 0) {\n return undefined;\n }\n\n const chartId = `chat_chart_${++chartCounter}`;\n\n return {\n type: 'chart',\n raw: src.substring(0, extracted.endIndex),\n chartId: chartId,\n json: extracted.json,\n };\n },\n renderer(token) {\n _pendingCharts.push({ chartId: token.chartId, config: token.json });\n window.__chartConfigs[token.chartId] = token.json;\n return createChartHtml(token.chartId);\n }\n }]\n });\n\n // Extract a [chart:{...json...}] marker. This avoids regex issues with nested brackets.\n function tryExtractChartMarker(text) {\n const token = '[chart:';\n const start = text.indexOf(token);\n if (start < 0) {\n return null;\n }\n\n // Find JSON object boundary by balancing braces\n const jsonStart = start + token.length;\n let i = jsonStart;\n while (i < text.length && (text[i] === ' ' || text[i] === '\\n' || text[i] === '\\r' || text[i] === '\\t')) {\n i++;\n }\n\n if (i >= text.length || text[i] !== '{') {\n return null;\n }\n\n let depth = 0;\n let inString = false;\n let escape = false;\n\n for (; i < text.length; i++) {\n const ch = text[i];\n\n if (inString) {\n if (escape) {\n escape = false;\n continue;\n }\n if (ch === '\\\\') {\n escape = true;\n continue;\n }\n if (ch === '\"') {\n inString = false;\n }\n continue;\n }\n\n if (ch === '\"') {\n inString = true;\n continue;\n }\n\n if (ch === '{') {\n depth++;\n } else if (ch === '}') {\n depth--;\n if (depth === 0) {\n const jsonEnd = i;\n // Expect closing bracket after JSON\n const closeBracketIndex = text.indexOf(']', jsonEnd + 1);\n if (closeBracketIndex < 0) {\n return null;\n }\n\n const json = text.substring(jsonStart, jsonEnd + 1).trim();\n return {\n startIndex: start,\n endIndex: closeBracketIndex + 1,\n json: json\n };\n }\n }\n }\n\n return null;\n }\n\n function renderChartsInMessage(message) {\n if (!message || !message._pendingCharts || !message._pendingCharts.length) {\n return;\n }\n\n // Copy and clear pending charts immediately to prevent duplicate renders.\n const charts = [...message._pendingCharts];\n message._pendingCharts = [];\n\n // Defer to requestAnimationFrame so the browser has fully laid out the\n // canvas elements before Chart.js reads their dimensions.\n requestAnimationFrame(() => {\n for (const c of charts) {\n renderChartOnCanvas(c.chartId, c.config);\n }\n });\n }\n\n function renderChartOnCanvas(chartId, config) {\n const canvas = document.getElementById(chartId);\n if (!canvas) {\n return false;\n }\n\n if (typeof Chart === 'undefined') {\n console.warn('Chart.js is not loaded. To render interactive charts, include the Chart.js library on the page (e.g., <script src=\"https://cdn.jsdelivr.net/npm/chart.js@4/dist/chart.umd.min.js\"></script>).');\n return false;\n }\n\n // When the canvas is inside a hidden container (e.g., a widget panel with\n // display:none), it has zero dimensions and Chart.js cannot render correctly.\n // Keep the config in __chartConfigs so renderPendingCharts() can retry later\n // once the container becomes visible.\n if (canvas.offsetParent === null) {\n window.__chartConfigs[chartId] = config;\n return false;\n }\n\n try {\n if (canvas._chartInstance) {\n canvas._chartInstance.destroy();\n }\n\n const cfg = typeof config === 'string' ? JSON.parse(config) : config;\n cfg.options ??= {};\n cfg.options.responsive = true;\n cfg.options.maintainAspectRatio = true;\n cfg.options.aspectRatio ??= 4 / 3;\n\n canvas._chartInstance = new Chart(canvas, cfg);\n delete window.__chartConfigs[chartId];\n return true;\n } catch (e) {\n console.error('Error creating chart:', e);\n return false;\n }\n }\n\n // Global function: renders any chart canvases whose configs are in the\n // global __chartConfigs map. Called by pages (e.g., Chat Interactions)\n // that share the marked instance but have their own rendering pipeline.\n window.renderPendingCharts = function () {\n if (typeof Chart === 'undefined') {\n return;\n }\n\n const configs = window.__chartConfigs;\n if (!configs) {\n return;\n }\n\n requestAnimationFrame(() => {\n for (const chartId of Object.keys(configs)) {\n renderChartOnCanvas(chartId, configs[chartId]);\n }\n });\n };\n\n // Parse markdown content via marked (which natively handles [chart:...] markers\n // through the registered extension) and collect pending chart configs for later\n // Chart.js rendering.\n function parseMarkdownContent(content, message) {\n _pendingCharts = [];\n const html = marked.parse(content, { renderer });\n message._pendingCharts = _pendingCharts.length > 0 ? [..._pendingCharts] : [];\n return DOMPurify.sanitize(html, { ADD_TAGS: ['canvas'], ADD_ATTR: ['target'] });\n }\n\n function compactObject(source) {\n if (!source || typeof source !== 'object') {\n return {};\n }\n\n return Object.fromEntries(\n Object.entries(source).filter(([, value]) => value !== undefined)\n );\n }\n\n function resolveIndicatorTemplate(template, assistantLabel) {\n if (!template) {\n return template;\n }\n\n const encodedAssistantLabel = escapeHtmlEntities(assistantLabel || 'Assistant');\n return template.replace(/\\{\\{\\s*assistantLabel\\s*\\}\\}/g, encodedAssistantLabel);\n }\n\n const initialize = (instanceConfig) => {\n const normalizedInstanceConfig = compactObject(instanceConfig);\n const normalizedWidgetConfig = compactObject(normalizedInstanceConfig.widget);\n const config = Object.assign({}, defaultConfig, normalizedInstanceConfig);\n config.widget = Object.assign({}, defaultConfig.widget || {}, normalizedWidgetConfig);\n config.indicatorTemplate = resolveIndicatorTemplate(config.indicatorTemplate, config.assistantLabel);\n const hasWidgetConfig = !!(normalizedWidgetConfig.chatWidgetContainer && normalizedWidgetConfig.chatWidgetStateName);\n const widgetBehavior = window.coreAIChatWidgetBehavior || null;\n // Keep defaultConfig in sync so renderers use overridden values\n defaultConfig = config;\n\n if (!config.signalRHubUrl) {\n console.error('The signalRHubUrl is required.');\n return;\n }\n\n if (!config.appElementSelector) {\n console.error('The appElementSelector is required.');\n return;\n }\n\n if (!config.chatContainerElementSelector) {\n console.error('The chatContainerElementSelector is required.');\n return;\n }\n\n if (!config.inputElementSelector) {\n console.error('The inputElementSelector is required.');\n return;\n }\n\n if (!config.sendButtonElementSelector) {\n console.error('The sendButtonElementSelector is required.');\n return;\n }\n\n const appDefinition = {\n data() {\n return {\n inputElement: null,\n buttonElement: null,\n chatContainer: null,\n placeholder: null,\n isSessionStarted: false,\n isPlaceholderVisible: true,\n isStreaming: false,\n isNavigatingAway: false,\n autoScroll: true,\n stream: null,\n messages: [],\n notifications: [],\n prompt: '',\n documents: config.existingDocuments || [],\n isUploading: false,\n isDocumentOperationPending: false,\n documentOperationQueue: null,\n uploadErrors: [],\n isDragOver: false,\n documentBar: null,\n metricsEnabled: !!config.metricsEnabled,\n userLabel: config.userLabel,\n assistantLabel: config.assistantLabel,\n thumbsUpTitle: config.thumbsUpTitle,\n thumbsDownTitle: config.thumbsDownTitle,\n copyTitle: config.copyTitle,\n copiedTitle: config.copiedTitle,\n isRecording: false,\n mediaRecorder: null,\n preRecordingPrompt: '',\n micButton: null,\n speechToTextEnabled: config.chatMode === 'AudioInput' || config.chatMode === 'Conversation',\n textToSpeechEnabled: config.chatMode === 'Conversation' || !!config.textToSpeechEnabled,\n ttsVoiceName: config.ttsVoiceName || null,\n audioChunks: [],\n audioPlayQueue: [],\n isPlayingAudio: false,\n currentAudioElement: null,\n currentAudioUrl: null,\n ttsButton: null,\n ttsPlayingMessageIndex: -1,\n ttsAudioCache: {},\n ttsInstanceId: 'ai-chat-' + Math.random().toString(36).slice(2),\n singleResponseMode: !!config.singleResponseMode,\n conversationModeEnabled: config.chatMode === 'Conversation',\n conversationButton: null,\n isConversationMode: false,\n notificationDismissTimers: {},\n pendingSessionPromise: null,\n pendingSessionResolver: null,\n pendingSessionRejector: null,\n pendingSessionTimeoutId: null,\n copiedMessageIndex: -1,\n copyResetTimeoutId: null,\n activeCopyButton: null,\n };\n },\n computed: {\n lastAssistantIndex() {\n for (var i = this.messages.length - 1; i >= 0; i--) {\n if (this.messages[i].role === 'assistant') {\n return i;\n }\n }\n return -1;\n }\n },\n methods: {\n handleBeforeUnload() {\n this.isNavigatingAway = true;\n },\n handleDragOver(e) {\n if (!config.sessionDocumentsEnabled) return;\n e.preventDefault();\n e.stopPropagation();\n this.isDragOver = true;\n var inputArea = this.inputElement ? this.inputElement.closest('.ai-admin-widget-input, .text-bg-light') : null;\n if (inputArea) inputArea.classList.add('ai-chat-drag-over');\n },\n handleDragLeave(e) {\n if (!config.sessionDocumentsEnabled) return;\n e.preventDefault();\n e.stopPropagation();\n this.isDragOver = false;\n var inputArea = this.inputElement ? this.inputElement.closest('.ai-admin-widget-input, .text-bg-light') : null;\n if (inputArea) inputArea.classList.remove('ai-chat-drag-over');\n },\n handleDrop(e) {\n if (!config.sessionDocumentsEnabled) return;\n e.preventDefault();\n e.stopPropagation();\n this.isDragOver = false;\n var inputArea = this.inputElement ? this.inputElement.closest('.ai-admin-widget-input, .text-bg-light') : null;\n if (inputArea) inputArea.classList.remove('ai-chat-drag-over');\n if (e.dataTransfer && e.dataTransfer.files && e.dataTransfer.files.length > 0) {\n this.uploadFiles(Array.from(e.dataTransfer.files));\n }\n },\n triggerFileInput() {\n if (!config.sessionDocumentsEnabled || this.isDocumentOperationPending) return;\n var fileInput = document.getElementById('ai-chat-doc-input');\n if (fileInput) fileInput.click();\n },\n handleFileInputChange(e) {\n var files = e.target.files ? Array.from(e.target.files) : [];\n if (files && files.length > 0) {\n this.uploadFiles(files);\n }\n e.target.value = '';\n },\n queueDocumentOperation(operation) {\n var self = this;\n var previousOperation = this.documentOperationQueue || Promise.resolve();\n var nextOperation = previousOperation\n .catch(function () { })\n .then(async function () {\n self.isDocumentOperationPending = true;\n try {\n return await operation();\n } finally {\n self.isDocumentOperationPending = false;\n }\n });\n\n this.documentOperationQueue = nextOperation.finally(function () {\n if (self.documentOperationQueue === nextOperation) {\n self.documentOperationQueue = null;\n }\n });\n\n return this.documentOperationQueue;\n },\n async uploadFiles(files) {\n if (!config.uploadDocumentUrl) return;\n\n var filesToUpload = Array.isArray(files) ? files.slice() : Array.from(files || []);\n if (filesToUpload.length === 0) return;\n\n return this.queueDocumentOperation(async () => {\n var sessionId = this.getSessionId();\n var profileId = this.getProfileId();\n\n if (!sessionId) {\n try {\n sessionId = await this.ensureSessionForDocuments(profileId);\n } catch (err) {\n console.error('Failed to create a chat session for document upload:', err);\n this.uploadErrors = [{ fileName: '', error: 'Could not create a chat session for the upload.' }];\n this.renderDocumentBar();\n return;\n }\n }\n\n if (!sessionId) {\n console.warn('Cannot upload documents without a session or profile.');\n this.uploadErrors = [{ fileName: '', error: 'Could not create a chat session for the upload.' }];\n this.renderDocumentBar();\n return;\n }\n\n this.isUploading = true;\n this.uploadErrors = [];\n this.renderDocumentBar();\n try {\n var formData = new FormData();\n formData.append('sessionId', sessionId);\n for (var i = 0; i < filesToUpload.length; i++) {\n formData.append('files', filesToUpload[i]);\n }\n\n var response = await fetch(config.uploadDocumentUrl, {\n method: 'POST',\n body: formData\n });\n\n if (!response.ok) {\n var errorText = await response.text();\n var uploadError = this.extractReadableErrorMessage(errorText, 'Upload failed. Please try again.');\n console.error('Upload failed:', errorText);\n this.uploadErrors = [{ fileName: '', error: uploadError }];\n return;\n }\n\n var result = await response.json();\n\n if (result.sessionId && result.sessionId !== this.getSessionId()) {\n this.initializeSession(result.sessionId);\n }\n\n if (Array.isArray(result.documents)) {\n this.documents = result.documents;\n } else if (result.uploaded && result.uploaded.length > 0) {\n this.documents = this.documents.concat(result.uploaded);\n }\n\n if (result.failed && result.failed.length > 0) {\n this.uploadErrors = result.failed;\n }\n } catch (err) {\n console.error('Upload error:', err);\n this.uploadErrors = [{ fileName: '', error: 'Upload failed. Please try again.' }];\n\n if (this.getSessionId()) {\n this.reloadCurrentSession();\n }\n } finally {\n this.isUploading = false;\n this.renderDocumentBar();\n }\n });\n },\n async removeDocument(doc) {\n if (!config.removeDocumentUrl) return;\n\n return this.queueDocumentOperation(async () => {\n try {\n var sessionId = this.getSessionId();\n var response = await fetch(config.removeDocumentUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ itemId: sessionId, documentId: doc.documentId })\n });\n\n if (response.ok) {\n var result = await response.json();\n\n if (Array.isArray(result.documents)) {\n this.documents = result.documents;\n } else {\n var idx = this.documents.indexOf(doc);\n if (idx > -1) {\n this.documents.splice(idx, 1);\n }\n }\n } else {\n var errorText = await response.text();\n var removeError = this.extractReadableErrorMessage(errorText, 'Failed to remove document. Please try again.');\n console.error('Failed to remove document:', response.status, errorText);\n this.uploadErrors = [{ fileName: doc.fileName || '', error: removeError }];\n if (sessionId) {\n this.reloadCurrentSession();\n }\n this.renderDocumentBar();\n }\n } catch (err) {\n console.error('Remove document error:', err);\n this.uploadErrors = [{ fileName: doc.fileName || '', error: 'Failed to remove document. Please try again.' }];\n if (this.getSessionId()) {\n this.reloadCurrentSession();\n }\n this.renderDocumentBar();\n }\n });\n },\n formatFileSize(bytes) {\n if (bytes < 1024) return bytes + ' B';\n if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB';\n return (bytes / (1024 * 1024)).toFixed(1) + ' MB';\n },\n renderDocumentBar() {\n if (!this.documentBar) return;\n\n if (!config.sessionDocumentsEnabled) {\n this.documentBar.classList.add('d-none');\n return;\n }\n\n this.documentBar.classList.remove('d-none');\n\n var html = '<div class=\"ai-chat-doc-bar p-2\">';\n html += '<div class=\"d-flex flex-wrap align-items-center gap-1\">';\n\n for (var i = 0; i < this.documents.length; i++) {\n var doc = this.documents[i];\n var name = doc.fileName || 'Document';\n if (name.length > 20) name = name.substring(0, 17) + '...';\n html += '<span class=\"badge bg-secondary bg-opacity-25 text-dark d-inline-flex align-items-center gap-1 px-2 py-1\" style=\"font-size: 0.8rem;\" title=\"' + this.escapeHtml(doc.fileName || '') + '\">';\n html += '<i class=\"fa-solid fa-file-lines\" style=\"font-size: 0.7rem;\"></i> ';\n html += this.escapeHtml(name);\n html += ' <button type=\"button\" class=\"btn-close btn-close-sm ms-1\" style=\"font-size: 0.5rem;\" data-doc-index=\"' + i + '\" aria-label=\"Remove\"' + (this.isDocumentOperationPending ? ' disabled' : '') + '></button>';\n html += '</span>';\n }\n\n for (var m = 0; m < this.uploadErrors.length; m++) {\n var failedItem = this.uploadErrors[m];\n var failedName = failedItem.fileName || 'File';\n var errorMsg = failedItem.error || 'Upload failed';\n if (failedName.length > 15) failedName = failedName.substring(0, 12) + '...';\n html += '<span class=\"badge bg-danger bg-opacity-25 text-danger d-inline-flex align-items-center gap-1 px-2 py-1\" style=\"font-size: 0.8rem;\" title=\"' + this.escapeHtml((failedItem.fileName || '') + ': ' + errorMsg) + '\">';\n html += '<i class=\"fa-solid fa-circle-exclamation\" style=\"font-size: 0.7rem;\"></i> ';\n html += this.escapeHtml(failedName);\n html += ' <button type=\"button\" class=\"btn-close btn-close-sm ms-1\" style=\"font-size: 0.5rem;\" data-error-index=\"' + m + '\" aria-label=\"Dismiss\"></button>';\n html += '</span>';\n }\n\n if (this.isUploading) {\n html += '<span class=\"badge bg-info bg-opacity-25 text-dark d-inline-flex align-items-center gap-1 px-2 py-1\" style=\"font-size: 0.8rem;\">';\n html += '<span class=\"spinner-border spinner-border-sm\" style=\"width: 0.7rem; height: 0.7rem;\"></span> Uploading...';\n html += '</span>';\n }\n\n html += '<button type=\"button\" class=\"btn btn-sm btn-outline-secondary rounded-pill ai-chat-doc-add-btn d-inline-flex align-items-center gap-1\" style=\"font-size: 0.75rem; padding: 0.15rem 0.5rem;\" title=\"Attach documents\"' + (this.isDocumentOperationPending ? ' disabled' : '') + '>';\n html += '<i class=\"fa-solid fa-paperclip\"></i>';\n if (this.documents.length === 0 && !this.isUploading) {\n html += ' <span>Attach files</span>';\n }\n html += '</button>';\n html += '</div>';\n if (config.supportedExtensionsText) {\n html += '<div class=\"small text-muted mt-2\">Supported formats: ' + this.escapeHtml(config.supportedExtensionsText) + '</div>';\n }\n\n html += '</div>';\n\n this.documentBar.replaceChildren(DOMPurify.sanitize(html, { RETURN_DOM_FRAGMENT: true }));\n\n // Bind remove handlers\n var self = this;\n var closeButtons = this.documentBar.querySelectorAll('[data-doc-index]');\n for (var j = 0; j < closeButtons.length; j++) {\n closeButtons[j].addEventListener('click', (function (idx) {\n return function (e) {\n e.preventDefault();\n e.stopPropagation();\n if (self.isDocumentOperationPending) {\n return;\n }\n\n var docToRemove = self.documents[idx];\n if (docToRemove) self.removeDocument(docToRemove);\n };\n })(parseInt(closeButtons[j].getAttribute('data-doc-index'))));\n }\n\n // Bind error dismiss handlers\n var errorCloseButtons = this.documentBar.querySelectorAll('[data-error-index]');\n for (var n = 0; n < errorCloseButtons.length; n++) {\n errorCloseButtons[n].addEventListener('click', (function (idx) {\n return function (e) {\n e.preventDefault();\n e.stopPropagation();\n self.uploadErrors.splice(idx, 1);\n self.renderDocumentBar();\n };\n })(parseInt(errorCloseButtons[n].getAttribute('data-error-index'))));\n }\n\n // Bind add button\n var addBtn = this.documentBar.querySelector('.ai-chat-doc-add-btn');\n if (addBtn) {\n addBtn.addEventListener('click', function (e) {\n e.preventDefault();\n if (self.isDocumentOperationPending) {\n return;\n }\n self.triggerFileInput();\n });\n }\n },\n escapeHtml(text) {\n var div = document.createElement('div');\n div.textContent = text;\n return div.innerHTML;\n },\n extractReadableErrorMessage(errorText, fallbackMessage) {\n if (!errorText || typeof errorText !== 'string') {\n return fallbackMessage;\n }\n\n var trimmed = errorText.trim();\n if (!trimmed) {\n return fallbackMessage;\n }\n\n if (trimmed.startsWith('{') || trimmed.startsWith('[')) {\n try {\n var parsed = JSON.parse(trimmed);\n var message = parsed?.error || parsed?.message || parsed?.title || parsed?.detail;\n return typeof message === 'string' && message.trim()\n ? message.trim()\n : fallbackMessage;\n } catch (err) {\n return fallbackMessage;\n }\n }\n\n if (/<[^>]+>/.test(trimmed)) {\n return fallbackMessage;\n }\n\n return trimmed;\n },\n normalizeAssistantAppearance(appearance) {\n if (!appearance) {\n return null;\n }\n\n var label = typeof appearance.label === 'string' ? appearance.label.trim() : '';\n var icon = typeof appearance.icon === 'string' ? appearance.icon.trim() : '';\n var cssClass = typeof appearance.cssClass === 'string' ? appearance.cssClass.trim() : '';\n var disableStreamingAnimation = !!appearance.disableStreamingAnimation;\n\n if (!label && !icon && !cssClass && !disableStreamingAnimation) {\n return null;\n }\n\n return {\n label: label,\n icon: icon,\n cssClass: cssClass,\n disableStreamingAnimation: disableStreamingAnimation,\n };\n },\n getAssistantLabel(message) {\n var appearance = message ? this.normalizeAssistantAppearance(message.appearance) : null;\n return appearance && appearance.label ? appearance.label : this.assistantLabel;\n },\n getAssistantRoleClasses(message) {\n var appearance = message ? this.normalizeAssistantAppearance(message.appearance) : null;\n var classes = ['ai-chat-msg-role'];\n\n if (appearance && appearance.cssClass) {\n classes.push(appearance.cssClass);\n } else {\n classes.push('ai-chat-msg-role-assistant');\n }\n\n return classes;\n },\n getAssistantIconClasses(message, index) {\n var appearance = message ? this.normalizeAssistantAppearance(message.appearance) : null;\n return [this.shouldAnimateAssistantIcon(message, index) ? 'ai-streaming-icon' : 'ai-bot-icon', appearance && appearance.cssClass ? appearance.cssClass : ''];\n },\n getAssistantIcon(message) {\n var appearance = message ? this.normalizeAssistantAppearance(message.appearance) : null;\n return appearance && appearance.icon ? appearance.icon : 'fa fa-robot';\n },\n shouldAnimateAssistantIcon(message, index) {\n var appearance = message ? this.normalizeAssistantAppearance(message.appearance) : null;\n return !!message &&\n message.isStreaming &&\n index === this.lastAssistantIndex &&\n !(appearance && appearance.disableStreamingAnimation);\n },\n async startConnection() {\n this.connection = new signalR.HubConnectionBuilder()\n .withUrl(config.signalRHubUrl)\n .withAutomaticReconnect()\n .build();\n\n // Allow long-running operations (e.g., multi-step MCP tool calls)\n // without the client disconnecting prematurely.\n this.connection.serverTimeoutInMilliseconds = 600000;\n this.connection.keepAliveIntervalInMilliseconds = 15000;\n\n this.connection.on(\"LoadSession\", (data) => {\n this.initializeSession(data.sessionId, true);\n this.messages = [];\n this.documents = data.documents || [];\n this.uploadErrors = [];\n\n (data.messages ?? []).forEach(msg => {\n this.addMessage(msg);\n\n this.$nextTick(() => {\n renderChartsInMessage(msg);\n });\n });\n\n // Update feedback icons in the DOM after all messages have rendered.\n this.$nextTick(() => {\n this.refreshAllFeedbackIcons();\n });\n\n // When the session is new (no messages) and an initial prompt is configured,\n // display it as the first assistant message without invoking the AI.\n if (this.messages.length === 0 && config.initialPrompt) {\n this.addMessage({\n role: 'assistant',\n content: config.initialPrompt\n });\n }\n });\n\n this.connection.on(\"ReceiveError\", (error) => {\n console.error(\"SignalR Error: \", error);\n\n if (this.isRecording) {\n this.stopRecording();\n }\n\n // A server-side error (for example a session-start rate-limit rejection) ends the\n // in-flight request. Reject any pending new-session promise so the UI stops waiting\n // until it times out, and clear the typing indicator that a send may have shown.\n this.rejectPendingSessionRequest(error);\n this.hideTypingIndicator();\n\n if (widgetBehavior && typeof widgetBehavior.handleReceiveError === 'function') {\n widgetBehavior.handleReceiveError(this, error, config);\n } else if (!this.isNavigatingAway) {\n // Surface the message to the user instead of failing silently.\n this.addMessage(this.getErrorMessage(error));\n }\n });\n\n this.connection.on(\"ReceiveSessionStartRejected\", (reason) => {\n // A rate-limit rejection is a definitive \"wait and retry\", not a recoverable\n // session/connection error. Unblock any pending new-session request, clear the\n // typing indicator, and show the message for every host (main app and widget)\n // without triggering the widget's clear-and-retry recovery, which would wipe the\n // visitor's state and fire another throttled StartSession.\n this.rejectPendingSessionRequest(reason);\n this.hideTypingIndicator();\n\n if (!this.isNavigatingAway) {\n this.addMessage(this.getErrorMessage(reason));\n }\n });\n\n this.connection.on(\"MessageRated\", (messageId, userRating) => {\n var msg = this.messages.find(m => m.id === messageId);\n if (msg) {\n msg.userRating = userRating;\n }\n });\n\n this.connection.on(\"ReceiveTranscript\", (sessionId, text, isFinal) => {\n if (this.isConversationMode) {\n if (!isFinal && text) {\n this._conversationPartialTranscript = text;\n var escaped = text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n var html = '<p class=\"ai-partial-transcript\">' + escaped + '</p>';\n\n // Show partial transcript as a live user message.\n if (!this._conversationPartialMessage) {\n this.hidePlaceholder();\n this._conversationPartialMessage = {\n role: 'user',\n content: text,\n htmlContent: html,\n isPartial: true\n };\n this.messages.push(this._conversationPartialMessage);\n } else {\n this._conversationPartialMessage.content = text;\n this._conversationPartialMessage.htmlContent = html;\n }\n this.scrollToBottom();\n }\n return;\n }\n\n if (text && !this._audioInputSent) {\n this.prompt = this.preRecordingPrompt + text;\n if (this.inputElement) {\n this.inputElement.value = this.prompt;\n this.inputElement.dispatchEvent(new Event('input'));\n }\n }\n });\n\n this.connection.on(\"ReceiveConversationUserMessage\", (sessionId, text) => {\n if (text) {\n this.stopAudio();\n\n // If there's an interrupted assistant message still streaming,\n // mark it as done to stop the spinner animation.\n if (this._conversationAssistantMessage) {\n var oldMsg = this.messages[this._conversationAssistantMessage.index];\n if (oldMsg) {\n oldMsg.isStreaming = false;\n }\n this._conversationAssistantMessage = null;\n }\n\n // Replace the partial transcript message with the final one.\n if (this._conversationPartialMessage) {\n var escaped = text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n this._conversationPartialMessage.content = text;\n this._conversationPartialMessage.htmlContent = '<p>' + escaped + '</p>';\n this._conversationPartialMessage.isPartial = false;\n this._conversationPartialMessage = null;\n } else {\n this.addMessage({\n role: 'user',\n content: text\n });\n }\n this.scrollToBottom();\n }\n });\n\n this.connection.on(\"ReceiveConversationAssistantToken\", (sessionId, messageId, token, responseId, references, appearance) => {\n if (!this._conversationAssistantMessage) {\n this.stopAudio();\n this.hideTypingIndicator();\n\n // Ensure no stale streaming indicators remain from prior messages.\n for (var j = 0; j < this.messages.length; j++) {\n if (this.messages[j].isStreaming) {\n this.messages[j].isStreaming = false;\n }\n }\n\n var msgIndex = this.messages.length;\n var newMessage = {\n id: messageId,\n role: \"assistant\",\n content: \"\",\n htmlContent: \"\",\n isStreaming: true,\n userRating: null,\n appearance: this.normalizeAssistantAppearance(appearance),\n references: {},\n };\n this.messages.push(newMessage);\n this._conversationAssistantMessage = { index: msgIndex, content: '' };\n }\n\n this._conversationAssistantMessage.content += token;\n var msg = this.messages[this._conversationAssistantMessage.index];\n if (msg) {\n if (!msg.appearance) {\n msg.appearance = this.normalizeAssistantAppearance(appearance);\n }\n msg.rawContent = this._conversationAssistantMessage.content;\n msg.references = normalizeReferences(Object.assign({}, msg.references || {}, references || {}));\n updateMessagePresentation(msg, msg.references);\n this.$nextTick(() => {\n renderChartsInMessage(msg);\n this.scrollToBottom();\n });\n }\n });\n\n this.connection.on(\"ReceiveConversationAssistantComplete\", (sessionId, messageId, references) => {\n if (this._conversationAssistantMessage) {\n var msg = this.messages[this._conversationAssistantMessage.index];\n if (msg) {\n msg.isStreaming = false;\n msg.references = normalizeReferences(Object.assign({}, msg.references || {}, references || {}));\n updateMessagePresentation(msg, msg.references);\n }\n this._conversationAssistantMessage = null;\n }\n });\n\n this.connection.on(\"ReceiveAudioChunk\", (sessionId, base64Audio, contentType) => {\n if (base64Audio) {\n const binaryString = atob(base64Audio);\n const bytes = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n this.audioChunks.push(bytes);\n }\n });\n\n this.connection.on(\"ReceiveAudioComplete\", (sessionId) => {\n this.playCollectedAudio();\n });\n\n this.connection.on(\"ReceiveNotification\", (notification) => {\n this.receiveNotification(notification);\n });\n\n this.connection.on(\"UpdateNotification\", (notification) => {\n this.updateNotification(notification);\n });\n\n this.connection.on(\"RemoveNotification\", (notificationType) => {\n this.removeNotification(notificationType);\n });\n\n this.connection.onreconnecting(() => {\n console.warn(\"SignalR: reconnecting...\");\n });\n\n this.connection.onreconnected(() => {\n console.info(\"SignalR: reconnected.\");\n\n if (this.isSessionStarted) {\n this.reloadCurrentSession();\n }\n });\n\n this.connection.onclose((error) => {\n if (this.isNavigatingAway) {\n return;\n }\n\n if (error) {\n console.warn(\"SignalR connection closed with error:\", error.message || error);\n }\n });\n\n try {\n await this.connection.start();\n } catch (err) {\n console.error(\"SignalR Connection Error: \", err);\n }\n },\n addMessageInternal(message) {\n if (message.role === 'assistant') {\n message.appearance = this.normalizeAssistantAppearance(message.appearance);\n }\n\n if (message.content && !message.htmlContent) {\n message.htmlContent = parseMarkdownContent(message.content, message);\n }\n this.fireEvent(new CustomEvent(\"addingCoreAIPromotMessage\", { detail: { message: message } }));\n this.messages.push(message);\n\n this.$nextTick(() => {\n this.fireEvent(new CustomEvent(\"addedCoreAIPromotMessage\", { detail: { message: message } }));\n });\n },\n addMessage(message) {\n\n // Ensure userRating is always defined for Vue reactivity.\n if (message.userRating === undefined) {\n message.userRating = null;\n }\n\n if (message.content) {\n message.rawContent = message.rawContent ?? message.content;\n updateMessagePresentation(message, message.references);\n }\n\n this.addMessageInternal(message);\n this.hidePlaceholder();\n\n this.$nextTick(() => {\n // Render any pending charts once the DOM is updated\n renderChartsInMessage(message);\n this.scrollToBottom();\n });\n },\n addMessages(messages) {\n\n for (let i = 0; i < messages.length; i++) {\n this.addMessageInternal(messages[i]);\n }\n\n this.hidePlaceholder();\n this.$nextTick(() => {\n this.scrollToBottom();\n });\n },\n hidePlaceholder() {\n if (this.placeholder) {\n this.placeholder.classList.add('d-none');\n }\n this.isPlaceholderVisible = false;\n },\n showPlaceholder() {\n if (this.placeholder) {\n this.placeholder.classList.remove('d-none');\n }\n this.isPlaceholderVisible = true;\n },\n isOrchestratorAvailable() {\n return config.isOrchestratorAvailable !== false;\n },\n applyOrchestratorAvailability() {\n if (this.isOrchestratorAvailable()) {\n return true;\n }\n\n const unavailableMessage = config.orchestratorUnavailableMessage || \"This orchestrator is not currently available.\";\n\n if (this.inputElement) {\n this.inputElement.disabled = true;\n this.inputElement.value = '';\n this.inputElement.placeholder = unavailableMessage;\n }\n\n if (this.buttonElement) {\n this.buttonElement.disabled = true;\n }\n\n if (this.micButtonElement) {\n this.micButtonElement.disabled = true;\n this.micButtonElement.style.display = 'none';\n }\n\n if (this.conversationButtonElement) {\n this.conversationButtonElement.disabled = true;\n this.conversationButtonElement.style.display = 'none';\n }\n\n return false;\n },\n fireEvent(event) {\n document.dispatchEvent(event);\n },\n isIndicator(message) {\n return message.role === 'indicator';\n },\n sendMessage() {\n if (!this.applyOrchestratorAvailability()) {\n return;\n }\n\n let trimmedPrompt = this.prompt.trim();\n\n if (!trimmedPrompt) {\n return;\n }\n\n // Stop any active recording before sending.\n if (this.isRecording) {\n this.stopRecording();\n }\n\n // Prevent stale ReceiveTranscript events from repopulating the prompt.\n this._audioInputSent = true;\n\n // In single-response mode, clear all previous messages.\n if (this.singleResponseMode) {\n this.messages.splice(0, this.messages.length);\n }\n\n this.addMessage({\n role: 'user',\n content: trimmedPrompt\n });\n\n this.streamMessage(this.getProfileId(), trimmedPrompt, null);\n this.inputElement.value = '';\n this.prompt = '';\n },\n startRecording() {\n if (this.isRecording || !this.connection) {\n return;\n }\n\n navigator.mediaDevices.getUserMedia({ audio: { echoCancellation: true, noiseSuppression: true, autoGainControl: true } })\n .then(stream => {\n var mimeType = MediaRecorder.isTypeSupported('audio/ogg;codecs=opus')\n ? 'audio/ogg;codecs=opus'\n : MediaRecorder.isTypeSupported('audio/webm;codecs=opus')\n ? 'audio/webm;codecs=opus'\n : 'audio/webm';\n\n this.mediaRecorder = new MediaRecorder(stream, {\n mimeType: mimeType,\n audioBitsPerSecond: 128000,\n });\n\n this.preRecordingPrompt = this.prompt;\n this._audioInputSent = false;\n\n var subject = new signalR.Subject();\n var profileId = this.getProfileId();\n var sessionId = this.getSessionId() || '';\n var pendingChunk = Promise.resolve();\n\n this.mediaRecorder.addEventListener('dataavailable', (e) => {\n if (e.data && e.data.size > 0) {\n pendingChunk = pendingChunk.then(async () => {\n var data = await e.data.arrayBuffer();\n var uint8Array = new Uint8Array(data);\n var binaryString = uint8Array.reduce(function (str, byte) { return str + String.fromCharCode(byte); }, '');\n var base64 = btoa(binaryString);\n subject.next(base64);\n });\n }\n });\n\n this.mediaRecorder.addEventListener('stop', () => {\n stream.getTracks().forEach(track => track.stop());\n pendingChunk.then(() => subject.complete());\n });\n\n var language = navigator.language || document.documentElement.lang || 'en-US';\n this.connection.send(\"SendAudioStream\", profileId, sessionId, subject, mimeType, language);\n this.mediaRecorder.start(250);\n this.isRecording = true;\n this.updateMicButton();\n })\n .catch(err => {\n console.error('Microphone access denied:', err);\n });\n },\n stopRecording() {\n if (!this.isRecording || !this.mediaRecorder) {\n return;\n }\n\n this.mediaRecorder.stop();\n this.isRecording = false;\n this.updateMicButton();\n },\n toggleRecording() {\n if (this.isRecording) {\n this.stopRecording();\n } else {\n this.startRecording();\n }\n },\n updateMicButton() {\n if (!this.micButton) {\n return;\n }\n\n if (this.isRecording) {\n this.micButton.classList.add('stt-recording');\n this.micButton.innerHTML = '<i class=\"fa-solid fa-stop\"></i>';\n } else {\n this.micButton.classList.remove('stt-recording');\n this.micButton.innerHTML = '<i class=\"fa-solid fa-microphone\"></i>';\n }\n },\n streamMessage(profileId, trimmedPrompt, sessionProfileId) {\n\n if (this.stream) {\n this.stream.dispose();\n this.stream = null;\n }\n\n this.streamingStarted();\n this.showTypingIndicator();\n this.autoScroll = true;\n\n var content = '';\n var references = {};\n var lastResponseId = null;\n\n // Get the index after showing typing indicator.\n var messageIndex = this.messages.length;\n var currentSessionId = this.getSessionId();\n\n this.stream = this.connection.stream(\"SendMessage\", profileId, trimmedPrompt, currentSessionId, sessionProfileId)\n .subscribe({\n next: (chunk) => {\n let message = this.messages[messageIndex];\n\n if (!message) {\n\n if (chunk.sessionId && !currentSessionId) {\n this.initializeSession(chunk.sessionId);\n }\n\n this.hideTypingIndicator();\n // Re-assign the index after hiding the typing indicator.\n messageIndex = this.messages.length;\n let newMessage = {\n id: chunk.messageId,\n role: \"assistant\",\n title: chunk.title,\n content: \"\",\n htmlContent: \"\",\n isStreaming: true,\n userRating: null,\n };\n\n this.messages.push(newMessage);\n\n message = newMessage;\n }\n\n if (chunk.title && (!message.title || message.title !== chunk.title)) {\n message.title = chunk.title;\n }\n\n if (chunk.references && typeof chunk.references === \"object\" && Object.keys(chunk.references).length) {\n\n for (const [key, value] of Object.entries(chunk.references)) {\n references[key] = normalizeReference(value) ?? {};\n }\n }\n\n if (chunk.content) {\n\n // When the responseId changes (e.g., after an internal tool call),\n // insert a line break to visually separate response segments.\n if (chunk.responseId && lastResponseId && chunk.responseId !== lastResponseId) {\n content += '\\n\\n';\n }\n\n if (chunk.responseId) {\n lastResponseId = chunk.responseId;\n }\n\n content += chunk.content;\n }\n\n // Update the existing message\n message.rawContent = content;\n updateMessagePresentation(message, references);\n\n this.messages[messageIndex] = message;\n\n this.$nextTick(() => {\n renderChartsInMessage(message);\n this.scrollToBottom();\n });\n },\n complete: () => {\n this.processReferences(references, messageIndex);\n this.streamingFinished();\n\n let msg = this.messages[messageIndex];\n if (msg) {\n msg.isStreaming = false;\n }\n\n if (!msg || !msg.content) {\n // No content received at all.\n this.hideTypingIndicator();\n }\n\n // Trigger text-to-speech only in conversation mode.\n if (this.isConversationMode && this.textToSpeechEnabled && msg && msg.content) {\n this.synthesizeSpeech(msg.content);\n }\n\n this.stream?.dispose();\n this.stream = null;\n },\n error: (err) => {\n this.processReferences(references, messageIndex);\n this.streamingFinished();\n\n let msg = this.messages[messageIndex];\n if (msg) {\n msg.isStreaming = false;\n }\n\n this.hideTypingIndicator();\n\n if (!this.isNavigatingAway) {\n this.addMessage(this.getServiceDownMessage());\n }\n\n this.stream?.dispose();\n this.stream = null;\n\n console.error(\"Stream error:\", err);\n }\n });\n },\n getServiceDownMessage() {\n let newMessage = {\n role: \"assistant\",\n content: \"Our service is currently unavailable. Please try again later. We apologize for the inconvenience.\",\n htmlContent: \"\",\n };\n\n return newMessage;\n },\n getErrorMessage(error) {\n var content = (typeof error === 'string' && error.trim())\n ? error\n : \"Something went wrong. Please try again.\";\n\n return {\n role: \"assistant\",\n content: content,\n htmlContent: \"\",\n };\n },\n processReferences(references, messageIndex) {\n references = normalizeReferences(references);\n\n if (Object.keys(references).length) {\n\n let message = this.messages[messageIndex];\n message.rawContent = message.rawContent ?? message.content ?? '';\n updateMessagePresentation(message, references);\n\n this.messages[messageIndex] = message;\n\n this.$nextTick(() => {\n renderChartsInMessage(message);\n this.scrollToBottom();\n });\n }\n },\n streamingStarted() {\n var stopIcon = this.buttonElement.getAttribute('data-stop-icon');\n\n if (stopIcon) {\n this.buttonElement.replaceChildren(DOMPurify.sanitize(stopIcon, { RETURN_DOM_FRAGMENT: true }));\n }\n\n if (this.inputElement) {\n this.inputElement.setAttribute('disabled', 'disabled');\n }\n },\n streamingFinished() {\n var startIcon = this.buttonElement.getAttribute('data-start-icon');\n\n if (startIcon) {\n this.buttonElement.replaceChildren(DOMPurify.sanitize(startIcon, { RETURN_DOM_FRAGMENT: true }));\n }\n\n if (this.inputElement) {\n this.inputElement.removeAttribute('disabled');\n this.inputElement.focus();\n }\n\n // Directly manipulate the DOM to stop all streaming animations.\n if (this.chatContainer) {\n var icons = this.chatContainer.querySelectorAll('.ai-streaming-icon');\n for (var i = 0; i < icons.length; i++) {\n icons[i].classList.remove('ai-streaming-icon');\n icons[i].classList.add('ai-bot-icon');\n }\n }\n\n // Also update Vue data for consistency.\n for (var i = 0; i < this.messages.length; i++) {\n if (this.messages[i].isStreaming) {\n this.messages[i].isStreaming = false;\n }\n }\n },\n handleExternalTtsStop(e) {\n if (e?.detail?.sourceId === this.ttsInstanceId) {\n return;\n }\n\n this.stopAudio(false);\n },\n updateTtsPlaybackButtons() {\n if (!this.chatContainer) {\n return;\n }\n\n var buttons = this.chatContainer.querySelectorAll('[data-tts-message-index]');\n\n buttons.forEach(button => {\n var buttonIndex = Number(button.getAttribute('data-tts-message-index'));\n var isPlaying = buttonIndex === this.ttsPlayingMessageIndex;\n\n button.classList.toggle('tts-playing', isPlaying);\n button.setAttribute('title', isPlaying ? 'Pause audio' : 'Read aloud');\n });\n },\n updateCopyButtons() {\n if (!this.chatContainer) {\n return;\n }\n\n var buttons = this.chatContainer.querySelectorAll('[data-copy-message-index]');\n\n buttons.forEach(button => {\n var buttonIndex = Number(button.getAttribute('data-copy-message-index'));\n var isCopied = buttonIndex === this.copiedMessageIndex;\n var iconHtml = isCopied\n ? '<i class=\"fa-solid fa-check\"></i>'\n : '<i class=\"fa-solid fa-copy\"></i>';\n\n button.classList.toggle('text-success', isCopied);\n button.classList.toggle('text-secondary', !isCopied);\n button.setAttribute('title', isCopied ? this.copiedTitle : this.copyTitle);\n button.replaceChildren(DOMPurify.sanitize(iconHtml, { RETURN_DOM_FRAGMENT: true }));\n });\n },\n setCopyButtonState(button, isCopied) {\n if (!button) {\n return;\n }\n\n var iconHtml = isCopied\n ? '<i class=\"fa-solid fa-check\"></i>'\n : '<i class=\"fa-solid fa-copy\"></i>';\n\n button.classList.toggle('text-success', isCopied);\n button.classList.toggle('text-secondary', !isCopied);\n button.setAttribute('title', isCopied ? this.copiedTitle : this.copyTitle);\n button.replaceChildren(DOMPurify.sanitize(iconHtml, { RETURN_DOM_FRAGMENT: true }));\n },\n synthesizeSpeech(text, cacheIndex) {\n if (!this.textToSpeechEnabled || !text || !this.connection) {\n return;\n }\n\n this.audioChunks = [];\n this.isPlayingAudio = true;\n this._ttsCacheIndex = cacheIndex !== undefined ? cacheIndex : -1;\n\n this.connection.invoke(\"SynthesizeSpeech\", this.getProfileId(), this.getSessionId(), text, this.ttsVoiceName)\n .catch(err => {\n console.error(\"TTS synthesis error:\", err);\n this.isPlayingAudio = false;\n this.ttsPlayingMessageIndex = -1;\n this._ttsCacheIndex = -1;\n this.$nextTick(() => this.updateTtsPlaybackButtons());\n });\n },\n toggleMessageTts(message, index) {\n if (this.ttsPlayingMessageIndex === index) {\n this.stopAudio();\n return;\n }\n\n this.stopAudio(false);\n window.dispatchEvent(new CustomEvent('crestapps-ai-chat-stop-tts', {\n detail: { sourceId: this.ttsInstanceId }\n }));\n this.ttsPlayingMessageIndex = index;\n this.$nextTick(() => this.updateTtsPlaybackButtons());\n\n if (this.ttsAudioCache[index]) {\n this.playAudioBlob(this.ttsAudioCache[index]);\n return;\n }\n\n this.synthesizeSpeech(message.content, index);\n },\n playCollectedAudio() {\n if (this.audioChunks.length === 0) {\n if (!this.currentAudioElement && this.audioPlayQueue.length === 0) {\n this.isPlayingAudio = false;\n this.ttsPlayingMessageIndex = -1;\n this.$nextTick(() => this.updateTtsPlaybackButtons());\n }\n return;\n }\n\n const totalLength = this.audioChunks.reduce((sum, chunk) => sum + chunk.length, 0);\n const combined = new Uint8Array(totalLength);\n let offset = 0;\n for (const chunk of this.audioChunks) {\n combined.set(chunk, offset);\n offset += chunk.length;\n }\n this.audioChunks = [];\n\n const blob = new Blob([combined], { type: 'audio/mp3' });\n\n if (this._ttsCacheIndex >= 0) {\n this.ttsAudioCache[this._ttsCacheIndex] = blob;\n this._ttsCacheIndex = -1;\n }\n\n // If audio is already playing, queue this blob for sequential playback.\n if (this.currentAudioElement) {\n this.audioPlayQueue.push(blob);\n return;\n }\n\n this.playAudioBlob(blob);\n },\n playAudioBlob(blob) {\n const url = URL.createObjectURL(blob);\n const audio = new Audio(url);\n\n this.currentAudioUrl = url;\n this.currentAudioElement = audio;\n this.isPlayingAudio = true;\n\n audio.addEventListener('ended', () => {\n this.currentAudioElement = null;\n this.currentAudioUrl = null;\n URL.revokeObjectURL(url);\n this.playNextInQueue();\n });\n\n audio.addEventListener('error', () => {\n this.currentAudioElement = null;\n this.currentAudioUrl = null;\n URL.revokeObjectURL(url);\n this.playNextInQueue();\n });\n\n audio.play().catch(err => {\n console.error(\"Audio playback error:\", err);\n this.currentAudioElement = null;\n this.currentAudioUrl = null;\n URL.revokeObjectURL(url);\n this.audioPlayQueue = [];\n this.isPlayingAudio = false;\n this.ttsPlayingMessageIndex = -1;\n this.$nextTick(() => this.updateTtsPlaybackButtons());\n });\n },\n playNextInQueue() {\n if (this.audioPlayQueue.length > 0) {\n var nextBlob = this.audioPlayQueue.shift();\n this.playAudioBlob(nextBlob);\n } else {\n this.isPlayingAudio = false;\n this.ttsPlayingMessageIndex = -1;\n this.$nextTick(() => this.updateTtsPlaybackButtons());\n this.conversationModeOnAudioEnded();\n }\n },\n stopAudio() {\n if (this.currentAudioElement) {\n this.currentAudioElement.pause();\n this.currentAudioElement.currentTime = 0;\n this.currentAudioElement = null;\n }\n if (this.currentAudioUrl) {\n URL.revokeObjectURL(this.currentAudioUrl);\n this.currentAudioUrl = null;\n }\n this.audioChunks = [];\n this.audioPlayQueue = [];\n this.isPlayingAudio = false;\n this.ttsPlayingMessageIndex = -1;\n this.$nextTick(() => this.updateTtsPlaybackButtons());\n },\n toggleConversationMode() {\n if (this.isConversationMode) {\n this.stopConversationMode();\n } else {\n this.startConversationMode();\n }\n },\n startConversationMode() {\n if (!this.conversationModeEnabled || this.isConversationMode || !this.connection) {\n return;\n }\n\n this.isConversationMode = true;\n this.updateConversationButton();\n this._conversationPartialTranscript = '';\n this._conversationAssistantMessage = null;\n this._conversationPartialMessage = null;\n\n // Remove any previous conversation ended notification.\n this.removeNotification('conversation-ended');\n navigator.mediaDevices.getUserMedia({ audio: { echoCancellation: true, noiseSuppression: true, autoGainControl: true } })\n .then(stream => {\n var mimeType = MediaRecorder.isTypeSupported('audio/ogg;codecs=opus')\n ? 'audio/ogg;codecs=opus'\n : MediaRecorder.isTypeSupported('audio/webm;codecs=opus')\n ? 'audio/webm;codecs=opus'\n : 'audio/webm';\n\n this.mediaRecorder = new MediaRecorder(stream, {\n mimeType: mimeType,\n audioBitsPerSecond: 128000,\n });\n\n this._conversationSubject = new signalR.Subject();\n this._conversationStream = stream;\n\n // Create an AnalyserNode for volume-based interrupt detection.\n // During TTS playback, detect when the user speaks above\n // the threshold to stop TTS (interrupt). Audio chunks are\n // always forwarded — browser echo cancellation handles\n // speaker echo so the STT stream has no gaps.\n var AudioCtx = window.AudioContext || window.webkitAudioContext;\n if (AudioCtx) {\n this._conversationAudioCtx = new AudioCtx();\n this._conversationAnalyser = this._conversationAudioCtx.createAnalyser();\n this._conversationAnalyser.fftSize = 256;\n var micSource = this._conversationAudioCtx.createMediaStreamSource(stream);\n micSource.connect(this._conversationAnalyser);\n }\n\n var pendingChunk = Promise.resolve();\n var analyser = this._conversationAnalyser;\n var interruptVolumeThreshold = 30;\n\n this.mediaRecorder.addEventListener('dataavailable', (e) => {\n if (e.data && e.data.size > 0) {\n // During TTS playback, check mic volume to detect\n // user interruption (speaking above threshold).\n if (this.isPlayingAudio && analyser) {\n var freqData = new Uint8Array(analyser.frequencyBinCount);\n analyser.getByteFrequencyData(freqData);\n var sum = 0;\n for (var k = 0; k < freqData.length; k++) { sum += freqData[k]; }\n var avg = sum / freqData.length;\n\n if (avg >= interruptVolumeThreshold) {\n // User is speaking — interrupt TTS playback.\n this.stopAudio();\n }\n }\n\n // Always send audio to STT — browser echo cancellation\n // handles speaker echo; continuous audio avoids gaps\n // that increase recognition latency.\n pendingChunk = pendingChunk.then(async () => {\n var data = await e.data.arrayBuffer();\n var uint8Array = new Uint8Array(data);\n var binaryString = uint8Array.reduce(function (str, byte) { return str + String.fromCharCode(byte); }, '');\n var base64 = btoa(binaryString);\n try {\n this._conversationSubject.next(base64);\n } catch (err) {\n // Subject may have been completed already.\n }\n });\n }\n });\n\n this.mediaRecorder.addEventListener('stop', () => {\n stream.getTracks().forEach(track => track.stop());\n pendingChunk.then(() => {\n try {\n this._conversationSubject.complete();\n } catch (err) {\n // Already completed.\n }\n });\n });\n\n var profileId = this.getProfileId();\n var sessionId = this.getSessionId() || '';\n var language = navigator.language || document.documentElement.lang || 'en-US';\n\n this.connection.send(\"StartConversation\", profileId, sessionId, this._conversationSubject, mimeType, language);\n this.mediaRecorder.start(250);\n this.isRecording = true;\n })\n .catch(err => {\n console.error('Microphone access denied:', err);\n this.isConversationMode = false;\n this.updateConversationButton();\n });\n },\n stopConversationMode() {\n if (!this.isConversationMode) {\n return;\n }\n\n this.isConversationMode = false;\n this.updateConversationButton();\n\n // Signal the server to cancel all in-progress STT/TTS streams immediately.\n if (this.connection) {\n this.connection.invoke(\"StopConversation\").catch(function () { });\n }\n\n if (this.isRecording && this.mediaRecorder) {\n this.mediaRecorder.stop();\n this.isRecording = false;\n }\n\n this.stopAudio();\n this._conversationPartialTranscript = '';\n this._conversationPartialMessage = null;\n\n // Clean up the AudioContext used for volume monitoring.\n if (this._conversationAudioCtx) {\n this._conversationAudioCtx.close().catch(function () { });\n this._conversationAudioCtx = null;\n this._conversationAnalyser = null;\n }\n\n // Mark any in-flight assistant message as done to stop the spinner.\n if (this._conversationAssistantMessage) {\n var msg = this.messages[this._conversationAssistantMessage.index];\n if (msg) {\n msg.isStreaming = false;\n }\n this._conversationAssistantMessage = null;\n }\n\n // Safety net: clear all lingering streaming indicators.\n for (var i = 0; i < this.messages.length; i++) {\n if (this.messages[i].isStreaming) {\n this.messages[i].isStreaming = false;\n }\n }\n\n // Show a \"conversation ended\" notification system message.\n this.receiveNotification({\n type: 'conversation-ended',\n content: 'Conversation ended.',\n icon: 'fa-solid fa-circle-check',\n dismissible: true,\n autoDismissMs: 5000\n });\n },\n updateConversationButton() {\n if (!this.conversationButton) {\n return;\n }\n\n if (this.isConversationMode) {\n this.conversationButton.classList.add('active', 'btn-primary');\n this.conversationButton.classList.remove('btn-dark', 'btn-outline-dark', 'btn-outline-secondary');\n this.conversationButton.title = this.conversationButton.getAttribute('data-end-title') || 'End Conversation';\n var endHtml = this.conversationButton.getAttribute('data-end-html');\n if (endHtml) {\n this.conversationButton.replaceChildren(DOMPurify.sanitize(endHtml, { RETURN_DOM_FRAGMENT: true }));\n }\n } else {\n this.conversationButton.classList.remove('active', 'btn-primary');\n this.conversationButton.classList.remove('btn-dark', 'btn-outline-secondary');\n this.conversationButton.classList.add('btn-outline-dark');\n this.conversationButton.blur();\n this.conversationButton.title = this.conversationButton.getAttribute('data-start-title') || 'Start Conversation';\n var startHtml = this.conversationButton.getAttribute('data-start-html');\n if (startHtml) {\n this.conversationButton.replaceChildren(DOMPurify.sanitize(startHtml, { RETURN_DOM_FRAGMENT: true }));\n }\n }\n },\n conversationModeSendPrompt() {\n // Legacy: only used by AudioInput mode's ReceiveTranscript.\n },\n conversationModeOnAudioEnded() {\n // Legacy: in conversation mode, audio playback continuation\n // is handled by the persistent stream. This method is only\n // called from playCollectedAudio for non-conversation TTS.\n },\n generatePrompt(element) {\n if (!element) {\n console.error('The element paramter is required.');\n\n return;\n }\n\n let templateProfileId = element.getAttribute('data-profile-id');\n let sessionId = this.getSessionId();\n let sessionProfileId = this.getProfileId();\n\n if (!templateProfileId || !sessionId) {\n\n console.error('The given element is missing data-profile-id or the session has not yet started.');\n return;\n }\n\n // streamMessage() already shows the typing indicator.\n this.streamMessage(templateProfileId, null, sessionProfileId);\n },\n createSessionUrl(baseUrl, param, value) {\n\n const fullUrl = baseUrl.toLowerCase().startsWith('http') ? baseUrl : window.location.origin + baseUrl;\n const url = new URL(fullUrl);\n\n url.searchParams.set(param, value);\n\n return url.toString();\n },\n showTypingIndicator() {\n this.addMessage({\n role: 'indicator',\n htmlContent: config.indicatorTemplate\n });\n },\n hideTypingIndicator() {\n const originalLength = this.messages.length;\n this.messages = this.messages.filter(msg => msg.role !== 'indicator');\n const removedCount = originalLength - this.messages.length;\n return removedCount;\n },\n receiveNotification(notification) {\n if (!notification || !notification.type) {\n return;\n }\n this.clearNotificationDismiss(notification.type);\n var existingIndex = this.notifications.findIndex(n => n.type === notification.type);\n if (existingIndex >= 0) {\n this.notifications.splice(existingIndex, 1, notification);\n } else {\n this.notifications.push(notification);\n }\n this.scheduleNotificationDismiss(notification);\n this.$nextTick(() => {\n this.scrollToBottom();\n });\n },\n updateNotification(notification) {\n if (!notification || !notification.type) {\n return;\n }\n this.clearNotificationDismiss(notification.type);\n var existingIndex = this.notifications.findIndex(n => n.type === notification.type);\n if (existingIndex >= 0) {\n this.notifications.splice(existingIndex, 1, notification);\n this.scheduleNotificationDismiss(notification);\n }\n },\n scheduleNotificationDismiss(notification) {\n if (!notification || !notification.type || !notification.autoDismissMs || notification.autoDismissMs <= 0) {\n return;\n }\n this.notificationDismissTimers[notification.type] = setTimeout(() => {\n this.removeNotification(notification.type);\n }, notification.autoDismissMs);\n },\n clearNotificationDismiss(notificationType) {\n var timerId = this.notificationDismissTimers[notificationType];\n if (!timerId) {\n return;\n }\n clearTimeout(timerId);\n delete this.notificationDismissTimers[notificationType];\n },\n removeNotification(notificationType) {\n this.clearNotificationDismiss(notificationType);\n this.notifications = this.notifications.filter(n => n.type !== notificationType);\n },\n dismissNotification(notificationType) {\n this.removeNotification(notificationType);\n },\n handleNotificationAction(notificationType, actionName) {\n if (!this.connection) {\n return;\n }\n var sessionId = this.getSessionId();\n this.connection.invoke(\"HandleNotificationAction\", sessionId, notificationType, actionName).catch(function (err) {\n console.error(\"Error handling notification action:\", err);\n });\n },\n scrollToBottom() {\n if (!this.autoScroll) {\n return;\n }\n setTimeout(() => {\n this.chatContainer.scrollTop = this.chatContainer.scrollHeight - this.chatContainer.clientHeight;\n }, 50);\n },\n handleUserInput(event) {\n this.prompt = event.target.value;\n },\n getProfileId() {\n return this.inputElement\n ? this.inputElement.getAttribute('data-profile-id')\n : null;\n },\n setSessionId(sessionId) {\n if (!this.inputElement) {\n return;\n }\n\n this.inputElement.setAttribute('data-session-id', sessionId || '');\n },\n resetSession() {\n this.stopRecording();\n this.rejectPendingSessionRequest('Session was reset.');\n this.setSessionId('');\n this.isSessionStarted = false;\n this.sessionRating = null;\n this.messages = [];\n this.documents = [];\n\n // When an initial prompt is configured, show it as the first\n // assistant message instead of the generic placeholder.\n if (config.initialPrompt) {\n this.addMessage({\n role: 'assistant',\n content: config.initialPrompt\n });\n } else {\n this.showPlaceholder();\n }\n\n if (widgetBehavior && typeof widgetBehavior.onSessionReset === 'function') {\n widgetBehavior.onSessionReset(this, config);\n }\n },\n startNewSession() {\n if (!this.applyOrchestratorAvailability()) {\n return;\n }\n\n const profileId = this.getProfileId();\n if (!profileId || !this.connection) {\n return;\n }\n\n this.requestNewSession(profileId).catch(err => console.error(err));\n },\n async ensureSessionForDocuments(profileId) {\n var sessionId = this.getSessionId();\n if (sessionId) {\n return sessionId;\n }\n\n if (!profileId || !this.connection) {\n return null;\n }\n\n return await this.requestNewSession(profileId);\n },\n requestNewSession(profileId) {\n if (this.pendingSessionPromise) {\n return this.pendingSessionPromise;\n }\n\n if (!profileId || !this.connection) {\n return Promise.resolve(null);\n }\n\n this.pendingSessionPromise = new Promise((resolve, reject) => {\n this.pendingSessionResolver = resolve;\n this.pendingSessionRejector = reject;\n this.pendingSessionTimeoutId = window.setTimeout(() => {\n this.rejectPendingSessionRequest('Timed out while creating a chat session.');\n }, 15000);\n });\n\n this.connection.invoke(\"StartSession\", profileId, null).catch(err => {\n this.rejectPendingSessionRequest(err);\n });\n\n return this.pendingSessionPromise;\n },\n resolvePendingSessionRequest(sessionId) {\n if (this.pendingSessionResolver) {\n this.pendingSessionResolver(sessionId);\n }\n\n this.clearPendingSessionRequest();\n },\n rejectPendingSessionRequest(error) {\n if (this.pendingSessionRejector) {\n this.pendingSessionRejector(error);\n }\n\n this.clearPendingSessionRequest();\n },\n clearPendingSessionRequest() {\n if (this.pendingSessionTimeoutId) {\n window.clearTimeout(this.pendingSessionTimeoutId);\n }\n\n this.pendingSessionPromise = null;\n this.pendingSessionResolver = null;\n this.pendingSessionRejector = null;\n this.pendingSessionTimeoutId = null;\n },\n initializeApp() {\n this.inputElement = document.querySelector(config.inputElementSelector);\n this.buttonElement = document.querySelector(config.sendButtonElementSelector);\n this.chatContainer = document.querySelector(config.chatContainerElementSelector);\n this.placeholder = document.querySelector(config.placeholderElementSelector);\n\n if (!this.inputElement || !this.buttonElement || !this.chatContainer || !this.placeholder) {\n console.error('AI chat app could not initialize because one or more required elements were not found.', {\n inputElementSelector: config.inputElementSelector,\n sendButtonElementSelector: config.sendButtonElementSelector,\n chatContainerElementSelector: config.chatContainerElementSelector,\n placeholderElementSelector: config.placeholderElementSelector\n });\n\n return false;\n }\n\n this.applyOrchestratorAvailability();\n\n const sessionId = this.getSessionId();\n if (!hasWidgetConfig && sessionId) {\n this.loadSession(sessionId);\n }\n\n // Initialize document bar if enabled.\n if (config.sessionDocumentsEnabled && config.documentBarSelector) {\n this.documentBar = document.querySelector(config.documentBarSelector);\n if (this.documentBar) {\n this.renderDocumentBar();\n\n // Create hidden file input for document uploads.\n var fileInput = document.createElement('input');\n fileInput.type = 'file';\n fileInput.id = 'ai-chat-doc-input';\n fileInput.className = 'd-none';\n fileInput.multiple = true;\n if (config.allowedExtensions) {\n fileInput.accept = config.allowedExtensions;\n }\n fileInput.addEventListener('change', (e) => this.handleFileInputChange(e));\n this.documentBar.parentElement.appendChild(fileInput);\n\n // Set up drag-and-drop on the input area.\n var inputArea = this.inputElement ? this.inputElement.closest('.ai-admin-widget-input, .text-bg-light') : null;\n if (inputArea) {\n inputArea.addEventListener('dragover', (e) => this.handleDragOver(e));\n inputArea.addEventListener('dragleave', (e) => this.handleDragLeave(e));\n inputArea.addEventListener('drop', (e) => this.handleDrop(e));\n }\n }\n }\n\n // Pause auto-scroll when the user manually scrolls up during streaming.\n this.chatContainer.addEventListener('scroll', () => {\n if (!this.stream) {\n return;\n }\n const threshold = 30;\n const atBottom = this.chatContainer.scrollHeight - this.chatContainer.clientHeight - this.chatContainer.scrollTop <= threshold;\n this.autoScroll = atBottom;\n });\n\n this.inputElement.addEventListener('keydown', event => {\n\n if (this.stream != null) {\n return;\n }\n\n if (event.key === \"Enter\" && !event.shiftKey) {\n event.preventDefault();\n this.buttonElement.click();\n }\n });\n\n this.inputElement.addEventListener('input', (e) => {\n this.handleUserInput(e);\n\n if (e.target.value.trim()) {\n this.buttonElement.removeAttribute('disabled');\n } else {\n this.buttonElement.setAttribute('disabled', true);\n }\n });\n\n this.buttonElement.addEventListener('click', () => {\n\n if (this.stream != null) {\n this.stream.dispose();\n this.stream = null;\n\n this.streamingFinished();\n this.hideTypingIndicator();\n\n // Clean up: remove empty assistant message or stop streaming animation.\n if (this.messages.length > 0) {\n const lastMsg = this.messages[this.messages.length - 1];\n if (lastMsg.role === 'assistant' && !lastMsg.content) {\n this.messages.pop();\n } else if (lastMsg.isStreaming) {\n lastMsg.isStreaming = false;\n }\n }\n\n return;\n }\n\n this.sendMessage();\n });\n\n const promptGenerators = document.getElementsByClassName('profile-generated-prompt');\n\n for (var i = 0; i < promptGenerators.length; i++) {\n promptGenerators[i].addEventListener('click', (e) => {\n e.preventDefault();\n this.generatePrompt(e.target);\n });\n }\n\n const chatSessions = document.getElementsByClassName('chat-session-history-item');\n\n for (var i = 0; i < chatSessions.length; i++) {\n chatSessions[i].addEventListener('click', (e) => {\n e.preventDefault();\n\n var sessionId = e.target.getAttribute('data-session-id');\n\n if (!sessionId) {\n console.error('an element with the class chat-session-history-item with no data-session-id set.');\n\n return;\n }\n\n this.loadSession(sessionId);\n this.showChatScreen();\n });\n }\n\n const initialMessages = Array.isArray(config.messages) ? config.messages : [];\n\n for (let i = 0; i < initialMessages.length; i++) {\n this.addMessage(initialMessages[i]);\n }\n\n // When no messages were loaded and an initial prompt is configured,\n // display it as the first assistant message without invoking the AI.\n if (this.messages.length === 0 && config.initialPrompt) {\n this.addMessage({\n role: 'assistant',\n content: config.initialPrompt\n });\n }\n\n // Update feedback icons in the DOM after initial messages have rendered.\n this.$nextTick(() => {\n this.refreshAllFeedbackIcons();\n });\n\n // Delegate click for code block copy buttons.\n if (this.chatContainer) {\n this.chatContainer.addEventListener('click', (e) => {\n var btn = e.target.closest('.ai-code-copy-btn');\n if (!btn) {\n return;\n }\n\n var block = btn.closest('.ai-code-block') || btn.closest('pre');\n if (!block) {\n return;\n }\n\n var codeEl = block.querySelector('code');\n if (codeEl) {\n navigator.clipboard.writeText(codeEl.textContent);\n var copiedText = config.codeCopiedText || 'Copied!';\n btn.innerHTML = '<i class=\"fa-solid fa-check\"></i> ' + copiedText;\n setTimeout(() => {\n btn.innerHTML = '<i class=\"fa-regular fa-copy\"></i>';\n }, 2000);\n }\n });\n }\n\n // Initialize speech-to-text microphone button.\n if (this.speechToTextEnabled && config.micButtonElementSelector) {\n this.micButton = document.querySelector(config.micButtonElementSelector);\n if (this.micButton) {\n this.micButton.style.display = '';\n this.micButton.addEventListener('click', () => {\n this.toggleRecording();\n });\n }\n }\n\n // Initialize conversation mode button.\n if (this.conversationModeEnabled && config.conversationButtonElementSelector) {\n this.conversationButton = document.querySelector(config.conversationButtonElementSelector);\n if (this.conversationButton) {\n this.conversationButton.addEventListener('click', () => {\n this.toggleConversationMode();\n });\n }\n }\n\n return true;\n },\n loadSession(sessionId) {\n this.connection.invoke(\"LoadSession\", sessionId).catch(err => console.error(err));\n },\n reloadCurrentSession() {\n\n var sessionId = this.getSessionId();\n if (sessionId) {\n this.loadSession(sessionId);\n }\n },\n initializeSession(sessionId, force) {\n if (this.isSessionStarted && !force) {\n if (sessionId && this.getSessionId() === sessionId) {\n this.resolvePendingSessionRequest(sessionId);\n }\n\n return\n }\n this.fireEvent(new CustomEvent(\"initializingSessionCoreAIChat\", { detail: { sessionId: sessionId } }))\n this.setSessionId(sessionId);\n this.isSessionStarted = true;\n this.resolvePendingSessionRequest(sessionId);\n\n if (widgetBehavior && typeof widgetBehavior.onSessionInitialized === 'function') {\n widgetBehavior.onSessionInitialized(this, sessionId, config);\n }\n\n // For non-widget pages, update the browser URL so that a page\n // refresh reloads the correct session instead of starting fresh.\n if (!hasWidgetConfig && sessionId && config.sessionUrlTemplate && typeof history !== 'undefined' && history.replaceState) {\n var sessionUrl = config.sessionUrlTemplate.replace('{sessionId}', encodeURIComponent(sessionId));\n history.replaceState(null, '', sessionUrl);\n }\n },\n getSessionId() {\n let sessionId = this.inputElement\n ? this.inputElement.getAttribute('data-session-id')\n : null;\n\n if (!sessionId && widgetBehavior && typeof widgetBehavior.resolveSessionId === 'function') {\n sessionId = widgetBehavior.resolveSessionId(this, config);\n }\n\n return sessionId;\n },\n clearCopiedMessageState() {\n if (this.copyResetTimeoutId) {\n window.clearTimeout(this.copyResetTimeoutId);\n this.copyResetTimeoutId = null;\n }\n\n if (this.activeCopyButton) {\n this.setCopyButtonState(this.activeCopyButton, false);\n this.activeCopyButton = null;\n }\n\n this.copiedMessageIndex = -1;\n },\n copyResponse(message, index, event) {\n const text = message && typeof message === 'object'\n ? message.copyContent ?? message.content ?? ''\n : message ?? '';\n const button = event?.currentTarget || event?.target?.closest?.('[data-copy-message-index]') || null;\n\n navigator.clipboard.writeText(text)\n .then(() => {\n this.clearCopiedMessageState();\n this.copiedMessageIndex = typeof index === 'number' ? index : -1;\n this.activeCopyButton = button;\n\n if (button) {\n this.setCopyButtonState(button, true);\n } else {\n this.$nextTick(() => this.updateCopyButtons());\n }\n\n this.copyResetTimeoutId = window.setTimeout(() => {\n this.clearCopiedMessageState();\n this.$nextTick(() => this.updateCopyButtons());\n }, Number(config.copyResetDelayMs) || 2000);\n })\n .catch(err => console.error('Failed to copy response:', err));\n },\n updateFeedbackIcons(container, userRating) {\n if (!container) {\n return;\n }\n\n var upBtn = container.querySelector('.rate-up-btn');\n var downBtn = container.querySelector('.rate-down-btn');\n\n // Keep feedback icons as simple span-based Font Awesome markup so\n // later state updates do not depend on i2svg replacement.\n if (upBtn) {\n var upClass = userRating === true ? 'fa-solid fa-thumbs-up' : 'fa-regular fa-thumbs-up';\n var upIcon = document.createElement('span');\n upIcon.className = upClass;\n upIcon.style.fontSize = '0.9rem';\n upBtn.textContent = '';\n upBtn.appendChild(upIcon);\n }\n\n if (downBtn) {\n var downClass = userRating === false ? 'fa-solid fa-thumbs-down' : 'fa-regular fa-thumbs-down';\n var downIcon = document.createElement('span');\n downIcon.className = downClass;\n downIcon.style.fontSize = '0.9rem';\n downBtn.textContent = '';\n downBtn.appendChild(downIcon);\n }\n },\n refreshAllFeedbackIcons() {\n var containers = this.$el.querySelectorAll('.ai-chat-message-assistant-feedback');\n\n for (var i = 0; i < containers.length; i++) {\n var msgId = containers[i].getAttribute('data-message-id');\n var msg = this.messages.find(m => m.id === msgId);\n\n if (msg) {\n this.updateFeedbackIcons(containers[i], msg.userRating);\n }\n }\n },\n rateMessage(message, isPositive, event) {\n var sessionId = this.getSessionId();\n\n if (!sessionId || !message.id || !this.connection) {\n return;\n }\n\n // Toggle: clicking the same rating again clears it.\n var newRating = message.userRating === isPositive ? null : isPositive;\n message.userRating = newRating;\n\n // Find the feedback container by message ID for reliable DOM targeting.\n var feedbackContainer = this.$el.querySelector(\n '.ai-chat-message-assistant-feedback[data-message-id=\"' + message.id + '\"]'\n );\n\n this.updateFeedbackIcons(feedbackContainer, newRating);\n\n // Trigger spark animation after Font Awesome has re-processed icons.\n if (newRating !== null && feedbackContainer) {\n setTimeout(() => {\n var btnClass = isPositive ? '.rate-up-btn' : '.rate-down-btn';\n var btn = feedbackContainer.querySelector(btnClass);\n\n if (btn) {\n btn.classList.remove('spark-effect');\n void btn.offsetWidth;\n btn.classList.add('spark-effect');\n btn.addEventListener('animationend', function onEnd() {\n btn.removeEventListener('animationend', onEnd);\n btn.classList.remove('spark-effect');\n });\n }\n }, 50);\n }\n\n this.connection.invoke(\"RateMessage\", sessionId, message.id, isPositive).catch(function (err) {\n console.error('Failed to rate message:', err);\n });\n }\n },\n watch: {\n documents: {\n handler() {\n this.renderDocumentBar();\n if (widgetBehavior && typeof widgetBehavior.onDocumentsChanged === 'function') {\n widgetBehavior.onDocumentsChanged(this, this.documents, config);\n }\n },\n deep: true\n },\n isUploading() { this.renderDocumentBar(); },\n isDocumentOperationPending() { this.renderDocumentBar(); },\n isPlayingAudio() {\n // Reserved for future use — volume-based interrupt detection\n // no longer mutes tracks; browser echo cancellation handles echo.\n },\n copiedMessageIndex() {\n this.$nextTick(() => this.updateCopyButtons());\n },\n isConversationMode(active) {\n // Hide/show mic button.\n if (this.micButton) {\n this.micButton.style.display = active ? 'none' : (this.speechToTextEnabled ? '' : 'none');\n }\n\n // Hide/show send button.\n if (this.buttonElement) {\n this.buttonElement.style.display = active ? 'none' : '';\n }\n\n // Disable/enable textarea.\n if (this.inputElement) {\n this.inputElement.disabled = active;\n if (active) {\n this.inputElement.placeholder = '';\n }\n }\n }\n },\n mounted() {\n (async () => {\n await this.startConnection();\n const isInitialized = this.initializeApp();\n if (isInitialized && hasWidgetConfig && widgetBehavior && typeof widgetBehavior.onMounted === 'function') {\n widgetBehavior.onMounted(this, config);\n }\n\n this.$nextTick(() => {\n this.updateCopyButtons();\n refreshFontAwesomeIcons(this.$el);\n this.fontAwesomeObserver = observeFontAwesomeIcons(this.$el);\n });\n })();\n\n window.addEventListener('beforeunload', this.handleBeforeUnload);\n window.addEventListener('crestapps-ai-chat-stop-tts', this.handleExternalTtsStop);\n },\n beforeUnmount() {\n window.removeEventListener('beforeunload', this.handleBeforeUnload);\n window.removeEventListener('crestapps-ai-chat-stop-tts', this.handleExternalTtsStop);\n\n if (this.fontAwesomeObserver) {\n this.fontAwesomeObserver.disconnect();\n this.fontAwesomeObserver = null;\n }\n\n this.clearCopiedMessageState();\n this.stopAudio(false);\n\n if (this.stream) {\n this.stream.dispose();\n this.stream = null;\n }\n if (this.connection) {\n this.connection.stop();\n }\n\n if (widgetBehavior && typeof widgetBehavior.onBeforeUnmount === 'function') {\n widgetBehavior.onBeforeUnmount(this, config);\n }\n },\n template: config.messageTemplate\n };\n\n const app = Vue.createApp(appDefinition).mount(config.appElementSelector);\n\n if (widgetBehavior && typeof widgetBehavior.attach === 'function') {\n widgetBehavior.attach(app, config);\n }\n\n return app;\n };\n\n const autoInitializeSelector = '[data-coreai-chat-config],[data-coreai-chat-app-element-selector]';\n\n function getAttributeValue(element, attributeName) {\n const value = element.getAttribute(attributeName);\n return value === null || value === '' ? null : value;\n }\n\n function parseBooleanAttributeValue(value) {\n if (value === null || value === undefined) {\n return null;\n }\n\n if (typeof value === 'boolean') {\n return value;\n }\n\n const normalized = String(value).trim().toLowerCase();\n if (normalized === 'true') {\n return true;\n }\n\n if (normalized === 'false') {\n return false;\n }\n\n return null;\n }\n\n function parseJsonAttribute(element, attributeName, description) {\n const rawValue = getAttributeValue(element, attributeName);\n if (!rawValue) {\n return null;\n }\n\n try {\n return JSON.parse(rawValue);\n } catch (error) {\n console.error('Failed to parse ' + description + ' JSON.', error);\n return null;\n }\n }\n\n function buildConfigFromDataAttributes(element, options) {\n const settings = options || {};\n\n if (element.hasAttribute('data-coreai-chat-widget-container-selector') && settings.allowWidgetHost !== true) {\n return null;\n }\n\n const appElementSelector = getAttributeValue(element, 'data-coreai-chat-app-element-selector');\n if (!appElementSelector) {\n return null;\n }\n\n const config = {\n signalRHubUrl: getAttributeValue(element, 'data-coreai-chat-signalr-hub-url'),\n appElementSelector: appElementSelector,\n chatContainerElementSelector: getAttributeValue(element, 'data-coreai-chat-container-element-selector'),\n inputElementSelector: getAttributeValue(element, 'data-coreai-chat-input-element-selector'),\n sendButtonElementSelector: getAttributeValue(element, 'data-coreai-chat-send-button-element-selector'),\n placeholderElementSelector: getAttributeValue(element, 'data-coreai-chat-placeholder-element-selector'),\n messages: parseJsonAttribute(element, 'data-coreai-chat-messages', 'CoreAI chat messages') ?? undefined,\n chatMode: getAttributeValue(element, 'data-coreai-chat-mode'),\n micButtonElementSelector: getAttributeValue(element, 'data-coreai-chat-mic-button-element-selector'),\n conversationButtonElementSelector: getAttributeValue(element, 'data-coreai-chat-conversation-button-element-selector'),\n ttsVoiceName: getAttributeValue(element, 'data-coreai-chat-tts-voice-name'),\n documentBarSelector: getAttributeValue(element, 'data-coreai-chat-document-bar-selector'),\n uploadDocumentUrl: getAttributeValue(element, 'data-coreai-chat-upload-document-url'),\n removeDocumentUrl: getAttributeValue(element, 'data-coreai-chat-remove-document-url'),\n allowedExtensions: getAttributeValue(element, 'data-coreai-chat-allowed-extensions'),\n supportedExtensionsText: getAttributeValue(element, 'data-coreai-chat-supported-extensions-text'),\n existingDocuments: parseJsonAttribute(element, 'data-coreai-chat-existing-documents', 'CoreAI chat existing documents') ?? undefined,\n initialPrompt: getAttributeValue(element, 'data-coreai-chat-initial-prompt'),\n sessionUrlTemplate: getAttributeValue(element, 'data-coreai-chat-session-url-template'),\n userLabel: getAttributeValue(element, 'data-coreai-chat-user-label'),\n assistantLabel: getAttributeValue(element, 'data-coreai-chat-assistant-label'),\n copyTitle: getAttributeValue(element, 'data-coreai-chat-copy-title'),\n copiedTitle: getAttributeValue(element, 'data-coreai-chat-copied-title'),\n };\n\n const booleanAttributes = {\n metricsEnabled: 'data-coreai-chat-metrics-enabled',\n textToSpeechEnabled: 'data-coreai-chat-text-to-speech-enabled',\n sessionDocumentsEnabled: 'data-coreai-chat-session-documents-enabled',\n singleResponseMode: 'data-coreai-chat-single-response-mode',\n };\n\n Object.keys(booleanAttributes).forEach(key => {\n const parsed = parseBooleanAttributeValue(getAttributeValue(element, booleanAttributes[key]));\n if (parsed !== null) {\n config[key] = parsed;\n }\n });\n\n return compactObject(config);\n }\n\n function buildConfigFromElement(element, options) {\n const jsonConfig = parseJsonAttribute(element, 'data-coreai-chat-config', 'CoreAI chat config');\n const attributeConfig = buildConfigFromDataAttributes(element, options);\n\n if (!jsonConfig && !attributeConfig) {\n return null;\n }\n\n return Object.assign({}, jsonConfig || {}, attributeConfig || {});\n }\n\n function initializeFromElement(element) {\n if (!element || element.dataset.coreAiChatInitialized === 'true') {\n return element ? element.__coreAIChatApp || null : null;\n }\n\n const config = buildConfigFromElement(element);\n if (!config) {\n return null;\n }\n\n const app = initialize(config);\n if (!app) {\n return null;\n }\n\n element.dataset.coreAiChatInitialized = 'true';\n element.__coreAIChatApp = app;\n\n return app;\n }\n\n function scanForAutoInitialization(root) {\n if (!root || typeof root.querySelectorAll !== 'function') {\n return;\n }\n\n if (typeof root.matches === 'function' && root.matches(autoInitializeSelector)) {\n initializeFromElement(root);\n }\n\n root.querySelectorAll(autoInitializeSelector).forEach(initializeFromElement);\n }\n\n function startAutoInitialization() {\n scanForAutoInitialization(document);\n\n if (typeof MutationObserver === 'undefined') {\n return;\n }\n\n const observer = new MutationObserver(mutations => {\n mutations.forEach(mutation => {\n mutation.addedNodes.forEach(node => {\n if (node && node.nodeType === 1) {\n scanForAutoInitialization(node);\n }\n });\n });\n });\n\n observer.observe(document.body, {\n childList: true,\n subtree: true,\n });\n }\n\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', startAutoInitialization, { once: true });\n } else {\n startAutoInitialization();\n }\n\n return {\n initialize: initialize,\n initializeFromElement: initializeFromElement,\n buildConfigFromElement: buildConfigFromElement,\n };\n}();\n\n// Download chart as image via event delegation (DOMPurify strips inline onclick).\ndocument.addEventListener('click', function (e) {\n const btn = e.target.closest('.download-chart-btn');\n if (!btn) {\n return;\n }\n const chartId = btn.getAttribute('data-chart-id');\n const canvas = chartId ? document.getElementById(chartId) : null;\n if (!canvas) {\n console.error('Chart canvas not found:', chartId);\n return;\n }\n const link = document.createElement('a');\n link.download = 'chart-' + chartId + '.png';\n link.href = canvas.toDataURL('image/png');\n link.click();\n});\n\n// Intercept download clicks for data-URI images and convert to blob downloads.\ndocument.addEventListener('click', function (e) {\n const link = e.target.closest('.ai-download-image');\n if (!link) {\n return;\n }\n\n const container = link.closest('.generated-image-container');\n const img = container?.querySelector('img');\n if (!img) {\n return;\n }\n\n const src = img.src;\n if (!src || !src.startsWith('data:')) {\n return; // Normal URL – let the default <a> behaviour handle it.\n }\n\n e.preventDefault();\n\n fetch(src)\n .then(function (res) { return res.blob(); })\n .then(function (blob) {\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = link.getAttribute('download') || 'generated-image.png';\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n setTimeout(function () { URL.revokeObjectURL(url); }, 100);\n })\n .catch(function (err) { console.error('Failed to download image:', err); });\n});\n"]}
1
+ {"version":3,"sources":["ai-chat.js"],"names":["_excluded","_regenerator","e","t","r","Symbol","n","iterator","o","toStringTag","i","c","prototype","Generator","u","Object","create","_regeneratorDefine2","f","p","y","G","v","a","d","bind","length","l","TypeError","call","done","value","GeneratorFunction","GeneratorFunctionPrototype","getPrototypeOf","this","setPrototypeOf","__proto__","displayName","w","m","defineProperty","_invoke","enumerable","configurable","writable","asyncGeneratorStep","Promise","resolve","then","_asyncToGenerator","arguments","apply","_next","_throw","_toConsumableArray","_arrayWithoutHoles","_iterableToArray","_unsupportedIterableToArray","_nonIterableSpread","Array","from","isArray","_arrayLikeToArray","_objectWithoutProperties","_objectWithoutPropertiesLoose","getOwnPropertySymbols","indexOf","propertyIsEnumerable","hasOwnProperty","_createForOfIteratorHelper","_n","F","s","next","_slicedToArray","_arrayWithHoles","_iterableToArrayLimit","_nonIterableRest","toString","slice","constructor","name","test","push","_typeof","window","coreAIChatManager","defaultConfig","generatedImageAltText","generatedImageMaxWidth","downloadImageTitle","downloadChartTitle","downloadChartButtonText","userLabel","assistantLabel","thumbsUpTitle","thumbsDownTitle","copyTitle","copiedTitle","codeCopiedText","copyResetDelayMs","widget","chatWidgetContainer","chatWidgetStateName","chatHistorySection","showHistoryButton","closeHistoryButton","newChatButton","toggleButtonSelector","resetSizeButtonSelector","dragHandleSelector","enableDragging","enableResizing","persistLayout","defaultWidth","defaultHeight","minWidth","minHeight","messageTemplate","indicatorTemplate","sanitizeUrl","url","trimmed","trim","escapeHtmlEntities","text","span","document","createElement","textContent","innerHTML","refreshFontAwesomeIcons","root","fontAwesome","FontAwesome","nodeType","selector","matches","querySelector","containsFontAwesomePlaceholders","dom","i2svg","node","observeFontAwesomeIcons","MutationObserver","observer","mutations","forEach","mutation","addedNodes","observe","childList","subtree","normalizeReference","reference","_ref","_normalized$index","_ref2","_normalized$text","_ref3","_normalized$title","_ref4","_normalized$link","_ref5","_normalized$reference","_normalized$isGenerat","normalized","assign","index","Index","Text","title","Title","link","Link","referenceType","ReferenceType","isGenerated","IsGenerated","isDownloadCitationReference","toLowerCase","normalizeReferences","references","_i","_Object$entries","entries","_normalizeReference","_Object$entries$_i","key","getCitationLabel","updateMessagePresentation","message","messageReferences","rawContent","content","citationDisplay","processedContent","referenceEntries","citations","citedRefs","filter","_ref6","includes","generatedRefs","_ref8","_ref9","sort","_ref0","_ref1","b","_ref12","_ref13","_step","displayIndex","_iterator","_step$value","placeholder","concat","replaceAll","referenceKey","label","isDownload","err","_i2","_citations","citation","_step2","_iterator2","_step2$value","map","_ref16","buildCitationDisplay","displayContent","citationReferences","copyContent","_step3","_iterator3","_step4","_iterator4","trimEnd","buildCopyContent","htmlContent","parseMarkdownContent","renderer","marked","Renderer","data","href","code","lang","highlighted","hljs","getLanguage","highlight","language","_","highlightAuto","langDisplay","image","src","alt","maxWidth","chartCounter","_pendingCharts","renderChartsInMessage","charts","requestAnimationFrame","_step5","_iterator5","renderChartOnCanvas","chartId","config","canvas","getElementById","Chart","console","warn","offsetParent","__chartConfigs","_cfg$options","_cfg$options2","_cfg$options2$aspectR","_chartInstance","destroy","cfg","JSON","parse","options","responsive","maintainAspectRatio","aspectRatio","error","html","DOMPurify","sanitize","ADD_TAGS","ADD_ATTR","compactObject","source","fromEntries","_ref17","undefined","use","extensions","level","start","idx","tokenizer","extracted","token","jsonStart","depth","inString","escape","ch","jsonEnd","closeBracketIndex","startIndex","endIndex","json","substring","tryExtractChartMarker","type","raw","renderPendingCharts","configs","_i3","_Object$keys","keys","initialize","instanceConfig","normalizedInstanceConfig","normalizedWidgetConfig","template","encodedAssistantLabel","replace","resolveIndicatorTemplate","hasWidgetConfig","widgetBehavior","coreAIChatWidgetBehavior","signalRHubUrl","appElementSelector","chatContainerElementSelector","inputElementSelector","sendButtonElementSelector","appDefinition","inputElement","buttonElement","chatContainer","isSessionStarted","isPlaceholderVisible","isStreaming","isNavigatingAway","autoScroll","stream","messages","notifications","prompt","documents","existingDocuments","isUploading","isDocumentOperationPending","documentOperationQueue","uploadErrors","isDragOver","documentBar","metricsEnabled","isRecording","mediaRecorder","preRecordingPrompt","micButton","speechToTextEnabled","chatMode","textToSpeechEnabled","ttsVoiceName","audioChunks","audioPlayQueue","isPlayingAudio","currentAudioElement","currentAudioUrl","ttsButton","ttsPlayingMessageIndex","ttsAudioCache","ttsInstanceId","Math","random","singleResponseMode","conversationModeEnabled","realtimeEnabled","realtimeWebRtcEnabled","RTCPeerConnection","realtimeWebRtcIceServers","realtimeVoiceName","conversationButton","isConversationMode","notificationDismissTimers","pendingSessionPromise","pendingSessionResolver","pendingSessionRejector","pendingSessionTimeoutId","copiedMessageIndex","copyResetTimeoutId","activeCopyButton","computed","lastAssistantIndex","role","methods","handleBeforeUnload","handleDragOver","sessionDocumentsEnabled","preventDefault","stopPropagation","inputArea","closest","classList","add","handleDragLeave","remove","handleDrop","dataTransfer","files","uploadFiles","triggerFileInput","fileInput","click","handleFileInputChange","target","queueDocumentOperation","operation","self","nextOperation","_callee","_context","_this","_callee3","filesToUpload","_context3","uploadDocumentUrl","_callee2","sessionId","profileId","formData","response","errorText","uploadError","result","_t","_t2","_context2","getSessionId","getProfileId","ensureSessionForDocuments","fileName","renderDocumentBar","FormData","append","fetch","method","body","ok","extractReadableErrorMessage","initializeSession","uploaded","failed","reloadCurrentSession","removeDocument","doc","_this2","_callee5","_context5","removeDocumentUrl","_callee4","removeError","_t3","_context4","headers","stringify","itemId","documentId","splice","status","formatFileSize","bytes","toFixed","escapeHtml","failedItem","failedName","errorMsg","supportedExtensionsText","replaceChildren","RETURN_DOM_FRAGMENT","closeButtons","querySelectorAll","j","addEventListener","docToRemove","parseInt","getAttribute","errorCloseButtons","addBtn","div","fallbackMessage","startsWith","parsed","detail","normalizeAssistantAppearance","appearance","icon","cssClass","disableStreamingAnimation","getAssistantLabel","getAssistantRoleClasses","classes","getAssistantIconClasses","shouldAnimateAssistantIcon","getAssistantIcon","startConnection","_this3","_callee6","_t4","_context6","connection","signalR","HubConnectionBuilder","withUrl","withAutomaticReconnect","build","serverTimeoutInMilliseconds","keepAliveIntervalInMilliseconds","on","_data$messages","forceStopActiveVoice","msg","addMessage","$nextTick","refreshAllFeedbackIcons","initialPrompt","stopRecording","rejectPendingSessionRequest","hideTypingIndicator","handleReceiveError","getErrorMessage","reason","messageId","userRating","find","id","isFinal","_conversationPartialTranscript","_conversationPartialMessage","hidePlaceholder","isPartial","scrollToBottom","_audioInputSent","dispatchEvent","Event","turnId","_realtimePendingTurns","pending","stopAudio","fillRealtimePendingTurn","escaped","_conversationAssistantMessage","at","userMsg","responseId","_conversationAssistantResponseId","prev","msgIndex","newMessage","base64Audio","contentType","binaryString","atob","Uint8Array","charCodeAt","realtimeController","receivePcm","playCollectedAudio","notification","receiveNotification","updateNotification","notificationType","removeNotification","onreconnecting","stopRealtimeConversation","onreconnected","info","onclose","ensureConnectionStarted","_this4","_callee7","states","_t5","_context7","HubConnectionState","state","Connected","Disconnected","settle","clearTimeout","timeoutId","clearInterval","intervalId","setTimeout","setInterval","addMessageInternal","_this5","fireEvent","CustomEvent","_message$rawContent","_this6","addMessages","_this7","showPlaceholder","isOrchestratorAvailable","applyOrchestratorAvailability","unavailableMessage","orchestratorUnavailableMessage","disabled","micButtonElement","style","display","conversationButtonElement","event","isIndicator","sendMessage","trimmedPrompt","streamMessage","startRecording","_this8","navigator","mediaDevices","getUserMedia","audio","echoCancellation","noiseSuppression","autoGainControl","subject","Subject","_sttCapture","_createPcmCapture","base64","_sttSubject","rate","sampleRate","documentElement","send","updateMicButton","_stopPcmCapture","complete","onChunk","audioContext","AudioCtx","AudioContext","webkitAudioContext","srcRate","createMediaStreamSource","processor","createScriptProcessor","onaudioprocess","input","inputBuffer","getChannelData","pcm16","_downsampleToInt16","sum","rms","sqrt","buffer","binary","String","fromCharCode","btoa","connect","destination","capture","disconnect","getTracks","stop","close","dstRate","same","Int16Array","max","min","ratio","newLen","floor","out","i0","i1","frac","toggleRecording","sessionProfileId","_this9","dispose","streamingStarted","showTypingIndicator","lastResponseId","messageIndex","currentSessionId","subscribe","chunk","_i4","_Object$entries2","_normalizeReference2","_Object$entries2$_i","_this9$stream","processReferences","streamingFinished","synthesizeSpeech","_this9$stream2","getServiceDownMessage","_this0","_ref22","_message$rawContent2","stopIcon","setAttribute","startIcon","removeAttribute","focus","icons","handleExternalTtsStop","_e$detail","sourceId","updateTtsPlaybackButtons","_this1","button","isPlaying","Number","toggle","updateCopyButtons","_this10","isCopied","iconHtml","setCopyButtonState","cacheIndex","_this11","_ttsCacheIndex","invoke","toggleMessageTts","_this12","playAudioBlob","_this13","_step6","totalLength","reduce","combined","offset","_iterator6","set","blob","Blob","_this14","URL","createObjectURL","Audio","revokeObjectURL","playNextInQueue","play","_this15","nextBlob","shift","conversationModeOnAudioEnded","_this16","pause","currentTime","toggleConversationMode","stopConversationMode","startConversationMode","startRealtimeConversation","setupRealtimeController","CoreAIRealtime","attach","ensureConnected","connected","Error","sendStart","voice","silenceMs","vadThreshold","allowInterruption","webRtcEnabled","sendStartWebRtc","offerSdp","webRtcIceServers","voiceName","getVoiceName","selectors","realtimeButton","conversationButtonElementSelector","onActivate","onDeactivate","finishRealtimeConversationCleanup","onUserTurnPending","addRealtimePendingTurn","onUserTurnDropped","dropRealtimePendingTurn","dismissible","autoDismissMs","emptyAt","dropped","_this17","updateConversationButton","_conversationSubject","_conversationStream","_conversationCapture","endHtml","blur","startHtml","conversationModeSendPrompt","generatePrompt","element","templateProfileId","createSessionUrl","baseUrl","param","fullUrl","location","origin","searchParams","originalLength","_this18","clearNotificationDismiss","existingIndex","findIndex","scheduleNotificationDismiss","_this19","timerId","dismissNotification","handleNotificationAction","actionName","_this20","scrollTop","scrollHeight","clientHeight","handleUserInput","setSessionId","resetSession","sessionRating","onSessionReset","startNewSession","requestNewSession","_this21","_callee8","_context8","_this22","reject","resolvePendingSessionRequest","clearPendingSessionRequest","initializeApp","_this23","placeholderElementSelector","loadSession","documentBarSelector","className","multiple","allowedExtensions","accept","parentElement","appendChild","atBottom","shiftKey","lastMsg","pop","promptGenerators","getElementsByClassName","chatSessions","showChatScreen","initialMessages","btn","block","codeEl","clipboard","writeText","copiedText","micButtonElementSelector","force","onSessionInitialized","sessionUrlTemplate","history","replaceState","sessionUrl","encodeURIComponent","resolveSessionId","clearCopiedMessageState","copyResponse","_ref23","_message$copyContent","_event$target","_event$target$closest","_this24","currentTarget","updateFeedbackIcons","container","upBtn","downBtn","upClass","upIcon","fontSize","downClass","downIcon","containers","$el","msgId","rateMessage","isPositive","newRating","feedbackContainer","btnClass","offsetWidth","onEnd","removeEventListener","watch","handler","onDocumentsChanged","deep","_this25","active","mounted","_this26","_callee9","_context9","onMounted","fontAwesomeObserver","beforeUnmount","onBeforeUnmount","app","Vue","createApp","mount","autoInitializeSelector","getAttributeValue","attributeName","parseJsonAttribute","description","rawValue","buildConfigFromDataAttributes","_parseJsonAttribute","_parseJsonAttribute2","settings","hasAttribute","allowWidgetHost","booleanAttributes","parseBooleanAttributeValue","buildConfigFromElement","jsonConfig","attributeConfig","initializeFromElement","dataset","coreAiChatInitialized","__coreAIChatApp","scanForAutoInitialization","startAutoInitialization","readyState","once","download","toDataURL","img","res","removeChild"],"mappings":"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","file":"ai-chat.min.js","sourcesContent":["window.coreAIChatManager = function () {\n\n // Defaults (can be overridden by instanceConfig)\n var defaultConfig = {\n // UI defaults for generated media\n generatedImageAltText: 'Generated Image',\n generatedImageMaxWidth: 400,\n downloadImageTitle: 'Download image',\n downloadChartTitle: 'Download chart as image',\n downloadChartButtonText: 'Download',\n userLabel: 'You',\n assistantLabel: 'Assistant',\n thumbsUpTitle: 'Thumbs up',\n thumbsDownTitle: 'Thumbs down',\n copyTitle: 'Click here to copy response to clipboard.',\n copiedTitle: 'Response copied to clipboard.',\n codeCopiedText: 'Copied!',\n copyResetDelayMs: 2000,\n widget: {\n chatWidgetContainer: null,\n chatWidgetStateName: null,\n chatHistorySection: null,\n showHistoryButton: null,\n closeHistoryButton: null,\n newChatButton: null,\n toggleButtonSelector: null,\n resetSizeButtonSelector: null,\n dragHandleSelector: '.ai-chat-widget-header',\n enableDragging: true,\n enableResizing: true,\n persistLayout: true,\n defaultWidth: null,\n defaultHeight: null,\n minWidth: 320,\n minHeight: 420\n },\n messageTemplate: `\n <div class=\"ai-chat-messages\">\n <div v-for=\"(message, index) in messages\" :key=\"'msg-' + index\" class=\"ai-chat-message-item\">\n <div>\n <div v-if=\"message.role === 'user'\" class=\"ai-chat-message-heading ai-chat-message-heading-user\">\n <span class=\"ai-chat-msg-role ai-chat-msg-role-user\">{{ userLabel }}</span>\n </div>\n <div v-else-if=\"message.role !== 'indicator'\" class=\"ai-chat-message-heading ai-chat-message-heading-assistant\">\n <div :class=\"getAssistantRoleClasses(message)\">\n <span :class=\"getAssistantIconClasses(message, index)\"><i :class=\"getAssistantIcon(message)\"></i></span>\n <span class=\"ai-chat-message-role-label\">{{ getAssistantLabel(message) }}</span>\n </div>\n </div>\n <div class=\"ai-chat-message-body lh-base\">\n <h4 v-if=\"message.title\">{{ message.title }}</h4>\n <div v-html=\"message.htmlContent\"></div>\n <ol v-if=\"message.citationReferences && message.citationReferences.length\" class=\"ai-chat-citation-list\">\n <li v-for=\"citation in message.citationReferences\" :key=\"'citation-' + (citation.referenceKey || citation.displayIndex)\" class=\"ai-chat-citation-item\">\n <a v-if=\"citation.link\" :href=\"citation.link\" :target=\"citation.isDownload ? null : '_blank'\" :rel=\"citation.isDownload ? null : 'noopener noreferrer'\">{{ citation.label }}</a>\n <span v-else>{{ citation.label }}</span>\n </li>\n </ol>\n <span class=\"message-buttons-container\" v-if=\"!isIndicator(message)\">\n <template v-if=\"metricsEnabled && message.role === 'assistant'\">\n <span class=\"ai-chat-message-assistant-feedback\" :data-message-id=\"message.id\">\n <button type=\"button\" class=\"btn btn-sm btn-link text-success p-0 me-2 button-message-toolbox rate-up-btn\" @click=\"rateMessage(message, true, $event)\" :title=\"thumbsUpTitle\">\n <i class=\"fa-regular fa-thumbs-up\"></i>\n </button>\n <button type=\"button\" class=\"btn btn-sm btn-link text-danger p-0 me-2 button-message-toolbox rate-down-btn\" @click=\"rateMessage(message, false, $event)\" :title=\"thumbsDownTitle\">\n <i class=\"fa-regular fa-thumbs-down\"></i>\n </button>\n </span>\n </template>\n <button type=\"button\" v-if=\"textToSpeechEnabled && !isConversationMode && message.role === 'assistant' && !message.isStreaming\" class=\"btn btn-sm btn-link text-secondary p-0 me-1 button-message-toolbox\" :class=\"{ 'tts-playing': ttsPlayingMessageIndex === index }\" :data-tts-message-index=\"index\" @click=\"toggleMessageTts(message, index)\" :title=\"ttsPlayingMessageIndex === index ? 'Pause audio' : 'Read aloud'\">\n <span :class=\"ttsPlayingMessageIndex === index ? 'fa-solid fa-circle-pause' : 'fa-solid fa-circle-play'\"></span>\n </button>\n <button type=\"button\" class=\"btn btn-sm btn-link p-0 button-message-toolbox ai-response-copy-btn\" :class=\"copiedMessageIndex === index ? 'text-success' : 'text-secondary'\" :data-copy-message-index=\"index\" @click=\"copyResponse(message, index, $event)\" :title=\"copiedMessageIndex === index ? copiedTitle : copyTitle\">\n <i :class=\"copiedMessageIndex === index ? 'fa-solid fa-check' : 'fa-solid fa-copy'\"></i>\n </button>\n </span>\n </div>\n </div>\n </div>\n <div v-for=\"notification in notifications\" :key=\"'notif-' + notification.type\" class=\"ai-chat-notification\" :class=\"'ai-chat-notification-' + (notification.type || 'info') + ' ' + (notification.cssClass || '')\">\n <div class=\"ai-chat-notification-content\">\n <i v-if=\"notification.icon\" :class=\"notification.icon\" class=\"ai-chat-notification-icon\"></i>\n <span class=\"ai-chat-notification-text\">{{ notification.content }}</span>\n <button type=\"button\" v-if=\"notification.dismissible\" class=\"btn btn-sm btn-link p-0 ms-2 ai-chat-notification-dismiss\" @click=\"dismissNotification(notification.type)\" title=\"Dismiss\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n <div v-if=\"notification.actions && notification.actions.length\" class=\"ai-chat-notification-actions\">\n <button type=\"button\" v-for=\"action in notification.actions\" :key=\"action.name\" class=\"btn btn-sm\" :class=\"action.cssClass || 'btn-outline-secondary'\" @click=\"handleNotificationAction(notification.type, action.name)\">\n <i v-if=\"action.icon\" :class=\"action.icon\" class=\"me-1\"></i>\n {{ action.label }}\n </button>\n </div>\n </div>\n </div>\n `,\n indicatorTemplate: `\n <div class=\"ai-chat-message-heading ai-chat-message-heading-assistant\">\n <div class=\"ai-chat-msg-role ai-chat-msg-role-assistant\">\n <span class=\"ai-streaming-icon\"><i class=\"fa fa-robot\" style=\"display: inline-block;\"></i></span>\n <span class=\"ai-chat-message-role-label\">Assistant</span>\n </div>\n </div>\n `\n };\n\n // Sanitize URLs to prevent javascript: protocol injection.\n function sanitizeUrl(url) {\n if (!url) return '';\n var trimmed = url.trim();\n if (/^javascript:/i.test(trimmed) || /^vbscript:/i.test(trimmed) || /^data:text\\/html/i.test(trimmed)) {\n return '';\n }\n return url;\n }\n\n // Safely HTML-encode a string using the DOM (avoids regex-based HTML filtering).\n function escapeHtmlEntities(text) {\n var span = document.createElement('span');\n span.textContent = text;\n return span.innerHTML;\n }\n\n function containsFontAwesomePlaceholders(root) {\n if (!root || root.nodeType !== 1) {\n return false;\n }\n\n var selector = 'i[class*=\"fa-\"],i.fa,i.fas,i.far,i.fab';\n if (typeof root.matches === 'function' && root.matches(selector)) {\n return true;\n }\n\n return typeof root.querySelector === 'function' && !!root.querySelector(selector);\n }\n\n function refreshFontAwesomeIcons(root) {\n var fontAwesome = window.FontAwesome;\n if (!containsFontAwesomePlaceholders(root) || !fontAwesome || !fontAwesome.dom || typeof fontAwesome.dom.i2svg !== 'function') {\n return;\n }\n\n fontAwesome.dom.i2svg({ node: root });\n }\n\n function observeFontAwesomeIcons(root) {\n if (!root || typeof MutationObserver === 'undefined') {\n return null;\n }\n\n var observer = new MutationObserver(function (mutations) {\n mutations.forEach(function (mutation) {\n mutation.addedNodes.forEach(function (node) {\n refreshFontAwesomeIcons(node);\n });\n });\n });\n\n observer.observe(root, {\n childList: true,\n subtree: true\n });\n\n return observer;\n }\n\n function parsePixelValue(value) {\n if (typeof value === 'number' && Number.isFinite(value)) {\n return value;\n }\n\n if (typeof value !== 'string') {\n return null;\n }\n\n var parsed = parseFloat(value);\n return Number.isFinite(parsed) ? parsed : null;\n }\n\n function clamp(value, min, max) {\n return Math.min(Math.max(value, min), max);\n }\n\n function normalizeReference(reference) {\n if (!reference || typeof reference !== 'object') {\n return null;\n }\n\n const normalized = Object.assign({}, reference);\n normalized.index = normalized.index ?? normalized.Index ?? 0;\n normalized.text = normalized.text ?? normalized.Text ?? null;\n normalized.title = normalized.title ?? normalized.Title ?? null;\n normalized.link = sanitizeUrl(normalized.link ?? normalized.Link ?? null);\n normalized.referenceType = normalized.referenceType ?? normalized.ReferenceType ?? null;\n normalized.isGenerated = (normalized.isGenerated ?? normalized.IsGenerated) === true;\n\n return normalized;\n }\n\n function isDownloadCitationReference(reference) {\n if (!reference || typeof reference !== 'object') {\n return false;\n }\n\n if (typeof reference.referenceType === 'string' && reference.referenceType.toLowerCase() === 'document') {\n return true;\n }\n\n if (typeof reference.link === 'string' && /\\/ai\\/documents\\/.+\\/download(?:$|\\?)/i.test(reference.link)) {\n return true;\n }\n\n return false;\n }\n\n function normalizeReferences(references) {\n if (!references || typeof references !== 'object') {\n return {};\n }\n\n const normalized = {};\n\n for (const [key, value] of Object.entries(references)) {\n normalized[key] = normalizeReference(value) ?? {};\n }\n\n return normalized;\n }\n\n function getCitationLabel(reference, key) {\n return reference.title || reference.text || key;\n }\n\n function buildCitationDisplay(content, references) {\n let processedContent = (content || '').trim();\n const messageReferences = normalizeReferences(references);\n const referenceEntries = Object.entries(messageReferences);\n\n if (!referenceEntries.length) {\n return { content: processedContent, citations: [] };\n }\n\n const citedRefs = referenceEntries.filter(([key]) => processedContent.includes(key));\n const generatedRefs = referenceEntries.filter(([key, value]) => value.isGenerated && !processedContent.includes(key));\n\n if (!citedRefs.length && !generatedRefs.length) {\n return { content: processedContent, citations: [] };\n }\n\n citedRefs.sort(([, a], [, b]) => a.index - b.index);\n generatedRefs.sort(([, a], [, b]) => a.index - b.index);\n\n const citations = [];\n let displayIndex = 1;\n\n for (const [key, value] of citedRefs) {\n const placeholder = `__CITE_${displayIndex}_${value.index || displayIndex}__`;\n processedContent = processedContent.replaceAll(key, placeholder);\n citations.push({\n referenceKey: key,\n displayIndex: displayIndex,\n label: getCitationLabel(value, key),\n link: value.link || null,\n isDownload: isDownloadCitationReference(value),\n placeholder: placeholder,\n });\n\n displayIndex++;\n }\n\n for (const citation of citations) {\n processedContent = processedContent.replaceAll(citation.placeholder, `<sup>${citation.displayIndex}</sup>`);\n }\n\n processedContent = processedContent.replaceAll('</sup><sup>', '</sup><sup>,</sup><sup>');\n\n // Generated files (such as exported tabular data) are always offered as a download even when\n // the model does not cite them inline, so the user never loses access to the produced file.\n for (const [key, value] of generatedRefs) {\n citations.push({\n referenceKey: key,\n displayIndex: displayIndex,\n label: getCitationLabel(value, key),\n link: value.link || null,\n isDownload: true,\n placeholder: null,\n });\n\n displayIndex++;\n }\n\n return {\n content: processedContent,\n citations: citations.map(({ placeholder, ...citation }) => citation),\n };\n }\n\n function buildCopyContent(content, citations) {\n let copyContent = (content || '').trim();\n\n if (!copyContent || !Array.isArray(citations) || citations.length === 0) {\n return copyContent;\n }\n\n for (const citation of citations) {\n copyContent = copyContent.replaceAll(citation.referenceKey, `[${citation.displayIndex}]`);\n }\n\n copyContent += '\\n\\nReferences:\\n';\n\n for (const citation of citations) {\n copyContent += `${citation.displayIndex}. ${citation.label}`;\n\n if (citation.link) {\n copyContent += ` - ${citation.link}`;\n }\n\n copyContent += '\\n';\n }\n\n return copyContent.trimEnd();\n }\n\n function updateMessagePresentation(message, references) {\n const messageReferences = normalizeReferences(references ?? message.references);\n const rawContent = typeof message.rawContent === 'string'\n ? message.rawContent\n : typeof message.content === 'string'\n ? message.content\n : '';\n const citationDisplay = buildCitationDisplay(rawContent, messageReferences);\n\n message.rawContent = rawContent;\n message.content = rawContent;\n message.displayContent = citationDisplay.content;\n message.references = messageReferences;\n message.citationReferences = citationDisplay.citations;\n message.copyContent = buildCopyContent(rawContent, citationDisplay.citations);\n message.htmlContent = parseMarkdownContent(citationDisplay.content, message);\n\n return message;\n }\n\n const renderer = new marked.Renderer();\n\n // Modify the link rendering to open in a new tab\n renderer.link = function (data) {\n var href = sanitizeUrl(data.href);\n if (!href) return data.text || '';\n return `<a href=\"${href}\" target=\"_blank\" rel=\"noopener noreferrer\">${data.text}</a>`;\n };\n\n // Custom code block renderer with highlight.js integration and copy button.\n renderer.code = function (data) {\n var code = data.text || '';\n var lang = (data.lang || '').trim();\n var highlighted = code;\n\n if (typeof hljs !== 'undefined') {\n if (lang && hljs.getLanguage(lang)) {\n try {\n highlighted = hljs.highlight(code, { language: lang }).value;\n } catch (_) { }\n } else {\n try {\n highlighted = hljs.highlightAuto(code).value;\n } catch (_) { }\n }\n } else {\n highlighted = escapeHtmlEntities(code);\n }\n\n var langDisplay = lang ? escapeHtmlEntities(lang) : 'code';\n return `<div class=\"ai-code-block\"><div class=\"ai-code-header\"><span class=\"ai-code-lang\"><i class=\"fa-solid fa-code\"></i> ${langDisplay}</span><button type=\"button\" class=\"ai-code-copy-btn\" title=\"Copy code\"><i class=\"fa-regular fa-copy\"></i></button></div><pre><code class=\"hljs${lang ? ' language-' + lang : ''}\">${highlighted}</code></pre></div>`;\n };\n\n // Custom image renderer for generated images with thumbnail styling and download button.\n // Handles both URL and data-URI sources (data URIs are converted to blobs for download).\n renderer.image = function (data) {\n const src = sanitizeUrl(data.href);\n if (!src) return '';\n const alt = data.text || defaultConfig.generatedImageAltText;\n const maxWidth = defaultConfig.generatedImageMaxWidth;\n return `<div class=\"generated-image-container\">\n <img src=\"${src}\" alt=\"${alt}\" class=\"img-thumbnail\" style=\"max-width: ${maxWidth}px; height: auto;\" />\n <div class=\"mt-2\">\n <a href=\"${src}\" target=\"_blank\" download=\"${alt}\" title=\"${defaultConfig.downloadImageTitle}\" class=\"btn btn-sm btn-outline-secondary ai-download-image\">\n <i class=\"fa-solid fa-download\"></i>\n </a>\n </div>\n </div>`;\n };\n\n // Chart counter for unique IDs\n let chartCounter = 0;\n\n // Collector for charts discovered during marked parsing.\n let _pendingCharts = [];\n\n // Global chart config map: any page (e.g., Chat Interactions) that uses\n // the shared marked instance can call window.renderPendingCharts() after\n // its DOM update to render charts it didn't create itself.\n window.__chartConfigs = window.__chartConfigs || {};\n\n function createChartHtml(chartId) {\n return `<div class=\"chart-container\" style=\"position: relative; width: 100%; max-width: 560px; min-height: 420px;\">`\n + `<canvas id=\"${chartId}\"></canvas>`\n + `</div>`\n + `<div class=\"mt-2\">`\n + `<button type=\"button\" class=\"btn btn-sm btn-outline-secondary download-chart-btn\" data-chart-id=\"${chartId}\" title=\"${defaultConfig.downloadChartTitle}\">`\n + `<i class=\"fa-solid fa-download\"></i> ${defaultConfig.downloadChartButtonText}`\n + `</button>`\n + `</div>`;\n }\n\n // Register [chart:{...json...}] as a native marked block extension so the\n // markdown parser handles chart markers inline with surrounding text.\n marked.use({\n extensions: [{\n name: 'chart',\n level: 'block',\n start(src) {\n const idx = src.indexOf('[chart:');\n return idx >= 0 ? idx : undefined;\n },\n tokenizer(src) {\n const extracted = tryExtractChartMarker(src);\n if (!extracted || extracted.startIndex !== 0) {\n return undefined;\n }\n\n const chartId = `chat_chart_${++chartCounter}`;\n\n return {\n type: 'chart',\n raw: src.substring(0, extracted.endIndex),\n chartId: chartId,\n json: extracted.json,\n };\n },\n renderer(token) {\n _pendingCharts.push({ chartId: token.chartId, config: token.json });\n window.__chartConfigs[token.chartId] = token.json;\n return createChartHtml(token.chartId);\n }\n }]\n });\n\n // Extract a [chart:{...json...}] marker. This avoids regex issues with nested brackets.\n function tryExtractChartMarker(text) {\n const token = '[chart:';\n const start = text.indexOf(token);\n if (start < 0) {\n return null;\n }\n\n // Find JSON object boundary by balancing braces\n const jsonStart = start + token.length;\n let i = jsonStart;\n while (i < text.length && (text[i] === ' ' || text[i] === '\\n' || text[i] === '\\r' || text[i] === '\\t')) {\n i++;\n }\n\n if (i >= text.length || text[i] !== '{') {\n return null;\n }\n\n let depth = 0;\n let inString = false;\n let escape = false;\n\n for (; i < text.length; i++) {\n const ch = text[i];\n\n if (inString) {\n if (escape) {\n escape = false;\n continue;\n }\n if (ch === '\\\\') {\n escape = true;\n continue;\n }\n if (ch === '\"') {\n inString = false;\n }\n continue;\n }\n\n if (ch === '\"') {\n inString = true;\n continue;\n }\n\n if (ch === '{') {\n depth++;\n } else if (ch === '}') {\n depth--;\n if (depth === 0) {\n const jsonEnd = i;\n // Expect closing bracket after JSON\n const closeBracketIndex = text.indexOf(']', jsonEnd + 1);\n if (closeBracketIndex < 0) {\n return null;\n }\n\n const json = text.substring(jsonStart, jsonEnd + 1).trim();\n return {\n startIndex: start,\n endIndex: closeBracketIndex + 1,\n json: json\n };\n }\n }\n }\n\n return null;\n }\n\n function renderChartsInMessage(message) {\n if (!message || !message._pendingCharts || !message._pendingCharts.length) {\n return;\n }\n\n // Copy and clear pending charts immediately to prevent duplicate renders.\n const charts = [...message._pendingCharts];\n message._pendingCharts = [];\n\n // Defer to requestAnimationFrame so the browser has fully laid out the\n // canvas elements before Chart.js reads their dimensions.\n requestAnimationFrame(() => {\n for (const c of charts) {\n renderChartOnCanvas(c.chartId, c.config);\n }\n });\n }\n\n function renderChartOnCanvas(chartId, config) {\n const canvas = document.getElementById(chartId);\n if (!canvas) {\n return false;\n }\n\n if (typeof Chart === 'undefined') {\n console.warn('Chart.js is not loaded. To render interactive charts, include the Chart.js library on the page (e.g., <script src=\"https://cdn.jsdelivr.net/npm/chart.js@4/dist/chart.umd.min.js\"></script>).');\n return false;\n }\n\n // When the canvas is inside a hidden container (e.g., a widget panel with\n // display:none), it has zero dimensions and Chart.js cannot render correctly.\n // Keep the config in __chartConfigs so renderPendingCharts() can retry later\n // once the container becomes visible.\n if (canvas.offsetParent === null) {\n window.__chartConfigs[chartId] = config;\n return false;\n }\n\n try {\n if (canvas._chartInstance) {\n canvas._chartInstance.destroy();\n }\n\n const cfg = typeof config === 'string' ? JSON.parse(config) : config;\n cfg.options ??= {};\n cfg.options.responsive = true;\n cfg.options.maintainAspectRatio = true;\n cfg.options.aspectRatio ??= 4 / 3;\n\n canvas._chartInstance = new Chart(canvas, cfg);\n delete window.__chartConfigs[chartId];\n return true;\n } catch (e) {\n console.error('Error creating chart:', e);\n return false;\n }\n }\n\n // Global function: renders any chart canvases whose configs are in the\n // global __chartConfigs map. Called by pages (e.g., Chat Interactions)\n // that share the marked instance but have their own rendering pipeline.\n window.renderPendingCharts = function () {\n if (typeof Chart === 'undefined') {\n return;\n }\n\n const configs = window.__chartConfigs;\n if (!configs) {\n return;\n }\n\n requestAnimationFrame(() => {\n for (const chartId of Object.keys(configs)) {\n renderChartOnCanvas(chartId, configs[chartId]);\n }\n });\n };\n\n // Parse markdown content via marked (which natively handles [chart:...] markers\n // through the registered extension) and collect pending chart configs for later\n // Chart.js rendering.\n function parseMarkdownContent(content, message) {\n _pendingCharts = [];\n const html = marked.parse(content, { renderer });\n message._pendingCharts = _pendingCharts.length > 0 ? [..._pendingCharts] : [];\n return DOMPurify.sanitize(html, { ADD_TAGS: ['canvas'], ADD_ATTR: ['target'] });\n }\n\n function compactObject(source) {\n if (!source || typeof source !== 'object') {\n return {};\n }\n\n return Object.fromEntries(\n Object.entries(source).filter(([, value]) => value !== undefined)\n );\n }\n\n function resolveIndicatorTemplate(template, assistantLabel) {\n if (!template) {\n return template;\n }\n\n const encodedAssistantLabel = escapeHtmlEntities(assistantLabel || 'Assistant');\n return template.replace(/\\{\\{\\s*assistantLabel\\s*\\}\\}/g, encodedAssistantLabel);\n }\n\n const initialize = (instanceConfig) => {\n const normalizedInstanceConfig = compactObject(instanceConfig);\n const normalizedWidgetConfig = compactObject(normalizedInstanceConfig.widget);\n const config = Object.assign({}, defaultConfig, normalizedInstanceConfig);\n config.widget = Object.assign({}, defaultConfig.widget || {}, normalizedWidgetConfig);\n config.indicatorTemplate = resolveIndicatorTemplate(config.indicatorTemplate, config.assistantLabel);\n const hasWidgetConfig = !!(normalizedWidgetConfig.chatWidgetContainer && normalizedWidgetConfig.chatWidgetStateName);\n const widgetBehavior = window.coreAIChatWidgetBehavior || null;\n // Keep defaultConfig in sync so renderers use overridden values\n defaultConfig = config;\n\n if (!config.signalRHubUrl) {\n console.error('The signalRHubUrl is required.');\n return;\n }\n\n if (!config.appElementSelector) {\n console.error('The appElementSelector is required.');\n return;\n }\n\n if (!config.chatContainerElementSelector) {\n console.error('The chatContainerElementSelector is required.');\n return;\n }\n\n if (!config.inputElementSelector) {\n console.error('The inputElementSelector is required.');\n return;\n }\n\n if (!config.sendButtonElementSelector) {\n console.error('The sendButtonElementSelector is required.');\n return;\n }\n\n const appDefinition = {\n data() {\n return {\n inputElement: null,\n buttonElement: null,\n chatContainer: null,\n placeholder: null,\n isSessionStarted: false,\n isPlaceholderVisible: true,\n isStreaming: false,\n isNavigatingAway: false,\n autoScroll: true,\n stream: null,\n messages: [],\n notifications: [],\n prompt: '',\n documents: config.existingDocuments || [],\n isUploading: false,\n isDocumentOperationPending: false,\n documentOperationQueue: null,\n uploadErrors: [],\n isDragOver: false,\n documentBar: null,\n metricsEnabled: !!config.metricsEnabled,\n userLabel: config.userLabel,\n assistantLabel: config.assistantLabel,\n thumbsUpTitle: config.thumbsUpTitle,\n thumbsDownTitle: config.thumbsDownTitle,\n copyTitle: config.copyTitle,\n copiedTitle: config.copiedTitle,\n isRecording: false,\n mediaRecorder: null,\n preRecordingPrompt: '',\n micButton: null,\n speechToTextEnabled: config.chatMode === 'AudioInput' || config.chatMode === 'Conversation',\n textToSpeechEnabled: config.chatMode === 'Conversation' || !!config.textToSpeechEnabled,\n ttsVoiceName: config.ttsVoiceName || null,\n audioChunks: [],\n audioPlayQueue: [],\n isPlayingAudio: false,\n currentAudioElement: null,\n currentAudioUrl: null,\n ttsButton: null,\n ttsPlayingMessageIndex: -1,\n ttsAudioCache: {},\n ttsInstanceId: 'ai-chat-' + Math.random().toString(36).slice(2),\n singleResponseMode: !!config.singleResponseMode,\n conversationModeEnabled: config.chatMode === 'Conversation',\n realtimeEnabled: config.chatMode === 'Realtime' || !!config.realtimeEnabled,\n // Server-relay WebRTC transport: primary when advertised and supported; the client falls back\n // to the WebSocket path below if the peer cannot connect.\n realtimeWebRtcEnabled: config.realtimeWebRtcEnabled === true && typeof window.RTCPeerConnection === 'function',\n // A host-supplied override. Normally the servers are fetched from the hub right before the\n // peer is created (resolveRealtimeIceServers) so configured TURN relays — and their\n // short-lived credentials — are actually used instead of a public STUN server.\n realtimeWebRtcIceServers: (Array.isArray(config.realtimeWebRtcIceServers) && config.realtimeWebRtcIceServers.length)\n ? config.realtimeWebRtcIceServers\n : null,\n realtimeVoiceName: config.realtimeVoiceName || null,\n conversationButton: null,\n isConversationMode: false,\n notificationDismissTimers: {},\n pendingSessionPromise: null,\n pendingSessionResolver: null,\n pendingSessionRejector: null,\n pendingSessionTimeoutId: null,\n copiedMessageIndex: -1,\n copyResetTimeoutId: null,\n activeCopyButton: null,\n };\n },\n computed: {\n lastAssistantIndex() {\n for (var i = this.messages.length - 1; i >= 0; i--) {\n if (this.messages[i].role === 'assistant') {\n return i;\n }\n }\n return -1;\n }\n },\n methods: {\n handleBeforeUnload() {\n this.isNavigatingAway = true;\n },\n handleDragOver(e) {\n if (!config.sessionDocumentsEnabled) return;\n e.preventDefault();\n e.stopPropagation();\n this.isDragOver = true;\n var inputArea = this.inputElement ? this.inputElement.closest('.ai-admin-widget-input, .text-bg-light') : null;\n if (inputArea) inputArea.classList.add('ai-chat-drag-over');\n },\n handleDragLeave(e) {\n if (!config.sessionDocumentsEnabled) return;\n e.preventDefault();\n e.stopPropagation();\n this.isDragOver = false;\n var inputArea = this.inputElement ? this.inputElement.closest('.ai-admin-widget-input, .text-bg-light') : null;\n if (inputArea) inputArea.classList.remove('ai-chat-drag-over');\n },\n handleDrop(e) {\n if (!config.sessionDocumentsEnabled) return;\n e.preventDefault();\n e.stopPropagation();\n this.isDragOver = false;\n var inputArea = this.inputElement ? this.inputElement.closest('.ai-admin-widget-input, .text-bg-light') : null;\n if (inputArea) inputArea.classList.remove('ai-chat-drag-over');\n if (e.dataTransfer && e.dataTransfer.files && e.dataTransfer.files.length > 0) {\n this.uploadFiles(Array.from(e.dataTransfer.files));\n }\n },\n triggerFileInput() {\n if (!config.sessionDocumentsEnabled || this.isDocumentOperationPending) return;\n var fileInput = document.getElementById('ai-chat-doc-input');\n if (fileInput) fileInput.click();\n },\n handleFileInputChange(e) {\n var files = e.target.files ? Array.from(e.target.files) : [];\n if (files && files.length > 0) {\n this.uploadFiles(files);\n }\n e.target.value = '';\n },\n queueDocumentOperation(operation) {\n var self = this;\n var previousOperation = this.documentOperationQueue || Promise.resolve();\n var nextOperation = previousOperation\n .catch(function () { })\n .then(async function () {\n self.isDocumentOperationPending = true;\n try {\n return await operation();\n } finally {\n self.isDocumentOperationPending = false;\n }\n });\n\n this.documentOperationQueue = nextOperation.finally(function () {\n if (self.documentOperationQueue === nextOperation) {\n self.documentOperationQueue = null;\n }\n });\n\n return this.documentOperationQueue;\n },\n async uploadFiles(files) {\n if (!config.uploadDocumentUrl) return;\n\n var filesToUpload = Array.isArray(files) ? files.slice() : Array.from(files || []);\n if (filesToUpload.length === 0) return;\n\n return this.queueDocumentOperation(async () => {\n var sessionId = this.getSessionId();\n var profileId = this.getProfileId();\n\n if (!sessionId) {\n try {\n sessionId = await this.ensureSessionForDocuments(profileId);\n } catch (err) {\n console.error('Failed to create a chat session for document upload:', err);\n this.uploadErrors = [{ fileName: '', error: 'Could not create a chat session for the upload.' }];\n this.renderDocumentBar();\n return;\n }\n }\n\n if (!sessionId) {\n console.warn('Cannot upload documents without a session or profile.');\n this.uploadErrors = [{ fileName: '', error: 'Could not create a chat session for the upload.' }];\n this.renderDocumentBar();\n return;\n }\n\n this.isUploading = true;\n this.uploadErrors = [];\n this.renderDocumentBar();\n try {\n var formData = new FormData();\n formData.append('sessionId', sessionId);\n for (var i = 0; i < filesToUpload.length; i++) {\n formData.append('files', filesToUpload[i]);\n }\n\n var response = await fetch(config.uploadDocumentUrl, {\n method: 'POST',\n body: formData\n });\n\n if (!response.ok) {\n var errorText = await response.text();\n var uploadError = this.extractReadableErrorMessage(errorText, 'Upload failed. Please try again.');\n console.error('Upload failed:', errorText);\n this.uploadErrors = [{ fileName: '', error: uploadError }];\n return;\n }\n\n var result = await response.json();\n\n if (result.sessionId && result.sessionId !== this.getSessionId()) {\n this.initializeSession(result.sessionId);\n }\n\n if (Array.isArray(result.documents)) {\n this.documents = result.documents;\n } else if (result.uploaded && result.uploaded.length > 0) {\n this.documents = this.documents.concat(result.uploaded);\n }\n\n if (result.failed && result.failed.length > 0) {\n this.uploadErrors = result.failed;\n }\n } catch (err) {\n console.error('Upload error:', err);\n this.uploadErrors = [{ fileName: '', error: 'Upload failed. Please try again.' }];\n\n if (this.getSessionId()) {\n this.reloadCurrentSession();\n }\n } finally {\n this.isUploading = false;\n this.renderDocumentBar();\n }\n });\n },\n async removeDocument(doc) {\n if (!config.removeDocumentUrl) return;\n\n return this.queueDocumentOperation(async () => {\n try {\n var sessionId = this.getSessionId();\n var response = await fetch(config.removeDocumentUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ itemId: sessionId, documentId: doc.documentId })\n });\n\n if (response.ok) {\n var result = await response.json();\n\n if (Array.isArray(result.documents)) {\n this.documents = result.documents;\n } else {\n var idx = this.documents.indexOf(doc);\n if (idx > -1) {\n this.documents.splice(idx, 1);\n }\n }\n } else {\n var errorText = await response.text();\n var removeError = this.extractReadableErrorMessage(errorText, 'Failed to remove document. Please try again.');\n console.error('Failed to remove document:', response.status, errorText);\n this.uploadErrors = [{ fileName: doc.fileName || '', error: removeError }];\n if (sessionId) {\n this.reloadCurrentSession();\n }\n this.renderDocumentBar();\n }\n } catch (err) {\n console.error('Remove document error:', err);\n this.uploadErrors = [{ fileName: doc.fileName || '', error: 'Failed to remove document. Please try again.' }];\n if (this.getSessionId()) {\n this.reloadCurrentSession();\n }\n this.renderDocumentBar();\n }\n });\n },\n formatFileSize(bytes) {\n if (bytes < 1024) return bytes + ' B';\n if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB';\n return (bytes / (1024 * 1024)).toFixed(1) + ' MB';\n },\n renderDocumentBar() {\n if (!this.documentBar) return;\n\n if (!config.sessionDocumentsEnabled) {\n this.documentBar.classList.add('d-none');\n return;\n }\n\n this.documentBar.classList.remove('d-none');\n\n var html = '<div class=\"ai-chat-doc-bar p-2\">';\n html += '<div class=\"d-flex flex-wrap align-items-center gap-1\">';\n\n for (var i = 0; i < this.documents.length; i++) {\n var doc = this.documents[i];\n var name = doc.fileName || 'Document';\n if (name.length > 20) name = name.substring(0, 17) + '...';\n html += '<span class=\"badge bg-secondary bg-opacity-25 text-dark d-inline-flex align-items-center gap-1 px-2 py-1\" style=\"font-size: 0.8rem;\" title=\"' + this.escapeHtml(doc.fileName || '') + '\">';\n html += '<i class=\"fa-solid fa-file-lines\" style=\"font-size: 0.7rem;\"></i> ';\n html += this.escapeHtml(name);\n html += ' <button type=\"button\" class=\"btn-close btn-close-sm ms-1\" style=\"font-size: 0.5rem;\" data-doc-index=\"' + i + '\" aria-label=\"Remove\"' + (this.isDocumentOperationPending ? ' disabled' : '') + '></button>';\n html += '</span>';\n }\n\n for (var m = 0; m < this.uploadErrors.length; m++) {\n var failedItem = this.uploadErrors[m];\n var failedName = failedItem.fileName || 'File';\n var errorMsg = failedItem.error || 'Upload failed';\n if (failedName.length > 15) failedName = failedName.substring(0, 12) + '...';\n html += '<span class=\"badge bg-danger bg-opacity-25 text-danger d-inline-flex align-items-center gap-1 px-2 py-1\" style=\"font-size: 0.8rem;\" title=\"' + this.escapeHtml((failedItem.fileName || '') + ': ' + errorMsg) + '\">';\n html += '<i class=\"fa-solid fa-circle-exclamation\" style=\"font-size: 0.7rem;\"></i> ';\n html += this.escapeHtml(failedName);\n html += ' <button type=\"button\" class=\"btn-close btn-close-sm ms-1\" style=\"font-size: 0.5rem;\" data-error-index=\"' + m + '\" aria-label=\"Dismiss\"></button>';\n html += '</span>';\n }\n\n if (this.isUploading) {\n html += '<span class=\"badge bg-info bg-opacity-25 text-dark d-inline-flex align-items-center gap-1 px-2 py-1\" style=\"font-size: 0.8rem;\">';\n html += '<span class=\"spinner-border spinner-border-sm\" style=\"width: 0.7rem; height: 0.7rem;\"></span> Uploading...';\n html += '</span>';\n }\n\n html += '<button type=\"button\" class=\"btn btn-sm btn-outline-secondary rounded-pill ai-chat-doc-add-btn d-inline-flex align-items-center gap-1\" style=\"font-size: 0.75rem; padding: 0.15rem 0.5rem;\" title=\"Attach documents\"' + (this.isDocumentOperationPending ? ' disabled' : '') + '>';\n html += '<i class=\"fa-solid fa-paperclip\"></i>';\n if (this.documents.length === 0 && !this.isUploading) {\n html += ' <span>Attach files</span>';\n }\n html += '</button>';\n html += '</div>';\n if (config.supportedExtensionsText) {\n html += '<div class=\"small text-muted mt-2\">Supported formats: ' + this.escapeHtml(config.supportedExtensionsText) + '</div>';\n }\n\n html += '</div>';\n\n this.documentBar.replaceChildren(DOMPurify.sanitize(html, { RETURN_DOM_FRAGMENT: true }));\n\n // Bind remove handlers\n var self = this;\n var closeButtons = this.documentBar.querySelectorAll('[data-doc-index]');\n for (var j = 0; j < closeButtons.length; j++) {\n closeButtons[j].addEventListener('click', (function (idx) {\n return function (e) {\n e.preventDefault();\n e.stopPropagation();\n if (self.isDocumentOperationPending) {\n return;\n }\n\n var docToRemove = self.documents[idx];\n if (docToRemove) self.removeDocument(docToRemove);\n };\n })(parseInt(closeButtons[j].getAttribute('data-doc-index'))));\n }\n\n // Bind error dismiss handlers\n var errorCloseButtons = this.documentBar.querySelectorAll('[data-error-index]');\n for (var n = 0; n < errorCloseButtons.length; n++) {\n errorCloseButtons[n].addEventListener('click', (function (idx) {\n return function (e) {\n e.preventDefault();\n e.stopPropagation();\n self.uploadErrors.splice(idx, 1);\n self.renderDocumentBar();\n };\n })(parseInt(errorCloseButtons[n].getAttribute('data-error-index'))));\n }\n\n // Bind add button\n var addBtn = this.documentBar.querySelector('.ai-chat-doc-add-btn');\n if (addBtn) {\n addBtn.addEventListener('click', function (e) {\n e.preventDefault();\n if (self.isDocumentOperationPending) {\n return;\n }\n self.triggerFileInput();\n });\n }\n },\n escapeHtml(text) {\n var div = document.createElement('div');\n div.textContent = text;\n return div.innerHTML;\n },\n extractReadableErrorMessage(errorText, fallbackMessage) {\n if (!errorText || typeof errorText !== 'string') {\n return fallbackMessage;\n }\n\n var trimmed = errorText.trim();\n if (!trimmed) {\n return fallbackMessage;\n }\n\n if (trimmed.startsWith('{') || trimmed.startsWith('[')) {\n try {\n var parsed = JSON.parse(trimmed);\n var message = parsed?.error || parsed?.message || parsed?.title || parsed?.detail;\n return typeof message === 'string' && message.trim()\n ? message.trim()\n : fallbackMessage;\n } catch (err) {\n return fallbackMessage;\n }\n }\n\n if (/<[^>]+>/.test(trimmed)) {\n return fallbackMessage;\n }\n\n return trimmed;\n },\n normalizeAssistantAppearance(appearance) {\n if (!appearance) {\n return null;\n }\n\n var label = typeof appearance.label === 'string' ? appearance.label.trim() : '';\n var icon = typeof appearance.icon === 'string' ? appearance.icon.trim() : '';\n var cssClass = typeof appearance.cssClass === 'string' ? appearance.cssClass.trim() : '';\n var disableStreamingAnimation = !!appearance.disableStreamingAnimation;\n\n if (!label && !icon && !cssClass && !disableStreamingAnimation) {\n return null;\n }\n\n return {\n label: label,\n icon: icon,\n cssClass: cssClass,\n disableStreamingAnimation: disableStreamingAnimation,\n };\n },\n getAssistantLabel(message) {\n var appearance = message ? this.normalizeAssistantAppearance(message.appearance) : null;\n return appearance && appearance.label ? appearance.label : this.assistantLabel;\n },\n getAssistantRoleClasses(message) {\n var appearance = message ? this.normalizeAssistantAppearance(message.appearance) : null;\n var classes = ['ai-chat-msg-role'];\n\n if (appearance && appearance.cssClass) {\n classes.push(appearance.cssClass);\n } else {\n classes.push('ai-chat-msg-role-assistant');\n }\n\n return classes;\n },\n getAssistantIconClasses(message, index) {\n var appearance = message ? this.normalizeAssistantAppearance(message.appearance) : null;\n return [this.shouldAnimateAssistantIcon(message, index) ? 'ai-streaming-icon' : 'ai-bot-icon', appearance && appearance.cssClass ? appearance.cssClass : ''];\n },\n getAssistantIcon(message) {\n var appearance = message ? this.normalizeAssistantAppearance(message.appearance) : null;\n return appearance && appearance.icon ? appearance.icon : 'fa fa-robot';\n },\n shouldAnimateAssistantIcon(message, index) {\n var appearance = message ? this.normalizeAssistantAppearance(message.appearance) : null;\n return !!message &&\n message.isStreaming &&\n index === this.lastAssistantIndex &&\n !(appearance && appearance.disableStreamingAnimation);\n },\n async startConnection() {\n this.connection = new signalR.HubConnectionBuilder()\n .withUrl(config.signalRHubUrl)\n .withAutomaticReconnect()\n .build();\n\n // Allow long-running operations (e.g., multi-step MCP tool calls)\n // without the client disconnecting prematurely.\n this.connection.serverTimeoutInMilliseconds = 600000;\n this.connection.keepAliveIntervalInMilliseconds = 15000;\n\n this.connection.on(\"LoadSession\", (data) => {\n // Switching to another session must not leave a prior realtime/voice session running.\n this.forceStopActiveVoice();\n this.initializeSession(data.sessionId, true);\n this.messages = [];\n this.documents = data.documents || [];\n this.uploadErrors = [];\n\n (data.messages ?? []).forEach(msg => {\n this.addMessage(msg);\n\n this.$nextTick(() => {\n renderChartsInMessage(msg);\n });\n });\n\n // Update feedback icons in the DOM after all messages have rendered.\n this.$nextTick(() => {\n this.refreshAllFeedbackIcons();\n });\n\n // When the session is new (no messages) and an initial prompt is configured,\n // display it as the first assistant message without invoking the AI.\n if (this.messages.length === 0 && config.initialPrompt) {\n this.addMessage({\n role: 'assistant',\n content: config.initialPrompt\n });\n }\n });\n\n // Realtime lifecycle events (ReceiveRealtimeEvent, and ReceiveError while a voice session is\n // live) are handled by the shared CoreAIRealtime module — see setupRealtimeController.\n\n this.connection.on(\"ReceiveError\", (error) => {\n console.error(\"SignalR Error: \", error);\n\n if (this.isRecording) {\n this.stopRecording();\n }\n\n // A server-side error (for example a session-start rate-limit rejection) ends the\n // in-flight request. Reject any pending new-session promise so the UI stops waiting\n // until it times out, and clear the typing indicator that a send may have shown.\n this.rejectPendingSessionRequest(error);\n this.hideTypingIndicator();\n\n if (widgetBehavior && typeof widgetBehavior.handleReceiveError === 'function') {\n widgetBehavior.handleReceiveError(this, error, config);\n } else if (!this.isNavigatingAway) {\n // Surface the message to the user instead of failing silently.\n this.addMessage(this.getErrorMessage(error));\n }\n });\n\n this.connection.on(\"ReceiveSessionStartRejected\", (reason) => {\n // A rate-limit rejection is a definitive \"wait and retry\", not a recoverable\n // session/connection error. Unblock any pending new-session request, clear the\n // typing indicator, and show the message for every host (main app and widget)\n // without triggering the widget's clear-and-retry recovery, which would wipe the\n // visitor's state and fire another throttled StartSession.\n this.rejectPendingSessionRequest(reason);\n this.hideTypingIndicator();\n\n if (!this.isNavigatingAway) {\n this.addMessage(this.getErrorMessage(reason));\n }\n });\n\n this.connection.on(\"MessageRated\", (messageId, userRating) => {\n var msg = this.messages.find(m => m.id === messageId);\n if (msg) {\n msg.userRating = userRating;\n }\n });\n\n this.connection.on(\"ReceiveTranscript\", (sessionId, text, isFinal) => {\n if (this.isConversationMode) {\n if (!isFinal && text) {\n this._conversationPartialTranscript = text;\n var escaped = text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n var html = '<p class=\"ai-partial-transcript\">' + escaped + '</p>';\n\n // Show partial transcript as a live user message.\n if (!this._conversationPartialMessage) {\n this.hidePlaceholder();\n this._conversationPartialMessage = {\n role: 'user',\n content: text,\n htmlContent: html,\n isPartial: true\n };\n this.messages.push(this._conversationPartialMessage);\n } else {\n this._conversationPartialMessage.content = text;\n this._conversationPartialMessage.htmlContent = html;\n }\n this.scrollToBottom();\n }\n return;\n }\n\n if (text && !this._audioInputSent) {\n this.prompt = this.preRecordingPrompt + text;\n if (this.inputElement) {\n this.inputElement.value = this.prompt;\n this.inputElement.dispatchEvent(new Event('input'));\n }\n }\n });\n\n this.connection.on(\"ReceiveConversationUserMessage\", (sessionId, turnId, text) => {\n // Realtime creates the chat session server-side; adopt its id (and update the page URL)\n // on the first turn so a refresh reloads the conversation instead of starting fresh.\n if (sessionId && this.getSessionId() !== sessionId) {\n this.initializeSession(sessionId);\n }\n\n // Realtime: a placeholder for this turn was already inserted in the right position when\n // the utterance was captured (see user_turn_pending), so just fill in its text.\n if (turnId && this._realtimePendingTurns && this._realtimePendingTurns[turnId]) {\n var pending = this._realtimePendingTurns[turnId];\n delete this._realtimePendingTurns[turnId];\n this.stopAudio();\n this.fillRealtimePendingTurn(pending, text);\n\n return;\n }\n\n if (text) {\n this.stopAudio();\n\n // Replace the partial transcript message with the final one.\n if (this._conversationPartialMessage) {\n var escaped = text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n this._conversationPartialMessage.content = text;\n this._conversationPartialMessage.htmlContent = '<p>' + escaped + '</p>';\n this._conversationPartialMessage.isPartial = false;\n this._conversationPartialMessage = null;\n } else if (this._conversationAssistantMessage) {\n // Realtime: the user's transcript lags the assistant's reply for the SAME turn (the\n // model answers the audio before speech-to-text finishes). Insert the user message\n // just before the streaming assistant message so the order stays You -> Assistant,\n // and keep that message streaming — ending it here split one reply into two bubbles\n // above the prompt.\n var at = this._conversationAssistantMessage.index;\n var userMsg = { role: 'user', content: text, rawContent: text, userRating: null, references: {} };\n updateMessagePresentation(userMsg, userMsg.references);\n this.messages.splice(at, 0, userMsg);\n this._conversationAssistantMessage.index = at + 1;\n } else {\n this.addMessage({\n role: 'user',\n content: text\n });\n }\n this.scrollToBottom();\n }\n });\n\n this.connection.on(\"ReceiveConversationAssistantToken\", (sessionId, messageId, token, responseId, references, appearance) => {\n // A new response id means a new turn — finalize the previous assistant message so two replies\n // never merge into one bubble (also covers barge-in, which starts a fresh response).\n if (this._conversationAssistantMessage && this._conversationAssistantResponseId && responseId && this._conversationAssistantResponseId !== responseId) {\n var prev = this.messages[this._conversationAssistantMessage.index];\n if (prev) { prev.isStreaming = false; }\n this._conversationAssistantMessage = null;\n }\n if (!this._conversationAssistantMessage) {\n this.stopAudio();\n this.hideTypingIndicator();\n\n // Ensure no stale streaming indicators remain from prior messages.\n for (var j = 0; j < this.messages.length; j++) {\n if (this.messages[j].isStreaming) {\n this.messages[j].isStreaming = false;\n }\n }\n\n var msgIndex = this.messages.length;\n var newMessage = {\n id: messageId,\n role: \"assistant\",\n content: \"\",\n htmlContent: \"\",\n isStreaming: true,\n userRating: null,\n appearance: this.normalizeAssistantAppearance(appearance),\n references: {},\n };\n this.messages.push(newMessage);\n this._conversationAssistantMessage = { index: msgIndex, content: '' };\n this._conversationAssistantResponseId = responseId;\n }\n\n this._conversationAssistantMessage.content += token;\n var msg = this.messages[this._conversationAssistantMessage.index];\n if (msg) {\n if (!msg.appearance) {\n msg.appearance = this.normalizeAssistantAppearance(appearance);\n }\n msg.rawContent = this._conversationAssistantMessage.content;\n msg.references = normalizeReferences(Object.assign({}, msg.references || {}, references || {}));\n updateMessagePresentation(msg, msg.references);\n this.$nextTick(() => {\n renderChartsInMessage(msg);\n this.scrollToBottom();\n });\n }\n });\n\n this.connection.on(\"ReceiveConversationAssistantComplete\", (sessionId, messageId, references) => {\n if (this._conversationAssistantMessage) {\n var msg = this.messages[this._conversationAssistantMessage.index];\n if (msg) {\n msg.isStreaming = false;\n msg.references = normalizeReferences(Object.assign({}, msg.references || {}, references || {}));\n updateMessagePresentation(msg, msg.references);\n }\n this._conversationAssistantMessage = null;\n this._conversationAssistantResponseId = null;\n }\n });\n\n this.connection.on(\"ReceiveAudioChunk\", (sessionId, base64Audio, contentType) => {\n if (!base64Audio) {\n return;\n }\n\n const binaryString = atob(base64Audio);\n const bytes = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n\n // Realtime audio arrives as raw PCM16 (WebSocket transport) and is scheduled for immediate\n // playback by the shared module; conversation/TTS audio (mp3/wav) is collected and played on\n // complete.\n if (contentType === 'audio/pcm') {\n if (this.realtimeController) { this.realtimeController.receivePcm(bytes); }\n } else {\n this.audioChunks.push(bytes);\n }\n });\n\n this.connection.on(\"ReceiveAudioComplete\", (sessionId) => {\n this.playCollectedAudio();\n });\n\n this.connection.on(\"ReceiveNotification\", (notification) => {\n this.receiveNotification(notification);\n });\n\n this.connection.on(\"UpdateNotification\", (notification) => {\n this.updateNotification(notification);\n });\n\n this.connection.on(\"RemoveNotification\", (notificationType) => {\n this.removeNotification(notificationType);\n });\n\n this.connection.onreconnecting(() => {\n console.warn(\"SignalR: reconnecting...\");\n\n // The realtime session lived inside the dropped connection; it cannot survive a reconnect.\n if (this.realtimeEnabled && this.isConversationMode) {\n this.stopRealtimeConversation();\n }\n });\n\n this.connection.onreconnected(() => {\n console.info(\"SignalR: reconnected.\");\n\n if (this.isSessionStarted) {\n this.reloadCurrentSession();\n }\n });\n\n this.connection.onclose((error) => {\n if (this.isNavigatingAway) {\n return;\n }\n\n if (this.realtimeEnabled && this.isConversationMode) {\n this.stopRealtimeConversation();\n }\n\n if (error) {\n console.warn(\"SignalR connection closed with error:\", error.message || error);\n }\n });\n\n try {\n await this.connection.start();\n } catch (err) {\n console.error(\"SignalR Connection Error: \", err);\n }\n },\n async ensureConnectionStarted() {\n if (!this.connection) {\n return false;\n }\n\n var states = signalR.HubConnectionState;\n if (this.connection.state === states.Connected) {\n return true;\n }\n\n // If the initial start failed or has not begun, start it now.\n if (this.connection.state === states.Disconnected) {\n try {\n await this.connection.start();\n } catch (err) {\n console.error(\"SignalR Connection Error: \", err);\n }\n\n return this.connection.state === states.Connected;\n }\n\n // The connection is still Connecting or Reconnecting: wait for it to settle so callers\n // (e.g. starting a realtime session) do not send before the socket is ready.\n return await new Promise((resolve) => {\n var settle = (value) => {\n clearTimeout(timeoutId);\n clearInterval(intervalId);\n resolve(value);\n };\n var timeoutId = setTimeout(() => settle(this.connection.state === states.Connected), 10000);\n var intervalId = setInterval(() => {\n if (this.connection.state === states.Connected) {\n settle(true);\n } else if (this.connection.state === states.Disconnected) {\n settle(false);\n }\n }, 100);\n });\n },\n addMessageInternal(message) {\n if (message.role === 'assistant') {\n message.appearance = this.normalizeAssistantAppearance(message.appearance);\n }\n\n if (message.content && !message.htmlContent) {\n message.htmlContent = parseMarkdownContent(message.content, message);\n }\n this.fireEvent(new CustomEvent(\"addingCoreAIPromotMessage\", { detail: { message: message } }));\n this.messages.push(message);\n\n this.$nextTick(() => {\n this.fireEvent(new CustomEvent(\"addedCoreAIPromotMessage\", { detail: { message: message } }));\n });\n },\n addMessage(message) {\n\n // Ensure userRating is always defined for Vue reactivity.\n if (message.userRating === undefined) {\n message.userRating = null;\n }\n\n if (message.content) {\n message.rawContent = message.rawContent ?? message.content;\n updateMessagePresentation(message, message.references);\n }\n\n this.addMessageInternal(message);\n this.hidePlaceholder();\n\n this.$nextTick(() => {\n // Render any pending charts once the DOM is updated\n renderChartsInMessage(message);\n this.scrollToBottom();\n });\n },\n addMessages(messages) {\n\n for (let i = 0; i < messages.length; i++) {\n this.addMessageInternal(messages[i]);\n }\n\n this.hidePlaceholder();\n this.$nextTick(() => {\n this.scrollToBottom();\n });\n },\n hidePlaceholder() {\n if (this.placeholder) {\n this.placeholder.classList.add('d-none');\n }\n this.isPlaceholderVisible = false;\n },\n showPlaceholder() {\n if (this.placeholder) {\n this.placeholder.classList.remove('d-none');\n }\n this.isPlaceholderVisible = true;\n },\n isOrchestratorAvailable() {\n return config.isOrchestratorAvailable !== false;\n },\n applyOrchestratorAvailability() {\n if (this.isOrchestratorAvailable()) {\n return true;\n }\n\n const unavailableMessage = config.orchestratorUnavailableMessage || \"This orchestrator is not currently available.\";\n\n if (this.inputElement) {\n this.inputElement.disabled = true;\n this.inputElement.value = '';\n this.inputElement.placeholder = unavailableMessage;\n }\n\n if (this.buttonElement) {\n this.buttonElement.disabled = true;\n }\n\n if (this.micButtonElement) {\n this.micButtonElement.disabled = true;\n this.micButtonElement.style.display = 'none';\n }\n\n if (this.conversationButtonElement) {\n this.conversationButtonElement.disabled = true;\n this.conversationButtonElement.style.display = 'none';\n }\n\n return false;\n },\n fireEvent(event) {\n document.dispatchEvent(event);\n },\n isIndicator(message) {\n return message.role === 'indicator';\n },\n sendMessage() {\n if (!this.applyOrchestratorAvailability()) {\n return;\n }\n\n let trimmedPrompt = this.prompt.trim();\n\n if (!trimmedPrompt) {\n return;\n }\n\n // Stop any active recording before sending.\n if (this.isRecording) {\n this.stopRecording();\n }\n\n // Prevent stale ReceiveTranscript events from repopulating the prompt.\n this._audioInputSent = true;\n\n // In single-response mode, clear all previous messages.\n if (this.singleResponseMode) {\n this.messages.splice(0, this.messages.length);\n }\n\n this.addMessage({\n role: 'user',\n content: trimmedPrompt\n });\n\n this.streamMessage(this.getProfileId(), trimmedPrompt, null);\n this.inputElement.value = '';\n this.prompt = '';\n },\n startRecording() {\n if (this.isRecording || !this.connection) {\n return;\n }\n\n navigator.mediaDevices.getUserMedia({ audio: { echoCancellation: true, noiseSuppression: true, autoGainControl: true } })\n .then(stream => {\n this.preRecordingPrompt = this.prompt;\n this._audioInputSent = false;\n\n var subject = new signalR.Subject();\n var profileId = this.getProfileId();\n var sessionId = this.getSessionId() || '';\n\n // Capture raw 16 kHz PCM (16-bit mono) via Web Audio instead of MediaRecorder.\n // Browsers only agree on WebM/Opus for MediaRecorder, and Azure's speech SDK cannot\n // demux that container from a streaming push (it fails inside GStreamer). Raw PCM is\n // decoded natively with no GStreamer and is produced identically by every browser.\n this._sttCapture = this._createPcmCapture(stream, (base64) => {\n try { subject.next(base64); } catch (err) { /* completed */ }\n });\n this._sttSubject = subject;\n\n var rate = (this._sttCapture && this._sttCapture.sampleRate) || 16000;\n var language = navigator.language || document.documentElement.lang || 'en-US';\n this.connection.send(\"SendAudioStream\", profileId, sessionId, subject, \"audio/pcm;rate=\" + rate, language);\n this.isRecording = true;\n this.updateMicButton();\n })\n .catch(err => {\n console.error('Microphone access denied:', err);\n });\n },\n stopRecording() {\n if (!this.isRecording) {\n return;\n }\n\n this._stopPcmCapture(this._sttCapture);\n this._sttCapture = null;\n if (this._sttSubject) {\n try { this._sttSubject.complete(); } catch (err) { /* already completed */ }\n this._sttSubject = null;\n }\n this.isRecording = false;\n this.updateMicButton();\n },\n // Captures microphone audio as raw 16 kHz, 16-bit mono PCM using Web Audio and invokes\n // onChunk(base64Pcm, rms) for each block. Returns a handle for _stopPcmCapture. This replaces\n // MediaRecorder so every browser streams a format Azure decodes without GStreamer.\n _createPcmCapture(stream, onChunk) {\n var AudioCtx = window.AudioContext || window.webkitAudioContext;\n // Ask the browser to resample the mic to 16 kHz; fall back to manual resampling if it will not.\n var audioContext;\n try {\n audioContext = new AudioCtx({ sampleRate: 16000 });\n } catch (e) {\n audioContext = new AudioCtx();\n }\n var srcRate = audioContext.sampleRate;\n var source = audioContext.createMediaStreamSource(stream);\n var processor = audioContext.createScriptProcessor(4096, 1, 1);\n var self = this;\n processor.onaudioprocess = function (e) {\n var input = e.inputBuffer.getChannelData(0);\n var pcm16 = self._downsampleToInt16(input, srcRate, 16000);\n if (!pcm16 || pcm16.length === 0) {\n return;\n }\n var sum = 0;\n for (var i = 0; i < pcm16.length; i++) {\n var v = pcm16[i] / 32768;\n sum += v * v;\n }\n var rms = Math.sqrt(sum / pcm16.length);\n var bytes = new Uint8Array(pcm16.buffer);\n var binary = '';\n for (var j = 0; j < bytes.length; j++) {\n binary += String.fromCharCode(bytes[j]);\n }\n onChunk(btoa(binary), rms);\n };\n source.connect(processor);\n // Some browsers only fire onaudioprocess while the node is connected to a destination.\n processor.connect(audioContext.destination);\n return { audioContext: audioContext, source: source, processor: processor, stream: stream, sampleRate: 16000 };\n },\n _stopPcmCapture(capture) {\n if (!capture) {\n return;\n }\n try { if (capture.processor) { capture.processor.onaudioprocess = null; capture.processor.disconnect(); } } catch (e) { }\n try { if (capture.source) { capture.source.disconnect(); } } catch (e) { }\n try { if (capture.stream) { capture.stream.getTracks().forEach(function (t) { t.stop(); }); } } catch (e) { }\n try { if (capture.audioContext) { capture.audioContext.close(); } } catch (e) { }\n },\n // Converts a Float32 sample block to 16-bit PCM, resampling from srcRate to dstRate when needed.\n _downsampleToInt16(input, srcRate, dstRate) {\n var s, i;\n if (!(dstRate < srcRate)) {\n var same = new Int16Array(input.length);\n for (i = 0; i < input.length; i++) {\n s = Math.max(-1, Math.min(1, input[i]));\n same[i] = s < 0 ? s * 0x8000 : s * 0x7FFF;\n }\n return same;\n }\n var ratio = srcRate / dstRate;\n var newLen = Math.floor(input.length / ratio);\n var out = new Int16Array(newLen);\n for (var j = 0; j < newLen; j++) {\n var idx = j * ratio;\n var i0 = Math.floor(idx);\n var i1 = (i0 + 1 < input.length) ? i0 + 1 : input.length - 1;\n var frac = idx - i0;\n s = input[i0] * (1 - frac) + input[i1] * frac;\n s = Math.max(-1, Math.min(1, s));\n out[j] = s < 0 ? s * 0x8000 : s * 0x7FFF;\n }\n return out;\n },\n toggleRecording() {\n if (this.isRecording) {\n this.stopRecording();\n } else {\n this.startRecording();\n }\n },\n updateMicButton() {\n if (!this.micButton) {\n return;\n }\n\n if (this.isRecording) {\n this.micButton.classList.add('stt-recording');\n this.micButton.innerHTML = '<i class=\"fa-solid fa-stop\"></i>';\n } else {\n this.micButton.classList.remove('stt-recording');\n this.micButton.innerHTML = '<i class=\"fa-solid fa-microphone\"></i>';\n }\n },\n streamMessage(profileId, trimmedPrompt, sessionProfileId) {\n\n if (this.stream) {\n this.stream.dispose();\n this.stream = null;\n }\n\n this.streamingStarted();\n this.showTypingIndicator();\n this.autoScroll = true;\n\n var content = '';\n var references = {};\n var lastResponseId = null;\n\n // Get the index after showing typing indicator.\n var messageIndex = this.messages.length;\n var currentSessionId = this.getSessionId();\n\n this.stream = this.connection.stream(\"SendMessage\", profileId, trimmedPrompt, currentSessionId, sessionProfileId)\n .subscribe({\n next: (chunk) => {\n let message = this.messages[messageIndex];\n\n if (!message) {\n\n if (chunk.sessionId && !currentSessionId) {\n this.initializeSession(chunk.sessionId);\n }\n\n this.hideTypingIndicator();\n // Re-assign the index after hiding the typing indicator.\n messageIndex = this.messages.length;\n let newMessage = {\n id: chunk.messageId,\n role: \"assistant\",\n title: chunk.title,\n content: \"\",\n htmlContent: \"\",\n isStreaming: true,\n userRating: null,\n };\n\n this.messages.push(newMessage);\n\n message = newMessage;\n }\n\n if (chunk.title && (!message.title || message.title !== chunk.title)) {\n message.title = chunk.title;\n }\n\n if (chunk.references && typeof chunk.references === \"object\" && Object.keys(chunk.references).length) {\n\n for (const [key, value] of Object.entries(chunk.references)) {\n references[key] = normalizeReference(value) ?? {};\n }\n }\n\n if (chunk.content) {\n\n // When the responseId changes (e.g., after an internal tool call),\n // insert a line break to visually separate response segments.\n if (chunk.responseId && lastResponseId && chunk.responseId !== lastResponseId) {\n content += '\\n\\n';\n }\n\n if (chunk.responseId) {\n lastResponseId = chunk.responseId;\n }\n\n content += chunk.content;\n }\n\n // Update the existing message\n message.rawContent = content;\n updateMessagePresentation(message, references);\n\n this.messages[messageIndex] = message;\n\n this.$nextTick(() => {\n renderChartsInMessage(message);\n this.scrollToBottom();\n });\n },\n complete: () => {\n this.processReferences(references, messageIndex);\n this.streamingFinished();\n\n let msg = this.messages[messageIndex];\n if (msg) {\n msg.isStreaming = false;\n }\n\n if (!msg || !msg.content) {\n // No content received at all.\n this.hideTypingIndicator();\n }\n\n // Trigger text-to-speech only in conversation mode.\n if (this.isConversationMode && this.textToSpeechEnabled && msg && msg.content) {\n this.synthesizeSpeech(msg.content);\n }\n\n this.stream?.dispose();\n this.stream = null;\n },\n error: (err) => {\n this.processReferences(references, messageIndex);\n this.streamingFinished();\n\n let msg = this.messages[messageIndex];\n if (msg) {\n msg.isStreaming = false;\n }\n\n this.hideTypingIndicator();\n\n if (!this.isNavigatingAway) {\n this.addMessage(this.getServiceDownMessage());\n }\n\n this.stream?.dispose();\n this.stream = null;\n\n console.error(\"Stream error:\", err);\n }\n });\n },\n getServiceDownMessage() {\n let newMessage = {\n role: \"assistant\",\n content: \"Our service is currently unavailable. Please try again later. We apologize for the inconvenience.\",\n htmlContent: \"\",\n };\n\n return newMessage;\n },\n getErrorMessage(error) {\n var content = (typeof error === 'string' && error.trim())\n ? error\n : \"Something went wrong. Please try again.\";\n\n return {\n role: \"assistant\",\n content: content,\n htmlContent: \"\",\n };\n },\n processReferences(references, messageIndex) {\n references = normalizeReferences(references);\n\n if (Object.keys(references).length) {\n\n let message = this.messages[messageIndex];\n message.rawContent = message.rawContent ?? message.content ?? '';\n updateMessagePresentation(message, references);\n\n this.messages[messageIndex] = message;\n\n this.$nextTick(() => {\n renderChartsInMessage(message);\n this.scrollToBottom();\n });\n }\n },\n streamingStarted() {\n var stopIcon = this.buttonElement.getAttribute('data-stop-icon');\n\n if (stopIcon) {\n this.buttonElement.replaceChildren(DOMPurify.sanitize(stopIcon, { RETURN_DOM_FRAGMENT: true }));\n }\n\n if (this.inputElement) {\n this.inputElement.setAttribute('disabled', 'disabled');\n }\n },\n streamingFinished() {\n var startIcon = this.buttonElement.getAttribute('data-start-icon');\n\n if (startIcon) {\n this.buttonElement.replaceChildren(DOMPurify.sanitize(startIcon, { RETURN_DOM_FRAGMENT: true }));\n }\n\n if (this.inputElement) {\n this.inputElement.removeAttribute('disabled');\n this.inputElement.focus();\n }\n\n // Directly manipulate the DOM to stop all streaming animations.\n if (this.chatContainer) {\n var icons = this.chatContainer.querySelectorAll('.ai-streaming-icon');\n for (var i = 0; i < icons.length; i++) {\n icons[i].classList.remove('ai-streaming-icon');\n icons[i].classList.add('ai-bot-icon');\n }\n }\n\n // Also update Vue data for consistency.\n for (var i = 0; i < this.messages.length; i++) {\n if (this.messages[i].isStreaming) {\n this.messages[i].isStreaming = false;\n }\n }\n },\n handleExternalTtsStop(e) {\n if (e?.detail?.sourceId === this.ttsInstanceId) {\n return;\n }\n\n this.stopAudio(false);\n },\n updateTtsPlaybackButtons() {\n if (!this.chatContainer) {\n return;\n }\n\n var buttons = this.chatContainer.querySelectorAll('[data-tts-message-index]');\n\n buttons.forEach(button => {\n var buttonIndex = Number(button.getAttribute('data-tts-message-index'));\n var isPlaying = buttonIndex === this.ttsPlayingMessageIndex;\n\n button.classList.toggle('tts-playing', isPlaying);\n button.setAttribute('title', isPlaying ? 'Pause audio' : 'Read aloud');\n });\n },\n updateCopyButtons() {\n if (!this.chatContainer) {\n return;\n }\n\n var buttons = this.chatContainer.querySelectorAll('[data-copy-message-index]');\n\n buttons.forEach(button => {\n var buttonIndex = Number(button.getAttribute('data-copy-message-index'));\n var isCopied = buttonIndex === this.copiedMessageIndex;\n var iconHtml = isCopied\n ? '<i class=\"fa-solid fa-check\"></i>'\n : '<i class=\"fa-solid fa-copy\"></i>';\n\n button.classList.toggle('text-success', isCopied);\n button.classList.toggle('text-secondary', !isCopied);\n button.setAttribute('title', isCopied ? this.copiedTitle : this.copyTitle);\n button.replaceChildren(DOMPurify.sanitize(iconHtml, { RETURN_DOM_FRAGMENT: true }));\n });\n },\n setCopyButtonState(button, isCopied) {\n if (!button) {\n return;\n }\n\n var iconHtml = isCopied\n ? '<i class=\"fa-solid fa-check\"></i>'\n : '<i class=\"fa-solid fa-copy\"></i>';\n\n button.classList.toggle('text-success', isCopied);\n button.classList.toggle('text-secondary', !isCopied);\n button.setAttribute('title', isCopied ? this.copiedTitle : this.copyTitle);\n button.replaceChildren(DOMPurify.sanitize(iconHtml, { RETURN_DOM_FRAGMENT: true }));\n },\n synthesizeSpeech(text, cacheIndex) {\n if (!this.textToSpeechEnabled || !text || !this.connection) {\n return;\n }\n\n this.audioChunks = [];\n this.isPlayingAudio = true;\n this._ttsCacheIndex = cacheIndex !== undefined ? cacheIndex : -1;\n\n this.connection.invoke(\"SynthesizeSpeech\", this.getProfileId(), this.getSessionId(), text, this.ttsVoiceName)\n .catch(err => {\n console.error(\"TTS synthesis error:\", err);\n this.isPlayingAudio = false;\n this.ttsPlayingMessageIndex = -1;\n this._ttsCacheIndex = -1;\n this.$nextTick(() => this.updateTtsPlaybackButtons());\n });\n },\n toggleMessageTts(message, index) {\n if (this.ttsPlayingMessageIndex === index) {\n this.stopAudio();\n return;\n }\n\n this.stopAudio(false);\n window.dispatchEvent(new CustomEvent('crestapps-ai-chat-stop-tts', {\n detail: { sourceId: this.ttsInstanceId }\n }));\n this.ttsPlayingMessageIndex = index;\n this.$nextTick(() => this.updateTtsPlaybackButtons());\n\n if (this.ttsAudioCache[index]) {\n this.playAudioBlob(this.ttsAudioCache[index]);\n return;\n }\n\n this.synthesizeSpeech(message.content, index);\n },\n playCollectedAudio() {\n if (this.audioChunks.length === 0) {\n if (!this.currentAudioElement && this.audioPlayQueue.length === 0) {\n this.isPlayingAudio = false;\n this.ttsPlayingMessageIndex = -1;\n this.$nextTick(() => this.updateTtsPlaybackButtons());\n }\n return;\n }\n\n const totalLength = this.audioChunks.reduce((sum, chunk) => sum + chunk.length, 0);\n const combined = new Uint8Array(totalLength);\n let offset = 0;\n for (const chunk of this.audioChunks) {\n combined.set(chunk, offset);\n offset += chunk.length;\n }\n this.audioChunks = [];\n\n const blob = new Blob([combined], { type: 'audio/mp3' });\n\n if (this._ttsCacheIndex >= 0) {\n this.ttsAudioCache[this._ttsCacheIndex] = blob;\n this._ttsCacheIndex = -1;\n }\n\n // If audio is already playing, queue this blob for sequential playback.\n if (this.currentAudioElement) {\n this.audioPlayQueue.push(blob);\n return;\n }\n\n this.playAudioBlob(blob);\n },\n playAudioBlob(blob) {\n const url = URL.createObjectURL(blob);\n const audio = new Audio(url);\n\n this.currentAudioUrl = url;\n this.currentAudioElement = audio;\n this.isPlayingAudio = true;\n\n audio.addEventListener('ended', () => {\n this.currentAudioElement = null;\n this.currentAudioUrl = null;\n URL.revokeObjectURL(url);\n this.playNextInQueue();\n });\n\n audio.addEventListener('error', () => {\n this.currentAudioElement = null;\n this.currentAudioUrl = null;\n URL.revokeObjectURL(url);\n this.playNextInQueue();\n });\n\n audio.play().catch(err => {\n console.error(\"Audio playback error:\", err);\n this.currentAudioElement = null;\n this.currentAudioUrl = null;\n URL.revokeObjectURL(url);\n this.audioPlayQueue = [];\n this.isPlayingAudio = false;\n this.ttsPlayingMessageIndex = -1;\n this.$nextTick(() => this.updateTtsPlaybackButtons());\n });\n },\n playNextInQueue() {\n if (this.audioPlayQueue.length > 0) {\n var nextBlob = this.audioPlayQueue.shift();\n this.playAudioBlob(nextBlob);\n } else {\n this.isPlayingAudio = false;\n this.ttsPlayingMessageIndex = -1;\n this.$nextTick(() => this.updateTtsPlaybackButtons());\n this.conversationModeOnAudioEnded();\n }\n },\n stopAudio() {\n if (this.currentAudioElement) {\n this.currentAudioElement.pause();\n this.currentAudioElement.currentTime = 0;\n this.currentAudioElement = null;\n }\n if (this.currentAudioUrl) {\n URL.revokeObjectURL(this.currentAudioUrl);\n this.currentAudioUrl = null;\n }\n this.audioChunks = [];\n this.audioPlayQueue = [];\n this.isPlayingAudio = false;\n this.ttsPlayingMessageIndex = -1;\n this.$nextTick(() => this.updateTtsPlaybackButtons());\n },\n toggleConversationMode() {\n if (this.realtimeEnabled) {\n // Realtime is driven by the shared module, which owns the button; this only exists for\n // callers that toggle programmatically.\n if (this.realtimeController) { this.realtimeController.toggle(); }\n\n return;\n }\n\n if (this.isConversationMode) {\n this.stopConversationMode();\n } else {\n this.startConversationMode();\n }\n },\n // Force-stop any in-progress voice/realtime session (mic, playback, and the streamed audio),\n // e.g. before starting a new chat or switching sessions, so it never keeps running in the background.\n forceStopActiveVoice() {\n if (!this.isConversationMode) {\n return;\n }\n if (this.realtimeEnabled) {\n this.stopRealtimeConversation();\n } else {\n this.stopConversationMode();\n }\n },\n startRealtimeConversation() {\n if (this.realtimeController) { this.realtimeController.start(); }\n },\n stopRealtimeConversation() {\n if (this.realtimeController) { this.realtimeController.stop(); }\n },\n // Realtime (speech-to-speech) is the shared CoreAIRealtime module (realtime-audio.js): microphone\n // capture and gating, the WebRTC transport with its WebSocket fallback, playback, the settings\n // popover, push-to-talk, and the server-driven session lifecycle all live there, so this app and the\n // chat-interaction client cannot drift apart. What is wired here is only how the module reaches this\n // app's hub and transcript.\n setupRealtimeController(config) {\n if (this.realtimeController || !this.conversationButton) { return; }\n if (!window.CoreAIRealtime || typeof window.CoreAIRealtime.attach !== 'function') {\n console.error('realtime-audio.js is not loaded; realtime voice is unavailable on this page.');\n\n return;\n }\n\n var self = this;\n this.realtimeController = window.CoreAIRealtime.attach({\n connection: this.connection,\n ensureConnected: function () {\n return self.ensureConnectionStarted().then(function (connected) {\n if (!connected) { throw new Error('The chat connection is not available.'); }\n\n return connected;\n });\n },\n sendStart: function (subject, voice, language, silenceMs, vadThreshold, allowInterruption) {\n self.connection.send('StartRealtimeConversation', self.getProfileId(), self.getSessionId() || '', subject, voice, language, silenceMs, vadThreshold, allowInterruption);\n },\n webRtcEnabled: this.realtimeWebRtcEnabled,\n sendStartWebRtc: function (offerSdp, voice, language, silenceMs, vadThreshold, allowInterruption) {\n self.connection.send('StartRealtimeWebRtc', self.getProfileId(), self.getSessionId() || '', offerSdp, voice, language, silenceMs, vadThreshold, allowInterruption);\n },\n webRtcIceServers: this.realtimeWebRtcIceServers || undefined,\n voiceName: this.realtimeVoiceName || '',\n getVoiceName: function () { return self.realtimeVoiceName || ''; },\n realtimeEnabled: true,\n // The conversation button doubles as the realtime button on this host; the module owns its\n // click, label and state from here on.\n selectors: { realtimeButton: config.conversationButtonElementSelector },\n onActivate: function () {\n self.isConversationMode = true;\n self._conversationAssistantMessage = null;\n self._conversationPartialMessage = null;\n self.removeNotification('conversation-ended');\n },\n onDeactivate: function () {\n self.isConversationMode = false;\n self.finishRealtimeConversationCleanup();\n },\n onUserTurnPending: function (turnId) { self.addRealtimePendingTurn(turnId); },\n onUserTurnDropped: function (turnId) { self.dropRealtimePendingTurn(turnId); }\n });\n },\n // Shared teardown tail: clears any in-flight streaming state and shows the conversation-ended\n // notification.\n finishRealtimeConversationCleanup() {\n if (this._conversationAssistantMessage) {\n var m = this.messages[this._conversationAssistantMessage.index];\n if (m) { m.isStreaming = false; }\n this._conversationAssistantMessage = null;\n }\n for (var i = 0; i < this.messages.length; i++) {\n if (this.messages[i].isStreaming) { this.messages[i].isStreaming = false; }\n }\n\n this.receiveNotification({\n type: 'conversation-ended',\n content: 'Conversation ended.',\n icon: 'fa-solid fa-circle-check',\n dismissible: true,\n autoDismissMs: 5000\n });\n },\n // The utterance has been captured but not transcribed yet. Showing a placeholder now puts the\n // prompt above the reply it produces: transcription lags the spoken answer, so a bubble added only\n // when the text arrives lands underneath its own reply.\n addRealtimePendingTurn(turnId) {\n if (!turnId) { return; }\n this._realtimePendingTurns = this._realtimePendingTurns || {};\n var index = this.messages.length;\n this.addMessage({ role: 'user', content: '', isPartial: true });\n this._realtimePendingTurns[turnId] = this.messages[index];\n },\n fillRealtimePendingTurn(pending, text) {\n if (!pending) { return; }\n if (!text) {\n var emptyAt = this.messages.indexOf(pending);\n if (emptyAt >= 0) { this.messages.splice(emptyAt, 1); }\n\n return;\n }\n var escaped = text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n pending.content = text;\n pending.htmlContent = '<p>' + escaped + '</p>';\n pending.isPartial = false;\n },\n dropRealtimePendingTurn(turnId) {\n if (!turnId || !this._realtimePendingTurns) { return; }\n var dropped = this._realtimePendingTurns[turnId];\n if (!dropped) { return; }\n delete this._realtimePendingTurns[turnId];\n var at = this.messages.indexOf(dropped);\n if (at >= 0) { this.messages.splice(at, 1); }\n },\n startConversationMode() {\n if (!this.conversationModeEnabled || this.isConversationMode || !this.connection) {\n return;\n }\n\n this.isConversationMode = true;\n this.updateConversationButton();\n this._conversationPartialTranscript = '';\n this._conversationAssistantMessage = null;\n this._conversationPartialMessage = null;\n\n // Remove any previous conversation ended notification.\n this.removeNotification('conversation-ended');\n navigator.mediaDevices.getUserMedia({ audio: { echoCancellation: true, noiseSuppression: true, autoGainControl: true } })\n .then(stream => {\n this._conversationSubject = new signalR.Subject();\n this._conversationStream = stream;\n\n // RMS (0..1) above which speech during TTS playback counts as an interrupt.\n var interruptRmsThreshold = 0.12;\n\n // Capture raw 16 kHz PCM (16-bit mono) via Web Audio instead of MediaRecorder — see\n // startRecording for why WebM/Opus is avoided. The per-block RMS drives interrupt\n // detection during TTS playback, replacing the previous AnalyserNode.\n this._conversationCapture = this._createPcmCapture(stream, (base64, rms) => {\n if (this.isPlayingAudio && rms >= interruptRmsThreshold) {\n // User is speaking over TTS — interrupt playback.\n this.stopAudio();\n }\n try {\n this._conversationSubject.next(base64);\n } catch (err) {\n // Subject may have been completed already.\n }\n });\n\n var profileId = this.getProfileId();\n var sessionId = this.getSessionId() || '';\n var language = navigator.language || document.documentElement.lang || 'en-US';\n var rate = (this._conversationCapture && this._conversationCapture.sampleRate) || 16000;\n\n this.connection.send(\"StartConversation\", profileId, sessionId, this._conversationSubject, \"audio/pcm;rate=\" + rate, language);\n this.isRecording = true;\n })\n .catch(err => {\n console.error('Microphone access denied:', err);\n this.isConversationMode = false;\n this.updateConversationButton();\n });\n },\n stopConversationMode() {\n if (!this.isConversationMode) {\n return;\n }\n\n this.isConversationMode = false;\n this.updateConversationButton();\n\n // Signal the server to cancel all in-progress STT/TTS streams immediately.\n if (this.connection) {\n this.connection.invoke(\"StopConversation\").catch(function () { });\n }\n\n if (this.isRecording) {\n this._stopPcmCapture(this._conversationCapture);\n this._conversationCapture = null;\n if (this._conversationSubject) {\n try { this._conversationSubject.complete(); } catch (err) { /* already completed */ }\n }\n this.isRecording = false;\n }\n\n this.stopAudio();\n this._conversationPartialTranscript = '';\n this._conversationPartialMessage = null;\n\n // Mark any in-flight assistant message as done to stop the spinner.\n if (this._conversationAssistantMessage) {\n var msg = this.messages[this._conversationAssistantMessage.index];\n if (msg) {\n msg.isStreaming = false;\n }\n this._conversationAssistantMessage = null;\n }\n\n // Safety net: clear all lingering streaming indicators.\n for (var i = 0; i < this.messages.length; i++) {\n if (this.messages[i].isStreaming) {\n this.messages[i].isStreaming = false;\n }\n }\n\n // Show a \"conversation ended\" notification system message.\n this.receiveNotification({\n type: 'conversation-ended',\n content: 'Conversation ended.',\n icon: 'fa-solid fa-circle-check',\n dismissible: true,\n autoDismissMs: 5000\n });\n },\n updateConversationButton() {\n if (!this.conversationButton) {\n return;\n }\n\n if (this.isConversationMode) {\n this.conversationButton.classList.add('active', 'btn-primary');\n this.conversationButton.classList.remove('btn-dark', 'btn-outline-dark', 'btn-outline-secondary');\n this.conversationButton.title = this.conversationButton.getAttribute('data-end-title') || 'End Conversation';\n var endHtml = this.conversationButton.getAttribute('data-end-html');\n if (endHtml) {\n this.conversationButton.replaceChildren(DOMPurify.sanitize(endHtml, { RETURN_DOM_FRAGMENT: true }));\n }\n } else {\n this.conversationButton.classList.remove('active', 'btn-primary');\n this.conversationButton.classList.remove('btn-dark', 'btn-outline-secondary');\n this.conversationButton.classList.add('btn-outline-dark');\n this.conversationButton.blur();\n this.conversationButton.title = this.conversationButton.getAttribute('data-start-title') || 'Start Conversation';\n var startHtml = this.conversationButton.getAttribute('data-start-html');\n if (startHtml) {\n this.conversationButton.replaceChildren(DOMPurify.sanitize(startHtml, { RETURN_DOM_FRAGMENT: true }));\n }\n }\n },\n conversationModeSendPrompt() {\n // Legacy: only used by AudioInput mode's ReceiveTranscript.\n },\n conversationModeOnAudioEnded() {\n // Legacy: in conversation mode, audio playback continuation\n // is handled by the persistent stream. This method is only\n // called from playCollectedAudio for non-conversation TTS.\n },\n generatePrompt(element) {\n if (!element) {\n console.error('The element paramter is required.');\n\n return;\n }\n\n let templateProfileId = element.getAttribute('data-profile-id');\n let sessionId = this.getSessionId();\n let sessionProfileId = this.getProfileId();\n\n if (!templateProfileId || !sessionId) {\n\n console.error('The given element is missing data-profile-id or the session has not yet started.');\n return;\n }\n\n // streamMessage() already shows the typing indicator.\n this.streamMessage(templateProfileId, null, sessionProfileId);\n },\n createSessionUrl(baseUrl, param, value) {\n\n const fullUrl = baseUrl.toLowerCase().startsWith('http') ? baseUrl : window.location.origin + baseUrl;\n const url = new URL(fullUrl);\n\n url.searchParams.set(param, value);\n\n return url.toString();\n },\n showTypingIndicator() {\n this.addMessage({\n role: 'indicator',\n htmlContent: config.indicatorTemplate\n });\n },\n hideTypingIndicator() {\n const originalLength = this.messages.length;\n this.messages = this.messages.filter(msg => msg.role !== 'indicator');\n const removedCount = originalLength - this.messages.length;\n return removedCount;\n },\n receiveNotification(notification) {\n if (!notification || !notification.type) {\n return;\n }\n this.clearNotificationDismiss(notification.type);\n var existingIndex = this.notifications.findIndex(n => n.type === notification.type);\n if (existingIndex >= 0) {\n this.notifications.splice(existingIndex, 1, notification);\n } else {\n this.notifications.push(notification);\n }\n this.scheduleNotificationDismiss(notification);\n this.$nextTick(() => {\n this.scrollToBottom();\n });\n },\n updateNotification(notification) {\n if (!notification || !notification.type) {\n return;\n }\n this.clearNotificationDismiss(notification.type);\n var existingIndex = this.notifications.findIndex(n => n.type === notification.type);\n if (existingIndex >= 0) {\n this.notifications.splice(existingIndex, 1, notification);\n this.scheduleNotificationDismiss(notification);\n }\n },\n scheduleNotificationDismiss(notification) {\n if (!notification || !notification.type || !notification.autoDismissMs || notification.autoDismissMs <= 0) {\n return;\n }\n this.notificationDismissTimers[notification.type] = setTimeout(() => {\n this.removeNotification(notification.type);\n }, notification.autoDismissMs);\n },\n clearNotificationDismiss(notificationType) {\n var timerId = this.notificationDismissTimers[notificationType];\n if (!timerId) {\n return;\n }\n clearTimeout(timerId);\n delete this.notificationDismissTimers[notificationType];\n },\n removeNotification(notificationType) {\n this.clearNotificationDismiss(notificationType);\n this.notifications = this.notifications.filter(n => n.type !== notificationType);\n },\n dismissNotification(notificationType) {\n this.removeNotification(notificationType);\n },\n handleNotificationAction(notificationType, actionName) {\n if (!this.connection) {\n return;\n }\n var sessionId = this.getSessionId();\n this.connection.invoke(\"HandleNotificationAction\", sessionId, notificationType, actionName).catch(function (err) {\n console.error(\"Error handling notification action:\", err);\n });\n },\n scrollToBottom() {\n if (!this.autoScroll) {\n return;\n }\n setTimeout(() => {\n this.chatContainer.scrollTop = this.chatContainer.scrollHeight - this.chatContainer.clientHeight;\n }, 50);\n },\n handleUserInput(event) {\n this.prompt = event.target.value;\n },\n getProfileId() {\n return this.inputElement\n ? this.inputElement.getAttribute('data-profile-id')\n : null;\n },\n setSessionId(sessionId) {\n if (!this.inputElement) {\n return;\n }\n\n this.inputElement.setAttribute('data-session-id', sessionId || '');\n },\n resetSession() {\n // Force-stop an in-progress voice/realtime conversation so it doesn't keep running under the new session.\n this.forceStopActiveVoice();\n this.stopRecording();\n this.rejectPendingSessionRequest('Session was reset.');\n this.setSessionId('');\n this.isSessionStarted = false;\n this.sessionRating = null;\n this.messages = [];\n this.documents = [];\n\n // When an initial prompt is configured, show it as the first\n // assistant message instead of the generic placeholder.\n if (config.initialPrompt) {\n this.addMessage({\n role: 'assistant',\n content: config.initialPrompt\n });\n } else {\n this.showPlaceholder();\n }\n\n if (widgetBehavior && typeof widgetBehavior.onSessionReset === 'function') {\n widgetBehavior.onSessionReset(this, config);\n }\n },\n startNewSession() {\n if (!this.applyOrchestratorAvailability()) {\n return;\n }\n\n const profileId = this.getProfileId();\n if (!profileId || !this.connection) {\n return;\n }\n\n // Force-stop any live voice/realtime session before starting a new chat.\n this.forceStopActiveVoice();\n this.requestNewSession(profileId).catch(err => console.error(err));\n },\n async ensureSessionForDocuments(profileId) {\n var sessionId = this.getSessionId();\n if (sessionId) {\n return sessionId;\n }\n\n if (!profileId || !this.connection) {\n return null;\n }\n\n return await this.requestNewSession(profileId);\n },\n requestNewSession(profileId) {\n if (this.pendingSessionPromise) {\n return this.pendingSessionPromise;\n }\n\n if (!profileId || !this.connection) {\n return Promise.resolve(null);\n }\n\n this.pendingSessionPromise = new Promise((resolve, reject) => {\n this.pendingSessionResolver = resolve;\n this.pendingSessionRejector = reject;\n this.pendingSessionTimeoutId = window.setTimeout(() => {\n this.rejectPendingSessionRequest('Timed out while creating a chat session.');\n }, 15000);\n });\n\n this.connection.invoke(\"StartSession\", profileId, null).catch(err => {\n this.rejectPendingSessionRequest(err);\n });\n\n return this.pendingSessionPromise;\n },\n resolvePendingSessionRequest(sessionId) {\n if (this.pendingSessionResolver) {\n this.pendingSessionResolver(sessionId);\n }\n\n this.clearPendingSessionRequest();\n },\n rejectPendingSessionRequest(error) {\n if (this.pendingSessionRejector) {\n this.pendingSessionRejector(error);\n }\n\n this.clearPendingSessionRequest();\n },\n clearPendingSessionRequest() {\n if (this.pendingSessionTimeoutId) {\n window.clearTimeout(this.pendingSessionTimeoutId);\n }\n\n this.pendingSessionPromise = null;\n this.pendingSessionResolver = null;\n this.pendingSessionRejector = null;\n this.pendingSessionTimeoutId = null;\n },\n initializeApp() {\n this.inputElement = document.querySelector(config.inputElementSelector);\n this.buttonElement = document.querySelector(config.sendButtonElementSelector);\n this.chatContainer = document.querySelector(config.chatContainerElementSelector);\n this.placeholder = document.querySelector(config.placeholderElementSelector);\n\n if (!this.inputElement || !this.buttonElement || !this.chatContainer || !this.placeholder) {\n console.error('AI chat app could not initialize because one or more required elements were not found.', {\n inputElementSelector: config.inputElementSelector,\n sendButtonElementSelector: config.sendButtonElementSelector,\n chatContainerElementSelector: config.chatContainerElementSelector,\n placeholderElementSelector: config.placeholderElementSelector\n });\n\n return false;\n }\n\n this.applyOrchestratorAvailability();\n\n const sessionId = this.getSessionId();\n if (!hasWidgetConfig && sessionId) {\n this.loadSession(sessionId);\n }\n\n // Initialize document bar if enabled.\n if (config.sessionDocumentsEnabled && config.documentBarSelector) {\n this.documentBar = document.querySelector(config.documentBarSelector);\n if (this.documentBar) {\n this.renderDocumentBar();\n\n // Create hidden file input for document uploads.\n var fileInput = document.createElement('input');\n fileInput.type = 'file';\n fileInput.id = 'ai-chat-doc-input';\n fileInput.className = 'd-none';\n fileInput.multiple = true;\n if (config.allowedExtensions) {\n fileInput.accept = config.allowedExtensions;\n }\n fileInput.addEventListener('change', (e) => this.handleFileInputChange(e));\n this.documentBar.parentElement.appendChild(fileInput);\n\n // Set up drag-and-drop on the input area.\n var inputArea = this.inputElement ? this.inputElement.closest('.ai-admin-widget-input, .text-bg-light') : null;\n if (inputArea) {\n inputArea.addEventListener('dragover', (e) => this.handleDragOver(e));\n inputArea.addEventListener('dragleave', (e) => this.handleDragLeave(e));\n inputArea.addEventListener('drop', (e) => this.handleDrop(e));\n }\n }\n }\n\n // Pause auto-scroll when the user manually scrolls up during streaming.\n this.chatContainer.addEventListener('scroll', () => {\n if (!this.stream) {\n return;\n }\n const threshold = 30;\n const atBottom = this.chatContainer.scrollHeight - this.chatContainer.clientHeight - this.chatContainer.scrollTop <= threshold;\n this.autoScroll = atBottom;\n });\n\n this.inputElement.addEventListener('keydown', event => {\n\n if (this.stream != null) {\n return;\n }\n\n if (event.key === \"Enter\" && !event.shiftKey) {\n event.preventDefault();\n this.buttonElement.click();\n }\n });\n\n this.inputElement.addEventListener('input', (e) => {\n this.handleUserInput(e);\n\n if (e.target.value.trim()) {\n this.buttonElement.removeAttribute('disabled');\n } else {\n this.buttonElement.setAttribute('disabled', true);\n }\n });\n\n this.buttonElement.addEventListener('click', () => {\n\n if (this.stream != null) {\n this.stream.dispose();\n this.stream = null;\n\n this.streamingFinished();\n this.hideTypingIndicator();\n\n // Clean up: remove empty assistant message or stop streaming animation.\n if (this.messages.length > 0) {\n const lastMsg = this.messages[this.messages.length - 1];\n if (lastMsg.role === 'assistant' && !lastMsg.content) {\n this.messages.pop();\n } else if (lastMsg.isStreaming) {\n lastMsg.isStreaming = false;\n }\n }\n\n return;\n }\n\n this.sendMessage();\n });\n\n const promptGenerators = document.getElementsByClassName('profile-generated-prompt');\n\n for (var i = 0; i < promptGenerators.length; i++) {\n promptGenerators[i].addEventListener('click', (e) => {\n e.preventDefault();\n this.generatePrompt(e.target);\n });\n }\n\n const chatSessions = document.getElementsByClassName('chat-session-history-item');\n\n for (var i = 0; i < chatSessions.length; i++) {\n chatSessions[i].addEventListener('click', (e) => {\n e.preventDefault();\n\n var sessionId = e.target.getAttribute('data-session-id');\n\n if (!sessionId) {\n console.error('an element with the class chat-session-history-item with no data-session-id set.');\n\n return;\n }\n\n this.loadSession(sessionId);\n this.showChatScreen();\n });\n }\n\n const initialMessages = Array.isArray(config.messages) ? config.messages : [];\n\n for (let i = 0; i < initialMessages.length; i++) {\n this.addMessage(initialMessages[i]);\n }\n\n // When no messages were loaded and an initial prompt is configured,\n // display it as the first assistant message without invoking the AI.\n if (this.messages.length === 0 && config.initialPrompt) {\n this.addMessage({\n role: 'assistant',\n content: config.initialPrompt\n });\n }\n\n // Update feedback icons in the DOM after initial messages have rendered.\n this.$nextTick(() => {\n this.refreshAllFeedbackIcons();\n });\n\n // Delegate click for code block copy buttons.\n if (this.chatContainer) {\n this.chatContainer.addEventListener('click', (e) => {\n var btn = e.target.closest('.ai-code-copy-btn');\n if (!btn) {\n return;\n }\n\n var block = btn.closest('.ai-code-block') || btn.closest('pre');\n if (!block) {\n return;\n }\n\n var codeEl = block.querySelector('code');\n if (codeEl) {\n navigator.clipboard.writeText(codeEl.textContent);\n var copiedText = config.codeCopiedText || 'Copied!';\n btn.innerHTML = '<i class=\"fa-solid fa-check\"></i> ' + copiedText;\n setTimeout(() => {\n btn.innerHTML = '<i class=\"fa-regular fa-copy\"></i>';\n }, 2000);\n }\n });\n }\n\n // Initialize speech-to-text microphone button.\n if (this.speechToTextEnabled && config.micButtonElementSelector) {\n this.micButton = document.querySelector(config.micButtonElementSelector);\n if (this.micButton) {\n this.micButton.style.display = '';\n this.micButton.addEventListener('click', () => {\n this.toggleRecording();\n });\n }\n }\n\n // Initialize conversation mode button (used for both STT/TTS conversation and realtime).\n if ((this.conversationModeEnabled || this.realtimeEnabled) && config.conversationButtonElementSelector) {\n this.conversationButton = document.querySelector(config.conversationButtonElementSelector);\n if (this.conversationButton) {\n if (this.realtimeEnabled) {\n // The shared realtime module owns the button (click, label, state) and adds the\n // voice settings popover next to it.\n this.setupRealtimeController(config);\n } else {\n this.conversationButton.addEventListener('click', () => {\n this.toggleConversationMode();\n });\n }\n }\n }\n\n return true;\n },\n loadSession(sessionId) {\n this.connection.invoke(\"LoadSession\", sessionId).catch(err => console.error(err));\n },\n reloadCurrentSession() {\n\n var sessionId = this.getSessionId();\n if (sessionId) {\n this.loadSession(sessionId);\n }\n },\n initializeSession(sessionId, force) {\n if (this.isSessionStarted && !force) {\n if (sessionId && this.getSessionId() === sessionId) {\n this.resolvePendingSessionRequest(sessionId);\n }\n\n return\n }\n this.fireEvent(new CustomEvent(\"initializingSessionCoreAIChat\", { detail: { sessionId: sessionId } }))\n this.setSessionId(sessionId);\n this.isSessionStarted = true;\n this.resolvePendingSessionRequest(sessionId);\n\n if (widgetBehavior && typeof widgetBehavior.onSessionInitialized === 'function') {\n widgetBehavior.onSessionInitialized(this, sessionId, config);\n }\n\n // For non-widget pages, update the browser URL so that a page\n // refresh reloads the correct session instead of starting fresh.\n if (!hasWidgetConfig && sessionId && config.sessionUrlTemplate && typeof history !== 'undefined' && history.replaceState) {\n var sessionUrl = config.sessionUrlTemplate.replace('{sessionId}', encodeURIComponent(sessionId));\n history.replaceState(null, '', sessionUrl);\n }\n },\n getSessionId() {\n let sessionId = this.inputElement\n ? this.inputElement.getAttribute('data-session-id')\n : null;\n\n if (!sessionId && widgetBehavior && typeof widgetBehavior.resolveSessionId === 'function') {\n sessionId = widgetBehavior.resolveSessionId(this, config);\n }\n\n return sessionId;\n },\n clearCopiedMessageState() {\n if (this.copyResetTimeoutId) {\n window.clearTimeout(this.copyResetTimeoutId);\n this.copyResetTimeoutId = null;\n }\n\n if (this.activeCopyButton) {\n this.setCopyButtonState(this.activeCopyButton, false);\n this.activeCopyButton = null;\n }\n\n this.copiedMessageIndex = -1;\n },\n copyResponse(message, index, event) {\n const text = message && typeof message === 'object'\n ? message.copyContent ?? message.content ?? ''\n : message ?? '';\n const button = event?.currentTarget || event?.target?.closest?.('[data-copy-message-index]') || null;\n\n navigator.clipboard.writeText(text)\n .then(() => {\n this.clearCopiedMessageState();\n this.copiedMessageIndex = typeof index === 'number' ? index : -1;\n this.activeCopyButton = button;\n\n if (button) {\n this.setCopyButtonState(button, true);\n } else {\n this.$nextTick(() => this.updateCopyButtons());\n }\n\n this.copyResetTimeoutId = window.setTimeout(() => {\n this.clearCopiedMessageState();\n this.$nextTick(() => this.updateCopyButtons());\n }, Number(config.copyResetDelayMs) || 2000);\n })\n .catch(err => console.error('Failed to copy response:', err));\n },\n updateFeedbackIcons(container, userRating) {\n if (!container) {\n return;\n }\n\n var upBtn = container.querySelector('.rate-up-btn');\n var downBtn = container.querySelector('.rate-down-btn');\n\n // Keep feedback icons as simple span-based Font Awesome markup so\n // later state updates do not depend on i2svg replacement.\n if (upBtn) {\n var upClass = userRating === true ? 'fa-solid fa-thumbs-up' : 'fa-regular fa-thumbs-up';\n var upIcon = document.createElement('span');\n upIcon.className = upClass;\n upIcon.style.fontSize = '0.9rem';\n upBtn.textContent = '';\n upBtn.appendChild(upIcon);\n }\n\n if (downBtn) {\n var downClass = userRating === false ? 'fa-solid fa-thumbs-down' : 'fa-regular fa-thumbs-down';\n var downIcon = document.createElement('span');\n downIcon.className = downClass;\n downIcon.style.fontSize = '0.9rem';\n downBtn.textContent = '';\n downBtn.appendChild(downIcon);\n }\n },\n refreshAllFeedbackIcons() {\n var containers = this.$el.querySelectorAll('.ai-chat-message-assistant-feedback');\n\n for (var i = 0; i < containers.length; i++) {\n var msgId = containers[i].getAttribute('data-message-id');\n var msg = this.messages.find(m => m.id === msgId);\n\n if (msg) {\n this.updateFeedbackIcons(containers[i], msg.userRating);\n }\n }\n },\n rateMessage(message, isPositive, event) {\n var sessionId = this.getSessionId();\n\n if (!sessionId || !message.id || !this.connection) {\n return;\n }\n\n // Toggle: clicking the same rating again clears it.\n var newRating = message.userRating === isPositive ? null : isPositive;\n message.userRating = newRating;\n\n // Find the feedback container by message ID for reliable DOM targeting.\n var feedbackContainer = this.$el.querySelector(\n '.ai-chat-message-assistant-feedback[data-message-id=\"' + message.id + '\"]'\n );\n\n this.updateFeedbackIcons(feedbackContainer, newRating);\n\n // Trigger spark animation after Font Awesome has re-processed icons.\n if (newRating !== null && feedbackContainer) {\n setTimeout(() => {\n var btnClass = isPositive ? '.rate-up-btn' : '.rate-down-btn';\n var btn = feedbackContainer.querySelector(btnClass);\n\n if (btn) {\n btn.classList.remove('spark-effect');\n void btn.offsetWidth;\n btn.classList.add('spark-effect');\n btn.addEventListener('animationend', function onEnd() {\n btn.removeEventListener('animationend', onEnd);\n btn.classList.remove('spark-effect');\n });\n }\n }, 50);\n }\n\n this.connection.invoke(\"RateMessage\", sessionId, message.id, isPositive).catch(function (err) {\n console.error('Failed to rate message:', err);\n });\n }\n },\n watch: {\n documents: {\n handler() {\n this.renderDocumentBar();\n if (widgetBehavior && typeof widgetBehavior.onDocumentsChanged === 'function') {\n widgetBehavior.onDocumentsChanged(this, this.documents, config);\n }\n },\n deep: true\n },\n isUploading() { this.renderDocumentBar(); },\n isDocumentOperationPending() { this.renderDocumentBar(); },\n isPlayingAudio() {\n // Reserved for future use — volume-based interrupt detection\n // no longer mutes tracks; browser echo cancellation handles echo.\n },\n copiedMessageIndex() {\n this.$nextTick(() => this.updateCopyButtons());\n },\n isConversationMode(active) {\n // Hide/show mic button.\n if (this.micButton) {\n this.micButton.style.display = active ? 'none' : (this.speechToTextEnabled ? '' : 'none');\n }\n\n // Hide/show send button.\n if (this.buttonElement) {\n this.buttonElement.style.display = active ? 'none' : '';\n }\n\n // Disable/enable textarea.\n if (this.inputElement) {\n this.inputElement.disabled = active;\n if (active) {\n this.inputElement.placeholder = '';\n }\n }\n }\n },\n mounted() {\n (async () => {\n await this.startConnection();\n const isInitialized = this.initializeApp();\n if (isInitialized && hasWidgetConfig && widgetBehavior && typeof widgetBehavior.onMounted === 'function') {\n widgetBehavior.onMounted(this, config);\n }\n\n this.$nextTick(() => {\n this.updateCopyButtons();\n refreshFontAwesomeIcons(this.$el);\n this.fontAwesomeObserver = observeFontAwesomeIcons(this.$el);\n });\n })();\n\n window.addEventListener('beforeunload', this.handleBeforeUnload);\n window.addEventListener('crestapps-ai-chat-stop-tts', this.handleExternalTtsStop);\n },\n beforeUnmount() {\n window.removeEventListener('beforeunload', this.handleBeforeUnload);\n window.removeEventListener('crestapps-ai-chat-stop-tts', this.handleExternalTtsStop);\n\n if (this.fontAwesomeObserver) {\n this.fontAwesomeObserver.disconnect();\n this.fontAwesomeObserver = null;\n }\n\n this.clearCopiedMessageState();\n this.stopAudio(false);\n\n if (this.stream) {\n this.stream.dispose();\n this.stream = null;\n }\n if (this.connection) {\n this.connection.stop();\n }\n\n if (widgetBehavior && typeof widgetBehavior.onBeforeUnmount === 'function') {\n widgetBehavior.onBeforeUnmount(this, config);\n }\n },\n template: config.messageTemplate\n };\n\n const app = Vue.createApp(appDefinition).mount(config.appElementSelector);\n\n if (widgetBehavior && typeof widgetBehavior.attach === 'function') {\n widgetBehavior.attach(app, config);\n }\n\n return app;\n };\n\n const autoInitializeSelector = '[data-coreai-chat-config],[data-coreai-chat-app-element-selector]';\n\n function getAttributeValue(element, attributeName) {\n const value = element.getAttribute(attributeName);\n return value === null || value === '' ? null : value;\n }\n\n function parseBooleanAttributeValue(value) {\n if (value === null || value === undefined) {\n return null;\n }\n\n if (typeof value === 'boolean') {\n return value;\n }\n\n const normalized = String(value).trim().toLowerCase();\n if (normalized === 'true') {\n return true;\n }\n\n if (normalized === 'false') {\n return false;\n }\n\n return null;\n }\n\n function parseJsonAttribute(element, attributeName, description) {\n const rawValue = getAttributeValue(element, attributeName);\n if (!rawValue) {\n return null;\n }\n\n try {\n return JSON.parse(rawValue);\n } catch (error) {\n console.error('Failed to parse ' + description + ' JSON.', error);\n return null;\n }\n }\n\n function buildConfigFromDataAttributes(element, options) {\n const settings = options || {};\n\n if (element.hasAttribute('data-coreai-chat-widget-container-selector') && settings.allowWidgetHost !== true) {\n return null;\n }\n\n const appElementSelector = getAttributeValue(element, 'data-coreai-chat-app-element-selector');\n if (!appElementSelector) {\n return null;\n }\n\n const config = {\n signalRHubUrl: getAttributeValue(element, 'data-coreai-chat-signalr-hub-url'),\n appElementSelector: appElementSelector,\n chatContainerElementSelector: getAttributeValue(element, 'data-coreai-chat-container-element-selector'),\n inputElementSelector: getAttributeValue(element, 'data-coreai-chat-input-element-selector'),\n sendButtonElementSelector: getAttributeValue(element, 'data-coreai-chat-send-button-element-selector'),\n placeholderElementSelector: getAttributeValue(element, 'data-coreai-chat-placeholder-element-selector'),\n messages: parseJsonAttribute(element, 'data-coreai-chat-messages', 'CoreAI chat messages') ?? undefined,\n chatMode: getAttributeValue(element, 'data-coreai-chat-mode'),\n micButtonElementSelector: getAttributeValue(element, 'data-coreai-chat-mic-button-element-selector'),\n conversationButtonElementSelector: getAttributeValue(element, 'data-coreai-chat-conversation-button-element-selector'),\n ttsVoiceName: getAttributeValue(element, 'data-coreai-chat-tts-voice-name'),\n realtimeVoiceName: getAttributeValue(element, 'data-coreai-chat-realtime-voice-name'),\n documentBarSelector: getAttributeValue(element, 'data-coreai-chat-document-bar-selector'),\n uploadDocumentUrl: getAttributeValue(element, 'data-coreai-chat-upload-document-url'),\n removeDocumentUrl: getAttributeValue(element, 'data-coreai-chat-remove-document-url'),\n allowedExtensions: getAttributeValue(element, 'data-coreai-chat-allowed-extensions'),\n supportedExtensionsText: getAttributeValue(element, 'data-coreai-chat-supported-extensions-text'),\n existingDocuments: parseJsonAttribute(element, 'data-coreai-chat-existing-documents', 'CoreAI chat existing documents') ?? undefined,\n initialPrompt: getAttributeValue(element, 'data-coreai-chat-initial-prompt'),\n sessionUrlTemplate: getAttributeValue(element, 'data-coreai-chat-session-url-template'),\n userLabel: getAttributeValue(element, 'data-coreai-chat-user-label'),\n assistantLabel: getAttributeValue(element, 'data-coreai-chat-assistant-label'),\n copyTitle: getAttributeValue(element, 'data-coreai-chat-copy-title'),\n copiedTitle: getAttributeValue(element, 'data-coreai-chat-copied-title'),\n };\n\n const booleanAttributes = {\n metricsEnabled: 'data-coreai-chat-metrics-enabled',\n textToSpeechEnabled: 'data-coreai-chat-text-to-speech-enabled',\n sessionDocumentsEnabled: 'data-coreai-chat-session-documents-enabled',\n singleResponseMode: 'data-coreai-chat-single-response-mode',\n realtimeEnabled: 'data-coreai-chat-realtime-enabled',\n realtimeWebRtcEnabled: 'data-coreai-chat-realtime-webrtc-enabled',\n };\n\n Object.keys(booleanAttributes).forEach(key => {\n const parsed = parseBooleanAttributeValue(getAttributeValue(element, booleanAttributes[key]));\n if (parsed !== null) {\n config[key] = parsed;\n }\n });\n\n return compactObject(config);\n }\n\n function buildConfigFromElement(element, options) {\n const jsonConfig = parseJsonAttribute(element, 'data-coreai-chat-config', 'CoreAI chat config');\n const attributeConfig = buildConfigFromDataAttributes(element, options);\n\n if (!jsonConfig && !attributeConfig) {\n return null;\n }\n\n return Object.assign({}, jsonConfig || {}, attributeConfig || {});\n }\n\n function initializeFromElement(element) {\n if (!element || element.dataset.coreAiChatInitialized === 'true') {\n return element ? element.__coreAIChatApp || null : null;\n }\n\n const config = buildConfigFromElement(element);\n if (!config) {\n return null;\n }\n\n const app = initialize(config);\n if (!app) {\n return null;\n }\n\n element.dataset.coreAiChatInitialized = 'true';\n element.__coreAIChatApp = app;\n\n return app;\n }\n\n function scanForAutoInitialization(root) {\n if (!root || typeof root.querySelectorAll !== 'function') {\n return;\n }\n\n if (typeof root.matches === 'function' && root.matches(autoInitializeSelector)) {\n initializeFromElement(root);\n }\n\n root.querySelectorAll(autoInitializeSelector).forEach(initializeFromElement);\n }\n\n function startAutoInitialization() {\n scanForAutoInitialization(document);\n\n if (typeof MutationObserver === 'undefined') {\n return;\n }\n\n const observer = new MutationObserver(mutations => {\n mutations.forEach(mutation => {\n mutation.addedNodes.forEach(node => {\n if (node && node.nodeType === 1) {\n scanForAutoInitialization(node);\n }\n });\n });\n });\n\n observer.observe(document.body, {\n childList: true,\n subtree: true,\n });\n }\n\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', startAutoInitialization, { once: true });\n } else {\n startAutoInitialization();\n }\n\n return {\n initialize: initialize,\n initializeFromElement: initializeFromElement,\n buildConfigFromElement: buildConfigFromElement,\n };\n}();\n\n// Download chart as image via event delegation (DOMPurify strips inline onclick).\ndocument.addEventListener('click', function (e) {\n const btn = e.target.closest('.download-chart-btn');\n if (!btn) {\n return;\n }\n const chartId = btn.getAttribute('data-chart-id');\n const canvas = chartId ? document.getElementById(chartId) : null;\n if (!canvas) {\n console.error('Chart canvas not found:', chartId);\n return;\n }\n const link = document.createElement('a');\n link.download = 'chart-' + chartId + '.png';\n link.href = canvas.toDataURL('image/png');\n link.click();\n});\n\n// Intercept download clicks for data-URI images and convert to blob downloads.\ndocument.addEventListener('click', function (e) {\n const link = e.target.closest('.ai-download-image');\n if (!link) {\n return;\n }\n\n const container = link.closest('.generated-image-container');\n const img = container?.querySelector('img');\n if (!img) {\n return;\n }\n\n const src = img.src;\n if (!src || !src.startsWith('data:')) {\n return; // Normal URL – let the default <a> behaviour handle it.\n }\n\n e.preventDefault();\n\n fetch(src)\n .then(function (res) { return res.blob(); })\n .then(function (blob) {\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = link.getAttribute('download') || 'generated-image.png';\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n setTimeout(function () { URL.revokeObjectURL(url); }, 100);\n })\n .catch(function (err) { console.error('Failed to download image:', err); });\n});\n"]}