@crestapps/ai-chat-ui 1.0.0-preview.8 → 1.0.0-preview.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai-chat.js +143 -111
- package/dist/ai-chat.js.map +1 -1
- package/dist/ai-chat.min.js +1 -1
- package/dist/ai-chat.min.js.map +1 -1
- package/dist/chat-interaction.js +9 -9
- package/dist/chat-interaction.js.map +1 -1
- package/dist/chat-interaction.min.js +1 -1
- package/dist/chat-interaction.min.js.map +1 -1
- package/package.json +1 -1
package/dist/ai-chat.min.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["ai-chat.js"],"names":["_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","_createForOfIteratorHelper","Array","isArray","_unsupportedIterableToArray","_n","F","s","next","_toConsumableArray","_arrayWithoutHoles","_iterableToArray","_nonIterableSpread","from","_arrayLikeToArray","_slicedToArray","_arrayWithHoles","_iterableToArrayLimit","_nonIterableRest","toString","slice","constructor","name","test","push","_typeof","window","openAIChatManager","defaultConfig","generatedImageAltText","generatedImageMaxWidth","downloadImageTitle","downloadChartTitle","downloadChartButtonText","userLabel","assistantLabel","thumbsUpTitle","thumbsDownTitle","copyTitle","codeCopiedText","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","parsePixelValue","Number","isFinite","parsed","parseFloat","clamp","min","max","Math","normalizeReference","reference","_ref","_normalized$index","_ref2","_normalized$text","_ref3","_normalized$link","normalized","assign","index","Index","Text","link","Link","normalizeReferences","references","_i","_Object$entries","entries","_normalizeReference","_Object$entries$_i","key","renderer","marked","Renderer","data","href","concat","code","lang","highlighted","hljs","getLanguage","highlight","language","_","highlightAuto","langDisplay","image","src","alt","maxWidth","chartCounter","_pendingCharts","renderChartsInMessage","message","charts","requestAnimationFrame","_step","_iterator","renderChartOnCanvas","chartId","config","err","canvas","getElementById","Chart","console","warn","offsetParent","__chartConfigs","_cfg$options","_cfg$options2","_cfg$options2$aspectR","_chartInstance","destroy","cfg","JSON","parse","options","responsive","maintainAspectRatio","aspectRatio","error","parseMarkdownContent","content","html","DOMPurify","sanitize","ADD_TAGS","ADD_ATTR","use","extensions","level","start","idx","indexOf","undefined","tokenizer","extracted","token","jsonStart","depth","inString","escape","ch","jsonEnd","closeBracketIndex","startIndex","endIndex","json","substring","tryExtractChartMarker","type","raw","renderPendingCharts","configs","_i2","_Object$keys","keys","initialize","instanceConfig","hasWidgetConfig","signalRHubUrl","appElementSelector","chatContainerElementSelector","inputElementSelector","sendButtonElementSelector","app","Vue","createApp","inputElement","buttonElement","chatContainer","placeholder","isSessionStarted","isPlaceholderVisible","chatWidgetStateSession","chatWidgetLayoutKey","widgetContainerElement","widgetToggleButtonElement","widgetResetSizeButtonElement","widgetResizeObserver","widgetViewportResizeHandler","widgetDefaultWidth","widgetDefaultHeight","widgetIsInitialized","isStreaming","isNavigatingAway","autoScroll","stream","messages","notifications","prompt","documents","existingDocuments","isUploading","uploadErrors","isDragOver","documentBar","metricsEnabled","isRecording","mediaRecorder","preRecordingPrompt","micButton","speechToTextEnabled","chatMode","textToSpeechEnabled","ttsVoiceName","audioChunks","audioPlayQueue","isPlayingAudio","currentAudioElement","currentAudioUrl","ttsButton","ttsPlayingMessageIndex","ttsAudioCache","ttsInstanceId","random","singleResponseMode","conversationModeEnabled","conversationButton","isConversationMode","notificationDismissTimers","computed","lastAssistantIndex","role","methods","handleBeforeUnload","getStoredWidgetLayout","storedLayout","localStorage","getItem","saveStoredWidgetLayout","partialLayout","currentLayout","nextLayout","panel","position","setItem","stringify","getElementSize","element","fallbackWidth","fallbackHeight","width","height","rect","getBoundingClientRect","getComputedStyle","round","getElementPosition","left","top","inlineLeft","style","inlineTop","computedLeft","computedTop","isHidden","display","clampWidgetPosition","maxLeft","innerWidth","maxTop","innerHeight","applyAbsolutePosition","right","bottom","getWidgetDefaultSize","getWidgetToggleGap","isWidgetPanelVisible","classList","contains","persistWidgetPanelPosition","panelDefaultSize","panelPosition","panelSize","toggleSize","linkedPosition","persistWidgetTogglePosition","persistWidgetPanelSize","defaultSize","currentSize","abs","syncTogglePositionToPanel","syncPanelPositionToToggle","togglePosition","updateWidgetResetSizeButtonVisibility","isResized","toggle","add","resetWidgetSize","removeProperty","constrainWidgetElementsToViewport","restoreWidgetLayout","attachDraggableWidgetElement","handle","layoutKey","suppressClickOnDrag","_this","activePointerId","startX","startY","startLeft","startTop","dragged","stopDragging","event","pointerId","removeEventListener","onPointerMove","remove","dataset","dragSuppressClick","setTimeout","deltaX","clientX","deltaY","clientY","hypot","nextPosition","addEventListener","button","target","closest","setPointerCapture","preventDefault","clampedPanel","clampedToggle","handleDragOver","sessionDocumentsEnabled","stopPropagation","inputArea","handleDragLeave","handleDrop","dataTransfer","files","uploadFiles","triggerFileInput","fileInput","click","handleFileInputChange","_this2","_callee","sessionId","profileId","formData","response","errorText","uploadError","result","j","_t","_context","uploadDocumentUrl","getSessionId","getProfileId","renderDocumentBar","FormData","append","fetch","method","body","ok","extractReadableErrorMessage","fileName","initializeSession","uploaded","failed","removeDocument","doc","_this3","_callee2","removeError","_t2","_context2","removeDocumentUrl","headers","itemId","documentId","splice","status","formatFileSize","bytes","toFixed","escapeHtml","failedItem","failedName","errorMsg","supportedExtensionsText","replaceChildren","RETURN_DOM_FRAGMENT","self","closeButtons","querySelectorAll","docToRemove","parseInt","getAttribute","errorCloseButtons","addBtn","querySelector","div","fallbackMessage","startsWith","title","detail","normalizeAssistantAppearance","appearance","label","icon","cssClass","disableStreamingAnimation","getAssistantLabel","getAssistantRoleClasses","classes","getAssistantIconClasses","shouldAnimateAssistantIcon","getAssistantIcon","startConnection","_this4","_callee3","_t3","_context3","connection","signalR","HubConnectionBuilder","withUrl","withAutomaticReconnect","build","serverTimeoutInMilliseconds","keepAliveIntervalInMilliseconds","on","_data$messages","forEach","msg","addMessage","$nextTick","refreshAllFeedbackIcons","initialPrompt","sendMessage","stopRecording","_attemptedSessionRecovery","removeItem","startNewSession","messageId","userRating","find","id","isFinal","_conversationPartialTranscript","replace","_conversationPartialMessage","htmlContent","hidePlaceholder","isPartial","scrollToBottom","_audioInputSent","dispatchEvent","Event","stopAudio","_conversationAssistantMessage","oldMsg","escaped","responseId","hideTypingIndicator","msgIndex","newMessage","base64Audio","contentType","binaryString","atob","Uint8Array","charCodeAt","playCollectedAudio","notification","receiveNotification","updateNotification","notificationType","removeNotification","onreconnecting","onreconnected","info","reloadCurrentSession","autoCreateSession","onclose","addMessageInternal","_this5","fireEvent","CustomEvent","_this6","processedContent","citedRefs","filter","_ref4","includes","sort","_ref6","_ref7","b","_step2","displayIndex","_iterator2","_step2$value","replaceAll","_displayIndex","_placeholder","_step3","_iterator3","_step4","_iterator4","_step4$value","addMessages","_this7","showPlaceholder","isOrchestratorAvailable","applyOrchestratorAvailability","unavailableMessage","orchestratorUnavailableMessage","disabled","micButtonElement","conversationButtonElement","isIndicator","trimmedPrompt","streamMessage","startRecording","_this8","navigator","mediaDevices","getUserMedia","audio","echoCancellation","noiseSuppression","autoGainControl","mimeType","MediaRecorder","isTypeSupported","audioBitsPerSecond","subject","Subject","pendingChunk","size","_callee4","uint8Array","base64","_context4","arrayBuffer","reduce","str","byte","String","fromCharCode","btoa","getTracks","track","stop","complete","documentElement","send","updateMicButton","toggleRecording","sessionProfileId","_this9","dispose","streamingStarted","showTypingIndicator","lastResponseId","messageIndex","currentSessionId","subscribe","chunk","_i3","_Object$entries2","_normalizeReference2","_Object$entries2$_i","_i4","_Object$entries3","_Object$entries3$_i","_this9$stream","processReferences","streamingFinished","synthesizeSpeech","_this9$stream2","getServiceDownMessage","_this0","_ref1","_ref10","_ref11","_ref12","_step5","processed","_iterator5","_step5$value","_step6","_iterator6","_step7","_iterator7","_step7$value","stopIcon","setAttribute","startIcon","removeAttribute","focus","icons","handleExternalTtsStop","_e$detail","sourceId","cacheIndex","_this1","_ttsCacheIndex","invoke","toggleMessageTts","playAudioBlob","_step8","totalLength","sum","combined","offset","_iterator8","set","blob","Blob","_this10","URL","createObjectURL","Audio","revokeObjectURL","playNextInQueue","play","nextBlob","shift","conversationModeOnAudioEnded","pause","currentTime","toggleConversationMode","stopConversationMode","startConversationMode","_this11","updateConversationButton","_conversationSubject","_conversationStream","AudioCtx","AudioContext","webkitAudioContext","_conversationAudioCtx","_conversationAnalyser","createAnalyser","fftSize","createMediaStreamSource","connect","analyser","freqData","frequencyBinCount","getByteFrequencyData","k","_callee5","_context5","close","dismissible","autoDismissMs","endHtml","blur","startHtml","conversationModeSendPrompt","generatePrompt","templateProfileId","createSessionUrl","baseUrl","param","fullUrl","toLowerCase","location","origin","searchParams","originalLength","_this12","clearNotificationDismiss","existingIndex","findIndex","scheduleNotificationDismiss","_this13","timerId","clearTimeout","dismissNotification","handleNotificationAction","actionName","_this14","scrollTop","scrollHeight","clientHeight","handleUserInput","setSessionId","resetSession","sessionRating","initializeApp","_this15","placeholderElementSelector","loadSession","documentBarSelector","className","multiple","allowedExtensions","accept","parentElement","appendChild","atBottom","shiftKey","lastMsg","pop","promptGenerators","getElementsByClassName","chatSessions","showChatScreen","btn","block","codeEl","clipboard","writeText","copiedText","micButtonElementSelector","conversationButtonElementSelector","force","initializeWidget","_this16","ResizeObserver","observe","dragHandle","copyResponse","updateFeedbackIcons","container","upBtn","downBtn","upClass","upIcon","fontSize","downClass","downIcon","FontAwesome","dom","i2svg","node","containers","$el","msgId","rateMessage","isPositive","newRating","feedbackContainer","btnClass","offsetWidth","onEnd","watch","handler","deep","active","mounted","_this17","_callee6","_context6","beforeUnmount","template","mount","download","toDataURL","img","res","removeChild"],"mappings":"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","file":"ai-chat.min.js","sourcesContent":["window.openAIChatManager = 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 codeCopiedText: 'Copied!',\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-msg-role ai-chat-msg-role-user\">{{ userLabel }}</div>\n <div v-else-if=\"message.role !== 'indicator'\" :class=\"getAssistantRoleClasses(message)\">\n <span :class=\"getAssistantIconClasses(message, index)\"><i :class=\"getAssistantIcon(message)\"></i></span>\n {{ getAssistantLabel(message) }}\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 <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 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 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 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 }\" @click=\"toggleMessageTts(message, index)\" :title=\"ttsPlayingMessageIndex === index ? 'Pause audio' : 'Read aloud'\">\n <i :class=\"ttsPlayingMessageIndex === index ? 'fa-solid fa-circle-pause' : 'fa-solid fa-circle-play'\"></i>\n </button>\n <button class=\"btn btn-sm btn-link text-secondary p-0 button-message-toolbox\" @click=\"copyResponse(message.content)\" :title=\"copyTitle\">\n <i class=\"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 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 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-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 Assistant\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 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.link = normalized.link ?? normalized.Link ?? null;\n\n return normalized;\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 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 const initialize = (instanceConfig) => {\n\n const config = Object.assign({}, defaultConfig, instanceConfig);\n config.widget = Object.assign({}, defaultConfig.widget || {}, instanceConfig && instanceConfig.widget ? instanceConfig.widget : {});\n const hasWidgetConfig = !!(instanceConfig && instanceConfig.widget && instanceConfig.widget.chatWidgetContainer && instanceConfig.widget.chatWidgetStateName);\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 app = Vue.createApp({\n data() {\n return {\n inputElement: null,\n buttonElement: null,\n chatContainer: null,\n placeholder: null,\n isSessionStarted: false,\n isPlaceholderVisible: true,\n chatWidgetStateName: null,\n chatWidgetStateSession: null,\n chatWidgetLayoutKey: null,\n chatHistorySection: null,\n widgetContainerElement: null,\n widgetToggleButtonElement: null,\n widgetResetSizeButtonElement: null,\n widgetResizeObserver: null,\n widgetViewportResizeHandler: null,\n widgetDefaultWidth: null,\n widgetDefaultHeight: null,\n widgetIsInitialized: false,\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 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 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 };\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 getStoredWidgetLayout() {\n if (!this.chatWidgetLayoutKey || !config.widget.persistLayout) {\n return {};\n }\n\n try {\n var storedLayout = localStorage.getItem(this.chatWidgetLayoutKey);\n return storedLayout ? JSON.parse(storedLayout) || {} : {};\n } catch (error) {\n console.warn('Failed to read widget layout state.', error);\n return {};\n }\n },\n saveStoredWidgetLayout(partialLayout) {\n if (!this.chatWidgetLayoutKey || !config.widget.persistLayout) {\n return;\n }\n\n var currentLayout = this.getStoredWidgetLayout();\n var nextLayout = Object.assign({}, currentLayout);\n\n if (partialLayout.panel !== undefined) {\n nextLayout.panel = Object.assign({}, currentLayout.panel || {}, partialLayout.panel || {});\n }\n\n if (partialLayout.position !== undefined) {\n nextLayout.position = Object.assign({}, currentLayout.position || {}, partialLayout.position || {});\n }\n\n localStorage.setItem(this.chatWidgetLayoutKey, JSON.stringify(nextLayout));\n },\n getElementSize(element, fallbackWidth, fallbackHeight) {\n if (!element) {\n return {\n width: fallbackWidth || 0,\n height: fallbackHeight || 0\n };\n }\n\n var rect = element.getBoundingClientRect();\n var computed = window.getComputedStyle(element);\n\n return {\n width: Math.round(rect.width || parsePixelValue(computed.width) || fallbackWidth || 0),\n height: Math.round(rect.height || parsePixelValue(computed.height) || fallbackHeight || 0)\n };\n },\n getElementPosition(element) {\n if (!element) {\n return {\n left: 0,\n top: 0\n };\n }\n\n var rect = element.getBoundingClientRect();\n var computed = window.getComputedStyle(element);\n var inlineLeft = parsePixelValue(element.style.left);\n var inlineTop = parsePixelValue(element.style.top);\n var computedLeft = parsePixelValue(computed.left);\n var computedTop = parsePixelValue(computed.top);\n var isHidden = computed.display === 'none';\n\n return {\n left: Math.round(\n isHidden && Number.isFinite(inlineLeft)\n ? inlineLeft\n : rect.left || inlineLeft || computedLeft || 0),\n top: Math.round(\n isHidden && Number.isFinite(inlineTop)\n ? inlineTop\n : rect.top || inlineTop || computedTop || 0)\n };\n },\n clampWidgetPosition(left, top, width, height) {\n var viewportPadding = 8;\n var maxLeft = Math.max(viewportPadding, window.innerWidth - width - viewportPadding);\n var maxTop = Math.max(viewportPadding, window.innerHeight - height - viewportPadding);\n\n return {\n left: Math.round(clamp(left, viewportPadding, maxLeft)),\n top: Math.round(clamp(top, viewportPadding, maxTop))\n };\n },\n applyAbsolutePosition(element, left, top) {\n if (!element) {\n return;\n }\n\n element.style.left = left + 'px';\n element.style.top = top + 'px';\n element.style.right = 'auto';\n element.style.bottom = 'auto';\n },\n getWidgetDefaultSize() {\n return {\n width: this.widgetDefaultWidth || parsePixelValue(config.widget.defaultWidth) || 380,\n height: this.widgetDefaultHeight || parsePixelValue(config.widget.defaultHeight) || 520\n };\n },\n getWidgetToggleGap() {\n return 8;\n },\n isWidgetPanelVisible() {\n if (!this.widgetContainerElement) {\n return false;\n }\n\n var computed = window.getComputedStyle(this.widgetContainerElement);\n return this.widgetContainerElement.classList.contains('open') && computed.display !== 'none';\n },\n persistWidgetPanelPosition() {\n if (!this.widgetContainerElement || !config.widget.persistLayout) {\n return;\n }\n\n var panelDefaultSize = this.getWidgetDefaultSize();\n var panelPosition = this.getElementPosition(this.widgetContainerElement);\n var panelSize = this.getElementSize(this.widgetContainerElement, panelDefaultSize.width, panelDefaultSize.height);\n var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);\n var linkedPosition = this.clampWidgetPosition(\n panelPosition.left + panelSize.width - toggleSize.width,\n panelPosition.top + panelSize.height + this.getWidgetToggleGap(),\n toggleSize.width,\n toggleSize.height);\n\n this.saveStoredWidgetLayout({\n position: {\n left: linkedPosition.left,\n top: linkedPosition.top\n }\n });\n },\n persistWidgetTogglePosition() {\n if (!this.widgetToggleButtonElement || !config.widget.persistLayout) {\n return;\n }\n\n var toggleRect = this.widgetToggleButtonElement.getBoundingClientRect();\n this.saveStoredWidgetLayout({\n position: {\n left: this.getElementPosition(this.widgetToggleButtonElement).left,\n top: this.getElementPosition(this.widgetToggleButtonElement).top\n }\n });\n },\n persistWidgetPanelSize() {\n if (!this.widgetContainerElement || !config.widget.enableResizing || !config.widget.persistLayout) {\n return;\n }\n\n var defaultSize = this.getWidgetDefaultSize();\n var currentSize = this.getElementSize(this.widgetContainerElement, defaultSize.width, defaultSize.height);\n\n this.saveStoredWidgetLayout({\n panel: {\n width: Math.abs(currentSize.width - defaultSize.width) <= 1 ? null : currentSize.width,\n height: Math.abs(currentSize.height - defaultSize.height) <= 1 ? null : currentSize.height\n }\n });\n },\n syncTogglePositionToPanel(persistLayout = true) {\n if (!this.widgetContainerElement || !this.widgetToggleButtonElement) {\n return;\n }\n\n var panelDefaultSize = this.getWidgetDefaultSize();\n var panelSize = this.getElementSize(this.widgetContainerElement, panelDefaultSize.width, panelDefaultSize.height);\n var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);\n var panelPosition = this.getElementPosition(this.widgetContainerElement);\n var linkedPosition = this.clampWidgetPosition(\n panelPosition.left + panelSize.width - toggleSize.width,\n panelPosition.top + panelSize.height + this.getWidgetToggleGap(),\n toggleSize.width,\n toggleSize.height);\n\n this.applyAbsolutePosition(this.widgetToggleButtonElement, linkedPosition.left, linkedPosition.top);\n\n if (persistLayout && config.widget.persistLayout) {\n this.persistWidgetTogglePosition();\n }\n },\n syncPanelPositionToToggle(persistLayout = true) {\n if (!this.widgetContainerElement || !this.widgetToggleButtonElement) {\n return;\n }\n\n var panelDefaultSize = this.getWidgetDefaultSize();\n var panelSize = this.getElementSize(this.widgetContainerElement, panelDefaultSize.width, panelDefaultSize.height);\n var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);\n var togglePosition = this.getElementPosition(this.widgetToggleButtonElement);\n var linkedPosition = this.clampWidgetPosition(\n togglePosition.left + toggleSize.width - panelSize.width,\n togglePosition.top - panelSize.height - this.getWidgetToggleGap(),\n panelSize.width,\n panelSize.height);\n\n this.applyAbsolutePosition(this.widgetContainerElement, linkedPosition.left, linkedPosition.top);\n\n if (persistLayout && config.widget.persistLayout) {\n this.persistWidgetPanelPosition();\n }\n },\n updateWidgetResetSizeButtonVisibility() {\n if (!this.widgetResetSizeButtonElement) {\n return;\n }\n\n if (!config.widget.enableResizing || !this.widgetContainerElement) {\n this.widgetResetSizeButtonElement.classList.add('d-none');\n return;\n }\n\n var defaultSize = this.getWidgetDefaultSize();\n var currentSize = this.getElementSize(this.widgetContainerElement, defaultSize.width, defaultSize.height);\n var isResized =\n Math.abs(currentSize.width - defaultSize.width) > 1 ||\n Math.abs(currentSize.height - defaultSize.height) > 1 ||\n !!this.widgetContainerElement.style.width ||\n !!this.widgetContainerElement.style.height;\n\n this.widgetResetSizeButtonElement.classList.toggle('d-none', !isResized);\n },\n resetWidgetSize() {\n if (!this.widgetContainerElement || !config.widget.enableResizing) {\n return;\n }\n\n this.widgetContainerElement.style.removeProperty('width');\n this.widgetContainerElement.style.removeProperty('height');\n this.persistWidgetPanelSize();\n this.constrainWidgetElementsToViewport();\n this.updateWidgetResetSizeButtonVisibility();\n },\n restoreWidgetLayout() {\n var storedLayout = this.getStoredWidgetLayout();\n\n if (this.widgetContainerElement && config.widget.enableResizing) {\n if (Number.isFinite(storedLayout.panel && storedLayout.panel.width)) {\n this.widgetContainerElement.style.width = storedLayout.panel.width + 'px';\n } else {\n this.widgetContainerElement.style.removeProperty('width');\n }\n\n if (Number.isFinite(storedLayout.panel && storedLayout.panel.height)) {\n this.widgetContainerElement.style.height = storedLayout.panel.height + 'px';\n } else {\n this.widgetContainerElement.style.removeProperty('height');\n }\n }\n\n if (this.widgetToggleButtonElement && config.widget.enableDragging &&\n Number.isFinite(storedLayout.position && storedLayout.position.left) &&\n Number.isFinite(storedLayout.position && storedLayout.position.top)) {\n this.applyAbsolutePosition(this.widgetToggleButtonElement, storedLayout.position.left, storedLayout.position.top);\n this.syncPanelPositionToToggle(false);\n } else if (this.widgetToggleButtonElement && config.widget.enableDragging &&\n Number.isFinite(storedLayout.toggle && storedLayout.toggle.left) &&\n Number.isFinite(storedLayout.toggle && storedLayout.toggle.top)) {\n this.applyAbsolutePosition(this.widgetToggleButtonElement, storedLayout.toggle.left, storedLayout.toggle.top);\n this.syncPanelPositionToToggle(false);\n } else if (this.widgetContainerElement && config.widget.enableDragging &&\n Number.isFinite(storedLayout.panel && storedLayout.panel.left) &&\n Number.isFinite(storedLayout.panel && storedLayout.panel.top)) {\n this.applyAbsolutePosition(this.widgetContainerElement, storedLayout.panel.left, storedLayout.panel.top);\n this.syncTogglePositionToPanel(false);\n }\n\n this.constrainWidgetElementsToViewport();\n this.updateWidgetResetSizeButtonVisibility();\n },\n attachDraggableWidgetElement(element, handle, layoutKey, suppressClickOnDrag) {\n if (!element || !handle || !config.widget.enableDragging) {\n return;\n }\n\n var activePointerId = null;\n var startX = 0;\n var startY = 0;\n var startLeft = 0;\n var startTop = 0;\n var dragged = false;\n var dragThreshold = 4;\n var interactiveSelector = 'button, a, input, textarea, select, option, label';\n\n var stopDragging = (event) => {\n if (activePointerId === null) {\n return;\n }\n\n if (event && event.pointerId !== undefined && event.pointerId !== activePointerId) {\n return;\n }\n\n document.removeEventListener('pointermove', onPointerMove);\n document.removeEventListener('pointerup', stopDragging);\n document.removeEventListener('pointercancel', stopDragging);\n element.classList.remove('ai-chat-widget-dragging');\n activePointerId = null;\n\n if (!dragged) {\n return;\n }\n\n if (layoutKey === 'panel') {\n this.syncTogglePositionToPanel(false);\n this.persistWidgetPanelPosition();\n } else if (layoutKey === 'toggle') {\n this.syncPanelPositionToToggle(false);\n this.persistWidgetTogglePosition();\n }\n\n if (config.widget.persistLayout) {\n this.persistWidgetPanelPosition();\n this.persistWidgetTogglePosition();\n }\n\n if (suppressClickOnDrag) {\n element.dataset.dragSuppressClick = 'true';\n window.setTimeout(() => {\n if (element.dataset.dragSuppressClick === 'true') {\n element.dataset.dragSuppressClick = 'false';\n }\n }, 0);\n }\n };\n\n var onPointerMove = (event) => {\n if (activePointerId === null || event.pointerId !== activePointerId) {\n return;\n }\n\n var deltaX = event.clientX - startX;\n var deltaY = event.clientY - startY;\n\n if (!dragged && Math.hypot(deltaX, deltaY) < dragThreshold) {\n return;\n }\n\n dragged = true;\n\n var defaultSize = this.getWidgetDefaultSize();\n var currentSize = this.getElementSize(\n element,\n layoutKey === 'panel' ? defaultSize.width : 52,\n layoutKey === 'panel' ? defaultSize.height : 52);\n var nextPosition = this.clampWidgetPosition(\n startLeft + deltaX,\n startTop + deltaY,\n currentSize.width,\n currentSize.height);\n\n this.applyAbsolutePosition(element, nextPosition.left, nextPosition.top);\n\n if (layoutKey === 'panel') {\n this.syncTogglePositionToPanel(false);\n } else if (layoutKey === 'toggle') {\n this.syncPanelPositionToToggle(false);\n }\n };\n\n handle.addEventListener('pointerdown', (event) => {\n if (event.button !== 0) {\n return;\n }\n\n if (layoutKey === 'panel' && event.target.closest(interactiveSelector)) {\n return;\n }\n\n var rect = element.getBoundingClientRect();\n startX = event.clientX;\n startY = event.clientY;\n startLeft = rect.left;\n startTop = rect.top;\n dragged = false;\n activePointerId = event.pointerId;\n element.classList.add('ai-chat-widget-dragging');\n\n if (handle.setPointerCapture) {\n handle.setPointerCapture(event.pointerId);\n }\n\n document.addEventListener('pointermove', onPointerMove);\n document.addEventListener('pointerup', stopDragging);\n document.addEventListener('pointercancel', stopDragging);\n event.preventDefault();\n });\n },\n constrainWidgetElementsToViewport() {\n if (this.widgetContainerElement && this.widgetContainerElement.style.left && this.isWidgetPanelVisible()) {\n var panelDefaultSize = this.getWidgetDefaultSize();\n var panelSize = this.getElementSize(this.widgetContainerElement, panelDefaultSize.width, panelDefaultSize.height);\n var panelPosition = this.getElementPosition(this.widgetContainerElement);\n var clampedPanel = this.clampWidgetPosition(panelPosition.left, panelPosition.top, panelSize.width, panelSize.height);\n\n this.applyAbsolutePosition(this.widgetContainerElement, clampedPanel.left, clampedPanel.top);\n this.syncTogglePositionToPanel(false);\n\n if (config.widget.persistLayout) {\n this.persistWidgetPanelPosition();\n this.persistWidgetTogglePosition();\n }\n } else if (this.widgetToggleButtonElement && this.widgetToggleButtonElement.style.left) {\n var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);\n var togglePosition = this.getElementPosition(this.widgetToggleButtonElement);\n var clampedToggle = this.clampWidgetPosition(togglePosition.left, togglePosition.top, toggleSize.width, toggleSize.height);\n\n this.applyAbsolutePosition(this.widgetToggleButtonElement, clampedToggle.left, clampedToggle.top);\n this.syncPanelPositionToToggle(false);\n\n if (config.widget.persistLayout) {\n this.persistWidgetTogglePosition();\n this.persistWidgetPanelPosition();\n }\n }\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(e.dataTransfer.files);\n }\n },\n triggerFileInput() {\n if (!config.sessionDocumentsEnabled) 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;\n if (files && files.length > 0) {\n this.uploadFiles(files);\n }\n e.target.value = '';\n },\n async uploadFiles(files) {\n if (!config.uploadDocumentUrl) return;\n\n var sessionId = this.getSessionId();\n var profileId = this.getProfileId();\n\n if (!sessionId && !profileId) {\n console.warn('Cannot upload documents without a session or profile.');\n return;\n }\n\n this.isUploading = true;\n this.uploadErrors = [];\n this.renderDocumentBar();\n try {\n var formData = new FormData();\n if (sessionId) {\n formData.append('sessionId', sessionId);\n } else {\n formData.append('profileId', profileId);\n }\n for (var i = 0; i < files.length; i++) {\n formData.append('files', files[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 the server created a new session, initialize it.\n if (result.sessionId && !sessionId) {\n this.initializeSession(result.sessionId);\n }\n\n if (result.uploaded && result.uploaded.length > 0) {\n for (var j = 0; j < result.uploaded.length; j++) {\n this.documents.push(result.uploaded[j]);\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 } finally {\n this.isUploading = false;\n this.renderDocumentBar();\n }\n },\n async removeDocument(doc) {\n if (!config.removeDocumentUrl) return;\n\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 idx = this.documents.indexOf(doc);\n if (idx > -1) this.documents.splice(idx, 1);\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 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 this.renderDocumentBar();\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\"></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\">';\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 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 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\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 // automatically send it as the first user message to trigger an AI response.\n if (this.messages.length === 0 && config.initialPrompt) {\n this.prompt = config.initialPrompt;\n this.sendMessage();\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 // If this is a widget with a stale cached session (e.g., profile was deleted),\n // clear the cached session and start fresh with the current profile.\n if (this.widgetIsInitialized && !this.isSessionStarted && !this._attemptedSessionRecovery) {\n this._attemptedSessionRecovery = true;\n localStorage.removeItem(this.chatWidgetStateSession);\n this.startNewSession();\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, '&').replace(/</g, '<').replace(/>/g, '>');\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, '&').replace(/</g, '<').replace(/>/g, '>');\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, 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 };\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.content = this._conversationAssistantMessage.content;\n msg.htmlContent = parseMarkdownContent(msg.content, msg);\n this.$nextTick(() => {\n renderChartsInMessage(msg);\n this.scrollToBottom();\n });\n }\n });\n\n this.connection.on(\"ReceiveConversationAssistantComplete\", (sessionId, messageId) => {\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\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 } else if (config.autoCreateSession) {\n this.startNewSession();\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(\"addingOpenAIPromotMessage\", { detail: { message: message } }));\n this.messages.push(message);\n\n this.$nextTick(() => {\n this.fireEvent(new CustomEvent(\"addedOpenAIPromotMessage\", { 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 let processedContent = message.content.trim();\n message.references = normalizeReferences(message.references);\n\n if (message.references && typeof message.references === \"object\" && Object.keys(message.references).length) {\n\n // Only include references that were actually cited in the response.\n const citedRefs = Object.entries(message.references).filter(([key]) => processedContent.includes(key));\n\n if (citedRefs.length) {\n // Sort by original index so display indices follow a natural order.\n citedRefs.sort(([, a], [, b]) => a.index - b.index);\n\n // Phase 1: Replace all markers with unique placeholders.\n let displayIndex = 1;\n for (const [key, value] of citedRefs) {\n const placeholder = `__CITE_${value.index}__`;\n processedContent = processedContent.replaceAll(key, placeholder);\n value._displayIndex = displayIndex++;\n value._placeholder = placeholder;\n }\n\n // Phase 2: Replace placeholders with sequential display indices.\n for (const [, value] of citedRefs) {\n processedContent = processedContent.replaceAll(value._placeholder, `<sup><strong>${value._displayIndex}</strong></sup>`);\n }\n\n // if we have multiple references, add a comma to ensure we don't concatenate numbers.\n processedContent = processedContent.replaceAll('</strong></sup><sup>', '</strong></sup><sup>,</sup><sup>');\n\n processedContent += '<br><br>';\n\n for (const [key, value] of citedRefs) {\n const label = value.text || key;\n processedContent += value.link\n ? `**${value._displayIndex}**. [${label}](${value.link})<br>`\n : `**${value._displayIndex}**. ${label}<br>`;\n }\n }\n }\n\n message.content = processedContent;\n message.htmlContent = parseMarkdownContent(processedContent, message);\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 let processedContent = chunk.content;\n\n for (const [key, value] of Object.entries(references)) {\n processedContent = processedContent.replaceAll(key, `<sup><strong>${value.index}</strong></sup>`);\n }\n\n // Append processed content to the message.\n // if we have multiple references, add a comma to ensure we don't concatenate numbers.\n content += processedContent.replaceAll('</strong></sup><sup>', '</strong></sup><sup>,</sup><sup>');\n }\n\n // Update the existing message\n message.content = content;\n\n message.htmlContent = parseMarkdownContent(content, message);\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 processReferences(references, messageIndex) {\n references = normalizeReferences(references);\n\n if (Object.keys(references).length) {\n\n let message = this.messages[messageIndex];\n const content = message.content || '';\n\n // Only include references that were actually cited in the response.\n // Check both raw [doc:N] markers and already-rendered <sup> tags from streaming.\n const citedRefs = Object.entries(references).filter(([key, value]) =>\n content.includes(key) || content.includes(`<sup><strong>${value.index}</strong></sup>`)\n );\n\n if (!citedRefs.length) {\n return;\n }\n\n // Sort by original index so display indices follow a natural order.\n citedRefs.sort(([, a], [, b]) => a.index - b.index);\n\n // Phase 1: Replace all markers with unique placeholders to avoid collisions during remapping.\n let processed = content.trim();\n let displayIndex = 1;\n for (const [key, value] of citedRefs) {\n const placeholder = `__CITE_${value.index}__`;\n processed = processed.replaceAll(key, placeholder);\n processed = processed.replaceAll(`<sup><strong>${value.index}</strong></sup>`, placeholder);\n value._displayIndex = displayIndex++;\n value._placeholder = placeholder;\n }\n\n // Phase 2: Replace placeholders with sequential display indices.\n for (const [, value] of citedRefs) {\n processed = processed.replaceAll(value._placeholder, `<sup><strong>${value._displayIndex}</strong></sup>`);\n }\n\n processed = processed.replaceAll('</strong></sup><sup>', '</strong></sup><sup>,</sup><sup>');\n\n processed += '<br><br>';\n\n for (const [key, value] of citedRefs) {\n const label = value.text || key;\n processed += value.link\n ? `**${value._displayIndex}**. [${label}](${value.link})<br>`\n : `**${value._displayIndex}**. ${label}<br>`;\n }\n\n message.content = processed;\n message.htmlContent = parseMarkdownContent(processed, message);\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 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 });\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\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 }\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 });\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.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 },\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.getAttribute('data-profile-id');\n },\n setSessionId(sessionId) {\n this.inputElement.setAttribute('data-session-id', sessionId || '');\n },\n resetSession() {\n this.stopRecording();\n this.setSessionId('');\n this.isSessionStarted = false;\n this.sessionRating = null;\n if (this.widgetIsInitialized) {\n localStorage.removeItem(this.chatWidgetStateSession);\n }\n this.messages = [];\n this.documents = [];\n if (!config.autoCreateSession) {\n this.showPlaceholder();\n }\n\n if (config.autoCreateSession) {\n this.startNewSession();\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.connection.invoke(\"StartSession\", profileId, null).catch(err => console.error(err));\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 this.applyOrchestratorAvailability();\n\n const sessionId = this.getSessionId();\n if (!hasWidgetConfig && sessionId) {\n this.loadSession(sessionId);\n } else if (this.isOrchestratorAvailable() && config.autoCreateSession && !hasWidgetConfig && !sessionId) {\n this.startNewSession();\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 for (let i = 0; i < config.messages.length; i++) {\n this.addMessage(config.messages[i]);\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 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 return\n }\n this.fireEvent(new CustomEvent(\"initializingSessionOpenAIChat\", { detail: { sessionId: sessionId } }))\n this.setSessionId(sessionId);\n this.isSessionStarted = true;\n\n if (this.widgetIsInitialized) {\n localStorage.setItem(this.chatWidgetStateSession, sessionId);\n }\n },\n initializeWidget() {\n\n if (!config.widget.chatWidgetContainer) {\n console.error('The widget chatWidgetContainer is required.');\n return;\n }\n\n if (!config.widget.chatWidgetStateName) {\n console.error('The widget chatWidgetStateName is required.');\n return;\n }\n\n const chatWidgetContainer = document.querySelector(config.widget.chatWidgetContainer);\n\n if (!chatWidgetContainer) {\n return;\n }\n\n if (config.widget.chatHistorySection) {\n this.chatHistorySection = document.querySelector(config.widget.chatHistorySection);\n }\n\n this.chatWidgetStateName = config.widget.chatWidgetStateName;\n this.chatWidgetStateSession = config.widget.chatWidgetStateName + 'Session';\n this.chatWidgetLayoutKey = config.widget.chatWidgetStateName + 'Layout';\n this.widgetContainerElement = chatWidgetContainer;\n this.widgetToggleButtonElement = config.widget.toggleButtonSelector\n ? document.querySelector(config.widget.toggleButtonSelector)\n : null;\n this.widgetResetSizeButtonElement = config.widget.resetSizeButtonSelector\n ? document.querySelector(config.widget.resetSizeButtonSelector)\n : null;\n this.widgetDefaultWidth = parsePixelValue(config.widget.defaultWidth) ||\n parsePixelValue(window.getComputedStyle(chatWidgetContainer).width) ||\n 380;\n this.widgetDefaultHeight = parsePixelValue(config.widget.defaultHeight) ||\n parsePixelValue(window.getComputedStyle(chatWidgetContainer).height) ||\n 520;\n this.widgetIsInitialized = true;\n\n if (config.widget.enableResizing) {\n chatWidgetContainer.classList.add('ai-chat-widget-resizable');\n chatWidgetContainer.style.minWidth = (parsePixelValue(config.widget.minWidth) || 320) + 'px';\n chatWidgetContainer.style.minHeight = (parsePixelValue(config.widget.minHeight) || 420) + 'px';\n\n if (typeof ResizeObserver !== 'undefined') {\n this.widgetResizeObserver = new ResizeObserver(() => {\n this.persistWidgetPanelSize();\n this.constrainWidgetElementsToViewport();\n this.updateWidgetResetSizeButtonVisibility();\n });\n\n this.widgetResizeObserver.observe(chatWidgetContainer);\n }\n }\n\n var dragHandleSelector = config.widget.dragHandleSelector || '.ai-chat-widget-header';\n var dragHandle = chatWidgetContainer.querySelector(dragHandleSelector);\n\n if (config.widget.enableDragging && dragHandle) {\n dragHandle.classList.add('ai-chat-widget-drag-handle');\n chatWidgetContainer.classList.add('ai-chat-widget-draggable');\n this.attachDraggableWidgetElement(chatWidgetContainer, dragHandle, 'panel', false);\n }\n\n if (config.widget.enableDragging && this.widgetToggleButtonElement) {\n this.widgetToggleButtonElement.classList.add('ai-chat-widget-draggable');\n this.attachDraggableWidgetElement(this.widgetToggleButtonElement, this.widgetToggleButtonElement, 'toggle', true);\n }\n\n if (this.widgetResetSizeButtonElement) {\n this.widgetResetSizeButtonElement.addEventListener('click', (event) => {\n event.preventDefault();\n this.resetWidgetSize();\n });\n }\n\n this.restoreWidgetLayout();\n\n if (!this.widgetViewportResizeHandler) {\n this.widgetViewportResizeHandler = () => {\n this.constrainWidgetElementsToViewport();\n this.updateWidgetResetSizeButtonVisibility();\n };\n\n window.addEventListener('resize', this.widgetViewportResizeHandler);\n }\n\n // Auto-load the last session so the user always sees previous chat history.\n this.reloadCurrentSession();\n\n if (config.autoCreateSession && !this.getSessionId()) {\n this.startNewSession();\n }\n\n if (config.widget.showHistoryButton && this.chatHistorySection) {\n\n const showHistoryButton = document.querySelector(config.widget.showHistoryButton);\n\n if (showHistoryButton) {\n showHistoryButton.addEventListener('click', () => {\n this.chatHistorySection.classList.toggle('show');\n });\n }\n\n if (config.widget.closeHistoryButton) {\n var closeHistoryButton = document.querySelector(config.widget.closeHistoryButton);\n\n if (closeHistoryButton) {\n closeHistoryButton.addEventListener('click', () => {\n this.showChatScreen();\n });\n }\n }\n }\n\n if (config.widget.newChatButton) {\n const newChatButton = document.querySelector(config.widget.newChatButton);\n\n if (newChatButton) {\n newChatButton.addEventListener('click', () => {\n this.resetSession();\n this.showChatScreen();\n });\n }\n }\n },\n showChatScreen() {\n\n if (!this.chatHistorySection) {\n return;\n }\n\n this.chatHistorySection.classList.remove('show');\n },\n getSessionId() {\n let sessionId = this.inputElement.getAttribute('data-session-id');\n\n if (!sessionId && this.widgetIsInitialized) {\n sessionId = localStorage.getItem(this.chatWidgetStateSession);\n }\n\n return sessionId;\n },\n copyResponse(message) {\n navigator.clipboard.writeText(message);\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 // Font Awesome SVG+JS replaces <i> with <svg>, so we must replace\n // the entire button content and let Font Awesome re-process.\n if (upBtn) {\n var upClass = userRating === true ? 'fa-solid fa-thumbs-up' : 'fa-regular fa-thumbs-up';\n var upIcon = document.createElement('i');\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('i');\n downIcon.className = downClass;\n downIcon.style.fontSize = '0.9rem';\n downBtn.textContent = '';\n downBtn.appendChild(downIcon);\n }\n\n // Trigger Font Awesome SVG+JS to convert the new <i> elements.\n if (window.FontAwesome && FontAwesome.dom && FontAwesome.dom.i2svg) {\n FontAwesome.dom.i2svg({ node: container });\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() { this.renderDocumentBar(); },\n deep: true\n },\n isUploading() { 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 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 this.initializeApp();\n if (hasWidgetConfig) {\n this.initializeWidget();\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 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 template: config.messageTemplate\n }).mount(config.appElementSelector);\n\n return app;\n };\n\n return {\n initialize: initialize\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":["_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","_createForOfIteratorHelper","Array","isArray","_unsupportedIterableToArray","_n","F","s","next","_toConsumableArray","_arrayWithoutHoles","_iterableToArray","_nonIterableSpread","from","_arrayLikeToArray","_slicedToArray","_arrayWithHoles","_iterableToArrayLimit","_nonIterableRest","toString","slice","constructor","name","test","push","_typeof","window","openAIChatManager","defaultConfig","generatedImageAltText","generatedImageMaxWidth","downloadImageTitle","downloadChartTitle","downloadChartButtonText","userLabel","assistantLabel","thumbsUpTitle","thumbsDownTitle","copyTitle","codeCopiedText","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","parsePixelValue","Number","isFinite","parsed","parseFloat","clamp","min","max","Math","normalizeReference","reference","_ref","_normalized$index","_ref2","_normalized$text","_ref3","_normalized$link","normalized","assign","index","Index","Text","link","Link","normalizeReferences","references","_i","_Object$entries","entries","_normalizeReference","_Object$entries$_i","key","renderer","marked","Renderer","data","href","concat","code","lang","highlighted","hljs","getLanguage","highlight","language","_","highlightAuto","langDisplay","image","src","alt","maxWidth","chartCounter","_pendingCharts","renderChartsInMessage","message","charts","requestAnimationFrame","_step","_iterator","renderChartOnCanvas","chartId","config","err","canvas","getElementById","Chart","console","warn","offsetParent","__chartConfigs","_cfg$options","_cfg$options2","_cfg$options2$aspectR","_chartInstance","destroy","cfg","JSON","parse","options","responsive","maintainAspectRatio","aspectRatio","error","parseMarkdownContent","content","html","DOMPurify","sanitize","ADD_TAGS","ADD_ATTR","use","extensions","level","start","idx","indexOf","undefined","tokenizer","extracted","token","jsonStart","depth","inString","escape","ch","jsonEnd","closeBracketIndex","startIndex","endIndex","json","substring","tryExtractChartMarker","type","raw","renderPendingCharts","configs","_i2","_Object$keys","keys","initialize","instanceConfig","hasWidgetConfig","signalRHubUrl","appElementSelector","chatContainerElementSelector","inputElementSelector","sendButtonElementSelector","app","Vue","createApp","inputElement","buttonElement","chatContainer","placeholder","isSessionStarted","isPlaceholderVisible","chatWidgetStateSession","chatWidgetLayoutKey","widgetContainerElement","widgetToggleButtonElement","widgetResetSizeButtonElement","widgetResizeObserver","widgetViewportResizeHandler","widgetDefaultWidth","widgetDefaultHeight","widgetIsInitialized","isStreaming","isNavigatingAway","autoScroll","stream","messages","notifications","prompt","documents","existingDocuments","isUploading","uploadErrors","isDragOver","documentBar","metricsEnabled","isRecording","mediaRecorder","preRecordingPrompt","micButton","speechToTextEnabled","chatMode","textToSpeechEnabled","ttsVoiceName","audioChunks","audioPlayQueue","isPlayingAudio","currentAudioElement","currentAudioUrl","ttsButton","ttsPlayingMessageIndex","ttsAudioCache","ttsInstanceId","random","singleResponseMode","conversationModeEnabled","conversationButton","isConversationMode","notificationDismissTimers","computed","lastAssistantIndex","role","methods","handleBeforeUnload","getStoredWidgetLayout","storedLayout","localStorage","getItem","saveStoredWidgetLayout","partialLayout","currentLayout","nextLayout","panel","position","setItem","stringify","getElementSize","element","fallbackWidth","fallbackHeight","width","height","rect","getBoundingClientRect","getComputedStyle","round","getElementPosition","left","top","inlineLeft","style","inlineTop","computedLeft","computedTop","isHidden","display","clampWidgetPosition","maxLeft","innerWidth","maxTop","innerHeight","applyAbsolutePosition","right","bottom","getWidgetDefaultSize","getWidgetToggleGap","isWidgetPanelVisible","classList","contains","persistWidgetPanelPosition","panelDefaultSize","panelPosition","panelSize","toggleSize","linkedPosition","persistWidgetTogglePosition","persistWidgetPanelSize","defaultSize","currentSize","abs","syncTogglePositionToPanel","syncPanelPositionToToggle","togglePosition","updateWidgetResetSizeButtonVisibility","isResized","toggle","add","resetWidgetSize","removeProperty","constrainWidgetElementsToViewport","restoreWidgetLayout","attachDraggableWidgetElement","handle","layoutKey","suppressClickOnDrag","_this","activePointerId","startX","startY","startLeft","startTop","dragged","stopDragging","event","pointerId","removeEventListener","onPointerMove","remove","dataset","dragSuppressClick","setTimeout","deltaX","clientX","deltaY","clientY","hypot","nextPosition","addEventListener","button","target","closest","setPointerCapture","preventDefault","clampedPanel","clampedToggle","handleDragOver","sessionDocumentsEnabled","stopPropagation","inputArea","handleDragLeave","handleDrop","dataTransfer","files","uploadFiles","triggerFileInput","fileInput","click","handleFileInputChange","_this2","_callee","sessionId","profileId","formData","response","errorText","uploadError","result","j","_t","_context","uploadDocumentUrl","getSessionId","getProfileId","renderDocumentBar","FormData","append","fetch","method","body","ok","extractReadableErrorMessage","fileName","initializeSession","uploaded","failed","removeDocument","doc","_this3","_callee2","removeError","_t2","_context2","removeDocumentUrl","headers","itemId","documentId","splice","status","formatFileSize","bytes","toFixed","escapeHtml","failedItem","failedName","errorMsg","supportedExtensionsText","replaceChildren","RETURN_DOM_FRAGMENT","self","closeButtons","querySelectorAll","docToRemove","parseInt","getAttribute","errorCloseButtons","addBtn","querySelector","div","fallbackMessage","startsWith","title","detail","normalizeAssistantAppearance","appearance","label","icon","cssClass","disableStreamingAnimation","getAssistantLabel","getAssistantRoleClasses","classes","getAssistantIconClasses","shouldAnimateAssistantIcon","getAssistantIcon","startConnection","_this4","_callee3","_t3","_context3","connection","signalR","HubConnectionBuilder","withUrl","withAutomaticReconnect","build","serverTimeoutInMilliseconds","keepAliveIntervalInMilliseconds","on","_data$messages","forEach","msg","addMessage","$nextTick","refreshAllFeedbackIcons","initialPrompt","sendMessage","stopRecording","_attemptedSessionRecovery","removeItem","startNewSession","messageId","userRating","find","id","isFinal","_conversationPartialTranscript","replace","_conversationPartialMessage","htmlContent","hidePlaceholder","isPartial","scrollToBottom","_audioInputSent","dispatchEvent","Event","stopAudio","_conversationAssistantMessage","oldMsg","escaped","responseId","hideTypingIndicator","msgIndex","newMessage","base64Audio","contentType","binaryString","atob","Uint8Array","charCodeAt","playCollectedAudio","notification","receiveNotification","updateNotification","notificationType","removeNotification","onreconnecting","onreconnected","info","reloadCurrentSession","autoCreateSession","onclose","addMessageInternal","_this5","fireEvent","CustomEvent","_this6","processedContent","citedRefs","filter","_ref4","includes","sort","_ref6","_ref7","b","_step2","displayIndex","_iterator2","_step2$value","replaceAll","_displayIndex","_placeholder","_step3","_iterator3","_step4","_iterator4","_step4$value","addMessages","_this7","showPlaceholder","isOrchestratorAvailable","applyOrchestratorAvailability","unavailableMessage","orchestratorUnavailableMessage","disabled","micButtonElement","conversationButtonElement","isIndicator","trimmedPrompt","streamMessage","startRecording","_this8","navigator","mediaDevices","getUserMedia","audio","echoCancellation","noiseSuppression","autoGainControl","mimeType","MediaRecorder","isTypeSupported","audioBitsPerSecond","subject","Subject","pendingChunk","size","_callee4","uint8Array","base64","_context4","arrayBuffer","reduce","str","byte","String","fromCharCode","btoa","getTracks","track","stop","complete","documentElement","send","updateMicButton","toggleRecording","sessionProfileId","_this9","dispose","streamingStarted","showTypingIndicator","lastResponseId","messageIndex","currentSessionId","subscribe","chunk","_i3","_Object$entries2","_normalizeReference2","_Object$entries2$_i","_i4","_Object$entries3","_Object$entries3$_i","_this9$stream","processReferences","streamingFinished","synthesizeSpeech","_this9$stream2","getServiceDownMessage","_this0","_ref1","_ref10","_ref11","_ref12","_step5","processed","_iterator5","_step5$value","_step6","_iterator6","_step7","_iterator7","_step7$value","stopIcon","setAttribute","startIcon","removeAttribute","focus","icons","handleExternalTtsStop","_e$detail","sourceId","updateTtsPlaybackButtons","_this1","isPlaying","iconHtml","cacheIndex","_this10","_ttsCacheIndex","invoke","toggleMessageTts","_this11","playAudioBlob","_this12","_step8","totalLength","sum","combined","offset","_iterator8","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","_callee5","_context5","close","dismissible","autoDismissMs","endHtml","blur","startHtml","conversationModeSendPrompt","generatePrompt","templateProfileId","createSessionUrl","baseUrl","param","fullUrl","toLowerCase","location","origin","searchParams","originalLength","_this17","clearNotificationDismiss","existingIndex","findIndex","scheduleNotificationDismiss","_this18","timerId","clearTimeout","dismissNotification","handleNotificationAction","actionName","_this19","scrollTop","scrollHeight","clientHeight","handleUserInput","setSessionId","resetSession","sessionRating","initializeApp","_this20","placeholderElementSelector","loadSession","documentBarSelector","className","multiple","allowedExtensions","accept","parentElement","appendChild","atBottom","shiftKey","lastMsg","pop","promptGenerators","getElementsByClassName","chatSessions","showChatScreen","btn","block","codeEl","clipboard","writeText","copiedText","micButtonElementSelector","conversationButtonElementSelector","force","initializeWidget","_this21","ResizeObserver","observe","dragHandle","copyResponse","updateFeedbackIcons","container","upBtn","downBtn","upClass","upIcon","fontSize","downClass","downIcon","containers","$el","msgId","rateMessage","isPositive","newRating","feedbackContainer","btnClass","offsetWidth","onEnd","watch","handler","deep","active","mounted","_this22","_callee6","_context6","beforeUnmount","template","mount","download","toDataURL","img","res","removeChild"],"mappings":"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","file":"ai-chat.min.js","sourcesContent":["window.openAIChatManager = 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 codeCopiedText: 'Copied!',\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-msg-role ai-chat-msg-role-user\">{{ userLabel }}</div>\n <div v-else-if=\"message.role !== 'indicator'\" :class=\"getAssistantRoleClasses(message)\">\n <span :class=\"getAssistantIconClasses(message, index)\"><span :class=\"getAssistantIcon(message)\"></span></span>\n {{ getAssistantLabel(message) }}\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 <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 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 <span class=\"fa-regular fa-thumbs-up\"></span>\n </button>\n <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 <span class=\"fa-regular fa-thumbs-down\"></span>\n </button>\n </span>\n </template>\n <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 class=\"btn btn-sm btn-link text-secondary p-0 button-message-toolbox\" @click=\"copyResponse(message.content)\" :title=\"copyTitle\">\n <span class=\"fa-solid fa-copy\"></span>\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 <span v-if=\"notification.icon\" :class=\"notification.icon\" class=\"ai-chat-notification-icon\"></span>\n <span class=\"ai-chat-notification-text\">{{ notification.content }}</span>\n <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 <span class=\"fa-solid fa-xmark\"></span>\n </button>\n </div>\n <div v-if=\"notification.actions && notification.actions.length\" class=\"ai-chat-notification-actions\">\n <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 <span v-if=\"action.icon\" :class=\"action.icon\" class=\"me-1\"></span>\n {{ action.label }}\n </button>\n </div>\n </div>\n </div>\n `,\n indicatorTemplate: `\n <div class=\"ai-chat-msg-role ai-chat-msg-role-assistant\">\n <span class=\"ai-streaming-icon\"><span class=\"fa fa-robot\" style=\"display: inline-block;\"></span></span>\n Assistant\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 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.link = normalized.link ?? normalized.Link ?? null;\n\n return normalized;\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 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\"><span class=\"fa-solid fa-code\"></span> ${langDisplay}</span><button type=\"button\" class=\"ai-code-copy-btn\" title=\"Copy code\"><span class=\"fa-regular fa-copy\"></span></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 <span class=\"fa-solid fa-download\"></span>\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 + `<span class=\"fa-solid fa-download\"></span> ${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 const initialize = (instanceConfig) => {\n\n const config = Object.assign({}, defaultConfig, instanceConfig);\n config.widget = Object.assign({}, defaultConfig.widget || {}, instanceConfig && instanceConfig.widget ? instanceConfig.widget : {});\n const hasWidgetConfig = !!(instanceConfig && instanceConfig.widget && instanceConfig.widget.chatWidgetContainer && instanceConfig.widget.chatWidgetStateName);\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 app = Vue.createApp({\n data() {\n return {\n inputElement: null,\n buttonElement: null,\n chatContainer: null,\n placeholder: null,\n isSessionStarted: false,\n isPlaceholderVisible: true,\n chatWidgetStateName: null,\n chatWidgetStateSession: null,\n chatWidgetLayoutKey: null,\n chatHistorySection: null,\n widgetContainerElement: null,\n widgetToggleButtonElement: null,\n widgetResetSizeButtonElement: null,\n widgetResizeObserver: null,\n widgetViewportResizeHandler: null,\n widgetDefaultWidth: null,\n widgetDefaultHeight: null,\n widgetIsInitialized: false,\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 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 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 };\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 getStoredWidgetLayout() {\n if (!this.chatWidgetLayoutKey || !config.widget.persistLayout) {\n return {};\n }\n\n try {\n var storedLayout = localStorage.getItem(this.chatWidgetLayoutKey);\n return storedLayout ? JSON.parse(storedLayout) || {} : {};\n } catch (error) {\n console.warn('Failed to read widget layout state.', error);\n return {};\n }\n },\n saveStoredWidgetLayout(partialLayout) {\n if (!this.chatWidgetLayoutKey || !config.widget.persistLayout) {\n return;\n }\n\n var currentLayout = this.getStoredWidgetLayout();\n var nextLayout = Object.assign({}, currentLayout);\n\n if (partialLayout.panel !== undefined) {\n nextLayout.panel = Object.assign({}, currentLayout.panel || {}, partialLayout.panel || {});\n }\n\n if (partialLayout.position !== undefined) {\n nextLayout.position = Object.assign({}, currentLayout.position || {}, partialLayout.position || {});\n }\n\n localStorage.setItem(this.chatWidgetLayoutKey, JSON.stringify(nextLayout));\n },\n getElementSize(element, fallbackWidth, fallbackHeight) {\n if (!element) {\n return {\n width: fallbackWidth || 0,\n height: fallbackHeight || 0\n };\n }\n\n var rect = element.getBoundingClientRect();\n var computed = window.getComputedStyle(element);\n\n return {\n width: Math.round(rect.width || parsePixelValue(computed.width) || fallbackWidth || 0),\n height: Math.round(rect.height || parsePixelValue(computed.height) || fallbackHeight || 0)\n };\n },\n getElementPosition(element) {\n if (!element) {\n return {\n left: 0,\n top: 0\n };\n }\n\n var rect = element.getBoundingClientRect();\n var computed = window.getComputedStyle(element);\n var inlineLeft = parsePixelValue(element.style.left);\n var inlineTop = parsePixelValue(element.style.top);\n var computedLeft = parsePixelValue(computed.left);\n var computedTop = parsePixelValue(computed.top);\n var isHidden = computed.display === 'none';\n\n return {\n left: Math.round(\n isHidden && Number.isFinite(inlineLeft)\n ? inlineLeft\n : rect.left || inlineLeft || computedLeft || 0),\n top: Math.round(\n isHidden && Number.isFinite(inlineTop)\n ? inlineTop\n : rect.top || inlineTop || computedTop || 0)\n };\n },\n clampWidgetPosition(left, top, width, height) {\n var viewportPadding = 8;\n var maxLeft = Math.max(viewportPadding, window.innerWidth - width - viewportPadding);\n var maxTop = Math.max(viewportPadding, window.innerHeight - height - viewportPadding);\n\n return {\n left: Math.round(clamp(left, viewportPadding, maxLeft)),\n top: Math.round(clamp(top, viewportPadding, maxTop))\n };\n },\n applyAbsolutePosition(element, left, top) {\n if (!element) {\n return;\n }\n\n element.style.left = left + 'px';\n element.style.top = top + 'px';\n element.style.right = 'auto';\n element.style.bottom = 'auto';\n },\n getWidgetDefaultSize() {\n return {\n width: this.widgetDefaultWidth || parsePixelValue(config.widget.defaultWidth) || 380,\n height: this.widgetDefaultHeight || parsePixelValue(config.widget.defaultHeight) || 520\n };\n },\n getWidgetToggleGap() {\n return 8;\n },\n isWidgetPanelVisible() {\n if (!this.widgetContainerElement) {\n return false;\n }\n\n var computed = window.getComputedStyle(this.widgetContainerElement);\n return this.widgetContainerElement.classList.contains('open') && computed.display !== 'none';\n },\n persistWidgetPanelPosition() {\n if (!this.widgetContainerElement || !config.widget.persistLayout) {\n return;\n }\n\n var panelDefaultSize = this.getWidgetDefaultSize();\n var panelPosition = this.getElementPosition(this.widgetContainerElement);\n var panelSize = this.getElementSize(this.widgetContainerElement, panelDefaultSize.width, panelDefaultSize.height);\n var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);\n var linkedPosition = this.clampWidgetPosition(\n panelPosition.left + panelSize.width - toggleSize.width,\n panelPosition.top + panelSize.height + this.getWidgetToggleGap(),\n toggleSize.width,\n toggleSize.height);\n\n this.saveStoredWidgetLayout({\n position: {\n left: linkedPosition.left,\n top: linkedPosition.top\n }\n });\n },\n persistWidgetTogglePosition() {\n if (!this.widgetToggleButtonElement || !config.widget.persistLayout) {\n return;\n }\n\n var toggleRect = this.widgetToggleButtonElement.getBoundingClientRect();\n this.saveStoredWidgetLayout({\n position: {\n left: this.getElementPosition(this.widgetToggleButtonElement).left,\n top: this.getElementPosition(this.widgetToggleButtonElement).top\n }\n });\n },\n persistWidgetPanelSize() {\n if (!this.widgetContainerElement || !config.widget.enableResizing || !config.widget.persistLayout) {\n return;\n }\n\n var defaultSize = this.getWidgetDefaultSize();\n var currentSize = this.getElementSize(this.widgetContainerElement, defaultSize.width, defaultSize.height);\n\n this.saveStoredWidgetLayout({\n panel: {\n width: Math.abs(currentSize.width - defaultSize.width) <= 1 ? null : currentSize.width,\n height: Math.abs(currentSize.height - defaultSize.height) <= 1 ? null : currentSize.height\n }\n });\n },\n syncTogglePositionToPanel(persistLayout = true) {\n if (!this.widgetContainerElement || !this.widgetToggleButtonElement) {\n return;\n }\n\n var panelDefaultSize = this.getWidgetDefaultSize();\n var panelSize = this.getElementSize(this.widgetContainerElement, panelDefaultSize.width, panelDefaultSize.height);\n var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);\n var panelPosition = this.getElementPosition(this.widgetContainerElement);\n var linkedPosition = this.clampWidgetPosition(\n panelPosition.left + panelSize.width - toggleSize.width,\n panelPosition.top + panelSize.height + this.getWidgetToggleGap(),\n toggleSize.width,\n toggleSize.height);\n\n this.applyAbsolutePosition(this.widgetToggleButtonElement, linkedPosition.left, linkedPosition.top);\n\n if (persistLayout && config.widget.persistLayout) {\n this.persistWidgetTogglePosition();\n }\n },\n syncPanelPositionToToggle(persistLayout = true) {\n if (!this.widgetContainerElement || !this.widgetToggleButtonElement) {\n return;\n }\n\n var panelDefaultSize = this.getWidgetDefaultSize();\n var panelSize = this.getElementSize(this.widgetContainerElement, panelDefaultSize.width, panelDefaultSize.height);\n var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);\n var togglePosition = this.getElementPosition(this.widgetToggleButtonElement);\n var linkedPosition = this.clampWidgetPosition(\n togglePosition.left + toggleSize.width - panelSize.width,\n togglePosition.top - panelSize.height - this.getWidgetToggleGap(),\n panelSize.width,\n panelSize.height);\n\n this.applyAbsolutePosition(this.widgetContainerElement, linkedPosition.left, linkedPosition.top);\n\n if (persistLayout && config.widget.persistLayout) {\n this.persistWidgetPanelPosition();\n }\n },\n updateWidgetResetSizeButtonVisibility() {\n if (!this.widgetResetSizeButtonElement) {\n return;\n }\n\n if (!config.widget.enableResizing || !this.widgetContainerElement) {\n this.widgetResetSizeButtonElement.classList.add('d-none');\n return;\n }\n\n var defaultSize = this.getWidgetDefaultSize();\n var currentSize = this.getElementSize(this.widgetContainerElement, defaultSize.width, defaultSize.height);\n var isResized =\n Math.abs(currentSize.width - defaultSize.width) > 1 ||\n Math.abs(currentSize.height - defaultSize.height) > 1 ||\n !!this.widgetContainerElement.style.width ||\n !!this.widgetContainerElement.style.height;\n\n this.widgetResetSizeButtonElement.classList.toggle('d-none', !isResized);\n },\n resetWidgetSize() {\n if (!this.widgetContainerElement || !config.widget.enableResizing) {\n return;\n }\n\n this.widgetContainerElement.style.removeProperty('width');\n this.widgetContainerElement.style.removeProperty('height');\n this.persistWidgetPanelSize();\n this.constrainWidgetElementsToViewport();\n this.updateWidgetResetSizeButtonVisibility();\n },\n restoreWidgetLayout() {\n var storedLayout = this.getStoredWidgetLayout();\n\n if (this.widgetContainerElement && config.widget.enableResizing) {\n if (Number.isFinite(storedLayout.panel && storedLayout.panel.width)) {\n this.widgetContainerElement.style.width = storedLayout.panel.width + 'px';\n } else {\n this.widgetContainerElement.style.removeProperty('width');\n }\n\n if (Number.isFinite(storedLayout.panel && storedLayout.panel.height)) {\n this.widgetContainerElement.style.height = storedLayout.panel.height + 'px';\n } else {\n this.widgetContainerElement.style.removeProperty('height');\n }\n }\n\n if (this.widgetToggleButtonElement && config.widget.enableDragging &&\n Number.isFinite(storedLayout.position && storedLayout.position.left) &&\n Number.isFinite(storedLayout.position && storedLayout.position.top)) {\n this.applyAbsolutePosition(this.widgetToggleButtonElement, storedLayout.position.left, storedLayout.position.top);\n this.syncPanelPositionToToggle(false);\n } else if (this.widgetToggleButtonElement && config.widget.enableDragging &&\n Number.isFinite(storedLayout.toggle && storedLayout.toggle.left) &&\n Number.isFinite(storedLayout.toggle && storedLayout.toggle.top)) {\n this.applyAbsolutePosition(this.widgetToggleButtonElement, storedLayout.toggle.left, storedLayout.toggle.top);\n this.syncPanelPositionToToggle(false);\n } else if (this.widgetContainerElement && config.widget.enableDragging &&\n Number.isFinite(storedLayout.panel && storedLayout.panel.left) &&\n Number.isFinite(storedLayout.panel && storedLayout.panel.top)) {\n this.applyAbsolutePosition(this.widgetContainerElement, storedLayout.panel.left, storedLayout.panel.top);\n this.syncTogglePositionToPanel(false);\n }\n\n this.constrainWidgetElementsToViewport();\n this.updateWidgetResetSizeButtonVisibility();\n },\n attachDraggableWidgetElement(element, handle, layoutKey, suppressClickOnDrag) {\n if (!element || !handle || !config.widget.enableDragging) {\n return;\n }\n\n var activePointerId = null;\n var startX = 0;\n var startY = 0;\n var startLeft = 0;\n var startTop = 0;\n var dragged = false;\n var dragThreshold = 4;\n var interactiveSelector = 'button, a, input, textarea, select, option, label';\n\n var stopDragging = (event) => {\n if (activePointerId === null) {\n return;\n }\n\n if (event && event.pointerId !== undefined && event.pointerId !== activePointerId) {\n return;\n }\n\n document.removeEventListener('pointermove', onPointerMove);\n document.removeEventListener('pointerup', stopDragging);\n document.removeEventListener('pointercancel', stopDragging);\n element.classList.remove('ai-chat-widget-dragging');\n activePointerId = null;\n\n if (!dragged) {\n return;\n }\n\n if (layoutKey === 'panel') {\n this.syncTogglePositionToPanel(false);\n this.persistWidgetPanelPosition();\n } else if (layoutKey === 'toggle') {\n this.syncPanelPositionToToggle(false);\n this.persistWidgetTogglePosition();\n }\n\n if (config.widget.persistLayout) {\n this.persistWidgetPanelPosition();\n this.persistWidgetTogglePosition();\n }\n\n if (suppressClickOnDrag) {\n element.dataset.dragSuppressClick = 'true';\n window.setTimeout(() => {\n if (element.dataset.dragSuppressClick === 'true') {\n element.dataset.dragSuppressClick = 'false';\n }\n }, 0);\n }\n };\n\n var onPointerMove = (event) => {\n if (activePointerId === null || event.pointerId !== activePointerId) {\n return;\n }\n\n var deltaX = event.clientX - startX;\n var deltaY = event.clientY - startY;\n\n if (!dragged && Math.hypot(deltaX, deltaY) < dragThreshold) {\n return;\n }\n\n dragged = true;\n\n var defaultSize = this.getWidgetDefaultSize();\n var currentSize = this.getElementSize(\n element,\n layoutKey === 'panel' ? defaultSize.width : 52,\n layoutKey === 'panel' ? defaultSize.height : 52);\n var nextPosition = this.clampWidgetPosition(\n startLeft + deltaX,\n startTop + deltaY,\n currentSize.width,\n currentSize.height);\n\n this.applyAbsolutePosition(element, nextPosition.left, nextPosition.top);\n\n if (layoutKey === 'panel') {\n this.syncTogglePositionToPanel(false);\n } else if (layoutKey === 'toggle') {\n this.syncPanelPositionToToggle(false);\n }\n };\n\n handle.addEventListener('pointerdown', (event) => {\n if (event.button !== 0) {\n return;\n }\n\n if (layoutKey === 'panel' && event.target.closest(interactiveSelector)) {\n return;\n }\n\n var rect = element.getBoundingClientRect();\n startX = event.clientX;\n startY = event.clientY;\n startLeft = rect.left;\n startTop = rect.top;\n dragged = false;\n activePointerId = event.pointerId;\n element.classList.add('ai-chat-widget-dragging');\n\n if (handle.setPointerCapture) {\n handle.setPointerCapture(event.pointerId);\n }\n\n document.addEventListener('pointermove', onPointerMove);\n document.addEventListener('pointerup', stopDragging);\n document.addEventListener('pointercancel', stopDragging);\n event.preventDefault();\n });\n },\n constrainWidgetElementsToViewport() {\n if (this.widgetContainerElement && this.widgetContainerElement.style.left && this.isWidgetPanelVisible()) {\n var panelDefaultSize = this.getWidgetDefaultSize();\n var panelSize = this.getElementSize(this.widgetContainerElement, panelDefaultSize.width, panelDefaultSize.height);\n var panelPosition = this.getElementPosition(this.widgetContainerElement);\n var clampedPanel = this.clampWidgetPosition(panelPosition.left, panelPosition.top, panelSize.width, panelSize.height);\n\n this.applyAbsolutePosition(this.widgetContainerElement, clampedPanel.left, clampedPanel.top);\n this.syncTogglePositionToPanel(false);\n\n if (config.widget.persistLayout) {\n this.persistWidgetPanelPosition();\n this.persistWidgetTogglePosition();\n }\n } else if (this.widgetToggleButtonElement && this.widgetToggleButtonElement.style.left) {\n var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);\n var togglePosition = this.getElementPosition(this.widgetToggleButtonElement);\n var clampedToggle = this.clampWidgetPosition(togglePosition.left, togglePosition.top, toggleSize.width, toggleSize.height);\n\n this.applyAbsolutePosition(this.widgetToggleButtonElement, clampedToggle.left, clampedToggle.top);\n this.syncPanelPositionToToggle(false);\n\n if (config.widget.persistLayout) {\n this.persistWidgetTogglePosition();\n this.persistWidgetPanelPosition();\n }\n }\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(e.dataTransfer.files);\n }\n },\n triggerFileInput() {\n if (!config.sessionDocumentsEnabled) 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;\n if (files && files.length > 0) {\n this.uploadFiles(files);\n }\n e.target.value = '';\n },\n async uploadFiles(files) {\n if (!config.uploadDocumentUrl) return;\n\n var sessionId = this.getSessionId();\n var profileId = this.getProfileId();\n\n if (!sessionId && !profileId) {\n console.warn('Cannot upload documents without a session or profile.');\n return;\n }\n\n this.isUploading = true;\n this.uploadErrors = [];\n this.renderDocumentBar();\n try {\n var formData = new FormData();\n if (sessionId) {\n formData.append('sessionId', sessionId);\n } else {\n formData.append('profileId', profileId);\n }\n for (var i = 0; i < files.length; i++) {\n formData.append('files', files[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 the server created a new session, initialize it.\n if (result.sessionId && !sessionId) {\n this.initializeSession(result.sessionId);\n }\n\n if (result.uploaded && result.uploaded.length > 0) {\n for (var j = 0; j < result.uploaded.length; j++) {\n this.documents.push(result.uploaded[j]);\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 } finally {\n this.isUploading = false;\n this.renderDocumentBar();\n }\n },\n async removeDocument(doc) {\n if (!config.removeDocumentUrl) return;\n\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 idx = this.documents.indexOf(doc);\n if (idx > -1) this.documents.splice(idx, 1);\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 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 this.renderDocumentBar();\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 += '<span class=\"fa-solid fa-file-lines\" style=\"font-size: 0.7rem;\"></span> ';\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\"></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 += '<span class=\"fa-solid fa-circle-exclamation\" style=\"font-size: 0.7rem;\"></span> ';\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\">';\n html += '<span class=\"fa-solid fa-paperclip\"></span>';\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 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 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\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 // automatically send it as the first user message to trigger an AI response.\n if (this.messages.length === 0 && config.initialPrompt) {\n this.prompt = config.initialPrompt;\n this.sendMessage();\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 // If this is a widget with a stale cached session (e.g., profile was deleted),\n // clear the cached session and start fresh with the current profile.\n if (this.widgetIsInitialized && !this.isSessionStarted && !this._attemptedSessionRecovery) {\n this._attemptedSessionRecovery = true;\n localStorage.removeItem(this.chatWidgetStateSession);\n this.startNewSession();\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, '&').replace(/</g, '<').replace(/>/g, '>');\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, '&').replace(/</g, '<').replace(/>/g, '>');\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, 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 };\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.content = this._conversationAssistantMessage.content;\n msg.htmlContent = parseMarkdownContent(msg.content, msg);\n this.$nextTick(() => {\n renderChartsInMessage(msg);\n this.scrollToBottom();\n });\n }\n });\n\n this.connection.on(\"ReceiveConversationAssistantComplete\", (sessionId, messageId) => {\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\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 } else if (config.autoCreateSession) {\n this.startNewSession();\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(\"addingOpenAIPromotMessage\", { detail: { message: message } }));\n this.messages.push(message);\n\n this.$nextTick(() => {\n this.fireEvent(new CustomEvent(\"addedOpenAIPromotMessage\", { 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 let processedContent = message.content.trim();\n message.references = normalizeReferences(message.references);\n\n if (message.references && typeof message.references === \"object\" && Object.keys(message.references).length) {\n\n // Only include references that were actually cited in the response.\n const citedRefs = Object.entries(message.references).filter(([key]) => processedContent.includes(key));\n\n if (citedRefs.length) {\n // Sort by original index so display indices follow a natural order.\n citedRefs.sort(([, a], [, b]) => a.index - b.index);\n\n // Phase 1: Replace all markers with unique placeholders.\n let displayIndex = 1;\n for (const [key, value] of citedRefs) {\n const placeholder = `__CITE_${value.index}__`;\n processedContent = processedContent.replaceAll(key, placeholder);\n value._displayIndex = displayIndex++;\n value._placeholder = placeholder;\n }\n\n // Phase 2: Replace placeholders with sequential display indices.\n for (const [, value] of citedRefs) {\n processedContent = processedContent.replaceAll(value._placeholder, `<sup><strong>${value._displayIndex}</strong></sup>`);\n }\n\n // if we have multiple references, add a comma to ensure we don't concatenate numbers.\n processedContent = processedContent.replaceAll('</strong></sup><sup>', '</strong></sup><sup>,</sup><sup>');\n\n processedContent += '<br><br>';\n\n for (const [key, value] of citedRefs) {\n const label = value.text || key;\n processedContent += value.link\n ? `**${value._displayIndex}**. [${label}](${value.link})<br>`\n : `**${value._displayIndex}**. ${label}<br>`;\n }\n }\n }\n\n message.content = processedContent;\n message.htmlContent = parseMarkdownContent(processedContent, message);\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 = '<span class=\"fa-solid fa-stop\"></span>';\n } else {\n this.micButton.classList.remove('stt-recording');\n this.micButton.innerHTML = '<span class=\"fa-solid fa-microphone\"></span>';\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 let processedContent = chunk.content;\n\n for (const [key, value] of Object.entries(references)) {\n processedContent = processedContent.replaceAll(key, `<sup><strong>${value.index}</strong></sup>`);\n }\n\n // Append processed content to the message.\n // if we have multiple references, add a comma to ensure we don't concatenate numbers.\n content += processedContent.replaceAll('</strong></sup><sup>', '</strong></sup><sup>,</sup><sup>');\n }\n\n // Update the existing message\n message.content = content;\n\n message.htmlContent = parseMarkdownContent(content, message);\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 processReferences(references, messageIndex) {\n references = normalizeReferences(references);\n\n if (Object.keys(references).length) {\n\n let message = this.messages[messageIndex];\n const content = message.content || '';\n\n // Only include references that were actually cited in the response.\n // Check both raw [doc:N] markers and already-rendered <sup> tags from streaming.\n const citedRefs = Object.entries(references).filter(([key, value]) =>\n content.includes(key) || content.includes(`<sup><strong>${value.index}</strong></sup>`)\n );\n\n if (!citedRefs.length) {\n return;\n }\n\n // Sort by original index so display indices follow a natural order.\n citedRefs.sort(([, a], [, b]) => a.index - b.index);\n\n // Phase 1: Replace all markers with unique placeholders to avoid collisions during remapping.\n let processed = content.trim();\n let displayIndex = 1;\n for (const [key, value] of citedRefs) {\n const placeholder = `__CITE_${value.index}__`;\n processed = processed.replaceAll(key, placeholder);\n processed = processed.replaceAll(`<sup><strong>${value.index}</strong></sup>`, placeholder);\n value._displayIndex = displayIndex++;\n value._placeholder = placeholder;\n }\n\n // Phase 2: Replace placeholders with sequential display indices.\n for (const [, value] of citedRefs) {\n processed = processed.replaceAll(value._placeholder, `<sup><strong>${value._displayIndex}</strong></sup>`);\n }\n\n processed = processed.replaceAll('</strong></sup><sup>', '</strong></sup><sup>,</sup><sup>');\n\n processed += '<br><br>';\n\n for (const [key, value] of citedRefs) {\n const label = value.text || key;\n processed += value.link\n ? `**${value._displayIndex}**. [${label}](${value.link})<br>`\n : `**${value._displayIndex}**. ${label}<br>`;\n }\n\n message.content = processed;\n message.htmlContent = parseMarkdownContent(processed, message);\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 var iconHtml = isPlaying\n ? '<span class=\"fa-solid fa-circle-pause\"></span>'\n : '<span class=\"fa-solid fa-circle-play\"></span>';\n\n button.classList.toggle('tts-playing', isPlaying);\n button.setAttribute('title', isPlaying ? 'Pause audio' : 'Read aloud');\n button.replaceChildren(DOMPurify.sanitize(iconHtml, { RETURN_DOM_FRAGMENT: true }));\n });\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.getAttribute('data-profile-id');\n },\n setSessionId(sessionId) {\n this.inputElement.setAttribute('data-session-id', sessionId || '');\n },\n resetSession() {\n this.stopRecording();\n this.setSessionId('');\n this.isSessionStarted = false;\n this.sessionRating = null;\n if (this.widgetIsInitialized) {\n localStorage.removeItem(this.chatWidgetStateSession);\n }\n this.messages = [];\n this.documents = [];\n if (!config.autoCreateSession) {\n this.showPlaceholder();\n }\n\n if (config.autoCreateSession) {\n this.startNewSession();\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.connection.invoke(\"StartSession\", profileId, null).catch(err => console.error(err));\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 this.applyOrchestratorAvailability();\n\n const sessionId = this.getSessionId();\n if (!hasWidgetConfig && sessionId) {\n this.loadSession(sessionId);\n } else if (this.isOrchestratorAvailable() && config.autoCreateSession && !hasWidgetConfig && !sessionId) {\n this.startNewSession();\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 for (let i = 0; i < config.messages.length; i++) {\n this.addMessage(config.messages[i]);\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 = '<span class=\"fa-solid fa-check\"></span> ' + copiedText;\n setTimeout(() => {\n btn.innerHTML = '<span class=\"fa-regular fa-copy\"></span>';\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 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 return\n }\n this.fireEvent(new CustomEvent(\"initializingSessionOpenAIChat\", { detail: { sessionId: sessionId } }))\n this.setSessionId(sessionId);\n this.isSessionStarted = true;\n\n if (this.widgetIsInitialized) {\n localStorage.setItem(this.chatWidgetStateSession, sessionId);\n }\n },\n initializeWidget() {\n\n if (!config.widget.chatWidgetContainer) {\n console.error('The widget chatWidgetContainer is required.');\n return;\n }\n\n if (!config.widget.chatWidgetStateName) {\n console.error('The widget chatWidgetStateName is required.');\n return;\n }\n\n const chatWidgetContainer = document.querySelector(config.widget.chatWidgetContainer);\n\n if (!chatWidgetContainer) {\n return;\n }\n\n if (config.widget.chatHistorySection) {\n this.chatHistorySection = document.querySelector(config.widget.chatHistorySection);\n }\n\n this.chatWidgetStateName = config.widget.chatWidgetStateName;\n this.chatWidgetStateSession = config.widget.chatWidgetStateName + 'Session';\n this.chatWidgetLayoutKey = config.widget.chatWidgetStateName + 'Layout';\n this.widgetContainerElement = chatWidgetContainer;\n this.widgetToggleButtonElement = config.widget.toggleButtonSelector\n ? document.querySelector(config.widget.toggleButtonSelector)\n : null;\n this.widgetResetSizeButtonElement = config.widget.resetSizeButtonSelector\n ? document.querySelector(config.widget.resetSizeButtonSelector)\n : null;\n this.widgetDefaultWidth = parsePixelValue(config.widget.defaultWidth) ||\n parsePixelValue(window.getComputedStyle(chatWidgetContainer).width) ||\n 380;\n this.widgetDefaultHeight = parsePixelValue(config.widget.defaultHeight) ||\n parsePixelValue(window.getComputedStyle(chatWidgetContainer).height) ||\n 520;\n this.widgetIsInitialized = true;\n\n if (config.widget.enableResizing) {\n chatWidgetContainer.classList.add('ai-chat-widget-resizable');\n chatWidgetContainer.style.minWidth = (parsePixelValue(config.widget.minWidth) || 320) + 'px';\n chatWidgetContainer.style.minHeight = (parsePixelValue(config.widget.minHeight) || 420) + 'px';\n\n if (typeof ResizeObserver !== 'undefined') {\n this.widgetResizeObserver = new ResizeObserver(() => {\n this.persistWidgetPanelSize();\n this.constrainWidgetElementsToViewport();\n this.updateWidgetResetSizeButtonVisibility();\n });\n\n this.widgetResizeObserver.observe(chatWidgetContainer);\n }\n }\n\n var dragHandleSelector = config.widget.dragHandleSelector || '.ai-chat-widget-header';\n var dragHandle = chatWidgetContainer.querySelector(dragHandleSelector);\n\n if (config.widget.enableDragging && dragHandle) {\n dragHandle.classList.add('ai-chat-widget-drag-handle');\n chatWidgetContainer.classList.add('ai-chat-widget-draggable');\n this.attachDraggableWidgetElement(chatWidgetContainer, dragHandle, 'panel', false);\n }\n\n if (config.widget.enableDragging && this.widgetToggleButtonElement) {\n this.widgetToggleButtonElement.classList.add('ai-chat-widget-draggable');\n this.attachDraggableWidgetElement(this.widgetToggleButtonElement, this.widgetToggleButtonElement, 'toggle', true);\n }\n\n if (this.widgetResetSizeButtonElement) {\n this.widgetResetSizeButtonElement.addEventListener('click', (event) => {\n event.preventDefault();\n this.resetWidgetSize();\n });\n }\n\n this.restoreWidgetLayout();\n\n if (!this.widgetViewportResizeHandler) {\n this.widgetViewportResizeHandler = () => {\n this.constrainWidgetElementsToViewport();\n this.updateWidgetResetSizeButtonVisibility();\n };\n\n window.addEventListener('resize', this.widgetViewportResizeHandler);\n }\n\n // Auto-load the last session so the user always sees previous chat history.\n this.reloadCurrentSession();\n\n if (config.autoCreateSession && !this.getSessionId()) {\n this.startNewSession();\n }\n\n if (config.widget.showHistoryButton && this.chatHistorySection) {\n\n const showHistoryButton = document.querySelector(config.widget.showHistoryButton);\n\n if (showHistoryButton) {\n showHistoryButton.addEventListener('click', () => {\n this.chatHistorySection.classList.toggle('show');\n });\n }\n\n if (config.widget.closeHistoryButton) {\n var closeHistoryButton = document.querySelector(config.widget.closeHistoryButton);\n\n if (closeHistoryButton) {\n closeHistoryButton.addEventListener('click', () => {\n this.showChatScreen();\n });\n }\n }\n }\n\n if (config.widget.newChatButton) {\n const newChatButton = document.querySelector(config.widget.newChatButton);\n\n if (newChatButton) {\n newChatButton.addEventListener('click', () => {\n this.resetSession();\n this.showChatScreen();\n });\n }\n }\n },\n showChatScreen() {\n\n if (!this.chatHistorySection) {\n return;\n }\n\n this.chatHistorySection.classList.remove('show');\n },\n getSessionId() {\n let sessionId = this.inputElement.getAttribute('data-session-id');\n\n if (!sessionId && this.widgetIsInitialized) {\n sessionId = localStorage.getItem(this.chatWidgetStateSession);\n }\n\n return sessionId;\n },\n copyResponse(message) {\n navigator.clipboard.writeText(message);\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() { this.renderDocumentBar(); },\n deep: true\n },\n isUploading() { 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 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 this.initializeApp();\n if (hasWidgetConfig) {\n this.initializeWidget();\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 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 template: config.messageTemplate\n }).mount(config.appElementSelector);\n\n return app;\n };\n\n return {\n initialize: initialize\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"]}
|