@crestapps/ai-chat-ui 1.0.0-preview.8 → 1.0.0-preview.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai-chat.js +143 -111
- package/dist/ai-chat.js.map +1 -1
- package/dist/ai-chat.min.js +1 -1
- package/dist/ai-chat.min.js.map +1 -1
- package/dist/chat-interaction.js +9 -9
- package/dist/chat-interaction.js.map +1 -1
- package/dist/chat-interaction.min.js +1 -1
- package/dist/chat-interaction.min.js.map +1 -1
- package/package.json +1 -1
|
@@ -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)\"><i :class=\"getAssistantIcon(message)\"></i></span>\n {{ getAssistantLabel(message) }}\n </div>\n <div class=\"ai-chat-message-body lh-base\">\n <h4 v-if=\"message.title\">{{ message.title }}</h4>\n <div v-html=\"message.htmlContent\"></div>\n <span class=\"message-buttons-container\" v-if=\"!isIndicator(message)\">\n <button v-if=\"textToSpeechEnabled && !isConversationMode && message.role === 'assistant' && !message.isStreaming\" class=\"btn btn-sm btn-link text-secondary p-0 me-1 button-message-toolbox\" :class=\"{ 'tts-playing': ttsPlayingMessageIndex === index }\" @click=\"toggleMessageTts(message, index)\" :title=\"ttsPlayingMessageIndex === index ? 'Pause audio' : 'Read aloud'\">\n <i :class=\"ttsPlayingMessageIndex === index ? 'fa-solid fa-circle-pause' : 'fa-solid fa-circle-play'\"></i>\n </button>\n <button class=\"btn btn-sm btn-link text-secondary p-0 button-message-toolbox\" @click=\"copyResponse(message.content)\" title=\"Click here to copy response to clipboard.\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n </span>\n </div>\n </div>\n </div>\n <div v-for=\"notification in notifications\" :key=\"'notif-' + notification.type\" class=\"ai-chat-notification\" :class=\"'ai-chat-notification-' + (notification.type || 'info') + ' ' + (notification.cssClass || '')\">\n <div class=\"ai-chat-notification-content\">\n <i v-if=\"notification.icon\" :class=\"notification.icon\" class=\"ai-chat-notification-icon\"></i>\n <span class=\"ai-chat-notification-text\">{{ notification.content }}</span>\n <button v-if=\"notification.dismissible\" class=\"btn btn-sm btn-link p-0 ms-2 ai-chat-notification-dismiss\" @click=\"dismissNotification(notification.type)\" title=\"Dismiss\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n <div v-if=\"notification.actions && notification.actions.length\" class=\"ai-chat-notification-actions\">\n <button v-for=\"action in notification.actions\" :key=\"action.name\" class=\"btn btn-sm\" :class=\"action.cssClass || 'btn-outline-secondary'\" @click=\"handleNotificationAction(notification.type, action.name)\">\n <i v-if=\"action.icon\" :class=\"action.icon\" class=\"me-1\"></i>\n {{ action.label }}\n </button>\n </div>\n </div>\n </div>\n `,\n indicatorTemplate: `\n <div class=\"ai-chat-msg-role ai-chat-msg-role-assistant\">\n <span class=\"ai-streaming-icon\"><i class=\"fa fa-robot\" style=\"display: inline-block;\"></i></span>\n Assistant\n </div>\n `,\n // 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\"><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 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, '&').replace(/</g, '<').replace(/>/g, '>');\n var html = '<p class=\"ai-partial-transcript\">' + escaped + '</p>';\n\n // Show partial transcript as a live user message.\n if (!this._conversationPartialMessage) {\n this.hidePlaceholder();\n this._conversationPartialMessage = {\n role: 'user',\n content: text,\n htmlContent: html,\n isPartial: true\n };\n this.messages.push(this._conversationPartialMessage);\n } else {\n this._conversationPartialMessage.content = text;\n this._conversationPartialMessage.htmlContent = html;\n }\n this.scrollToBottom();\n }\n return;\n }\n\n if (text && !this._audioInputSent) {\n this.prompt = this.preRecordingPrompt + text;\n if (this.inputElement) {\n this.inputElement.value = this.prompt;\n this.inputElement.dispatchEvent(new Event('input'));\n }\n }\n });\n\n this.connection.on(\"ReceiveConversationUserMessage\", (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, '&').replace(/</g, '<').replace(/>/g, '>');\n this._conversationPartialMessage.content = text;\n this._conversationPartialMessage.htmlContent = '<p>' + escaped + '</p>';\n this._conversationPartialMessage.isPartial = false;\n this._conversationPartialMessage = null;\n } else {\n this.addMessage({\n role: 'user',\n content: text\n });\n }\n this.scrollToBottom();\n }\n });\n\n this.connection.on(\"ReceiveConversationAssistantToken\", (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 = '<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], .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 = '<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 },\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":["_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, '&').replace(/</g, '<').replace(/>/g, '>');\n var html = '<p class=\"ai-partial-transcript\">' + escaped + '</p>';\n\n // Show partial transcript as a live user message.\n if (!this._conversationPartialMessage) {\n this.hidePlaceholder();\n this._conversationPartialMessage = {\n role: 'user',\n content: text,\n htmlContent: html,\n isPartial: true\n };\n this.messages.push(this._conversationPartialMessage);\n } else {\n this._conversationPartialMessage.content = text;\n this._conversationPartialMessage.htmlContent = html;\n }\n this.scrollToBottom();\n }\n return;\n }\n\n if (text && !this._audioInputSent) {\n this.prompt = this.preRecordingPrompt + text;\n if (this.inputElement) {\n this.inputElement.value = this.prompt;\n this.inputElement.dispatchEvent(new Event('input'));\n }\n }\n });\n\n this.connection.on(\"ReceiveConversationUserMessage\", (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, '&').replace(/</g, '<').replace(/>/g, '>');\n this._conversationPartialMessage.content = text;\n this._conversationPartialMessage.htmlContent = '<p>' + escaped + '</p>';\n this._conversationPartialMessage.isPartial = false;\n this._conversationPartialMessage = null;\n } else {\n this.addMessage({\n role: 'user',\n content: text\n });\n }\n this.scrollToBottom();\n }\n });\n\n this.connection.on(\"ReceiveConversationAssistantToken\", (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"]}
|