@crestapps/ai-chat-ui 1.0.0-preview.9 → 1.0.0-preview.95

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.
Files changed (35) hide show
  1. package/dist/ai-chat-widget.js +962 -0
  2. package/dist/ai-chat-widget.js.map +1 -0
  3. package/dist/ai-chat-widget.min.js +2 -0
  4. package/dist/ai-chat-widget.min.js.map +1 -0
  5. package/dist/ai-chat.css +45 -14
  6. package/dist/ai-chat.css.map +1 -1
  7. package/dist/ai-chat.js +1076 -1019
  8. package/dist/ai-chat.js.map +1 -1
  9. package/dist/ai-chat.min.css +1 -1
  10. package/dist/ai-chat.min.js +1 -1
  11. package/dist/ai-chat.min.js.map +1 -1
  12. package/dist/chat-interaction-settings.js +297 -0
  13. package/dist/chat-interaction-settings.js.map +1 -0
  14. package/dist/chat-interaction-settings.min.js +2 -0
  15. package/dist/chat-interaction-settings.min.js.map +1 -0
  16. package/dist/chat-interaction.js +1224 -325
  17. package/dist/chat-interaction.js.map +1 -1
  18. package/dist/chat-interaction.min.js +1 -1
  19. package/dist/chat-interaction.min.js.map +1 -1
  20. package/dist/chat-widget.css +48 -26
  21. package/dist/chat-widget.css.map +1 -1
  22. package/dist/chat-widget.min.css +1 -1
  23. package/dist/document-drop-zone.css +10 -10
  24. package/dist/document-drop-zone.css.map +1 -1
  25. package/dist/document-drop-zone.js +92 -14
  26. package/dist/document-drop-zone.js.map +1 -1
  27. package/dist/document-drop-zone.min.css +1 -1
  28. package/dist/document-drop-zone.min.js +1 -1
  29. package/dist/document-drop-zone.min.js.map +1 -1
  30. package/dist/technical-name-generator.js +36 -8
  31. package/dist/technical-name-generator.js.map +1 -1
  32. package/dist/technical-name-generator.min.js +1 -1
  33. package/dist/technical-name-generator.min.js.map +1 -1
  34. package/package.json +9 -1
  35. package/README.md +0 -145
@@ -1 +1 @@
1
- {"version":3,"sources":["chat-interaction.js"],"names":["_slicedToArray","r","e","_arrayWithHoles","_iterableToArrayLimit","_unsupportedIterableToArray","_nonIterableRest","TypeError","l","t","Symbol","iterator","n","i","u","a","f","o","call","next","Object","done","push","value","length","Array","isArray","_typeof","constructor","prototype","_regenerator","toStringTag","c","Generator","create","_regeneratorDefine2","p","y","G","v","d","bind","GeneratorFunction","GeneratorFunctionPrototype","getPrototypeOf","this","setPrototypeOf","__proto__","displayName","w","m","defineProperty","_invoke","enumerable","configurable","writable","asyncGeneratorStep","Promise","resolve","then","_asyncToGenerator","arguments","apply","_next","_throw","_createForOfIteratorHelper","_n","F","s","_toConsumableArray","_arrayWithoutHoles","_iterableToArray","_nonIterableSpread","_arrayLikeToArray","toString","slice","name","from","test","window","chatInteractionManager","defaultConfig","generatedImageAltText","generatedImageMaxWidth","downloadImageTitle","downloadChartTitle","downloadChartButtonText","codeCopiedText","assistantLabel","messageTemplate","indicatorTemplate","untitledText","clearHistoryTitle","clearHistoryMessage","clearHistoryOkText","clearHistoryCancelText","sanitizeUrl","url","trimmed","trim","escapeHtmlEntities","text","span","document","createElement","textContent","innerHTML","renderer","marked","Renderer","link","data","href","concat","code","lang","highlighted","hljs","getLanguage","highlight","language","_","highlightAuto","langDisplay","image","src","alt","maxWidth","chartCounter","_pendingCharts","renderChartsInMessage","message","charts","requestAnimationFrame","_step","_iterator","canvas","getElementById","chartId","Chart","offsetParent","_cfg$options","_cfg$options2","_cfg$options2$aspectR","_chartInstance","destroy","cfg","config","JSON","parse","options","responsive","maintainAspectRatio","aspectRatio","console","error","__chartConfigs","warn","err","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","initialize","instanceConfig","assign","signalRHubUrl","appElementSelector","chatContainerElementSelector","inputElementSelector","sendButtonElementSelector","Vue","createApp","inputElement","buttonElement","chatContainer","placeholder","isInteractionStarted","isPlaceholderVisible","isStreaming","isNavigatingAway","autoScroll","stream","messages","prompt","initialFieldValues","Map","settingsDirty","saveSettingsTimeout","saveIndicatorTimeout","isRecording","mediaRecorder","preRecordingPrompt","micButton","speechToTextEnabled","chatMode","textToSpeechEnabled","ttsVoiceName","audioChunks","audioPlayQueue","isPlayingAudio","currentAudioElement","currentAudioUrl","ttsPlayingMessageIndex","ttsAudioCache","ttsInstanceId","Math","random","conversationModeEnabled","conversationButton","isConversationMode","notifications","notificationDismissTimers","computed","lastAssistantIndex","role","methods","handleBeforeUnload","startConnection","_this","_callee","_t","_context","connection","signalR","HubConnectionBuilder","withUrl","withAutomaticReconnect","build","serverTimeoutInMilliseconds","keepAliveIntervalInMilliseconds","on","_data$messages","initializeInteraction","itemId","titleInput","querySelector","title","forEach","msg","addMessage","$nextTick","historyItem","showSaveIndicator","stopRecording","isFinal","_conversationPartialTranscript","replace","_conversationPartialMessage","htmlContent","hidePlaceholder","isPartial","scrollToBottom","_audioInputSent","dispatchEvent","Event","stopAudio","_conversationAssistantMessage","oldMsg","index","escaped","messageId","responseId","appearance","hideTypingIndicator","j","msgIndex","newMessage","id","normalizeAssistantAppearance","base64Audio","contentType","binaryString","atob","bytes","Uint8Array","charCodeAt","playCollectedAudio","showPlaceholder","clearHistoryBtn","classList","add","notification","receiveNotification","updateNotification","notificationType","removeNotification","onreconnecting","onreconnected","info","reloadCurrentInteraction","onclose","addMessageInternal","_this2","fireEvent","CustomEvent","detail","_this3","processedContent","references","keys","citedRefs","entries","filter","_ref","key","includes","sort","_ref3","_ref4","b","_step2","displayIndex","_iterator2","_step2$value","replaceAll","_displayIndex","_placeholder","_step3","_iterator3","_step4","_iterator4","_step4$value","label","remove","event","icon","cssClass","disableStreamingAnimation","getAssistantLabel","getAssistantRoleClasses","classes","getAssistantIconClasses","shouldAnimateAssistantIcon","getAssistantIcon","isIndicator","sendMessage","_this4","_callee2","trimmedPrompt","_context2","flushPendingSave","streamMessage","_this5","dispose","streamingStarted","showTypingIndicator","lastResponseId","messageIndex","currentItemId","getItemId","subscribe","chunk","sessionId","setItemId","_i","_Object$entries","_Object$entries$_i","_i2","_Object$entries2","_Object$entries2$_i","complete","_this5$stream","processReferences","streamingFinished","synthesizeSpeech","_this5$stream2","getServiceDownMessage","_this6","_ref7","_ref8","_ref9","_ref0","_step5","processed","_iterator5","_step5$value","_step6","_iterator6","_step7","_iterator7","_step7$value","stopIcon","getAttribute","replaceChildren","RETURN_DOM_FRAGMENT","startIcon","icons","querySelectorAll","debouncedSaveSettings","handleExternalTtsStop","_e$detail","sourceId","cacheIndex","_this7","_ttsCacheIndex","invoke","toggleMessageTts","playAudioBlob","_step8","totalLength","reduce","sum","combined","offset","_iterator8","set","blob","Blob","_this8","URL","createObjectURL","audio","Audio","addEventListener","revokeObjectURL","playNextInQueue","play","nextBlob","shift","conversationModeOnAudioEnded","pause","currentTime","toggleConversationMode","stopConversationMode","startConversationMode","_this9","updateConversationButton","navigator","mediaDevices","getUserMedia","echoCancellation","noiseSuppression","autoGainControl","mimeType","MediaRecorder","isTypeSupported","audioBitsPerSecond","_conversationSubject","Subject","_conversationStream","AudioCtx","AudioContext","webkitAudioContext","_conversationAudioCtx","_conversationAnalyser","createAnalyser","fftSize","createMediaStreamSource","connect","pendingChunk","analyser","size","freqData","frequencyBinCount","getByteFrequencyData","k","_callee3","uint8Array","base64","_context3","arrayBuffer","str","byte","String","fromCharCode","btoa","getTracks","track","stop","documentElement","send","close","dismissible","autoDismissMs","endHtml","blur","startHtml","conversationModeSendPrompt","originalLength","_this0","setTimeout","scrollTop","scrollHeight","clientHeight","handleUserInput","target","getSaveIndicatorElement","saveIndicatorElementSelector","className","_this1","indicator","clearTimeout","clearPendingSettingsSave","getFieldLabel","input","_input$closest","closest","dataset","setting","getValidationFeedbackElement","feedback","nextElementSibling","contains","insertAdjacentElement","clearSettingValidationError","removeAttribute","setSettingValidationError","setAttribute","getSettingValidationMessage","disabled","number","Number","fieldLabel","isNaN","min","max","validateSettingInput","validateSettings","_this10","isValid","getSettingInputs","queueSettingsSave","explicitInputs","getSelectedGroupValues","groupName","fallbackSelector","explicitSelections","values","checkbox","baseName","hiddenInput","getPromptTemplateSelections","promptTemplates","card","templateIdInput","promptParametersInput","templateId","promptParameters","clearNotificationDismiss","findIndex","splice","scheduleNotificationDismiss","_this11","timerId","dismissNotification","handleNotificationAction","actionName","resetInteraction","initializeApp","_this12","placeholderElementSelector","loadInteraction","atBottom","shiftKey","click","lastMsg","pop","chatInteractionItems","getElementsByClassName","preventDefault","btn","block","codeEl","clipboard","writeText","copiedText","matches","clearHistory","micButtonElementSelector","style","display","toggleRecording","conversationButtonElementSelector","self","confirmDialog","okText","cancelText","callback","confirmed","_this13","saveSettings","getSelectedToolNames","getSelectedMcpConnectionIds","getSelectedA2AConnectionIds","getSelectedAgentNames","_this14","settings","match","toLowerCase","checked","parseFloat","toolNames","mcpConnectionIds","a2aConnectionIds","agentNames","promptTemplateIds","map","template","force","copyResponse","startRecording","_this15","subject","_callee4","_context4","updateMicButton","watch","active","mounted","_this16","_callee5","_context5","beforeUnmount","removeEventListener","mount","download","toDataURL","container","img","startsWith","fetch","res","body","appendChild","removeChild"],"mappings":"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","file":"chat-interaction.min.js","sourcesContent":["window.chatInteractionManager = 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 codeCopiedText: 'Copied!',\n assistantLabel: 'Assistant',\n\n messageTemplate: `\n <div class=\"ai-chat-messages\">\n <div v-for=\"(message, index) in messages\" :key=\"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\">You</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 <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 <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=\"Click here to copy response to clipboard.\">\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 // Localizable strings\n untitledText: 'Untitled',\n clearHistoryTitle: 'Clear History',\n clearHistoryMessage: 'Are you sure you want to clear the chat history? This action cannot be undone. Your documents, parameters, and tools will be preserved.',\n clearHistoryOkText: 'Yes',\n clearHistoryCancelText: 'Cancel'\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 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 shared with ai-chat.js\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 const canvas = document.getElementById(c.chartId);\n if (!canvas) {\n continue;\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 continue;\n }\n\n // When the canvas is inside a hidden container (e.g., display:none),\n // it has zero dimensions. Keep the config for later rendering.\n if (canvas.offsetParent === null) {\n window.__chartConfigs[c.chartId] = c.config;\n continue;\n }\n\n try {\n // Destroy existing chart instance if re-rendering\n if (canvas._chartInstance) {\n canvas._chartInstance.destroy();\n }\n\n const cfg = typeof c.config === 'string' ? JSON.parse(c.config) : c.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 } catch (e) {\n console.error('Error creating chart:', e);\n }\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 // 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 isInteractionStarted: false,\n isPlaceholderVisible: true,\n isStreaming: false,\n isNavigatingAway: false,\n autoScroll: true,\n stream: null,\n messages: [],\n prompt: '',\n initialFieldValues: new Map(),\n settingsDirty: false,\n saveSettingsTimeout: null,\n saveIndicatorTimeout: null,\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 ttsPlayingMessageIndex: -1,\n ttsAudioCache: {},\n ttsInstanceId: 'chat-interaction-' + Math.random().toString(36).slice(2),\n conversationModeEnabled: config.chatMode === 'Conversation',\n conversationButton: null,\n isConversationMode: false,\n notifications: [],\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 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(\"LoadInteraction\", (data) => {\n this.initializeInteraction(data.itemId, true);\n this.messages = [];// Update the title field if it exists\n const titleInput = document.querySelector('[data-chat-interaction-title], .setting-input[data-setting=\"title\"], input[name=\"ChatInteraction.Title\"], input[name=\"Title\"]');\n if (titleInput && data.title) {\n titleInput.value = data.title;\n }\n\n (data.messages ?? []).forEach(msg => {\n this.addMessage(msg);\n\n this.$nextTick(() => {\n renderChartsInMessage(msg);\n });\n });\n });\n\n this.connection.on(\"SettingsSaved\", (itemId, title) => {\n // Update the history list item if it exists\n // Use a more specific selector to only target history list items, not other elements like the Clear History button\n const historyItem = document.querySelector(`.chat-interaction-history-item[data-interaction-id=\"${itemId}\"]`);\n if (historyItem) {\n historyItem.textContent = title || config.untitledText;\n }\n\n const titleInput = document.querySelector('[data-chat-interaction-title], .setting-input[data-setting=\"title\"], input[name=\"ChatInteraction.Title\"], input[name=\"Title\"]');\n if (titleInput && title) {\n titleInput.value = title;\n }\n\n this.showSaveIndicator('Saved', 'text-success');\n });\n\n this.connection.on(\"ReceiveError\", (error) => {\n console.error(\"SignalR Error: \", error);\n this.showSaveIndicator('Save failed', 'text-danger');\n\n if (this.isRecording) {\n this.stopRecording();\n }\n });\n\n this.connection.on(\"ReceiveTranscript\", (itemId, text, isFinal) => {\n if (this.isConversationMode) {\n if (!isFinal && text) {\n this._conversationPartialTranscript = text;\n var escaped = text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n var html = '<p class=\"ai-partial-transcript\">' + escaped + '</p>';\n\n // Show partial transcript as a live user message.\n if (!this._conversationPartialMessage) {\n this.hidePlaceholder();\n this._conversationPartialMessage = {\n role: 'user',\n content: text,\n htmlContent: html,\n isPartial: true\n };\n this.messages.push(this._conversationPartialMessage);\n } else {\n this._conversationPartialMessage.content = text;\n this._conversationPartialMessage.htmlContent = html;\n }\n this.scrollToBottom();\n }\n return;\n }\n\n if (text && !this._audioInputSent) {\n this.prompt = this.preRecordingPrompt + text;\n if (this.inputElement) {\n this.inputElement.value = this.prompt;\n this.inputElement.dispatchEvent(new Event('input'));\n }\n }\n });\n\n this.connection.on(\"ReceiveConversationUserMessage\", (itemId, text) => {\n if (text) {\n this.stopAudio();\n\n // If there's an interrupted assistant message still streaming,\n // mark it as done to stop the spinner animation.\n if (this._conversationAssistantMessage) {\n var oldMsg = this.messages[this._conversationAssistantMessage.index];\n if (oldMsg) {\n oldMsg.isStreaming = false;\n }\n this._conversationAssistantMessage = null;\n }\n\n // Replace the partial transcript message with the final one.\n if (this._conversationPartialMessage) {\n var escaped = text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n this._conversationPartialMessage.content = text;\n this._conversationPartialMessage.htmlContent = '<p>' + escaped + '</p>';\n this._conversationPartialMessage.isPartial = false;\n this._conversationPartialMessage = null;\n } else {\n this.addMessage({\n role: 'user',\n content: text\n });\n }\n this.scrollToBottom();\n }\n });\n\n this.connection.on(\"ReceiveConversationAssistantToken\", (itemId, 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 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\", (itemId, 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\", (itemId, 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\", (itemId) => {\n this.playCollectedAudio();\n });\n\n this.connection.on(\"HistoryCleared\", (itemId) => {\n // Clear messages and show placeholder\n this.messages = [];\n this.showPlaceholder();\n\n // Hide the clear history button since there's no history now\n const clearHistoryBtn = document.getElementById('clearHistoryBtn');\n if (clearHistoryBtn) {\n clearHistoryBtn.classList.add('d-none');\n }\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 this.reloadCurrentInteraction();\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(\"addingChatInteractionMessage\", { detail: { message: message } }));\n this.messages.push(message);\n\n this.$nextTick(() => {\n this.fireEvent(new CustomEvent(\"addedChatInteractionMessage\", { detail: { message: message } }));\n });\n },\n addMessage(message) {\n if (message.content) {\n let processedContent = message.content.trim();\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 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 || `[doc:${value.index}]`;\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 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 fireEvent(event) {\n document.dispatchEvent(event);\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 : defaultConfig.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 isIndicator(message) {\n return message.role === 'indicator';\n },\n async sendMessage() {\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 // Flush any pending settings save before sending a message\n // to prevent concurrent hub calls that can cause database deadlocks.\n await this.flushPendingSave();\n\n this.addMessage({\n role: 'user',\n content: trimmedPrompt\n });\n\n // Show the clear history button since we now have prompts\n const clearHistoryBtn = document.getElementById('clearHistoryBtn');\n if (clearHistoryBtn) {\n clearHistoryBtn.classList.remove('d-none');\n }\n\n this.streamMessage(trimmedPrompt);\n this.inputElement.value = '';\n this.prompt = '';\n },\n streamMessage(trimmedPrompt) {\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 var messageIndex = this.messages.length;\n var currentItemId = this.getItemId();\n\n this.stream = this.connection.stream(\"SendMessage\", currentItemId, trimmedPrompt)\n .subscribe({\n next: (chunk) => {\n let message = this.messages[messageIndex];\n\n if (!message) {\n if (chunk.sessionId && !currentItemId) {\n this.setItemId(chunk.sessionId);\n }\n\n this.hideTypingIndicator();\n messageIndex = this.messages.length;\n let newMessage = {\n role: \"assistant\",\n content: \"\",\n htmlContent: \"\",\n isStreaming: true,\n };\n\n this.messages.push(newMessage);\n message = newMessage;\n }\n\n if (chunk.references && typeof chunk.references === \"object\" && Object.keys(chunk.references).length) {\n for (const [key, value] of Object.entries(chunk.references)) {\n references[key] = value;\n }\n }\n\n if (chunk.content) {\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 content += processedContent.replaceAll('</strong></sup><sup>', '</strong></sup><sup>,</sup><sup>');\n }\n\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 return {\n role: \"assistant\",\n content: \"Our service is currently unavailable. Please try again later. We apologize for the inconvenience.\",\n htmlContent: \"\",\n };\n },\n processReferences(references, messageIndex) {\n if (Object.keys(references).length) {\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 || `[doc:${value.index}]`;\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 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 // 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 // Save any settings that were deferred during streaming.\n if (this.settingsDirty) {\n this.debouncedSaveSettings();\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.getItemId(), 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.isPlayingAudio && 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 currently playing, queue this blob for later.\n if (this.isPlayingAudio && 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 const 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\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 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 itemId = this.getItemId();\n\n var language = navigator.language || document.documentElement.lang || 'en-US';\n this.connection.send(\"StartConversation\", itemId, 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, continuation is handled\n // by the persistent stream.\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 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 getItemId() {\n return this.inputElement.getAttribute('data-interaction-id')\n || this.inputElement.getAttribute('data-item-id');\n },\n getSaveIndicatorElement() {\n if (config.saveIndicatorElementSelector) {\n return document.querySelector(config.saveIndicatorElementSelector);\n }\n\n return document.querySelector('[data-chat-interaction-save-indicator]');\n },\n showSaveIndicator(text, className) {\n const indicator = this.getSaveIndicatorElement();\n if (!indicator) {\n return;\n }\n\n indicator.textContent = text || '';\n indicator.className = 'settings-save-indicator ' + (className || 'text-muted');\n\n if (this.saveIndicatorTimeout) {\n clearTimeout(this.saveIndicatorTimeout);\n this.saveIndicatorTimeout = null;\n }\n\n if (!text) {\n return;\n }\n\n this.saveIndicatorTimeout = setTimeout(() => {\n indicator.textContent = '';\n this.saveIndicatorTimeout = null;\n }, 3000);\n },\n clearPendingSettingsSave() {\n if (this.saveSettingsTimeout) {\n clearTimeout(this.saveSettingsTimeout);\n this.saveSettingsTimeout = null;\n }\n },\n getFieldLabel(input) {\n const label = input\n .closest('.mb-3, .col-6, .col, .form-group, .form-floating')\n ?.querySelector('label');\n\n if (!label) {\n return input.dataset.setting || 'This field';\n }\n\n return (label.textContent || '')\n .replace(/\\s+/g, ' ')\n .trim()\n || input.dataset.setting\n || 'This field';\n },\n getValidationFeedbackElement(input) {\n let feedback = input.nextElementSibling;\n if (feedback && feedback.classList.contains('invalid-feedback')) {\n return feedback;\n }\n\n feedback = document.createElement('div');\n feedback.className = 'invalid-feedback';\n input.insertAdjacentElement('afterend', feedback);\n\n return feedback;\n },\n clearSettingValidationError(input) {\n input.classList.remove('is-invalid');\n input.removeAttribute('aria-invalid');\n\n const feedback = input.nextElementSibling;\n if (feedback && feedback.classList.contains('invalid-feedback')) {\n feedback.textContent = '';\n }\n },\n setSettingValidationError(input, message) {\n const feedback = this.getValidationFeedbackElement(input);\n input.classList.add('is-invalid');\n input.setAttribute('aria-invalid', 'true');\n feedback.textContent = message;\n },\n getSettingValidationMessage(input) {\n if (!input || input.disabled || input.type !== 'number') {\n return null;\n }\n\n const value = (input.value || '').trim();\n if (!value) {\n return null;\n }\n\n const number = Number(value);\n const fieldLabel = this.getFieldLabel(input);\n\n if (Number.isNaN(number)) {\n return `${fieldLabel} must be a valid number.`;\n }\n\n const min = input.getAttribute('min');\n if (min !== null && number < Number(min)) {\n return `${fieldLabel} must be ${min} or greater.`;\n }\n\n const max = input.getAttribute('max');\n if (max !== null && number > Number(max)) {\n return `${fieldLabel} must be ${max} or less.`;\n }\n\n return null;\n },\n validateSettingInput(input) {\n const message = this.getSettingValidationMessage(input);\n if (!message) {\n this.clearSettingValidationError(input);\n return true;\n }\n\n this.setSettingValidationError(input, message);\n return false;\n },\n validateSettings() {\n let isValid = true;\n\n this.getSettingInputs().forEach(input => {\n isValid = this.validateSettingInput(input) && isValid;\n });\n\n return isValid;\n },\n queueSettingsSave() {\n if (!this.validateSettings()) {\n this.clearPendingSettingsSave();\n this.settingsDirty = false;\n this.showSaveIndicator('Fix errors', 'text-danger');\n return;\n }\n\n this.settingsDirty = true;\n this.showSaveIndicator('Saving...', 'text-warning');\n this.debouncedSaveSettings();\n },\n getSettingInputs() {\n const explicitInputs = document.querySelectorAll('.setting-input[data-setting]');\n if (explicitInputs.length > 0) {\n return explicitInputs;\n }\n\n return document.querySelectorAll(\n 'input[name^=\"ChatInteraction.\"]:not([name*=\".Tools[\"]):not([name*=\".Connections[\"]), ' +\n 'select[name^=\"ChatInteraction.\"]:not([name*=\".Tools[\"]):not([name*=\".Connections[\"]), ' +\n 'textarea[name^=\"ChatInteraction.\"]:not([name*=\".Tools[\"]):not([name*=\".Connections[\"])'\n );\n },\n getSelectedGroupValues(groupName, fallbackSelector) {\n const explicitSelections = document.querySelectorAll(`.capability-checkbox[data-save-group=\"${groupName}\"]:checked`);\n if (explicitSelections.length > 0) {\n const values = [];\n\n explicitSelections.forEach(checkbox => {\n const value = checkbox.getAttribute('data-item-id') || checkbox.value;\n if (value) {\n values.push(value);\n }\n });\n\n return values;\n }\n\n if (!fallbackSelector) {\n return [];\n }\n\n const values = [];\n const checkboxes = document.querySelectorAll(fallbackSelector);\n\n checkboxes.forEach(checkbox => {\n const baseName = checkbox.name.replace('.IsSelected', '.ItemId');\n const hiddenInput = document.querySelector(`input[type=\"hidden\"][name=\"${baseName}\"]`);\n\n if (hiddenInput && hiddenInput.value) {\n values.push(hiddenInput.value);\n }\n });\n\n return values;\n },\n getPromptTemplateSelections() {\n const promptTemplates = [];\n\n document.querySelectorAll('.prompt-template-card').forEach(card => {\n const templateIdInput = card.querySelector('.prompt-template-id-input');\n const promptParametersInput = card.querySelector('.prompt-template-parameters-input');\n const templateId = templateIdInput ? templateIdInput.value : card.getAttribute('data-template-id');\n\n if (!templateId) {\n return;\n }\n\n promptTemplates.push({\n templateId: templateId,\n promptParameters: promptParametersInput ? (promptParametersInput.value || '').trim() : ''\n });\n });\n\n return promptTemplates;\n },\n receiveNotification(notification) {\n if (!notification || !notification.type) {\n return;\n }\n this.clearNotificationDismiss(notification.type);\n // Replace existing notification with same type, or add new one.\n var idx = this.notifications.findIndex(n => n.type === notification.type);\n if (idx >= 0) {\n this.notifications.splice(idx, 1, notification);\n } else {\n this.notifications.push(notification);\n }\n this.scheduleNotificationDismiss(notification);\n this.scrollToBottom();\n },\n updateNotification(notification) {\n if (!notification || !notification.type) {\n return;\n }\n this.clearNotificationDismiss(notification.type);\n var idx = this.notifications.findIndex(n => n.type === notification.type);\n if (idx >= 0) {\n this.notifications.splice(idx, 1, notification);\n this.scheduleNotificationDismiss(notification);\n this.scrollToBottom();\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 itemId = this.getItemId();\n this.connection.invoke('HandleNotificationAction', itemId, notificationType, actionName)\n .catch(err => console.error('Failed to handle notification action:', err));\n },\n setItemId(itemId) {\n this.inputElement.setAttribute('data-interaction-id', itemId || '');\n this.inputElement.setAttribute('data-item-id', itemId || '');\n },\n resetInteraction() {\n this.setItemId('');\n this.isInteractionStarted = false;\n this.messages = [];\n this.showPlaceholder();\n },\n initializeApp() {\n this.inputElement = document.querySelector(config.inputElementSelector);\n this.buttonElement = document.querySelector(config.sendButtonElementSelector);\n this.chatContainer = document.querySelector(config.chatContainerElementSelector);\n this.placeholder = document.querySelector(config.placeholderElementSelector);\n\n const itemId = this.getItemId();\n if (itemId) {\n this.loadInteraction(itemId);\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('keyup', event => {\n if (this.stream != null) {\n return;\n }\n\n if (event.key === \"Enter\" && !event.shiftKey) {\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.inputElement.addEventListener('paste', (e) => {\n // Use setTimeout to allow the paste to complete before checking the value\n setTimeout(() => {\n this.prompt = this.inputElement.value;\n if (this.inputElement.value.trim()) {\n this.buttonElement.removeAttribute('disabled');\n } else {\n this.buttonElement.setAttribute('disabled', true);\n }\n }, 0);\n });\n\n this.buttonElement.addEventListener('click', () => {\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 chatInteractionItems = document.getElementsByClassName('chat-interaction-history-item');\n\n for (var i = 0; i < chatInteractionItems.length; i++) {\n chatInteractionItems[i].addEventListener('click', (e) => {\n e.preventDefault();\n\n var itemId = e.target.getAttribute('data-interaction-id');\n\n if (!itemId) {\n console.error('An element with the class chat-interaction-history-item with no data-interaction-id set.');\n return;\n }\n\n this.loadInteraction(itemId);\n });\n }\n\n for (let i = 0; i < config.messages.length; i++) {\n this.addMessage(config.messages[i]);\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 document.addEventListener('input', event => {\n if (event.target.matches('.setting-input[data-setting]')) {\n this.validateSettingInput(event.target);\n this.queueSettingsSave();\n }\n });\n\n document.addEventListener('change', event => {\n if (event.target.matches('.setting-input[data-setting], .capability-checkbox[data-save-group], .group-toggle, .ci-agent-global-toggle')) {\n if (event.target.matches('.setting-input[data-setting]')) {\n this.validateSettingInput(event.target);\n }\n\n this.queueSettingsSave();\n return;\n }\n\n if (event.target.closest('.prompt-template-parameters-input, .prompt-template-id-input')) {\n this.queueSettingsSave();\n }\n });\n\n document.addEventListener('click', event => {\n if (!event.target.closest('.prompt-template-add-btn, .remove-prompt-template-btn')) {\n return;\n }\n\n setTimeout(() => {\n this.queueSettingsSave();\n }, 0);\n });\n\n // Add event listener for clear history button\n const clearHistoryBtn = document.getElementById('clearHistoryBtn');\n if (clearHistoryBtn) {\n clearHistoryBtn.addEventListener('click', () => {\n const itemId = clearHistoryBtn.getAttribute('data-interaction-id');\n if (itemId) {\n this.clearHistory(itemId);\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 loadInteraction(itemId) {\n this.connection.invoke(\"LoadInteraction\", itemId).catch(err => console.error(err));\n },\n reloadCurrentInteraction() {\n const itemId = this.getItemId();\n if (itemId) {\n this.loadInteraction(itemId);\n }\n },\n clearHistory(itemId) {\n const self = this;\n confirmDialog({\n title: config.clearHistoryTitle,\n message: config.clearHistoryMessage,\n okText: config.clearHistoryOkText,\n cancelText: config.clearHistoryCancelText,\n callback: function (confirmed) {\n if (confirmed) {\n // Cancel any active stream before clearing history.\n if (self.stream) {\n self.stream.dispose();\n self.stream = null;\n self.hideTypingIndicator();\n self.streamingFinished();\n }\n\n self.connection.invoke(\"ClearHistory\", itemId)\n .catch(err => console.error('Error clearing history:', err));\n }\n }\n });\n },\n debouncedSaveSettings() {\n // Clear any existing timeout to reset the debounce timer\n this.clearPendingSettingsSave();\n\n // Don't save while streaming — it will be saved when streaming completes.\n if (this.stream) {\n return;\n }\n\n // Set a new timeout to save after 850ms of no changes\n this.saveSettingsTimeout = setTimeout(() => {\n if (this.settingsDirty) {\n this.saveSettings();\n this.settingsDirty = false;\n }\n this.saveSettingsTimeout = null;\n }, 850);\n },\n getSelectedToolNames() {\n return this.getSelectedGroupValues(\n 'toolNames',\n 'input[type=\"checkbox\"][name$=\"].IsSelected\"][name^=\"ChatInteraction.Tools[\"]:checked'\n );\n },\n getSelectedMcpConnectionIds() {\n return this.getSelectedGroupValues(\n 'mcpConnectionIds',\n 'input[type=\"checkbox\"][name$=\"].IsSelected\"][name^=\"ChatInteraction.Connections[\"]:checked'\n );\n },\n getSelectedA2AConnectionIds() {\n return this.getSelectedGroupValues('a2aConnectionIds');\n },\n getSelectedAgentNames() {\n return this.getSelectedGroupValues(\n 'agentNames',\n 'input[type=\"checkbox\"][name$=\"].IsSelected\"][name^=\"ChatInteraction.Agents[\"]:checked'\n );\n },\n saveSettings() {\n const itemId = this.getItemId();\n if (!itemId) {\n return Promise.resolve();\n }\n\n if (!this.validateSettings()) {\n this.showSaveIndicator('Fix errors', 'text-danger');\n return Promise.resolve();\n }\n\n const settings = {};\n\n // Collect all form inputs with the \"ChatInteraction.\" prefix generically.\n // This avoids coupling the JS to specific field names — new fields added by\n // any module are automatically included.\n const inputs = this.getSettingInputs();\n\n inputs.forEach(input => {\n const key = input.dataset.setting\n || ((input.name || '').replace('ChatInteraction.', '').replace(/^[A-Z]/, match => match.toLowerCase()));\n\n if (!key) {\n return;\n }\n\n if (input.type === 'checkbox') {\n settings[key] = input.checked;\n } else if (input.type === 'number') {\n settings[key] = input.value ? parseFloat(input.value) : null;\n } else {\n settings[key] = input.value || null;\n }\n });\n\n // Add tool, MCP connection, and agent collections (special handling).\n settings.toolNames = this.getSelectedToolNames();\n settings.mcpConnectionIds = this.getSelectedMcpConnectionIds();\n settings.a2aConnectionIds = this.getSelectedA2AConnectionIds();\n settings.agentNames = this.getSelectedAgentNames();\n\n const promptTemplates = this.getPromptTemplateSelections();\n if (promptTemplates.length > 0) {\n settings.promptTemplates = promptTemplates;\n settings.promptTemplateIds = promptTemplates.map(template => template.templateId);\n }\n\n return this.connection.invoke(\"SaveSettings\", itemId, settings)\n .catch(err => {\n console.error('Error saving settings:', err);\n this.showSaveIndicator('Save failed', 'text-danger');\n });\n },\n flushPendingSave() {\n if (this.saveSettingsTimeout) {\n clearTimeout(this.saveSettingsTimeout);\n this.saveSettingsTimeout = null;\n }\n\n if (this.settingsDirty) {\n this.settingsDirty = false;\n return this.saveSettings();\n }\n\n return Promise.resolve();\n },\n initializeInteraction(itemId, force) {\n if (this.isInteractionStarted && !force) {\n return;\n }\n this.fireEvent(new CustomEvent(\"initializingChatInteraction\", { detail: { itemId: itemId } }));\n this.setItemId(itemId);\n this.isInteractionStarted = true;\n },\n copyResponse(message) {\n navigator.clipboard.writeText(message);\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 itemId = this.getItemId();\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\", itemId, 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 },\n watch: {\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 if (this.micButton) {\n this.micButton.style.display = active ? 'none' : (this.speechToTextEnabled ? '' : 'none');\n }\n\n if (this.buttonElement) {\n this.buttonElement.style.display = active ? 'none' : '';\n }\n\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 })();\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":["chat-interaction.js"],"names":["_excluded","_regenerator","e","t","r","Symbol","n","iterator","o","toStringTag","i","c","prototype","Generator","u","Object","create","_regeneratorDefine2","f","p","y","G","v","a","d","bind","length","l","TypeError","call","done","value","GeneratorFunction","GeneratorFunctionPrototype","getPrototypeOf","this","setPrototypeOf","__proto__","displayName","w","m","defineProperty","_invoke","enumerable","configurable","writable","asyncGeneratorStep","Promise","resolve","then","_asyncToGenerator","arguments","apply","_next","_throw","_toConsumableArray","_arrayWithoutHoles","_iterableToArray","_unsupportedIterableToArray","_nonIterableSpread","Array","from","isArray","_arrayLikeToArray","_objectWithoutProperties","_objectWithoutPropertiesLoose","getOwnPropertySymbols","indexOf","propertyIsEnumerable","hasOwnProperty","_createForOfIteratorHelper","_n","F","s","next","_slicedToArray","_arrayWithHoles","_iterableToArrayLimit","_nonIterableRest","toString","slice","constructor","name","test","push","_typeof","window","chatInteractionManager","defaultConfig","generatedImageAltText","generatedImageMaxWidth","downloadImageTitle","downloadChartTitle","downloadChartButtonText","codeCopiedText","copyTitle","copiedTitle","copyResetDelayMs","assistantLabel","messageTemplate","indicatorTemplate","untitledText","clearHistoryTitle","clearHistoryMessage","clearHistoryOkText","clearHistoryCancelText","sanitizeUrl","url","trimmed","trim","escapeHtmlEntities","text","span","document","createElement","textContent","innerHTML","refreshFontAwesomeIcons","root","fontAwesome","FontAwesome","nodeType","selector","matches","querySelector","containsFontAwesomePlaceholders","dom","i2svg","node","observeFontAwesomeIcons","MutationObserver","observer","mutations","forEach","mutation","addedNodes","observe","childList","subtree","normalizeReference","reference","_ref","_normalized$index","_ref2","_normalized$text","_ref3","_normalized$title","_ref4","_normalized$link","_ref5","_normalized$reference","_normalized$isGenerat","normalized","assign","index","Index","Text","title","Title","link","Link","referenceType","ReferenceType","isGenerated","IsGenerated","isDownloadCitationReference","toLowerCase","normalizeReferences","references","_i","_Object$entries","entries","_normalizeReference","_Object$entries$_i","key","getCitationLabel","updateMessagePresentation","message","messageReferences","rawContent","content","citationDisplay","processedContent","referenceEntries","citations","citedRefs","filter","_ref6","includes","generatedRefs","_ref8","_ref9","sort","_ref0","_ref1","b","_ref12","_ref13","_step","displayIndex","_iterator","_step$value","placeholder","concat","replaceAll","referenceKey","label","isDownload","err","_i2","_citations","citation","_step2","_iterator2","_step2$value","map","_ref16","buildCitationDisplay","displayContent","citationReferences","copyContent","_step3","_iterator3","_step4","_iterator4","trimEnd","buildCopyContent","htmlContent","parseMarkdownContent","renderer","marked","Renderer","data","href","code","lang","highlighted","hljs","getLanguage","highlight","language","_","highlightAuto","langDisplay","image","src","alt","maxWidth","chartCounter","_pendingCharts","renderChartsInMessage","charts","requestAnimationFrame","_step5","_iterator5","canvas","getElementById","chartId","Chart","offsetParent","_cfg$options","_cfg$options2","_cfg$options2$aspectR","_chartInstance","destroy","cfg","config","JSON","parse","options","responsive","maintainAspectRatio","aspectRatio","console","error","__chartConfigs","warn","html","DOMPurify","sanitize","ADD_TAGS","ADD_ATTR","use","extensions","level","start","idx","undefined","tokenizer","extracted","token","jsonStart","depth","inString","escape","ch","jsonEnd","closeBracketIndex","startIndex","endIndex","json","substring","tryExtractChartMarker","type","raw","initialize","instanceConfig","source","fromEntries","_ref17","signalRHubUrl","appElementSelector","chatContainerElementSelector","inputElementSelector","sendButtonElementSelector","Vue","createApp","inputElement","buttonElement","chatContainer","isInteractionStarted","isPlaceholderVisible","isStreaming","isNavigatingAway","autoScroll","stream","messages","prompt","initialFieldValues","Map","settingsDirty","saveSettingsTimeout","saveIndicatorTimeout","isRecording","mediaRecorder","preRecordingPrompt","micButton","speechToTextEnabled","chatMode","textToSpeechEnabled","ttsVoiceName","audioChunks","audioPlayQueue","isPlayingAudio","currentAudioElement","currentAudioUrl","ttsPlayingMessageIndex","ttsAudioCache","ttsInstanceId","Math","random","conversationModeEnabled","conversationButton","isConversationMode","notifications","notificationDismissTimers","copiedMessageIndex","copyResetTimeoutId","activeCopyButton","computed","lastAssistantIndex","role","methods","handleBeforeUnload","startConnection","_this","_callee","_t","_context","connection","signalR","HubConnectionBuilder","withUrl","withAutomaticReconnect","build","serverTimeoutInMilliseconds","keepAliveIntervalInMilliseconds","on","_data$messages","initializeInteraction","itemId","titleInput","msg","addMessage","$nextTick","historyItem","showSaveIndicator","stopRecording","isFinal","_conversationPartialTranscript","replace","_conversationPartialMessage","hidePlaceholder","isPartial","scrollToBottom","_audioInputSent","dispatchEvent","Event","stopAudio","_conversationAssistantMessage","oldMsg","escaped","messageId","responseId","appearance","hideTypingIndicator","j","msgIndex","newMessage","id","normalizeAssistantAppearance","base64Audio","contentType","binaryString","atob","bytes","Uint8Array","charCodeAt","playCollectedAudio","showPlaceholder","clearHistoryBtn","classList","add","notification","receiveNotification","updateNotification","notificationType","removeNotification","onreconnecting","onreconnected","info","reloadCurrentInteraction","onclose","addMessageInternal","_this2","fireEvent","CustomEvent","detail","_message$rawContent","_this3","remove","event","icon","cssClass","disableStreamingAnimation","getAssistantLabel","getAssistantRoleClasses","classes","getAssistantIconClasses","shouldAnimateAssistantIcon","getAssistantIcon","isIndicator","sendMessage","_this4","_callee2","trimmedPrompt","_context2","flushPendingSave","streamMessage","_this5","dispose","streamingStarted","showTypingIndicator","lastResponseId","messageIndex","currentItemId","getItemId","subscribe","chunk","sessionId","setItemId","keys","_i3","_Object$entries2","_normalizeReference2","_Object$entries2$_i","complete","_this5$stream","processReferences","streamingFinished","synthesizeSpeech","_this5$stream2","getServiceDownMessage","_this6","_ref19","_message$rawContent2","stopIcon","getAttribute","replaceChildren","RETURN_DOM_FRAGMENT","startIcon","icons","querySelectorAll","debouncedSaveSettings","handleExternalTtsStop","_e$detail","sourceId","updateTtsPlaybackButtons","_this7","button","isPlaying","Number","iconHtml","toggle","setAttribute","updateCopyButtons","_this8","isCopied","setCopyButtonState","cacheIndex","_this9","_ttsCacheIndex","invoke","toggleMessageTts","_this0","playAudioBlob","_this1","_step6","totalLength","reduce","sum","combined","offset","_iterator6","set","blob","Blob","_this10","URL","createObjectURL","audio","Audio","addEventListener","revokeObjectURL","playNextInQueue","play","_this11","nextBlob","shift","conversationModeOnAudioEnded","_this12","pause","currentTime","toggleConversationMode","stopConversationMode","startConversationMode","_this13","updateConversationButton","navigator","mediaDevices","getUserMedia","echoCancellation","noiseSuppression","autoGainControl","mimeType","MediaRecorder","isTypeSupported","audioBitsPerSecond","_conversationSubject","Subject","_conversationStream","AudioCtx","AudioContext","webkitAudioContext","_conversationAudioCtx","_conversationAnalyser","createAnalyser","fftSize","createMediaStreamSource","connect","pendingChunk","analyser","size","freqData","frequencyBinCount","getByteFrequencyData","k","_callee3","uint8Array","base64","_context3","arrayBuffer","str","byte","String","fromCharCode","btoa","getTracks","track","stop","documentElement","send","close","dismissible","autoDismissMs","endHtml","blur","startHtml","conversationModeSendPrompt","originalLength","_this14","setTimeout","scrollTop","scrollHeight","clientHeight","handleUserInput","target","getSaveIndicatorElement","saveIndicatorElementSelector","className","_this15","indicator","clearTimeout","clearPendingSettingsSave","getFieldLabel","input","_input$closest","closest","dataset","setting","getValidationFeedbackElement","feedback","nextElementSibling","contains","insertAdjacentElement","clearSettingValidationError","removeAttribute","setSettingValidationError","getSettingValidationMessage","disabled","number","fieldLabel","isNaN","min","max","validateSettingInput","validateSettings","_this16","isValid","getSettingInputs","queueSettingsSave","explicitInputs","getSelectedGroupValues","groupName","fallbackSelector","explicitSelections","values","checkbox","baseName","hiddenInput","getPromptTemplateSelections","promptTemplates","card","templateIdInput","promptParametersInput","templateId","promptParameters","clearNotificationDismiss","findIndex","splice","scheduleNotificationDismiss","_this17","timerId","dismissNotification","handleNotificationAction","actionName","resetInteraction","initializeApp","_this18","placeholderElementSelector","loadInteraction","atBottom","shiftKey","click","lastMsg","pop","chatInteractionItems","getElementsByClassName","preventDefault","initialMessages","btn","block","codeEl","clipboard","writeText","copiedText","clearHistory","micButtonElementSelector","style","display","toggleRecording","conversationButtonElementSelector","self","clearHistoryConfirmed","confirmDialog","confirm","okText","cancelText","callback","confirmed","_this19","saveSettings","getSelectedToolNames","getSelectedMcpConnectionIds","getSelectedA2AConnectionIds","getSelectedAgentNames","_this20","settings","match","checked","parseFloat","toolNames","mcpConnectionIds","a2aConnectionIds","agentNames","promptTemplateIds","template","force","clearCopiedMessageState","copyResponse","_ref21","_message$copyContent","_event$target","_event$target$closest","_this21","currentTarget","startRecording","_this22","subject","_callee4","_context4","updateMicButton","watch","active","_this23","mounted","_this24","_callee5","_context5","$el","fontAwesomeObserver","beforeUnmount","removeEventListener","disconnect","mount","autoInitializeSelector","initializeFromElement","element","chatInteractionInitialized","__chatInteractionApp","attributeName","description","rawValue","parseJsonAttribute","app","scanForAutoInitialization","startAutoInitialization","body","readyState","once","chatInteractionDocumentManager","managerStateKey","normalizeDocumentInfo","documentId","DocumentId","fileName","FileName","fileSize","FileSize","formatFileSize","toFixed","getDocumentKey","isDuplicateFile","file","knownKeys","has","fileInput","documentsList","status","progressContainer","progressBar","uploadQueue","previousState","container","interactionDocuments","existingDocuments","chatDocumentId","chatDocumentName","chatDocumentSize","uploadItems","isUploadingDocuments","onFileInputChange","_x","_uploadDocuments","uploadDocuments","files","renderDocuments","renderUploadQueue","showUploadStatus","showUploadProgress","createTextElement","tagName","documentInfo","row","details","prepend","appendChild","removeButton","removeIcon","_x2","_removeDocument","removeDocument","progress","width","roundedProgress","round","item","presentation","state","badgeClass","progressClass","getUploadStatePresentation","header","fileDetails","badge","progressState","formatUploadMessage","createUploadItem","lastModified","Date","now","updateUploadItem","updates","removeUploadItems","predicate","uploadSingleDocument","itemIdToUpdate","fileIndex","totalFiles","reject","formData","FormData","append","xhr","XMLHttpRequest","open","uploadDocumentUrl","upload","lengthComputable","fileProgress","loaded","total","responseText","Error","_callee6","filesToUpload","duplicateItems","knownDocumentKeys","pendingItems","uploadedCount","failedUploads","pendingItem","result","uploaded","failed","missingUploadMessage","failedMessage","errorMessage","_t2","_t3","_context6","Set","join","entry","_callee7","response","serverDocuments","_t4","_t5","_context7","removeDocumentUrl","fetch","method","headers","stringify","ok","documents","chatInteractionDocumentManagerInitialized","download","toDataURL","img","startsWith","res","removeChild"],"mappings":"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","file":"chat-interaction.min.js","sourcesContent":["window.chatInteractionManager = 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 codeCopiedText: 'Copied!',\n copyTitle: 'Click here to copy response to clipboard.',\n copiedTitle: 'Response copied to clipboard.',\n copyResetDelayMs: 2000,\n assistantLabel: 'Assistant',\n\n messageTemplate: `\n <div class=\"ai-chat-messages\">\n <div v-for=\"(message, index) in messages\" :key=\"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\">You</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 <ol v-if=\"message.citationReferences && message.citationReferences.length\" class=\"ai-chat-citation-list\">\n <li v-for=\"citation in message.citationReferences\" :key=\"'citation-' + (citation.referenceKey || citation.displayIndex)\" class=\"ai-chat-citation-item\">\n <a v-if=\"citation.link\" :href=\"citation.link\" :target=\"citation.isDownload ? null : '_blank'\" :rel=\"citation.isDownload ? null : 'noopener noreferrer'\">{{ citation.label }}</a>\n <span v-else>{{ citation.label }}</span>\n </li>\n </ol>\n <span class=\"message-buttons-container\" v-if=\"!isIndicator(message)\">\n <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 <i :class=\"ttsPlayingMessageIndex === index ? 'fa-solid fa-circle-pause' : 'fa-solid fa-circle-play'\"></i>\n </button>\n <button type=\"button\" class=\"btn btn-sm btn-link p-0 button-message-toolbox ai-response-copy-btn\" :class=\"copiedMessageIndex === index ? 'text-success' : 'text-secondary'\" :data-copy-message-index=\"index\" @click=\"copyResponse(message, index, $event)\" :title=\"copiedMessageIndex === index ? copiedTitle : copyTitle\">\n <i :class=\"copiedMessageIndex === index ? 'fa-solid fa-check' : 'fa-solid fa-copy'\"></i>\n </button>\n </span>\n </div>\n </div>\n </div>\n <div v-for=\"notification in notifications\" :key=\"'notif-' + notification.type\" class=\"ai-chat-notification\" :class=\"'ai-chat-notification-' + (notification.type || 'info') + ' ' + (notification.cssClass || '')\">\n <div class=\"ai-chat-notification-content\">\n <i v-if=\"notification.icon\" :class=\"notification.icon\" class=\"ai-chat-notification-icon\"></i>\n <span class=\"ai-chat-notification-text\">{{ notification.content }}</span>\n <button 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 // Localizable strings\n untitledText: 'Untitled',\n clearHistoryTitle: 'Clear History',\n clearHistoryMessage: 'Are you sure you want to clear the chat history? This action cannot be undone. Your documents, parameters, and tools will be preserved.',\n clearHistoryOkText: 'Yes',\n clearHistoryCancelText: 'Cancel'\n };\n\n // Sanitize URLs to prevent javascript: protocol injection.\n function sanitizeUrl(url) {\n if (!url) return '';\n var trimmed = url.trim();\n if (/^javascript:/i.test(trimmed) || /^vbscript:/i.test(trimmed) || /^data:text\\/html/i.test(trimmed)) {\n return '';\n }\n return url;\n }\n\n // Safely HTML-encode a string using the DOM (avoids regex-based HTML filtering).\n function escapeHtmlEntities(text) {\n var span = document.createElement('span');\n span.textContent = text;\n return span.innerHTML;\n }\n\n function containsFontAwesomePlaceholders(root) {\n if (!root || root.nodeType !== 1) {\n return false;\n }\n\n var selector = 'i[class*=\"fa-\"],i.fa,i.fas,i.far,i.fab';\n if (typeof root.matches === 'function' && root.matches(selector)) {\n return true;\n }\n\n return typeof root.querySelector === 'function' && !!root.querySelector(selector);\n }\n\n function refreshFontAwesomeIcons(root) {\n var fontAwesome = window.FontAwesome;\n if (!containsFontAwesomePlaceholders(root) || !fontAwesome || !fontAwesome.dom || typeof fontAwesome.dom.i2svg !== 'function') {\n return;\n }\n\n fontAwesome.dom.i2svg({ node: root });\n }\n\n function observeFontAwesomeIcons(root) {\n if (!root || typeof MutationObserver === 'undefined') {\n return null;\n }\n\n var observer = new MutationObserver(function (mutations) {\n mutations.forEach(function (mutation) {\n mutation.addedNodes.forEach(function (node) {\n refreshFontAwesomeIcons(node);\n });\n });\n });\n\n observer.observe(root, {\n childList: true,\n subtree: true\n });\n\n return observer;\n }\n\n function normalizeReference(reference) {\n if (!reference || typeof reference !== 'object') {\n return null;\n }\n\n const normalized = Object.assign({}, reference);\n normalized.index = normalized.index ?? normalized.Index ?? 0;\n normalized.text = normalized.text ?? normalized.Text ?? null;\n normalized.title = normalized.title ?? normalized.Title ?? null;\n normalized.link = sanitizeUrl(normalized.link ?? normalized.Link ?? null);\n normalized.referenceType = normalized.referenceType ?? normalized.ReferenceType ?? null;\n normalized.isGenerated = (normalized.isGenerated ?? normalized.IsGenerated) === true;\n\n return normalized;\n }\n\n function isDownloadCitationReference(reference) {\n if (!reference || typeof reference !== 'object') {\n return false;\n }\n\n if (typeof reference.referenceType === 'string' && reference.referenceType.toLowerCase() === 'document') {\n return true;\n }\n\n if (typeof reference.link === 'string' && /\\/ai\\/documents\\/.+\\/download(?:$|\\?)/i.test(reference.link)) {\n return true;\n }\n\n return false;\n }\n\n function normalizeReferences(references) {\n if (!references || typeof references !== 'object') {\n return {};\n }\n\n const normalized = {};\n\n for (const [key, value] of Object.entries(references)) {\n normalized[key] = normalizeReference(value) ?? {};\n }\n\n return normalized;\n }\n\n function getCitationLabel(reference, key) {\n return reference.title || reference.text || key;\n }\n\n function buildCitationDisplay(content, references) {\n let processedContent = (content || '').trim();\n const messageReferences = normalizeReferences(references);\n const referenceEntries = Object.entries(messageReferences);\n\n if (!referenceEntries.length) {\n return { content: processedContent, citations: [] };\n }\n\n const citedRefs = referenceEntries.filter(([key]) => processedContent.includes(key));\n const generatedRefs = referenceEntries.filter(([key, value]) => value.isGenerated && !processedContent.includes(key));\n\n if (!citedRefs.length && !generatedRefs.length) {\n return { content: processedContent, citations: [] };\n }\n\n citedRefs.sort(([, a], [, b]) => a.index - b.index);\n generatedRefs.sort(([, a], [, b]) => a.index - b.index);\n\n const citations = [];\n let displayIndex = 1;\n\n for (const [key, value] of citedRefs) {\n const placeholder = `__CITE_${displayIndex}_${value.index || displayIndex}__`;\n processedContent = processedContent.replaceAll(key, placeholder);\n citations.push({\n referenceKey: key,\n displayIndex: displayIndex,\n label: getCitationLabel(value, key),\n link: value.link || null,\n isDownload: isDownloadCitationReference(value),\n placeholder: placeholder,\n });\n\n displayIndex++;\n }\n\n for (const citation of citations) {\n processedContent = processedContent.replaceAll(citation.placeholder, `<sup>${citation.displayIndex}</sup>`);\n }\n\n processedContent = processedContent.replaceAll('</sup><sup>', '</sup><sup>,</sup><sup>');\n\n // Generated files (such as exported tabular data) are always offered as a download even when\n // the model does not cite them inline, so the user never loses access to the produced file.\n for (const [key, value] of generatedRefs) {\n citations.push({\n referenceKey: key,\n displayIndex: displayIndex,\n label: getCitationLabel(value, key),\n link: value.link || null,\n isDownload: true,\n placeholder: null,\n });\n\n displayIndex++;\n }\n\n return {\n content: processedContent,\n citations: citations.map(({ placeholder, ...citation }) => citation),\n };\n }\n\n function buildCopyContent(content, citations) {\n let copyContent = (content || '').trim();\n\n if (!copyContent || !Array.isArray(citations) || citations.length === 0) {\n return copyContent;\n }\n\n for (const citation of citations) {\n copyContent = copyContent.replaceAll(citation.referenceKey, `[${citation.displayIndex}]`);\n }\n\n copyContent += '\\n\\nReferences:\\n';\n\n for (const citation of citations) {\n copyContent += `${citation.displayIndex}. ${citation.label}`;\n\n if (citation.link) {\n copyContent += ` - ${citation.link}`;\n }\n\n copyContent += '\\n';\n }\n\n return copyContent.trimEnd();\n }\n\n function updateMessagePresentation(message, references) {\n const messageReferences = normalizeReferences(references ?? message.references);\n const rawContent = typeof message.rawContent === 'string'\n ? message.rawContent\n : typeof message.content === 'string'\n ? message.content\n : '';\n const citationDisplay = buildCitationDisplay(rawContent, messageReferences);\n\n message.rawContent = rawContent;\n message.content = rawContent;\n message.displayContent = citationDisplay.content;\n message.references = messageReferences;\n message.citationReferences = citationDisplay.citations;\n message.copyContent = buildCopyContent(rawContent, citationDisplay.citations);\n message.htmlContent = parseMarkdownContent(citationDisplay.content, message);\n\n return message;\n }\n\n const renderer = new marked.Renderer();\n\n // Modify the link rendering to open in a new tab\n renderer.link = function (data) {\n var href = sanitizeUrl(data.href);\n if (!href) return data.text || '';\n return `<a href=\"${href}\" target=\"_blank\" rel=\"noopener noreferrer\">${data.text}</a>`;\n };\n\n // Custom code block renderer with highlight.js integration and copy button.\n renderer.code = function (data) {\n var code = data.text || '';\n var lang = (data.lang || '').trim();\n var highlighted = code;\n\n if (typeof hljs !== 'undefined') {\n if (lang && hljs.getLanguage(lang)) {\n try {\n highlighted = hljs.highlight(code, { language: lang }).value;\n } catch (_) { }\n } else {\n try {\n highlighted = hljs.highlightAuto(code).value;\n } catch (_) { }\n }\n } else {\n highlighted = escapeHtmlEntities(code);\n }\n\n var langDisplay = lang ? escapeHtmlEntities(lang) : 'code';\n return `<div class=\"ai-code-block\"><div class=\"ai-code-header\"><span class=\"ai-code-lang\"><i class=\"fa-solid fa-code\"></i> ${langDisplay}</span><button type=\"button\" class=\"ai-code-copy-btn\" title=\"Copy code\"><i class=\"fa-regular fa-copy\"></i></button></div><pre><code class=\"hljs${lang ? ' language-' + lang : ''}\">${highlighted}</code></pre></div>`;\n };\n\n // Custom image renderer for generated images with thumbnail styling and download button.\n // Handles both URL and data-URI sources (data URIs are converted to blobs for download).\n renderer.image = function (data) {\n const src = sanitizeUrl(data.href);\n if (!src) return '';\n const alt = data.text || defaultConfig.generatedImageAltText;\n const maxWidth = defaultConfig.generatedImageMaxWidth;\n return `<div class=\"generated-image-container\">\n <img src=\"${src}\" alt=\"${alt}\" class=\"img-thumbnail\" style=\"max-width: ${maxWidth}px; height: auto;\" />\n <div class=\"mt-2\">\n <a href=\"${src}\" target=\"_blank\" download=\"${alt}\" title=\"${defaultConfig.downloadImageTitle}\" class=\"btn btn-sm btn-outline-secondary ai-download-image\">\n <i class=\"fa-solid fa-download\"></i>\n </a>\n </div>\n </div>`;\n };\n\n // Chart counter for unique IDs\n let chartCounter = 0;\n\n // Collector for charts discovered during marked parsing.\n let _pendingCharts = [];\n\n // Global chart config map shared with ai-chat.js\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 const canvas = document.getElementById(c.chartId);\n if (!canvas) {\n continue;\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 continue;\n }\n\n // When the canvas is inside a hidden container (e.g., display:none),\n // it has zero dimensions. Keep the config for later rendering.\n if (canvas.offsetParent === null) {\n window.__chartConfigs[c.chartId] = c.config;\n continue;\n }\n\n try {\n // Destroy existing chart instance if re-rendering\n if (canvas._chartInstance) {\n canvas._chartInstance.destroy();\n }\n\n const cfg = typeof c.config === 'string' ? JSON.parse(c.config) : c.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 } catch (e) {\n console.error('Error creating chart:', e);\n }\n }\n });\n }\n\n // Parse markdown content via marked (which natively handles [chart:...] markers\n // through the registered extension) and collect pending chart configs for later\n // Chart.js rendering.\n function parseMarkdownContent(content, message) {\n _pendingCharts = [];\n const html = marked.parse(content, { renderer });\n message._pendingCharts = _pendingCharts.length > 0 ? [..._pendingCharts] : [];\n return DOMPurify.sanitize(html, { ADD_TAGS: ['canvas'], ADD_ATTR: ['target'] });\n }\n\n function compactObject(source) {\n if (!source || typeof source !== 'object') {\n return {};\n }\n\n return Object.fromEntries(\n Object.entries(source).filter(([, value]) => value !== undefined)\n );\n }\n\n const initialize = (instanceConfig) => {\n const config = Object.assign({}, defaultConfig, compactObject(instanceConfig));\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 isInteractionStarted: false,\n isPlaceholderVisible: true,\n isStreaming: false,\n isNavigatingAway: false,\n autoScroll: true,\n stream: null,\n messages: [],\n prompt: '',\n initialFieldValues: new Map(),\n settingsDirty: false,\n saveSettingsTimeout: null,\n saveIndicatorTimeout: null,\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 ttsPlayingMessageIndex: -1,\n ttsAudioCache: {},\n ttsInstanceId: 'chat-interaction-' + Math.random().toString(36).slice(2),\n conversationModeEnabled: config.chatMode === 'Conversation',\n conversationButton: null,\n isConversationMode: false,\n notifications: [],\n notificationDismissTimers: {},\n copyTitle: config.copyTitle,\n copiedTitle: config.copiedTitle,\n copiedMessageIndex: -1,\n copyResetTimeoutId: null,\n activeCopyButton: null,\n };\n },\n computed: {\n lastAssistantIndex() {\n for (var i = this.messages.length - 1; i >= 0; i--) {\n if (this.messages[i].role === 'assistant') {\n return i;\n }\n }\n return -1;\n }\n },\n methods: {\n handleBeforeUnload() {\n this.isNavigatingAway = true;\n },\n 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(\"LoadInteraction\", (data) => {\n this.initializeInteraction(data.itemId, true);\n this.messages = [];// Update the title field if it exists\n const titleInput = document.querySelector('[data-chat-interaction-title], .setting-input[data-setting=\"title\"], input[name=\"ChatInteraction.Title\"], input[name=\"Title\"]');\n if (titleInput && data.title) {\n titleInput.value = data.title;\n }\n\n (data.messages ?? []).forEach(msg => {\n this.addMessage(msg);\n\n this.$nextTick(() => {\n renderChartsInMessage(msg);\n });\n });\n });\n\n this.connection.on(\"SettingsSaved\", (itemId, title) => {\n // Update the history list item if it exists\n // Use a more specific selector to only target history list items, not other elements like the Clear History button\n const historyItem = document.querySelector(`.chat-interaction-history-item[data-interaction-id=\"${itemId}\"]`);\n if (historyItem) {\n historyItem.textContent = title || config.untitledText;\n }\n\n const titleInput = document.querySelector('[data-chat-interaction-title], .setting-input[data-setting=\"title\"], input[name=\"ChatInteraction.Title\"], input[name=\"Title\"]');\n if (titleInput && title) {\n titleInput.value = title;\n }\n\n this.showSaveIndicator('Saved', 'text-success');\n });\n\n this.connection.on(\"ReceiveError\", (error) => {\n console.error(\"SignalR Error: \", error);\n this.showSaveIndicator('Save failed', 'text-danger');\n\n if (this.isRecording) {\n this.stopRecording();\n }\n });\n\n this.connection.on(\"ReceiveTranscript\", (itemId, text, isFinal) => {\n if (this.isConversationMode) {\n if (!isFinal && text) {\n this._conversationPartialTranscript = text;\n var escaped = text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n var html = '<p class=\"ai-partial-transcript\">' + escaped + '</p>';\n\n // Show partial transcript as a live user message.\n if (!this._conversationPartialMessage) {\n this.hidePlaceholder();\n this._conversationPartialMessage = {\n role: 'user',\n content: text,\n htmlContent: html,\n isPartial: true\n };\n this.messages.push(this._conversationPartialMessage);\n } else {\n this._conversationPartialMessage.content = text;\n this._conversationPartialMessage.htmlContent = html;\n }\n this.scrollToBottom();\n }\n return;\n }\n\n if (text && !this._audioInputSent) {\n this.prompt = this.preRecordingPrompt + text;\n if (this.inputElement) {\n this.inputElement.value = this.prompt;\n this.inputElement.dispatchEvent(new Event('input'));\n }\n }\n });\n\n this.connection.on(\"ReceiveConversationUserMessage\", (itemId, text) => {\n if (text) {\n this.stopAudio();\n\n // If there's an interrupted assistant message still streaming,\n // mark it as done to stop the spinner animation.\n if (this._conversationAssistantMessage) {\n var oldMsg = this.messages[this._conversationAssistantMessage.index];\n if (oldMsg) {\n oldMsg.isStreaming = false;\n }\n this._conversationAssistantMessage = null;\n }\n\n // Replace the partial transcript message with the final one.\n if (this._conversationPartialMessage) {\n var escaped = text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n this._conversationPartialMessage.content = text;\n this._conversationPartialMessage.htmlContent = '<p>' + escaped + '</p>';\n this._conversationPartialMessage.isPartial = false;\n this._conversationPartialMessage = null;\n } else {\n this.addMessage({\n role: 'user',\n content: text\n });\n }\n this.scrollToBottom();\n }\n });\n\n this.connection.on(\"ReceiveConversationAssistantToken\", (itemId, messageId, token, responseId, references, appearance) => {\n if (!this._conversationAssistantMessage) {\n this.stopAudio();\n this.hideTypingIndicator();\n\n // Ensure no stale streaming indicators remain from prior messages.\n for (var j = 0; j < this.messages.length; j++) {\n if (this.messages[j].isStreaming) {\n this.messages[j].isStreaming = false;\n }\n }\n\n var msgIndex = this.messages.length;\n var newMessage = {\n id: messageId,\n role: \"assistant\",\n content: \"\",\n htmlContent: \"\",\n isStreaming: true,\n appearance: this.normalizeAssistantAppearance(appearance),\n references: {},\n };\n this.messages.push(newMessage);\n this._conversationAssistantMessage = { index: msgIndex, content: '' };\n }\n\n this._conversationAssistantMessage.content += token;\n var msg = this.messages[this._conversationAssistantMessage.index];\n if (msg) {\n if (!msg.appearance) {\n msg.appearance = this.normalizeAssistantAppearance(appearance);\n }\n msg.rawContent = this._conversationAssistantMessage.content;\n msg.references = normalizeReferences(Object.assign({}, msg.references || {}, references || {}));\n updateMessagePresentation(msg, msg.references);\n this.$nextTick(() => {\n renderChartsInMessage(msg);\n this.scrollToBottom();\n });\n }\n });\n\n this.connection.on(\"ReceiveConversationAssistantComplete\", (itemId, messageId, references) => {\n if (this._conversationAssistantMessage) {\n var msg = this.messages[this._conversationAssistantMessage.index];\n if (msg) {\n msg.isStreaming = false;\n msg.references = normalizeReferences(Object.assign({}, msg.references || {}, references || {}));\n updateMessagePresentation(msg, msg.references);\n }\n this._conversationAssistantMessage = null;\n }\n });\n\n this.connection.on(\"ReceiveAudioChunk\", (itemId, 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\", (itemId) => {\n this.playCollectedAudio();\n });\n\n this.connection.on(\"HistoryCleared\", (itemId) => {\n // Clear messages and show placeholder\n this.messages = [];\n this.showPlaceholder();\n\n // Hide the clear history button since there's no history now\n const clearHistoryBtn = document.getElementById('clearHistoryBtn');\n if (clearHistoryBtn) {\n clearHistoryBtn.classList.add('d-none');\n }\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 this.reloadCurrentInteraction();\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(\"addingChatInteractionMessage\", { detail: { message: message } }));\n this.messages.push(message);\n\n this.$nextTick(() => {\n this.fireEvent(new CustomEvent(\"addedChatInteractionMessage\", { detail: { message: message } }));\n });\n },\n addMessage(message) {\n if (message.content) {\n message.rawContent = message.rawContent ?? message.content;\n updateMessagePresentation(message, message.references);\n }\n\n this.addMessageInternal(message);\n this.hidePlaceholder();\n\n this.$nextTick(() => {\n // Render any pending charts once the DOM is updated\n renderChartsInMessage(message);\n this.scrollToBottom();\n });\n },\n 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 fireEvent(event) {\n document.dispatchEvent(event);\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 : defaultConfig.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 isIndicator(message) {\n return message.role === 'indicator';\n },\n async sendMessage() {\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 // Flush any pending settings save before sending a message\n // to prevent concurrent hub calls that can cause database deadlocks.\n await this.flushPendingSave();\n\n this.addMessage({\n role: 'user',\n content: trimmedPrompt\n });\n\n // Show the clear history button since we now have prompts\n const clearHistoryBtn = document.getElementById('clearHistoryBtn');\n if (clearHistoryBtn) {\n clearHistoryBtn.classList.remove('d-none');\n }\n\n this.streamMessage(trimmedPrompt);\n this.inputElement.value = '';\n this.prompt = '';\n },\n streamMessage(trimmedPrompt) {\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 var messageIndex = this.messages.length;\n var currentItemId = this.getItemId();\n\n this.stream = this.connection.stream(\"SendMessage\", currentItemId, trimmedPrompt)\n .subscribe({\n next: (chunk) => {\n let message = this.messages[messageIndex];\n\n if (!message) {\n if (chunk.sessionId && !currentItemId) {\n this.setItemId(chunk.sessionId);\n }\n\n this.hideTypingIndicator();\n messageIndex = this.messages.length;\n let newMessage = {\n role: \"assistant\",\n content: \"\",\n htmlContent: \"\",\n isStreaming: true,\n };\n\n this.messages.push(newMessage);\n message = newMessage;\n }\n\n if (chunk.references && typeof chunk.references === \"object\" && Object.keys(chunk.references).length) {\n for (const [key, value] of Object.entries(chunk.references)) {\n references[key] = normalizeReference(value) ?? {};\n }\n }\n\n if (chunk.content) {\n // When the responseId changes (e.g., after an internal tool call),\n // insert a line break to visually separate response segments.\n if (chunk.responseId && lastResponseId && chunk.responseId !== lastResponseId) {\n content += '\\n\\n';\n }\n\n if (chunk.responseId) {\n lastResponseId = chunk.responseId;\n }\n\n content += chunk.content;\n }\n\n message.rawContent = content;\n updateMessagePresentation(message, references);\n\n this.messages[messageIndex] = message;\n\n this.$nextTick(() => {\n renderChartsInMessage(message);\n this.scrollToBottom();\n });\n },\n complete: () => {\n this.processReferences(references, messageIndex);\n this.streamingFinished();\n\n let msg = this.messages[messageIndex];\n if (msg) {\n msg.isStreaming = false;\n }\n\n if (!msg || !msg.content) {\n // No content received at all.\n this.hideTypingIndicator();\n }\n\n // Trigger text-to-speech only in conversation mode.\n if (this.isConversationMode && this.textToSpeechEnabled && msg && msg.content) {\n this.synthesizeSpeech(msg.content);\n }\n\n this.stream?.dispose();\n this.stream = null;\n },\n error: (err) => {\n this.processReferences(references, messageIndex);\n this.streamingFinished();\n\n let msg = this.messages[messageIndex];\n if (msg) {\n msg.isStreaming = false;\n }\n\n this.hideTypingIndicator();\n\n if (!this.isNavigatingAway) {\n this.addMessage(this.getServiceDownMessage());\n }\n\n this.stream?.dispose();\n this.stream = null;\n\n console.error(\"Stream error:\", err);\n }\n });\n },\n getServiceDownMessage() {\n return {\n role: \"assistant\",\n content: \"Our service is currently unavailable. Please try again later. We apologize for the inconvenience.\",\n htmlContent: \"\",\n };\n },\n processReferences(references, messageIndex) {\n references = normalizeReferences(references);\n\n if (Object.keys(references).length) {\n let message = this.messages[messageIndex];\n message.rawContent = message.rawContent ?? message.content ?? '';\n updateMessagePresentation(message, references);\n\n this.messages[messageIndex] = message;\n\n this.$nextTick(() => {\n renderChartsInMessage(message);\n this.scrollToBottom();\n });\n }\n },\n streamingStarted() {\n var stopIcon = this.buttonElement.getAttribute('data-stop-icon');\n\n if (stopIcon) {\n this.buttonElement.replaceChildren(DOMPurify.sanitize(stopIcon, { RETURN_DOM_FRAGMENT: true }));\n }\n },\n 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 // 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 // Save any settings that were deferred during streaming.\n if (this.settingsDirty) {\n this.debouncedSaveSettings();\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 ? '<i class=\"fa-solid fa-circle-pause\"></i>'\n : '<i class=\"fa-solid fa-circle-play\"></i>';\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 updateCopyButtons() {\n if (!this.chatContainer) {\n return;\n }\n\n var buttons = this.chatContainer.querySelectorAll('[data-copy-message-index]');\n\n buttons.forEach(button => {\n var buttonIndex = Number(button.getAttribute('data-copy-message-index'));\n var isCopied = buttonIndex === this.copiedMessageIndex;\n var iconHtml = isCopied\n ? '<i class=\"fa-solid fa-check\"></i>'\n : '<i class=\"fa-solid fa-copy\"></i>';\n\n button.classList.toggle('text-success', isCopied);\n button.classList.toggle('text-secondary', !isCopied);\n button.setAttribute('title', isCopied ? this.copiedTitle : this.copyTitle);\n button.replaceChildren(DOMPurify.sanitize(iconHtml, { RETURN_DOM_FRAGMENT: true }));\n });\n },\n setCopyButtonState(button, isCopied) {\n if (!button) {\n return;\n }\n\n var iconHtml = isCopied\n ? '<i class=\"fa-solid fa-check\"></i>'\n : '<i class=\"fa-solid fa-copy\"></i>';\n\n button.classList.toggle('text-success', isCopied);\n button.classList.toggle('text-secondary', !isCopied);\n button.setAttribute('title', isCopied ? this.copiedTitle : this.copyTitle);\n button.replaceChildren(DOMPurify.sanitize(iconHtml, { RETURN_DOM_FRAGMENT: true }));\n },\n synthesizeSpeech(text, cacheIndex) {\n if (!this.textToSpeechEnabled || !text || !this.connection) {\n return;\n }\n\n this.audioChunks = [];\n this.isPlayingAudio = true;\n this._ttsCacheIndex = cacheIndex !== undefined ? cacheIndex : -1;\n\n this.connection.invoke(\"SynthesizeSpeech\", this.getItemId(), 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.isPlayingAudio && 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 currently playing, queue this blob for later.\n if (this.isPlayingAudio && 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 const 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\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 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 itemId = this.getItemId();\n\n var language = navigator.language || document.documentElement.lang || 'en-US';\n this.connection.send(\"StartConversation\", itemId, 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, continuation is handled\n // by the persistent stream.\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 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 getItemId() {\n return this.inputElement.getAttribute('data-interaction-id')\n || this.inputElement.getAttribute('data-item-id');\n },\n getSaveIndicatorElement() {\n if (config.saveIndicatorElementSelector) {\n return document.querySelector(config.saveIndicatorElementSelector);\n }\n\n return document.querySelector('[data-chat-interaction-save-indicator]');\n },\n showSaveIndicator(text, className) {\n const indicator = this.getSaveIndicatorElement();\n if (!indicator) {\n return;\n }\n\n indicator.textContent = text || '';\n indicator.className = 'settings-save-indicator ' + (className || 'text-muted');\n\n if (this.saveIndicatorTimeout) {\n clearTimeout(this.saveIndicatorTimeout);\n this.saveIndicatorTimeout = null;\n }\n\n if (!text) {\n return;\n }\n\n this.saveIndicatorTimeout = setTimeout(() => {\n indicator.textContent = '';\n this.saveIndicatorTimeout = null;\n }, 3000);\n },\n clearPendingSettingsSave() {\n if (this.saveSettingsTimeout) {\n clearTimeout(this.saveSettingsTimeout);\n this.saveSettingsTimeout = null;\n }\n },\n getFieldLabel(input) {\n const label = input\n .closest('.mb-3, .col-6, .col, .form-group, .form-floating')\n ?.querySelector('label');\n\n if (!label) {\n return input.dataset.setting || 'This field';\n }\n\n return (label.textContent || '')\n .replace(/\\s+/g, ' ')\n .trim()\n || input.dataset.setting\n || 'This field';\n },\n getValidationFeedbackElement(input) {\n let feedback = input.nextElementSibling;\n if (feedback && feedback.classList.contains('invalid-feedback')) {\n return feedback;\n }\n\n feedback = document.createElement('div');\n feedback.className = 'invalid-feedback';\n input.insertAdjacentElement('afterend', feedback);\n\n return feedback;\n },\n clearSettingValidationError(input) {\n input.classList.remove('is-invalid');\n input.removeAttribute('aria-invalid');\n\n const feedback = input.nextElementSibling;\n if (feedback && feedback.classList.contains('invalid-feedback')) {\n feedback.textContent = '';\n }\n },\n setSettingValidationError(input, message) {\n const feedback = this.getValidationFeedbackElement(input);\n input.classList.add('is-invalid');\n input.setAttribute('aria-invalid', 'true');\n feedback.textContent = message;\n },\n getSettingValidationMessage(input) {\n if (!input || input.disabled || input.type !== 'number') {\n return null;\n }\n\n const value = (input.value || '').trim();\n if (!value) {\n return null;\n }\n\n const number = Number(value);\n const fieldLabel = this.getFieldLabel(input);\n\n if (Number.isNaN(number)) {\n return `${fieldLabel} must be a valid number.`;\n }\n\n const min = input.getAttribute('min');\n if (min !== null && number < Number(min)) {\n return `${fieldLabel} must be ${min} or greater.`;\n }\n\n const max = input.getAttribute('max');\n if (max !== null && number > Number(max)) {\n return `${fieldLabel} must be ${max} or less.`;\n }\n\n return null;\n },\n validateSettingInput(input) {\n const message = this.getSettingValidationMessage(input);\n if (!message) {\n this.clearSettingValidationError(input);\n return true;\n }\n\n this.setSettingValidationError(input, message);\n return false;\n },\n validateSettings() {\n let isValid = true;\n\n this.getSettingInputs().forEach(input => {\n isValid = this.validateSettingInput(input) && isValid;\n });\n\n return isValid;\n },\n queueSettingsSave() {\n if (!this.validateSettings()) {\n this.clearPendingSettingsSave();\n this.settingsDirty = false;\n this.showSaveIndicator('Fix errors', 'text-danger');\n return;\n }\n\n this.settingsDirty = true;\n this.showSaveIndicator('Saving...', 'text-warning');\n this.debouncedSaveSettings();\n },\n getSettingInputs() {\n const explicitInputs = document.querySelectorAll('.setting-input[data-setting]');\n if (explicitInputs.length > 0) {\n return explicitInputs;\n }\n\n return document.querySelectorAll(\n 'input[name^=\"ChatInteraction.\"]:not([name*=\".Tools[\"]):not([name*=\".Connections[\"]), ' +\n 'select[name^=\"ChatInteraction.\"]:not([name*=\".Tools[\"]):not([name*=\".Connections[\"]), ' +\n 'textarea[name^=\"ChatInteraction.\"]:not([name*=\".Tools[\"]):not([name*=\".Connections[\"])'\n );\n },\n getSelectedGroupValues(groupName, fallbackSelector) {\n const explicitSelections = document.querySelectorAll(`.capability-checkbox[data-save-group=\"${groupName}\"]:checked, .capability-checkbox[data-group=\"${groupName}\"]:checked`);\n if (explicitSelections.length > 0) {\n const values = [];\n\n explicitSelections.forEach(checkbox => {\n const value = checkbox.getAttribute('data-item-id') || checkbox.value;\n if (value) {\n values.push(value);\n }\n });\n\n return values;\n }\n\n if (!fallbackSelector) {\n return [];\n }\n\n const values = [];\n const checkboxes = document.querySelectorAll(fallbackSelector);\n\n checkboxes.forEach(checkbox => {\n const baseName = checkbox.name.replace('.IsSelected', '.ItemId');\n const hiddenInput = document.querySelector(`input[type=\"hidden\"][name=\"${baseName}\"]`);\n\n if (hiddenInput && hiddenInput.value) {\n values.push(hiddenInput.value);\n }\n });\n\n return values;\n },\n getPromptTemplateSelections() {\n const promptTemplates = [];\n\n document.querySelectorAll('.prompt-template-card').forEach(card => {\n const templateIdInput = card.querySelector('.prompt-template-id-input');\n const promptParametersInput = card.querySelector('.prompt-template-parameters-input');\n const templateId = templateIdInput ? templateIdInput.value : card.getAttribute('data-template-id');\n\n if (!templateId) {\n return;\n }\n\n promptTemplates.push({\n templateId: templateId,\n promptParameters: promptParametersInput ? (promptParametersInput.value || '').trim() : ''\n });\n });\n\n return promptTemplates;\n },\n receiveNotification(notification) {\n if (!notification || !notification.type) {\n return;\n }\n this.clearNotificationDismiss(notification.type);\n // Replace existing notification with same type, or add new one.\n var idx = this.notifications.findIndex(n => n.type === notification.type);\n if (idx >= 0) {\n this.notifications.splice(idx, 1, notification);\n } else {\n this.notifications.push(notification);\n }\n this.scheduleNotificationDismiss(notification);\n this.scrollToBottom();\n },\n updateNotification(notification) {\n if (!notification || !notification.type) {\n return;\n }\n this.clearNotificationDismiss(notification.type);\n var idx = this.notifications.findIndex(n => n.type === notification.type);\n if (idx >= 0) {\n this.notifications.splice(idx, 1, notification);\n this.scheduleNotificationDismiss(notification);\n this.scrollToBottom();\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 itemId = this.getItemId();\n this.connection.invoke('HandleNotificationAction', itemId, notificationType, actionName)\n .catch(err => console.error('Failed to handle notification action:', err));\n },\n setItemId(itemId) {\n this.inputElement.setAttribute('data-interaction-id', itemId || '');\n this.inputElement.setAttribute('data-item-id', itemId || '');\n },\n resetInteraction() {\n this.setItemId('');\n this.isInteractionStarted = false;\n this.messages = [];\n this.showPlaceholder();\n },\n initializeApp() {\n this.inputElement = document.querySelector(config.inputElementSelector);\n this.buttonElement = document.querySelector(config.sendButtonElementSelector);\n this.chatContainer = document.querySelector(config.chatContainerElementSelector);\n this.placeholder = document.querySelector(config.placeholderElementSelector);\n\n const itemId = this.getItemId();\n if (itemId) {\n this.loadInteraction(itemId);\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('keyup', event => {\n if (this.stream != null) {\n return;\n }\n\n if (event.key === \"Enter\" && !event.shiftKey) {\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.inputElement.addEventListener('paste', (e) => {\n // Use setTimeout to allow the paste to complete before checking the value\n setTimeout(() => {\n this.prompt = this.inputElement.value;\n if (this.inputElement.value.trim()) {\n this.buttonElement.removeAttribute('disabled');\n } else {\n this.buttonElement.setAttribute('disabled', true);\n }\n }, 0);\n });\n\n this.buttonElement.addEventListener('click', () => {\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 chatInteractionItems = document.getElementsByClassName('chat-interaction-history-item');\n\n for (var i = 0; i < chatInteractionItems.length; i++) {\n chatInteractionItems[i].addEventListener('click', (e) => {\n e.preventDefault();\n\n var itemId = e.target.getAttribute('data-interaction-id');\n\n if (!itemId) {\n console.error('An element with the class chat-interaction-history-item with no data-interaction-id set.');\n return;\n }\n\n this.loadInteraction(itemId);\n });\n }\n\n const initialMessages = Array.isArray(config.messages) ? config.messages : [];\n\n for (let i = 0; i < initialMessages.length; i++) {\n this.addMessage(initialMessages[i]);\n }\n\n // 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 document.addEventListener('input', event => {\n if (event.target.matches('.setting-input[data-setting]')) {\n this.validateSettingInput(event.target);\n this.queueSettingsSave();\n }\n });\n\n document.addEventListener('change', event => {\n if (event.target.matches('.setting-input[data-setting], .capability-checkbox[data-save-group], .capability-checkbox[data-group], .group-toggle, .ci-agent-global-toggle')) {\n if (event.target.matches('.setting-input[data-setting]')) {\n this.validateSettingInput(event.target);\n }\n\n this.queueSettingsSave();\n return;\n }\n\n if (event.target.closest('.prompt-template-parameters-input, .prompt-template-id-input')) {\n this.queueSettingsSave();\n }\n });\n\n document.addEventListener('click', event => {\n if (!event.target.closest('.prompt-template-add-btn, .remove-prompt-template-btn')) {\n return;\n }\n\n setTimeout(() => {\n this.queueSettingsSave();\n }, 0);\n });\n\n // Add event listener for clear history button\n const clearHistoryBtn = document.getElementById('clearHistoryBtn');\n if (clearHistoryBtn) {\n clearHistoryBtn.addEventListener('click', () => {\n const itemId = clearHistoryBtn.getAttribute('data-interaction-id');\n if (itemId) {\n this.clearHistory(itemId);\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 loadInteraction(itemId) {\n this.connection.invoke(\"LoadInteraction\", itemId).catch(err => console.error(err));\n },\n reloadCurrentInteraction() {\n const itemId = this.getItemId();\n if (itemId) {\n this.loadInteraction(itemId);\n }\n },\n clearHistory(itemId) {\n const self = this;\n const clearHistoryConfirmed = () => {\n // Cancel any active stream before clearing history.\n if (self.stream) {\n self.stream.dispose();\n self.stream = null;\n self.hideTypingIndicator();\n self.streamingFinished();\n }\n\n self.connection.invoke(\"ClearHistory\", itemId)\n .catch(err => console.error('Error clearing history:', err));\n };\n\n if (typeof confirmDialog === 'function') {\n confirmDialog({\n title: config.clearHistoryTitle,\n message: config.clearHistoryMessage,\n okText: config.clearHistoryOkText,\n cancelText: config.clearHistoryCancelText,\n callback: function (confirmed) {\n if (confirmed) {\n clearHistoryConfirmed();\n }\n }\n });\n\n return;\n }\n\n if (window.confirm(config.clearHistoryMessage || 'Clear all messages?')) {\n clearHistoryConfirmed();\n }\n },\n debouncedSaveSettings() {\n // Clear any existing timeout to reset the debounce timer\n this.clearPendingSettingsSave();\n\n // Don't save while streaming — it will be saved when streaming completes.\n if (this.stream) {\n return;\n }\n\n // Set a new timeout to save after 850ms of no changes\n this.saveSettingsTimeout = setTimeout(() => {\n if (this.settingsDirty) {\n this.saveSettings();\n this.settingsDirty = false;\n }\n this.saveSettingsTimeout = null;\n }, 850);\n },\n getSelectedToolNames() {\n return this.getSelectedGroupValues(\n 'toolNames',\n 'input[type=\"checkbox\"][name$=\"].IsSelected\"][name^=\"ChatInteraction.Tools[\"]:checked'\n );\n },\n getSelectedMcpConnectionIds() {\n return this.getSelectedGroupValues(\n 'mcpConnectionIds',\n 'input[type=\"checkbox\"][name$=\"].IsSelected\"][name^=\"ChatInteraction.Connections[\"]:checked'\n );\n },\n getSelectedA2AConnectionIds() {\n return this.getSelectedGroupValues('a2aConnectionIds');\n },\n getSelectedAgentNames() {\n return this.getSelectedGroupValues(\n 'agentNames',\n 'input[type=\"checkbox\"][name$=\"].IsSelected\"][name^=\"ChatInteraction.Agents[\"]:checked'\n );\n },\n saveSettings() {\n const itemId = this.getItemId();\n if (!itemId) {\n return Promise.resolve();\n }\n\n if (!this.validateSettings()) {\n this.showSaveIndicator('Fix errors', 'text-danger');\n return Promise.resolve();\n }\n\n const settings = {};\n\n // Collect all form inputs with the \"ChatInteraction.\" prefix generically.\n // This avoids coupling the JS to specific field names — new fields added by\n // any module are automatically included.\n const inputs = this.getSettingInputs();\n\n inputs.forEach(input => {\n const key = input.dataset.setting\n || ((input.name || '').replace('ChatInteraction.', '').replace(/^[A-Z]/, match => match.toLowerCase()));\n\n if (!key) {\n return;\n }\n\n if (input.type === 'checkbox') {\n settings[key] = input.checked;\n } else if (input.type === 'number') {\n settings[key] = input.value ? parseFloat(input.value) : null;\n } else {\n settings[key] = input.value || null;\n }\n });\n\n // Add tool, MCP connection, and agent collections (special handling).\n settings.toolNames = this.getSelectedToolNames();\n settings.mcpConnectionIds = this.getSelectedMcpConnectionIds();\n settings.a2aConnectionIds = this.getSelectedA2AConnectionIds();\n settings.agentNames = this.getSelectedAgentNames();\n\n const promptTemplates = this.getPromptTemplateSelections();\n if (promptTemplates.length > 0) {\n settings.promptTemplates = promptTemplates;\n settings.promptTemplateIds = promptTemplates.map(template => template.templateId);\n }\n\n return this.connection.invoke(\"SaveSettings\", itemId, settings)\n .catch(err => {\n console.error('Error saving settings:', err);\n this.showSaveIndicator('Save failed', 'text-danger');\n });\n },\n flushPendingSave() {\n if (this.saveSettingsTimeout) {\n clearTimeout(this.saveSettingsTimeout);\n this.saveSettingsTimeout = null;\n }\n\n if (this.settingsDirty) {\n this.settingsDirty = false;\n return this.saveSettings();\n }\n\n return Promise.resolve();\n },\n initializeInteraction(itemId, force) {\n if (this.isInteractionStarted && !force) {\n return;\n }\n this.fireEvent(new CustomEvent(\"initializingChatInteraction\", { detail: { itemId: itemId } }));\n this.setItemId(itemId);\n this.isInteractionStarted = true;\n },\n clearCopiedMessageState() {\n if (this.copyResetTimeoutId) {\n window.clearTimeout(this.copyResetTimeoutId);\n this.copyResetTimeoutId = null;\n }\n\n if (this.activeCopyButton) {\n this.setCopyButtonState(this.activeCopyButton, false);\n this.activeCopyButton = null;\n }\n\n this.copiedMessageIndex = -1;\n },\n copyResponse(message, index, event) {\n const text = message && typeof message === 'object'\n ? message.copyContent ?? message.content ?? ''\n : message ?? '';\n const button = event?.currentTarget || event?.target?.closest?.('[data-copy-message-index]') || null;\n\n navigator.clipboard.writeText(text)\n .then(() => {\n this.clearCopiedMessageState();\n this.copiedMessageIndex = typeof index === 'number' ? index : -1;\n this.activeCopyButton = button;\n\n if (button) {\n this.setCopyButtonState(button, true);\n } else {\n this.$nextTick(() => this.updateCopyButtons());\n }\n\n this.copyResetTimeoutId = window.setTimeout(() => {\n this.clearCopiedMessageState();\n this.$nextTick(() => this.updateCopyButtons());\n }, Number(config.copyResetDelayMs) || 2000);\n })\n .catch(err => console.error('Failed to copy response:', err));\n },\n 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 itemId = this.getItemId();\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\", itemId, 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 },\n watch: {\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 if (this.micButton) {\n this.micButton.style.display = active ? 'none' : (this.speechToTextEnabled ? '' : 'none');\n }\n\n if (this.buttonElement) {\n this.buttonElement.style.display = active ? 'none' : '';\n }\n\n if (this.inputElement) {\n this.inputElement.disabled = active;\n if (active) {\n this.inputElement.placeholder = '';\n }\n }\n },\n copiedMessageIndex() {\n this.$nextTick(() => this.updateCopyButtons());\n }\n },\n mounted() {\n (async () => {\n await this.startConnection();\n this.initializeApp();\n\n this.$nextTick(() => {\n this.updateCopyButtons();\n refreshFontAwesomeIcons(this.$el);\n this.fontAwesomeObserver = observeFontAwesomeIcons(this.$el);\n });\n })();\n\n window.addEventListener('beforeunload', this.handleBeforeUnload);\n window.addEventListener('crestapps-ai-chat-stop-tts', this.handleExternalTtsStop);\n },\n beforeUnmount() {\n window.removeEventListener('beforeunload', this.handleBeforeUnload);\n window.removeEventListener('crestapps-ai-chat-stop-tts', this.handleExternalTtsStop);\n\n if (this.fontAwesomeObserver) {\n this.fontAwesomeObserver.disconnect();\n this.fontAwesomeObserver = null;\n }\n\n this.clearCopiedMessageState();\n this.stopAudio(false);\n\n if (this.stream) {\n this.stream.dispose();\n this.stream = null;\n }\n if (this.connection) {\n this.connection.stop();\n }\n },\n template: config.messageTemplate\n }).mount(config.appElementSelector);\n\n return app;\n };\n\n const autoInitializeSelector = '[data-chat-interaction-config]';\n\n function parseJsonAttribute(element, attributeName, description) {\n const rawValue = element.getAttribute(attributeName);\n if (!rawValue) {\n return null;\n }\n\n try {\n return JSON.parse(rawValue);\n } catch (error) {\n console.error('Failed to parse ' + description + ' JSON.', error);\n return null;\n }\n }\n\n function initializeFromElement(element) {\n if (!element || element.dataset.chatInteractionInitialized === 'true') {\n return element ? element.__chatInteractionApp || null : null;\n }\n\n const config = parseJsonAttribute(element, 'data-chat-interaction-config', 'chat interaction config');\n if (!config) {\n return null;\n }\n\n const app = initialize(config);\n if (!app) {\n return null;\n }\n\n element.dataset.chatInteractionInitialized = 'true';\n element.__chatInteractionApp = app;\n\n return app;\n }\n\n function scanForAutoInitialization(root) {\n if (!root || typeof root.querySelectorAll !== 'function') {\n return;\n }\n\n if (typeof root.matches === 'function' && root.matches(autoInitializeSelector)) {\n initializeFromElement(root);\n }\n\n root.querySelectorAll(autoInitializeSelector).forEach(initializeFromElement);\n }\n\n function startAutoInitialization() {\n scanForAutoInitialization(document);\n\n if (typeof MutationObserver === 'undefined') {\n return;\n }\n\n const observer = new MutationObserver(mutations => {\n mutations.forEach(mutation => {\n mutation.addedNodes.forEach(node => {\n if (node && node.nodeType === 1) {\n scanForAutoInitialization(node);\n }\n });\n });\n });\n\n observer.observe(document.body, {\n childList: true,\n subtree: true,\n });\n }\n\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', startAutoInitialization, { once: true });\n } else {\n startAutoInitialization();\n }\n\n return {\n initialize: initialize,\n initializeFromElement: initializeFromElement,\n };\n}();\n\nwindow.chatInteractionDocumentManager = function () {\n const managerStateKey = '__chatInteractionDocumentManagerState';\n\n function normalizeDocumentInfo(document) {\n if (!document || typeof document !== 'object') {\n return null;\n }\n\n return {\n documentId: document.documentId || document.DocumentId || '',\n fileName: document.fileName || document.FileName || '',\n fileSize: document.fileSize || document.FileSize || 0\n };\n }\n\n function formatFileSize(bytes) {\n if (!bytes || bytes < 1024) {\n return (bytes || 0) + ' B';\n }\n\n if (bytes < 1024 * 1024) {\n return (bytes / 1024).toFixed(1) + ' KB';\n }\n\n return (bytes / (1024 * 1024)).toFixed(1) + ' MB';\n }\n\n function getDocumentKey(fileName, fileSize) {\n return ((fileName || '').trim().toLowerCase()) + '::' + (fileSize || 0);\n }\n\n function isDuplicateFile(file, knownKeys) {\n return knownKeys.has(getDocumentKey(file.name, file.size));\n }\n\n function getDocumentsFromDom(container) {\n if (!container) {\n return [];\n }\n\n return Array.from(container.querySelectorAll('[data-chat-document-id]'))\n .map(element => normalizeDocumentInfo({\n documentId: element.dataset.chatDocumentId,\n fileName: element.dataset.chatDocumentName,\n fileSize: Number(element.dataset.chatDocumentSize || 0)\n }))\n .filter(document => document && document.documentId);\n }\n\n function initialize(config) {\n if (!config || !config.itemId) {\n return;\n }\n\n const fileInput = document.getElementById('chat-doc-upload');\n const documentsList = document.getElementById('chat-documents-list');\n const status = document.getElementById('chat-doc-upload-status');\n const progressContainer = document.getElementById('chat-doc-upload-progress');\n const progressBar = document.getElementById('chat-doc-upload-progress-bar');\n const uploadQueue = document.getElementById('chat-doc-upload-queue');\n\n if (!fileInput || !documentsList || !status || !progressContainer || !progressBar || !uploadQueue) {\n return;\n }\n\n const previousState = fileInput[managerStateKey];\n if (previousState && typeof previousState.dispose === 'function') {\n previousState.dispose();\n }\n\n let interactionDocuments = (Array.isArray(config.existingDocuments) ? config.existingDocuments : [])\n .map(normalizeDocumentInfo)\n .filter(document => document && document.documentId);\n\n if (interactionDocuments.length === 0) {\n interactionDocuments = getDocumentsFromDom(documentsList);\n }\n\n let uploadItems = [];\n let isUploadingDocuments = false;\n\n function createTextElement(tagName, className, text) {\n const element = document.createElement(tagName);\n if (className) {\n element.className = className;\n }\n\n element.textContent = text;\n return element;\n }\n\n function renderDocuments() {\n documentsList.innerHTML = '';\n\n if (interactionDocuments.length === 0) {\n documentsList.appendChild(createTextElement('div', 'text-muted small', 'No documents uploaded yet.'));\n return;\n }\n\n interactionDocuments.forEach(documentInfo => {\n const row = window.document.createElement('div');\n row.className = 'd-flex justify-content-between align-items-start gap-2 border rounded px-2 py-2 bg-white chat-document-row';\n row.dataset.chatDocumentId = documentInfo.documentId;\n row.dataset.chatDocumentName = documentInfo.fileName;\n row.dataset.chatDocumentSize = documentInfo.fileSize;\n\n const details = window.document.createElement('div');\n details.className = 'me-2 min-w-0';\n\n const name = createTextElement('div', 'fw-semibold small', documentInfo.fileName || 'Document');\n const icon = window.document.createElement('i');\n icon.className = 'bi bi-file-earmark-text me-1';\n name.prepend(icon);\n\n const size = createTextElement('div', 'text-muted small', formatFileSize(documentInfo.fileSize));\n\n details.appendChild(name);\n details.appendChild(size);\n\n const removeButton = createTextElement('button', 'btn btn-sm btn-outline-danger remove-chat-document-btn', ' Remove');\n removeButton.type = 'button';\n removeButton.dataset.documentId = documentInfo.documentId;\n const removeIcon = window.document.createElement('i');\n removeIcon.className = 'bi bi-trash';\n removeButton.prepend(removeIcon);\n removeButton.addEventListener('click', () => removeDocument(documentInfo.documentId));\n\n row.appendChild(details);\n row.appendChild(removeButton);\n documentsList.appendChild(row);\n });\n }\n\n function showUploadStatus(message, cssClass) {\n if (!message) {\n status.textContent = '';\n status.className = 'small mt-2 d-none';\n return;\n }\n\n status.textContent = message;\n status.className = 'small mt-2 ' + (cssClass || 'text-muted');\n }\n\n function showUploadProgress(progress, message, cssClass) {\n if (progress === null || progress === undefined) {\n progressContainer.className = 'progress mt-2 d-none';\n progressContainer.setAttribute('aria-valuenow', '0');\n progressBar.className = 'progress-bar progress-bar-striped progress-bar-animated';\n progressBar.style.width = '0%';\n progressBar.textContent = '0%';\n return;\n }\n\n const roundedProgress = Math.max(0, Math.min(100, Math.round(progress)));\n progressContainer.className = 'progress mt-2';\n progressContainer.setAttribute('aria-valuenow', roundedProgress.toString());\n progressBar.className = 'progress-bar ' + (cssClass || 'progress-bar-striped progress-bar-animated');\n progressBar.style.width = roundedProgress + '%';\n progressBar.textContent = message || (roundedProgress + '%');\n }\n\n function getUploadStatePresentation(state) {\n switch (state) {\n case 'uploaded':\n return { label: 'Uploaded', badgeClass: 'text-bg-success', progressClass: 'bg-success' };\n case 'failed':\n return { label: 'Failed', badgeClass: 'text-bg-danger', progressClass: 'bg-danger' };\n case 'uploading':\n return { label: 'Uploading', badgeClass: 'text-bg-warning', progressClass: 'bg-warning progress-bar-striped progress-bar-animated' };\n default:\n return { label: 'Queued', badgeClass: 'text-bg-secondary', progressClass: 'bg-secondary progress-bar-striped progress-bar-animated' };\n }\n }\n\n function formatUploadMessage(item) {\n if (item.status === 'failed' && item.error) {\n return item.error;\n }\n\n if (item.status === 'uploaded') {\n return 'Upload completed successfully.';\n }\n\n if (item.status === 'uploading') {\n return item.progress + '% uploaded';\n }\n\n return 'Waiting to upload...';\n }\n\n function renderUploadQueue() {\n uploadQueue.innerHTML = '';\n\n uploadItems.forEach(item => {\n const presentation = getUploadStatePresentation(item.status);\n const card = document.createElement('div');\n card.className = 'border rounded px-2 py-2 bg-white';\n\n const header = document.createElement('div');\n header.className = 'd-flex justify-content-between align-items-start gap-2';\n\n const fileDetails = document.createElement('div');\n fileDetails.className = 'flex-grow-1 min-w-0';\n fileDetails.appendChild(createTextElement('div', 'fw-semibold small', item.fileName));\n fileDetails.appendChild(createTextElement('div', 'text-muted small', formatFileSize(item.fileSize)));\n\n const badge = createTextElement('span', 'badge ' + presentation.badgeClass, presentation.label);\n\n header.appendChild(fileDetails);\n header.appendChild(badge);\n\n const progress = document.createElement('div');\n progress.className = 'progress mt-2';\n progress.setAttribute('role', 'progressbar');\n progress.setAttribute('aria-valuemin', '0');\n progress.setAttribute('aria-valuemax', '100');\n progress.setAttribute('aria-valuenow', item.progress.toString());\n\n const progressState = document.createElement('div');\n progressState.className = 'progress-bar ' + presentation.progressClass;\n progressState.style.width = item.progress + '%';\n progressState.textContent = item.progress + '%';\n progress.appendChild(progressState);\n\n const message = createTextElement('div', item.status === 'failed' ? 'small text-danger mt-2' : 'small text-muted mt-2', formatUploadMessage(item));\n\n card.appendChild(header);\n card.appendChild(progress);\n card.appendChild(message);\n uploadQueue.appendChild(card);\n });\n }\n\n function createUploadItem(file, index) {\n return {\n id: file.name + '::' + file.size + '::' + file.lastModified + '::' + index + '::' + Date.now(),\n fileName: file.name,\n fileSize: file.size,\n status: 'queued',\n progress: 0,\n error: null\n };\n }\n\n function updateUploadItem(itemId, updates) {\n uploadItems = uploadItems.map(item => item.id === itemId ? Object.assign({}, item, updates) : item);\n renderUploadQueue();\n }\n\n function removeUploadItems(predicate) {\n uploadItems = uploadItems.filter(item => !predicate(item));\n renderUploadQueue();\n }\n\n function uploadSingleDocument(file, itemIdToUpdate, fileIndex, totalFiles) {\n return new Promise((resolve, reject) => {\n const formData = new FormData();\n formData.append('chatInteractionId', config.itemId);\n formData.append('files', file);\n\n const xhr = new XMLHttpRequest();\n xhr.open('POST', config.uploadDocumentUrl, true);\n\n xhr.upload.addEventListener('progress', event => {\n if (!event.lengthComputable) {\n return;\n }\n\n const fileProgress = Math.round((event.loaded / event.total) * 100);\n updateUploadItem(itemIdToUpdate, {\n status: 'uploading',\n progress: fileProgress\n });\n\n const overallProgress = ((fileIndex + (event.loaded / event.total)) / totalFiles) * 100;\n showUploadProgress(overallProgress, 'Uploading ' + (fileIndex + 1) + ' of ' + totalFiles, 'progress-bar-striped progress-bar-animated');\n });\n\n xhr.addEventListener('load', () => {\n if (xhr.status >= 200 && xhr.status < 300) {\n try {\n resolve(JSON.parse(xhr.responseText));\n } catch (error) {\n reject(new Error('Upload failed: invalid server response.'));\n }\n\n return;\n }\n\n reject(new Error((xhr.responseText || 'Upload failed.').trim()));\n });\n\n xhr.addEventListener('error', () => {\n reject(new Error('Upload failed. Please check your connection and try again.'));\n });\n\n xhr.send(formData);\n });\n }\n\n async function uploadDocuments(files) {\n if (!config.uploadDocumentUrl || !files || files.length === 0) {\n return;\n }\n\n if (isUploadingDocuments) {\n showUploadStatus('A document upload is already in progress.', 'text-warning');\n return;\n }\n\n isUploadingDocuments = true;\n\n const filesToUpload = [];\n const duplicateItems = [];\n const knownDocumentKeys = new Set(interactionDocuments.map(document => getDocumentKey(document.fileName, document.fileSize)));\n\n Array.from(files).forEach(file => {\n if (isDuplicateFile(file, knownDocumentKeys)) {\n duplicateItems.push(file);\n return;\n }\n\n knownDocumentKeys.add(getDocumentKey(file.name, file.size));\n filesToUpload.push(file);\n });\n\n if (duplicateItems.length > 0) {\n uploadItems = uploadItems.concat(duplicateItems.map((file, index) => Object.assign(createUploadItem(file, index), {\n status: 'failed',\n progress: 100,\n error: 'This document is already attached.'\n })));\n renderUploadQueue();\n }\n\n if (filesToUpload.length === 0) {\n isUploadingDocuments = false;\n showUploadStatus(duplicateItems.map(file => file.name + ': This document is already attached.').join(' | '), 'text-warning');\n showUploadProgress(null);\n return;\n }\n\n const pendingItems = filesToUpload.map(createUploadItem);\n uploadItems = uploadItems.concat(pendingItems);\n renderUploadQueue();\n showUploadProgress(0, 'Preparing upload...', 'progress-bar-striped progress-bar-animated');\n fileInput.disabled = true;\n\n try {\n let uploadedCount = 0;\n const failedUploads = duplicateItems.map(file => file.name + ': This document is already attached.');\n\n for (let i = 0; i < filesToUpload.length; i++) {\n const file = filesToUpload[i];\n const pendingItem = pendingItems[i];\n\n updateUploadItem(pendingItem.id, {\n status: 'uploading',\n progress: 0,\n error: null\n });\n\n showUploadStatus('Uploading ' + (i + 1) + ' of ' + filesToUpload.length + ' document(s)...', 'text-warning');\n\n try {\n const result = await uploadSingleDocument(file, pendingItem.id, i, filesToUpload.length);\n const uploaded = (Array.isArray(result.uploaded) ? result.uploaded : [])\n .map(normalizeDocumentInfo)\n .filter(document => document && document.documentId);\n const failed = Array.isArray(result.failed) ? result.failed : [];\n\n if (uploaded.length > 0) {\n uploadedCount += uploaded.length;\n interactionDocuments = interactionDocuments.concat(uploaded);\n updateUploadItem(pendingItem.id, {\n status: 'uploaded',\n progress: 100,\n error: null\n });\n } else {\n const missingUploadMessage = failed.length > 0\n ? failed.map(entry => entry.fileName + ': ' + entry.error).join(' | ')\n : 'The server did not confirm that the file was uploaded.';\n if (failed.length === 0) {\n failedUploads.push(missingUploadMessage);\n }\n updateUploadItem(pendingItem.id, {\n status: 'failed',\n progress: 100,\n error: missingUploadMessage\n });\n }\n\n if (failed.length > 0) {\n const failedMessage = failed.map(entry => entry.fileName + ': ' + entry.error).join(' | ');\n failedUploads.push(failedMessage);\n updateUploadItem(pendingItem.id, {\n status: 'failed',\n progress: 100,\n error: failedMessage\n });\n }\n } catch (error) {\n const errorMessage = error && error.message\n ? error.message\n : 'Upload failed. Please try again.';\n console.error('Upload failed:', error);\n failedUploads.push(file.name + ': ' + errorMessage);\n updateUploadItem(pendingItem.id, {\n status: 'failed',\n progress: pendingItem.progress || 0,\n error: errorMessage\n });\n }\n }\n\n renderDocuments();\n\n if (failedUploads.length > 0) {\n removeUploadItems(item => item.status === 'uploaded');\n showUploadStatus(\n (uploadedCount > 0 ? ('Uploaded ' + uploadedCount + ' document(s). ') : '') + failedUploads.join(' | '),\n uploadedCount > 0 ? 'text-warning' : 'text-danger');\n showUploadProgress(null);\n return;\n }\n\n removeUploadItems(() => true);\n showUploadStatus('Uploaded ' + uploadedCount + ' document(s).', 'text-success');\n showUploadProgress(null);\n } catch (error) {\n console.error('Upload failed:', error);\n showUploadStatus('Upload failed. Please try again.', 'text-danger');\n showUploadProgress(null);\n } finally {\n isUploadingDocuments = false;\n fileInput.disabled = false;\n fileInput.value = '';\n }\n }\n\n async function removeDocument(documentId) {\n if (!config.removeDocumentUrl || !documentId || !window.confirm('Remove this document?')) {\n return;\n }\n\n try {\n const response = await fetch(config.removeDocumentUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify({\n itemId: config.itemId,\n documentId: documentId\n })\n });\n\n if (!response.ok) {\n console.error('Failed to remove document:', await response.text());\n showUploadStatus('Failed to remove document.', 'text-danger');\n return;\n }\n\n const result = await response.json();\n const serverDocuments = (Array.isArray(result.documents) ? result.documents : [])\n .map(normalizeDocumentInfo)\n .filter(document => document && document.documentId);\n\n interactionDocuments = serverDocuments.length > 0\n ? serverDocuments\n : interactionDocuments.filter(document => document.documentId !== documentId);\n renderDocuments();\n showUploadStatus('Document removed.', 'text-success');\n } catch (error) {\n console.error('Remove failed:', error);\n showUploadStatus('Failed to remove document.', 'text-danger');\n }\n }\n\n const onFileInputChange = event => {\n const selectedFiles = event.target.files ? Array.from(event.target.files) : [];\n uploadDocuments(selectedFiles);\n };\n\n fileInput.addEventListener('change', onFileInputChange);\n fileInput[managerStateKey] = {\n dispose: () => {\n fileInput.removeEventListener('change', onFileInputChange);\n }\n };\n\n renderDocuments();\n renderUploadQueue();\n showUploadStatus(null);\n showUploadProgress(null);\n\n return fileInput[managerStateKey];\n }\n\n function parseJsonAttribute(element, attributeName, description) {\n const rawValue = element.getAttribute(attributeName);\n if (!rawValue) {\n return null;\n }\n\n try {\n return JSON.parse(rawValue);\n } catch (error) {\n console.error('Failed to parse ' + description + ' JSON.', error);\n return null;\n }\n }\n\n function initializeFromElement(element) {\n if (!element || element.dataset.chatInteractionDocumentManagerInitialized === 'true') {\n return element ? element[managerStateKey] || null : null;\n }\n\n const config = parseJsonAttribute(element, 'data-chat-interaction-document-manager-config', 'chat interaction document manager config');\n if (!config) {\n return null;\n }\n\n const state = initialize(config);\n if (!state) {\n return null;\n }\n\n element.dataset.chatInteractionDocumentManagerInitialized = 'true';\n\n return state;\n }\n\n function scanForAutoInitialization(root) {\n if (!root || typeof root.querySelectorAll !== 'function') {\n return;\n }\n\n if (typeof root.matches === 'function' && root.matches('[data-chat-interaction-document-manager-config]')) {\n initializeFromElement(root);\n }\n\n root.querySelectorAll('[data-chat-interaction-document-manager-config]').forEach(initializeFromElement);\n }\n\n function startAutoInitialization() {\n scanForAutoInitialization(document);\n\n if (typeof MutationObserver === 'undefined') {\n return;\n }\n\n const observer = new MutationObserver(mutations => {\n mutations.forEach(mutation => {\n mutation.addedNodes.forEach(node => {\n if (node && node.nodeType === 1) {\n scanForAutoInitialization(node);\n }\n });\n });\n });\n\n observer.observe(document.body, {\n childList: true,\n subtree: true,\n });\n }\n\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', startAutoInitialization, { once: true });\n } else {\n startAutoInitialization();\n }\n\n return {\n initialize: initialize,\n initializeFromElement: initializeFromElement,\n };\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"]}