@crestapps/ai-chat-ui 2.0.0-preview.223 → 2.0.0-preview.225
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.css +31 -0
- package/dist/ai-chat.js +23 -11
- package/dist/ai-chat.js.map +1 -1
- package/dist/ai-chat.min.css +1 -1
- package/dist/ai-chat.min.js +6 -6
- package/dist/ai-chat.min.js.map +1 -1
- package/dist/chat-image-carousel.js +21 -4
- package/dist/chat-image-carousel.js.map +1 -1
- package/dist/chat-image-carousel.min.js +2 -1
- package/dist/chat-image-carousel.min.js.map +1 -1
- package/dist/chat-interaction.js +33 -8
- package/dist/chat-interaction.js.map +1 -1
- package/dist/chat-interaction.min.js +6 -6
- package/dist/chat-interaction.min.js.map +1 -1
- package/dist/chat-markers.js +1 -1
- package/dist/chat-markers.js.map +1 -1
- package/dist/chat-markers.min.js +1 -1
- package/dist/chat-markers.min.js.map +1 -1
- package/dist/chat-widget.css +31 -0
- package/dist/chat-widget.min.css +1 -1
- package/dist/realtime-audio.js +4 -2
- package/dist/realtime-audio.js.map +1 -1
- package/dist/realtime-audio.min.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
(function(){window.chatInteractionManager=function(){var e={generatedImageAltText:`Generated Image`,generatedImageMaxWidth:400,downloadImageTitle:`Download image`,downloadChartTitle:`Download chart as image`,downloadChartButtonText:`Download`,codeCopiedText:`Copied!`,copyTitle:`Click here to copy response to clipboard.`,copiedTitle:`Response copied to clipboard.`,copyResetDelayMs:2e3,assistantLabel:`Assistant`,messageTemplate:`
|
|
1
|
+
(function(){window.chatInteractionManager=function(){var e={generatedImageAltText:`Generated Image`,generatedImageMaxWidth:400,downloadImageTitle:`Download image`,downloadChartTitle:`Download chart as image`,downloadChartButtonText:`Download`,codeCopiedText:`Copied!`,copyTitle:`Click here to copy response to clipboard.`,copiedTitle:`Response copied to clipboard.`,copyResetDelayMs:2e3,assistantLabel:`Assistant`,assistantAvatarUrl:null,messageTemplate:`
|
|
2
2
|
<div class="ai-chat-messages">
|
|
3
3
|
<div v-for="(message, index) in messages" :key="index" class="ai-chat-message-item">
|
|
4
4
|
<div>
|
|
5
5
|
<div v-if="message.role === 'user'" class="ai-chat-msg-role ai-chat-msg-role-user">You</div>
|
|
6
6
|
<div v-else-if="message.role !== 'indicator'" :class="getAssistantRoleClasses(message)">
|
|
7
|
-
<span :class="getAssistantIconClasses(message, index)"><i :class="getAssistantIcon(message)"></i></span>
|
|
7
|
+
<span :class="getAssistantIconClasses(message, index)"><img v-if="getAssistantAvatarUrl(message)" class="ai-chat-assistant-avatar" :src="getAssistantAvatarUrl(message)" alt="" /><i v-else :class="getAssistantIcon(message)"></i></span>
|
|
8
8
|
{{ getAssistantLabel(message) }}
|
|
9
9
|
</div>
|
|
10
10
|
<div class="ai-chat-message-body lh-base">
|
|
@@ -45,8 +45,8 @@
|
|
|
45
45
|
</div>
|
|
46
46
|
`,indicatorTemplate:`
|
|
47
47
|
<div class="ai-chat-msg-role ai-chat-msg-role-assistant">
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
{{ assistantIcon }}
|
|
49
|
+
{{ assistantLabel }}
|
|
50
50
|
</div>
|
|
51
51
|
`,untitledText:`Untitled`,clearHistoryTitle:`Clear History`,clearHistoryMessage:`Are you sure you want to clear the chat history? This action cannot be undone. Your documents, parameters, and tools will be preserved.`,clearHistoryOkText:`Yes`,clearHistoryCancelText:`Cancel`};function t(e){if(!e)return``;var t=e.trim();return/^javascript:/i.test(t)||/^vbscript:/i.test(t)||/^data:text\/html/i.test(t)?``:e}function n(e){var t=document.createElement(`span`);return t.textContent=e,t.innerHTML}function r(e){if(!e||e.nodeType!==1)return!1;var t=`i[class*="fa-"],i.fa,i.fas,i.far,i.fab`;return typeof e.matches==`function`&&e.matches(t)?!0:typeof e.querySelector==`function`&&!!e.querySelector(t)}function i(e){var t=window.FontAwesome;r(e)&&t&&t.dom&&typeof t.dom.i2svg==`function`&&t.dom.i2svg({node:e})}function a(e){if(!e||typeof MutationObserver>`u`)return null;var t=new MutationObserver(function(e){e.forEach(function(e){e.addedNodes.forEach(function(e){i(e)})})});return t.observe(e,{childList:!0,subtree:!0}),t}function o(e){if(!e||typeof e!=`object`)return null;let n=Object.assign({},e);return n.index=n.index??n.Index??0,n.text=n.text??n.Text??null,n.title=n.title??n.Title??null,n.link=t(n.link??n.Link??null),n.referenceType=n.referenceType??n.ReferenceType??null,n.isGenerated=(n.isGenerated??n.IsGenerated)===!0,n.isImage=(n.isImage??n.IsImage)===!0,n}function s(e){return!e||typeof e!=`object`?!1:!!(typeof e.referenceType==`string`&&e.referenceType.toLowerCase()===`document`||typeof e.link==`string`&&/\/ai\/documents\/.+\/download(?:$|\?)/i.test(e.link))}function c(e){if(!e||typeof e!=`object`)return{};let t={};for(let[n,r]of Object.entries(e))t[n]=o(r)??{};return t}let l=window.CoreAIChatMarkers.expandImageMarkers;function u(e,t){return e.title||e.text||t}let d=0,f=window.CoreAIChatMarkers?.citationIdentity??(()=>`unmerged-${++d}`),p=window.CoreAIChatMarkers?.splitCombinedCitations??(e=>e),m=window.CoreAIChatMarkers?.collapseRepeatedCitations??(e=>e),h=window.CoreAIChatMarkers?.separateAdjacentCitations??(e=>e),g=window.CoreAIChatMarkers?.citationMarkerHtml??(e=>`<sup>${e}</sup>`);function _(e,t){let n=p((e||``).trim()),r=c(t),i=Object.entries(r);if(!i.length)return{content:n,citations:[]};let a=i.filter(([e])=>n.includes(e)),o=i.filter(([e,t])=>t.isGenerated&&!n.includes(e));if(!a.length&&!o.length)return{content:n,citations:[]};a.sort(([,e],[,t])=>e.index-t.index),o.sort(([,e],[,t])=>e.index-t.index);let l=[],d=new Map,_=[],v=1;for(let[e,t]of a){let r=u(t,e),i=t.link||null,a=f(r,i),o=d.get(a);o||(o={referenceKey:e,referenceKeys:[],displayIndex:v++,label:r,link:i,isDownload:s(t)},d.set(a,o),l.push(o)),o.referenceKeys.push(e);let c=`__CITE_${o.displayIndex}_${t.index||o.displayIndex}__`;n=n.replaceAll(e,c),_.push({placeholder:c,displayIndex:o.displayIndex,label:o.label})}for(let e of _)n=n.replaceAll(e.placeholder,g(e.displayIndex,e.label));n=m(n),n=h(n);for(let[e,t]of o)l.push({referenceKey:e,referenceKeys:[e],displayIndex:v,label:u(t,e),link:t.link||null,isDownload:!0,placeholder:null}),v++;return{content:n,citations:l.map(({placeholder:e,...t})=>t)}}function v(e,t){let n=(e||``).trim();if(!n||!Array.isArray(t)||t.length===0)return n;for(let e of t)for(let t of e.referenceKeys?.length?e.referenceKeys:[e.referenceKey])n=n.replaceAll(t,`[${e.displayIndex}]`);n+=`
|
|
52
52
|
|
|
@@ -57,7 +57,7 @@ References:
|
|
|
57
57
|
<a href="${r}" target="_blank" download="${i}" title="${e.downloadImageTitle}" class="btn btn-sm btn-outline-secondary ai-download-image">
|
|
58
58
|
<i class="fa-solid fa-download"></i>
|
|
59
59
|
</a>
|
|
60
|
-
</span>`};let x=0,S=[];window.__chartConfigs=window.__chartConfigs||{};function C(t){return`<div class="chart-container" style="position: relative; width: 100%; max-width: 560px; min-height: 420px;"><canvas id="${t}"></canvas></div><div class="mt-2"><button type="button" class="btn btn-sm btn-outline-secondary download-chart-btn" data-chart-id="${t}" title="${e.downloadChartTitle}"><i class="fa-solid fa-download"></i> ${e.downloadChartButtonText}</button></div>`}let w=window.CoreAIChatMarkers.findChartMarker;marked.use({extensions:[{name:`chart`,level:`block`,start(e){let t=e.indexOf(`[chart:`);return t>=0?t:void 0},tokenizer(e){let t=w(e);if(!t||t.startIndex!==0)return;let n=`chat_chart_${++x}`;return{type:`chart`,raw:e.substring(0,t.endIndex),chartId:n,json:t.json}},renderer(e){return S.push({chartId:e.chartId,config:e.json}),window.__chartConfigs[e.chartId]=e.json,C(e.chartId)}}]});function T(){typeof document<`u`&&typeof requestAnimationFrame==`function`&&(requestAnimationFrame(D),requestAnimationFrame(E))}function E(){if(typeof mediumZoom!=`function`)return;let e=document.querySelectorAll(`.generated-image-container img:not([data-zoom-wired])`);if(e.length!==0){for(let t of e)t.setAttribute(`data-zoom-wired`,`true`);mediumZoom(e,{margin:16,background:`rgba(15, 15, 15, 0.92)`})}}function D(){let e=document.querySelectorAll(`.generated-image-container img:not([data-broken-wired])`);for(let t of e)t.setAttribute(`data-broken-wired`,`true`),t.addEventListener(`error`,function(){let e=t.closest(`.generated-image-container`);if(!e||e.dataset.brokenHandled)return;e.dataset.brokenHandled=`true`,e.hidden=!0;let n=document.createElement(`p`);n.className=`text-muted small fst-italic mb-2`,n.textContent=t.alt?`(the picture "${t.alt}" could not be loaded)`:`(that picture could not be loaded)`,e.insertAdjacentElement(`afterend`,n)},{once:!0})}function O(e){if(T(),!e||!e._pendingCharts||!e._pendingCharts.length)return;let t=[...e._pendingCharts];e._pendingCharts=[],requestAnimationFrame(()=>{for(let e of t){let t=document.getElementById(e.chartId);if(t){if(typeof Chart>`u`)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>).`);else if(t.offsetParent===null)window.__chartConfigs[e.chartId]=e.config;else try{t._chartInstance&&t._chartInstance.destroy();let n=typeof e.config==`string`?JSON.parse(e.config):e.config;n.options??={},n.options.responsive=!0,n.options.maintainAspectRatio=!0,n.options.aspectRatio??=4/3,t._chartInstance=new Chart(t,n)}catch(e){console.error(`Error creating chart:`,e)}}}})}function k(e){return e.replace(/<table>/g,`<div class="table-responsive"><table class="table table-sm table-bordered table-striped align-middle">`).replace(/<\/table>/g,`</table></div>`)}function A(e,t){S=[];let n=k(marked.parse(e,{renderer:b}));t._pendingCharts=S.length>0?[...S]:[];let r=DOMPurify.sanitize(n,{ADD_TAGS:[`canvas`],ADD_ATTR:[`target`]});return window.CoreAIChatImageCarousel?window.CoreAIChatImageCarousel.stackAdjacentImages(r):r}function j(e){return!e||typeof e!=`object`?{}:Object.fromEntries(Object.entries(e).filter(([,e])=>e!==void 0))}let M=t=>{let n=Object.assign({},e,j(t));if(e=n,!n.signalRHubUrl)console.error(`The signalRHubUrl is required.`);else if(!n.appElementSelector)console.error(`The appElementSelector is required.`);else if(!n.chatContainerElementSelector)console.error(`The chatContainerElementSelector is required.`);else if(!n.inputElementSelector)console.error(`The inputElementSelector is required.`);else if(!n.sendButtonElementSelector)console.error(`The sendButtonElementSelector is required.`);else return Vue.createApp({data(){return{inputElement:null,buttonElement:null,chatContainer:null,placeholder:null,isInteractionStarted:!1,isPlaceholderVisible:!0,isStreaming:!1,isNavigatingAway:!1,autoScroll:!0,stream:null,messages:[],prompt:``,initialFieldValues:new Map,settingsDirty:!1,saveSettingsTimeout:null,saveIndicatorTimeout:null,isRecording:!1,mediaRecorder:null,preRecordingPrompt:``,micButton:null,speechToTextEnabled:n.chatMode===`AudioInput`||n.chatMode===`Conversation`,textToSpeechEnabled:n.chatMode===`Conversation`||!!n.textToSpeechEnabled,ttsVoiceName:n.ttsVoiceName||null,audioChunks:[],audioPlayQueue:[],isPlayingAudio:!1,currentAudioElement:null,currentAudioUrl:null,ttsPlayingMessageIndex:-1,ttsAudioCache:{},ttsInstanceId:`chat-interaction-`+Math.random().toString(36).slice(2),conversationModeEnabled:n.chatMode===`Conversation`,conversationButton:null,isConversationMode:!1,realtimeController:null,realtimeButton:null,realtimeEnabled:n.realtimeEnabled===!0,notifications:[],notificationDismissTimers:{},copyTitle:n.copyTitle,copiedTitle:n.copiedTitle,copiedMessageIndex:-1,copyResetTimeoutId:null,activeCopyButton:null}},computed:{lastAssistantIndex(){for(var e=this.messages.length-1;e>=0;e--)if(this.messages[e].role===`assistant`)return e;return-1}},methods:{handleBeforeUnload(){this.isNavigatingAway=!0},async startConnection(){this.connection=new signalR.HubConnectionBuilder().withUrl(n.signalRHubUrl).withAutomaticReconnect().build(),this.connection.serverTimeoutInMilliseconds=6e5,this.connection.keepAliveIntervalInMilliseconds=15e3,this.connection.on(`LoadInteraction`,e=>{this.initializeInteraction(e.itemId,!0),this.messages=[];let t=document.querySelector(`[data-chat-interaction-title], .setting-input[data-setting="title"], input[name="ChatInteraction.Title"], input[name="Title"]`);t&&e.title&&(t.value=e.title),(e.messages??[]).forEach(e=>{this.addMessage(e),this.$nextTick(()=>{O(e)})})}),this.connection.on(`SettingsSaved`,(e,t)=>{let r=document.querySelector(`.chat-interaction-history-item[data-interaction-id="${e}"]`);r&&(r.textContent=t||n.untitledText);let i=document.querySelector(`[data-chat-interaction-title], .setting-input[data-setting="title"], input[name="ChatInteraction.Title"], input[name="Title"]`);i&&t&&(i.value=t),this.showSaveIndicator(`Saved`,`text-success`)}),this.connection.on(`ReceiveError`,e=>{console.error(`SignalR Error: `,e),this.showSaveIndicator(`Save failed`,`text-danger`),this.isRecording&&this.stopRecording()}),this.connection.on(`ReceiveTranscript`,(e,t,n)=>{if(this.isConversationMode){if(!n&&t){this._conversationPartialTranscript=t;var r=`<p class="ai-partial-transcript">`+t.replace(/&/g,`&`).replace(/</g,`<`).replace(/>/g,`>`)+`</p>`;this._conversationPartialMessage?(this._conversationPartialMessage.content=t,this._conversationPartialMessage.htmlContent=r):(this.hidePlaceholder(),this._conversationPartialMessage={role:`user`,content:t,htmlContent:r,isPartial:!0},this.messages.push(this._conversationPartialMessage)),this.scrollToBottom()}}else t&&!this._audioInputSent&&(this.prompt=this.preRecordingPrompt+t,this.inputElement&&(this.inputElement.value=this.prompt,this.inputElement.dispatchEvent(new Event(`input`))))}),this.connection.on(`ReceiveConversationUserMessage`,(e,t,n)=>{if(t&&this._realtimePendingTurns&&this._realtimePendingTurns[t]){var r=this._realtimePendingTurns[t];if(delete this._realtimePendingTurns[t],this.stopAudio(),n)r.content=n,r.rawContent=n,r.isPartial=!1,y(r,r.references);else{var i=this.messages.indexOf(r);i>=0&&this.messages.splice(i,1)}}else if(n){if(this.stopAudio(),this._conversationPartialMessage){var a=n.replace(/&/g,`&`).replace(/</g,`<`).replace(/>/g,`>`);this._conversationPartialMessage.content=n,this._conversationPartialMessage.htmlContent=`<p>`+a+`</p>`,this._conversationPartialMessage.isPartial=!1,this._conversationPartialMessage=null}else if(this._conversationAssistantMessage){var o=this._conversationAssistantMessage.index,s={role:`user`,content:n,rawContent:n,references:{}};y(s,s.references),this.messages.splice(o,0,s),this._conversationAssistantMessage.index=o+1}else this.addMessage({role:`user`,content:n});this.scrollToBottom()}}),this.connection.on(`ReceiveConversationAssistantToken`,(e,t,n,r,i,a)=>{if(this._conversationAssistantMessage&&this._conversationAssistantResponseId&&r&&this._conversationAssistantResponseId!==r){var o=this.messages[this._conversationAssistantMessage.index];o&&(o.isStreaming=!1),this._conversationAssistantMessage=null}if(!this._conversationAssistantMessage){this.stopAudio(),this.hideTypingIndicator();for(var s=0;s<this.messages.length;s++)this.messages[s].isStreaming&&(this.messages[s].isStreaming=!1);var l=this.messages.length,u={id:t,role:`assistant`,content:``,htmlContent:``,isStreaming:!0,appearance:this.normalizeAssistantAppearance(a),references:{}};this.messages.push(u),this._conversationAssistantMessage={index:l,content:``},this._conversationAssistantResponseId=r}this._conversationAssistantMessage.content+=n;var d=this.messages[this._conversationAssistantMessage.index];d&&(d.appearance||=this.normalizeAssistantAppearance(a),d.rawContent=this._conversationAssistantMessage.content,d.references=c(Object.assign({},d.references||{},i||{})),y(d,d.references),this.$nextTick(()=>{O(d),this.scrollToBottom()}))}),this.connection.on(`ReceiveConversationAssistantComplete`,(e,t,n)=>{if(this._conversationAssistantMessage){var r=this.messages[this._conversationAssistantMessage.index];r&&(r.isStreaming=!1,r.references=c(Object.assign({},r.references||{},n||{})),y(r,r.references)),this._conversationAssistantMessage=null,this._conversationAssistantResponseId=null}}),this.connection.on(`ReceiveAudioChunk`,(e,t,n)=>{if(t){let e=atob(t),r=new Uint8Array(e.length);for(let t=0;t<e.length;t++)r[t]=e.charCodeAt(t);n===`audio/pcm`&&this.realtimeController?this.realtimeController.receivePcm(r):this.audioChunks.push(r)}}),this.connection.on(`ReceiveAudioComplete`,e=>{this.playCollectedAudio()}),this.connection.on(`HistoryCleared`,e=>{this.messages=[],this.showPlaceholder();let t=document.getElementById(`clearHistoryBtn`);t&&t.classList.add(`d-none`)}),this.connection.on(`ReceiveNotification`,e=>{this.receiveNotification(e)}),this.connection.on(`UpdateNotification`,e=>{this.updateNotification(e)}),this.connection.on(`RemoveNotification`,e=>{this.removeNotification(e)}),this.connection.onreconnecting(()=>{console.warn(`SignalR: reconnecting...`)}),this.connection.onreconnected(()=>{console.info(`SignalR: reconnected.`),this.reloadCurrentInteraction()}),this.connection.onclose(e=>{this.isNavigatingAway||e&&console.warn(`SignalR connection closed with error:`,e.message||e)});try{await this.connection.start()}catch(e){console.error(`SignalR Connection Error: `,e)}},addMessageInternal(e){e.role===`assistant`&&(e.appearance=this.normalizeAssistantAppearance(e.appearance)),e.content&&!e.htmlContent&&(e.htmlContent=A(e.content,e)),this.fireEvent(new CustomEvent(`addingChatInteractionMessage`,{detail:{message:e}})),this.messages.push(e),this.$nextTick(()=>{this.fireEvent(new CustomEvent(`addedChatInteractionMessage`,{detail:{message:e}}))})},addMessage(e){e.content&&(e.rawContent=e.rawContent??e.content,y(e,e.references)),this.addMessageInternal(e),this.hidePlaceholder(),this.$nextTick(()=>{O(e),this.scrollToBottom()})},hidePlaceholder(){this.placeholder&&this.placeholder.classList.add(`d-none`),this.isPlaceholderVisible=!1},showPlaceholder(){this.placeholder&&this.placeholder.classList.remove(`d-none`),this.isPlaceholderVisible=!0},fireEvent(e){document.dispatchEvent(e)},normalizeAssistantAppearance(e){if(!e)return null;var t=typeof e.label==`string`?e.label.trim():``,n=typeof e.icon==`string`?e.icon.trim():``,r=typeof e.cssClass==`string`?e.cssClass.trim():``,i=!!e.disableStreamingAnimation;return!t&&!n&&!r&&!i?null:{label:t,icon:n,cssClass:r,disableStreamingAnimation:i}},getAssistantLabel(t){var n=t?this.normalizeAssistantAppearance(t.appearance):null;return n&&n.label?n.label:e.assistantLabel},getAssistantRoleClasses(e){var t=e?this.normalizeAssistantAppearance(e.appearance):null,n=[`ai-chat-msg-role`];return t&&t.cssClass?n.push(t.cssClass):n.push(`ai-chat-msg-role-assistant`),n},getAssistantIconClasses(e,t){var n=e?this.normalizeAssistantAppearance(e.appearance):null;return[this.shouldAnimateAssistantIcon(e,t)?`ai-streaming-icon`:`ai-bot-icon`,n&&n.cssClass?n.cssClass:``]},getAssistantIcon(e){var t=e?this.normalizeAssistantAppearance(e.appearance):null;return t&&t.icon?t.icon:`fa fa-robot`},shouldAnimateAssistantIcon(e,t){var n=e?this.normalizeAssistantAppearance(e.appearance):null;return!!e&&e.isStreaming&&t===this.lastAssistantIndex&&!(n&&n.disableStreamingAnimation)},isIndicator(e){return e.role===`indicator`},async sendMessage(){let e=this.prompt.trim();if(!e)return;this.endActiveVoiceSession(),this.isRecording&&this.stopRecording(),this._audioInputSent=!0,await this.flushPendingSave(),this.addMessage({role:`user`,content:e});let t=document.getElementById(`clearHistoryBtn`);t&&t.classList.remove(`d-none`),this.streamMessage(e),this.inputElement.value=``,this.prompt=``},streamMessage(e){this.stream&&=(this.stream.dispose(),null),this.streamingStarted(),this.showTypingIndicator(),this.autoScroll=!0;var t=``,n={},r=null,i=this.messages.length,a=this.getItemId();this.stream=this.connection.stream(`SendMessage`,a,e).subscribe({next:e=>{let s=this.messages[i];if(!s){e.sessionId&&!a&&this.setItemId(e.sessionId),this.hideTypingIndicator(),i=this.messages.length;let t={role:`assistant`,content:``,htmlContent:``,isStreaming:!0};this.messages.push(t),s=t}if(e.references&&typeof e.references==`object`&&Object.keys(e.references).length)for(let[t,r]of Object.entries(e.references))n[t]=o(r)??{};e.content&&(e.responseId&&r&&e.responseId!==r&&(t+=`
|
|
60
|
+
</span>`};let x=0,S=[];window.__chartConfigs=window.__chartConfigs||{};function C(t){return`<div class="chart-container" style="position: relative; width: 100%; max-width: 560px; min-height: 420px;"><canvas id="${t}"></canvas></div><div class="mt-2"><button type="button" class="btn btn-sm btn-outline-secondary download-chart-btn" data-chart-id="${t}" title="${e.downloadChartTitle}"><i class="fa-solid fa-download"></i> ${e.downloadChartButtonText}</button></div>`}let w=window.CoreAIChatMarkers.findChartMarker;marked.use({extensions:[{name:`chart`,level:`block`,start(e){let t=e.indexOf(`[chart:`);return t>=0?t:void 0},tokenizer(e){let t=w(e);if(!t||t.startIndex!==0)return;let n=`chat_chart_${++x}`;return{type:`chart`,raw:e.substring(0,t.endIndex),chartId:n,json:t.json}},renderer(e){return S.push({chartId:e.chartId,config:e.json}),window.__chartConfigs[e.chartId]=e.json,C(e.chartId)}}]});function T(){typeof document<`u`&&typeof requestAnimationFrame==`function`&&(requestAnimationFrame(D),requestAnimationFrame(E))}function E(){if(typeof mediumZoom!=`function`)return;let e=document.querySelectorAll(`.generated-image-container img:not([data-zoom-wired])`);if(e.length!==0){for(let t of e)t.setAttribute(`data-zoom-wired`,`true`);mediumZoom(e,{margin:16,background:`rgba(15, 15, 15, 0.92)`})}}function D(){let e=document.querySelectorAll(`.generated-image-container img:not([data-broken-wired])`);for(let t of e)t.setAttribute(`data-broken-wired`,`true`),t.addEventListener(`error`,function(){let e=t.closest(`.generated-image-container`);if(!e||e.dataset.brokenHandled)return;e.dataset.brokenHandled=`true`,e.hidden=!0;let n=document.createElement(`p`);n.className=`text-muted small fst-italic mb-2`,n.textContent=t.alt?`(the picture "${t.alt}" could not be loaded)`:`(that picture could not be loaded)`,e.insertAdjacentElement(`afterend`,n)},{once:!0})}function O(e){if(T(),!e||!e._pendingCharts||!e._pendingCharts.length)return;let t=[...e._pendingCharts];e._pendingCharts=[],requestAnimationFrame(()=>{for(let e of t){let t=document.getElementById(e.chartId);if(t){if(typeof Chart>`u`)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>).`);else if(t.offsetParent===null)window.__chartConfigs[e.chartId]=e.config;else try{t._chartInstance&&t._chartInstance.destroy();let n=typeof e.config==`string`?JSON.parse(e.config):e.config;n.options??={},n.options.responsive=!0,n.options.maintainAspectRatio=!0,n.options.aspectRatio??=4/3,t._chartInstance=new Chart(t,n)}catch(e){console.error(`Error creating chart:`,e)}}}})}function k(e){return e.replace(/<table>/g,`<div class="table-responsive"><table class="table table-sm table-bordered table-striped align-middle">`).replace(/<\/table>/g,`</table></div>`)}function A(e,t){S=[];let n=k(marked.parse(e,{renderer:b}));t._pendingCharts=S.length>0?[...S]:[];let r=DOMPurify.sanitize(n,{ADD_TAGS:[`canvas`],ADD_ATTR:[`target`]});return window.CoreAIChatImageCarousel?window.CoreAIChatImageCarousel.stackAdjacentImages(r):r}function j(e){return!e||typeof e!=`object`?{}:Object.fromEntries(Object.entries(e).filter(([,e])=>e!==void 0))}function M(e,r,i){if(!e)return e;let a=n(r||`Assistant`),o=t(i),s=o?`<span class="ai-streaming-avatar"><img class="ai-chat-assistant-avatar" src="`+N(o)+`" alt="" /></span>`:`<span class="ai-streaming-icon"><i class="fa fa-robot" style="display: inline-block;"></i></span>`;return e.replace(/\{\{\s*assistantLabel\s*\}\}/g,a).replace(/\{\{\s*assistantIcon\s*\}\}/g,s)}function N(e){return n(e).replace(/"/g,`"`).replace(/'/g,`'`)}let P=n=>{let r=Object.assign({},e,j(n));if(r.indicatorTemplate=M(r.indicatorTemplate,r.assistantLabel,r.assistantAvatarUrl),e=r,!r.signalRHubUrl)console.error(`The signalRHubUrl is required.`);else if(!r.appElementSelector)console.error(`The appElementSelector is required.`);else if(!r.chatContainerElementSelector)console.error(`The chatContainerElementSelector is required.`);else if(!r.inputElementSelector)console.error(`The inputElementSelector is required.`);else if(!r.sendButtonElementSelector)console.error(`The sendButtonElementSelector is required.`);else return Vue.createApp({data(){return{inputElement:null,buttonElement:null,chatContainer:null,placeholder:null,isInteractionStarted:!1,isPlaceholderVisible:!0,isStreaming:!1,isNavigatingAway:!1,autoScroll:!0,stream:null,messages:[],prompt:``,initialFieldValues:new Map,settingsDirty:!1,saveSettingsTimeout:null,saveIndicatorTimeout:null,isRecording:!1,mediaRecorder:null,preRecordingPrompt:``,micButton:null,speechToTextEnabled:r.chatMode===`AudioInput`||r.chatMode===`Conversation`,textToSpeechEnabled:r.chatMode===`Conversation`||!!r.textToSpeechEnabled,ttsVoiceName:r.ttsVoiceName||null,audioChunks:[],audioPlayQueue:[],isPlayingAudio:!1,currentAudioElement:null,currentAudioUrl:null,ttsPlayingMessageIndex:-1,ttsAudioCache:{},ttsInstanceId:`chat-interaction-`+Math.random().toString(36).slice(2),conversationModeEnabled:r.chatMode===`Conversation`,conversationButton:null,isConversationMode:!1,realtimeController:null,realtimeButton:null,realtimeEnabled:r.realtimeEnabled===!0,notifications:[],notificationDismissTimers:{},copyTitle:r.copyTitle,copiedTitle:r.copiedTitle,assistantAvatarUrl:t(r.assistantAvatarUrl)||null,copiedMessageIndex:-1,copyResetTimeoutId:null,activeCopyButton:null}},computed:{lastAssistantIndex(){for(var e=this.messages.length-1;e>=0;e--)if(this.messages[e].role===`assistant`)return e;return-1}},methods:{handleBeforeUnload(){this.isNavigatingAway=!0},async startConnection(){this.connection=new signalR.HubConnectionBuilder().withUrl(r.signalRHubUrl).withAutomaticReconnect().build(),this.connection.serverTimeoutInMilliseconds=6e5,this.connection.keepAliveIntervalInMilliseconds=15e3,this.connection.on(`LoadInteraction`,e=>{this.initializeInteraction(e.itemId,!0),this.messages=[];let t=document.querySelector(`[data-chat-interaction-title], .setting-input[data-setting="title"], input[name="ChatInteraction.Title"], input[name="Title"]`);t&&e.title&&(t.value=e.title),(e.messages??[]).forEach(e=>{this.addMessage(e),this.$nextTick(()=>{O(e)})})}),this.connection.on(`SettingsSaved`,(e,t)=>{let n=document.querySelector(`.chat-interaction-history-item[data-interaction-id="${e}"]`);n&&(n.textContent=t||r.untitledText);let i=document.querySelector(`[data-chat-interaction-title], .setting-input[data-setting="title"], input[name="ChatInteraction.Title"], input[name="Title"]`);i&&t&&(i.value=t),this.showSaveIndicator(`Saved`,`text-success`)}),this.connection.on(`ReceiveError`,e=>{console.error(`SignalR Error: `,e),this.showSaveIndicator(`Save failed`,`text-danger`),this.isRecording&&this.stopRecording()}),this.connection.on(`ReceiveTranscript`,(e,t,n)=>{if(this.isConversationMode){if(!n&&t){this._conversationPartialTranscript=t;var r=`<p class="ai-partial-transcript">`+t.replace(/&/g,`&`).replace(/</g,`<`).replace(/>/g,`>`)+`</p>`;this._conversationPartialMessage?(this._conversationPartialMessage.content=t,this._conversationPartialMessage.htmlContent=r):(this.hidePlaceholder(),this._conversationPartialMessage={role:`user`,content:t,htmlContent:r,isPartial:!0},this.messages.push(this._conversationPartialMessage)),this.scrollToBottom()}}else t&&!this._audioInputSent&&(this.prompt=this.preRecordingPrompt+t,this.inputElement&&(this.inputElement.value=this.prompt,this.inputElement.dispatchEvent(new Event(`input`))))}),this.connection.on(`ReceiveConversationUserMessage`,(e,t,n)=>{if(t&&this._realtimePendingTurns&&this._realtimePendingTurns[t]){var r=this._realtimePendingTurns[t];if(delete this._realtimePendingTurns[t],this.stopAudio(),n)r.content=n,r.rawContent=n,r.isPartial=!1,y(r,r.references);else{var i=this.messages.indexOf(r);i>=0&&this.messages.splice(i,1)}}else if(n){if(this.stopAudio(),this._conversationPartialMessage){var a=n.replace(/&/g,`&`).replace(/</g,`<`).replace(/>/g,`>`);this._conversationPartialMessage.content=n,this._conversationPartialMessage.htmlContent=`<p>`+a+`</p>`,this._conversationPartialMessage.isPartial=!1,this._conversationPartialMessage=null}else if(this._conversationAssistantMessage){var o=this._conversationAssistantMessage.index,s={role:`user`,content:n,rawContent:n,references:{}};y(s,s.references),this.messages.splice(o,0,s),this._conversationAssistantMessage.index=o+1}else this.addMessage({role:`user`,content:n});this.scrollToBottom()}}),this.connection.on(`ReceiveConversationAssistantToken`,(e,t,n,r,i,a)=>{if(this._conversationAssistantMessage&&this._conversationAssistantResponseId&&r&&this._conversationAssistantResponseId!==r){var o=this.messages[this._conversationAssistantMessage.index];o&&(o.isStreaming=!1),this._conversationAssistantMessage=null}if(!this._conversationAssistantMessage){this.stopAudio(),this.hideTypingIndicator();for(var s=0;s<this.messages.length;s++)this.messages[s].isStreaming&&(this.messages[s].isStreaming=!1);var l=this.messages.length,u={id:t,role:`assistant`,content:``,htmlContent:``,isStreaming:!0,appearance:this.normalizeAssistantAppearance(a),references:{}};this.messages.push(u),this._conversationAssistantMessage={index:l,content:``},this._conversationAssistantResponseId=r}this._conversationAssistantMessage.content+=n;var d=this.messages[this._conversationAssistantMessage.index];d&&(d.appearance||=this.normalizeAssistantAppearance(a),d.rawContent=this._conversationAssistantMessage.content,d.references=c(Object.assign({},d.references||{},i||{})),y(d,d.references),this.$nextTick(()=>{O(d),this.scrollToBottom()}))}),this.connection.on(`ReceiveConversationAssistantComplete`,(e,t,n)=>{if(this._conversationAssistantMessage){var r=this.messages[this._conversationAssistantMessage.index];r&&(r.isStreaming=!1,r.references=c(Object.assign({},r.references||{},n||{})),y(r,r.references)),this._conversationAssistantMessage=null,this._conversationAssistantResponseId=null}}),this.connection.on(`ReceiveAudioChunk`,(e,t,n)=>{if(t){let e=atob(t),r=new Uint8Array(e.length);for(let t=0;t<e.length;t++)r[t]=e.charCodeAt(t);n===`audio/pcm`&&this.realtimeController?this.realtimeController.receivePcm(r):this.audioChunks.push(r)}}),this.connection.on(`ReceiveAudioComplete`,()=>{this.playCollectedAudio()}),this.connection.on(`HistoryCleared`,()=>{this.messages=[],this.showPlaceholder();let e=document.getElementById(`clearHistoryBtn`);e&&e.classList.add(`d-none`)}),this.connection.on(`ReceiveNotification`,e=>{this.receiveNotification(e)}),this.connection.on(`UpdateNotification`,e=>{this.updateNotification(e)}),this.connection.on(`RemoveNotification`,e=>{this.removeNotification(e)}),this.connection.onreconnecting(()=>{console.warn(`SignalR: reconnecting...`)}),this.connection.onreconnected(()=>{console.info(`SignalR: reconnected.`),this.reloadCurrentInteraction()}),this.connection.onclose(e=>{this.isNavigatingAway||e&&console.warn(`SignalR connection closed with error:`,e.message||e)});try{await this.connection.start()}catch(e){console.error(`SignalR Connection Error: `,e)}},addMessageInternal(e){e.role===`assistant`&&(e.appearance=this.normalizeAssistantAppearance(e.appearance)),e.content&&!e.htmlContent&&(e.htmlContent=A(e.content,e)),this.fireEvent(new CustomEvent(`addingChatInteractionMessage`,{detail:{message:e}})),this.messages.push(e),this.$nextTick(()=>{this.fireEvent(new CustomEvent(`addedChatInteractionMessage`,{detail:{message:e}}))})},addMessage(e){e.content&&(e.rawContent=e.rawContent??e.content,y(e,e.references)),this.addMessageInternal(e),this.hidePlaceholder(),this.$nextTick(()=>{O(e),this.scrollToBottom()})},hidePlaceholder(){this.placeholder&&this.placeholder.classList.add(`d-none`),this.isPlaceholderVisible=!1},showPlaceholder(){this.placeholder&&this.placeholder.classList.remove(`d-none`),this.isPlaceholderVisible=!0},fireEvent(e){document.dispatchEvent(e)},normalizeAssistantAppearance(e){if(!e)return null;var t=typeof e.label==`string`?e.label.trim():``,n=typeof e.icon==`string`?e.icon.trim():``,r=typeof e.cssClass==`string`?e.cssClass.trim():``,i=!!e.disableStreamingAnimation;return!t&&!n&&!r&&!i?null:{label:t,icon:n,cssClass:r,disableStreamingAnimation:i}},getAssistantLabel(t){var n=t?this.normalizeAssistantAppearance(t.appearance):null;return n&&n.label?n.label:e.assistantLabel},getAssistantRoleClasses(e){var t=e?this.normalizeAssistantAppearance(e.appearance):null,n=[`ai-chat-msg-role`];return t&&t.cssClass?n.push(t.cssClass):n.push(`ai-chat-msg-role-assistant`),n},getAssistantIconClasses(e,t){var n=e?this.normalizeAssistantAppearance(e.appearance):null;return this.getAssistantAvatarUrl(e)?[this.shouldAnimateAssistantIcon(e,t)?`ai-streaming-avatar`:`ai-bot-avatar`]:[this.shouldAnimateAssistantIcon(e,t)?`ai-streaming-icon`:`ai-bot-icon`,n&&n.cssClass?n.cssClass:``]},getAssistantAvatarUrl(e){return!this.assistantAvatarUrl||e&&this.normalizeAssistantAppearance(e.appearance)?null:this.assistantAvatarUrl},getAssistantIcon(e){var t=e?this.normalizeAssistantAppearance(e.appearance):null;return t&&t.icon?t.icon:`fa fa-robot`},shouldAnimateAssistantIcon(e,t){var n=e?this.normalizeAssistantAppearance(e.appearance):null;return!!e&&e.isStreaming&&t===this.lastAssistantIndex&&!(n&&n.disableStreamingAnimation)},isIndicator(e){return e.role===`indicator`},async sendMessage(){let e=this.prompt.trim();if(!e)return;this.endActiveVoiceSession(),this.isRecording&&this.stopRecording(),this._audioInputSent=!0,await this.flushPendingSave(),this.addMessage({role:`user`,content:e});let t=document.getElementById(`clearHistoryBtn`);t&&t.classList.remove(`d-none`),this.streamMessage(e),this.inputElement.value=``,this.prompt=``},streamMessage(e){this.stream&&=(this.stream.dispose(),null),this.streamingStarted(),this.showTypingIndicator(),this.autoScroll=!0;var t=``,n={},r=null,i=this.messages.length,a=this.getItemId();this.stream=this.connection.stream(`SendMessage`,a,e).subscribe({next:e=>{let s=this.messages[i];if(!s){e.sessionId&&!a&&this.setItemId(e.sessionId),this.hideTypingIndicator(),i=this.messages.length;let t={role:`assistant`,content:``,htmlContent:``,isStreaming:!0};this.messages.push(t),s=t}if(e.references&&typeof e.references==`object`&&Object.keys(e.references).length)for(let[t,r]of Object.entries(e.references))n[t]=o(r)??{};e.content&&(e.responseId&&r&&e.responseId!==r&&(t+=`
|
|
61
61
|
|
|
62
|
-
`),e.responseId&&(r=e.responseId),t+=e.content),s.rawContent=t,y(s,n),this.messages[i]=s,this.$nextTick(()=>{O(s),this.scrollToBottom()})},complete:()=>{this.processReferences(n,i),this.streamingFinished();let e=this.messages[i];e&&(e.isStreaming=!1),(!e||!e.content)&&this.hideTypingIndicator(),this.isConversationMode&&this.textToSpeechEnabled&&e&&e.content&&this.synthesizeSpeech(e.content),this.stream?.dispose(),this.stream=null},error:e=>{this.processReferences(n,i),this.streamingFinished();let t=this.messages[i];t&&(t.isStreaming=!1),this.hideTypingIndicator(),this.isNavigatingAway||this.addMessage(this.getServiceDownMessage()),this.stream?.dispose(),this.stream=null,console.error(`Stream error:`,e)}})},getServiceDownMessage(){return{role:`assistant`,content:`Our service is currently unavailable. Please try again later. We apologize for the inconvenience.`,htmlContent:``}},processReferences(e,t){if(e=c(e),Object.keys(e).length){let n=this.messages[t];n.rawContent=n.rawContent??n.content??``,y(n,e),this.messages[t]=n,this.$nextTick(()=>{O(n),this.scrollToBottom()})}},streamingStarted(){var e=this.buttonElement.getAttribute(`data-stop-icon`);e&&this.buttonElement.replaceChildren(DOMPurify.sanitize(e,{RETURN_DOM_FRAGMENT:!0}))},streamingFinished(){var e=this.buttonElement.getAttribute(`data-start-icon`);if(e&&this.buttonElement.replaceChildren(DOMPurify.sanitize(e,{RETURN_DOM_FRAGMENT:!0})),this.chatContainer)for(var t=this.chatContainer.querySelectorAll(`.ai-streaming-icon`),n=0;n<t.length;n++)t[n].classList.remove(`ai-streaming-icon`),t[n].classList.add(`ai-bot-icon`);for(var n=0;n<this.messages.length;n++)this.messages[n].isStreaming&&(this.messages[n].isStreaming=!1);this.settingsDirty&&this.debouncedSaveSettings()},handleExternalTtsStop(e){e?.detail?.sourceId!==this.ttsInstanceId&&this.stopAudio(!1)},updateTtsPlaybackButtons(){this.chatContainer&&this.chatContainer.querySelectorAll(`[data-tts-message-index]`).forEach(e=>{var t=Number(e.getAttribute(`data-tts-message-index`))===this.ttsPlayingMessageIndex,n=t?`<i class="fa-solid fa-circle-pause"></i>`:`<i class="fa-solid fa-circle-play"></i>`;e.classList.toggle(`tts-playing`,t),e.setAttribute(`title`,t?`Pause audio`:`Read aloud`),e.replaceChildren(DOMPurify.sanitize(n,{RETURN_DOM_FRAGMENT:!0}))})},updateCopyButtons(){this.chatContainer&&this.chatContainer.querySelectorAll(`[data-copy-message-index]`).forEach(e=>{var t=Number(e.getAttribute(`data-copy-message-index`))===this.copiedMessageIndex,n=t?`<i class="fa-solid fa-check"></i>`:`<i class="fa-solid fa-copy"></i>`;e.classList.toggle(`text-success`,t),e.classList.toggle(`text-secondary`,!t),e.setAttribute(`title`,t?this.copiedTitle:this.copyTitle),e.replaceChildren(DOMPurify.sanitize(n,{RETURN_DOM_FRAGMENT:!0}))})},setCopyButtonState(e,t){if(e){var n=t?`<i class="fa-solid fa-check"></i>`:`<i class="fa-solid fa-copy"></i>`;e.classList.toggle(`text-success`,t),e.classList.toggle(`text-secondary`,!t),e.setAttribute(`title`,t?this.copiedTitle:this.copyTitle),e.replaceChildren(DOMPurify.sanitize(n,{RETURN_DOM_FRAGMENT:!0}))}},synthesizeSpeech(e,t){this.textToSpeechEnabled&&e&&this.connection&&(this.audioChunks=[],this.isPlayingAudio=!0,this._ttsCacheIndex=t===void 0?-1:t,this.connection.invoke(`SynthesizeSpeech`,this.getItemId(),e,this.ttsVoiceName).catch(e=>{console.error(`TTS synthesis error:`,e),this.isPlayingAudio=!1,this.ttsPlayingMessageIndex=-1,this._ttsCacheIndex=-1,this.$nextTick(()=>this.updateTtsPlaybackButtons())}))},toggleMessageTts(e,t){this.ttsPlayingMessageIndex===t?this.stopAudio():(this.stopAudio(!1),window.dispatchEvent(new CustomEvent(`crestapps-ai-chat-stop-tts`,{detail:{sourceId:this.ttsInstanceId}})),this.ttsPlayingMessageIndex=t,this.$nextTick(()=>this.updateTtsPlaybackButtons()),this.ttsAudioCache[t]?this.playAudioBlob(this.ttsAudioCache[t]):this.synthesizeSpeech(e.content,t))},playCollectedAudio(){if(this.audioChunks.length===0){!this.isPlayingAudio&&this.audioPlayQueue.length===0&&(this.isPlayingAudio=!1,this.ttsPlayingMessageIndex=-1,this.$nextTick(()=>this.updateTtsPlaybackButtons()));return}let e=this.audioChunks.reduce((e,t)=>e+t.length,0),t=new Uint8Array(e),n=0;for(let e of this.audioChunks)t.set(e,n),n+=e.length;this.audioChunks=[];let r=new Blob([t],{type:`audio/mp3`});this._ttsCacheIndex>=0&&(this.ttsAudioCache[this._ttsCacheIndex]=r,this._ttsCacheIndex=-1),this.isPlayingAudio&&this.currentAudioElement?this.audioPlayQueue.push(r):this.playAudioBlob(r)},playAudioBlob(e){let t=URL.createObjectURL(e),n=new Audio(t);this.currentAudioUrl=t,this.currentAudioElement=n,this.isPlayingAudio=!0,n.addEventListener(`ended`,()=>{this.currentAudioElement=null,this.currentAudioUrl=null,URL.revokeObjectURL(t),this.playNextInQueue()}),n.addEventListener(`error`,()=>{this.currentAudioElement=null,this.currentAudioUrl=null,URL.revokeObjectURL(t),this.playNextInQueue()}),n.play().catch(e=>{console.error(`Audio playback error:`,e),this.currentAudioElement=null,this.currentAudioUrl=null,URL.revokeObjectURL(t),this.audioPlayQueue=[],this.isPlayingAudio=!1,this.ttsPlayingMessageIndex=-1,this.$nextTick(()=>this.updateTtsPlaybackButtons())})},playNextInQueue(){if(this.audioPlayQueue.length>0){let e=this.audioPlayQueue.shift();this.playAudioBlob(e)}else this.isPlayingAudio=!1,this.ttsPlayingMessageIndex=-1,this.$nextTick(()=>this.updateTtsPlaybackButtons()),this.conversationModeOnAudioEnded()},stopAudio(){this.currentAudioElement&&=(this.currentAudioElement.pause(),this.currentAudioElement.currentTime=0,null),this.currentAudioUrl&&=(URL.revokeObjectURL(this.currentAudioUrl),null),this.audioChunks=[],this.audioPlayQueue=[],this.isPlayingAudio=!1,this.ttsPlayingMessageIndex=-1,this.$nextTick(()=>this.updateTtsPlaybackButtons())},setVoiceSessionLive(e){this.inputElement&&(this.inputElement.hidden=e),this.buttonElement&&(this.buttonElement.hidden=e),[this.realtimeButton,this.conversationButton].forEach(function(t){t&&t.classList.toggle(`flex-grow-1`,e)});var t=this.realtimeButton&&this.realtimeButton.nextElementSibling,n=t&&t.id===`realtime-audio-settings`?t:null;n&&(n.hidden=!e)},toggleConversationMode(){this.isConversationMode?this.stopConversationMode():this.startConversationMode()},endActiveVoiceSession(){this.realtimeController&&this.realtimeController.isActive()?this.realtimeController.stop():this.isConversationMode&&this.stopConversationMode()},startConversationMode(){this.conversationModeEnabled&&!this.isConversationMode&&this.connection&&(this.isConversationMode=!0,this.updateConversationButton(),this._conversationPartialTranscript=``,this._conversationAssistantMessage=null,this._conversationPartialMessage=null,this.removeNotification(`conversation-ended`),navigator.mediaDevices.getUserMedia({audio:{echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0}}).then(e=>{var t=MediaRecorder.isTypeSupported(`audio/ogg;codecs=opus`)?`audio/ogg;codecs=opus`:MediaRecorder.isTypeSupported(`audio/webm;codecs=opus`)?`audio/webm;codecs=opus`:`audio/webm`;this.mediaRecorder=new MediaRecorder(e,{mimeType:t,audioBitsPerSecond:128e3}),this._conversationSubject=new signalR.Subject,this._conversationStream=e;var n=window.AudioContext||window.webkitAudioContext;n&&(this._conversationAudioCtx=new n,this._conversationAnalyser=this._conversationAudioCtx.createAnalyser(),this._conversationAnalyser.fftSize=256,this._conversationAudioCtx.createMediaStreamSource(e).connect(this._conversationAnalyser));var r=Promise.resolve(),i=this._conversationAnalyser,a=30;this.mediaRecorder.addEventListener(`dataavailable`,e=>{if(e.data&&e.data.size>0){if(this.isPlayingAudio&&i){var t=new Uint8Array(i.frequencyBinCount);i.getByteFrequencyData(t);for(var n=0,o=0;o<t.length;o++)n+=t[o];n/t.length>=a&&this.stopAudio()}r=r.then(async()=>{var t=await e.data.arrayBuffer(),n=new Uint8Array(t).reduce(function(e,t){return e+String.fromCharCode(t)},``),r=btoa(n);try{this._conversationSubject.next(r)}catch{}})}}),this.mediaRecorder.addEventListener(`stop`,()=>{e.getTracks().forEach(e=>e.stop()),r.then(()=>{try{this._conversationSubject.complete()}catch{}})});var o=this.getItemId(),s=navigator.language||document.documentElement.lang||`en-US`;this.connection.send(`StartConversation`,o,this._conversationSubject,t,s),this.mediaRecorder.start(250),this.isRecording=!0}).catch(e=>{console.error(`Microphone access denied:`,e),this.isConversationMode=!1,this.updateConversationButton()}))},stopConversationMode(){if(this.isConversationMode){if(this.isConversationMode=!1,this.updateConversationButton(),this.connection&&this.connection.invoke(`StopConversation`).catch(function(){}),this.isRecording&&this.mediaRecorder&&(this.mediaRecorder.stop(),this.isRecording=!1),this.stopAudio(),this._conversationPartialTranscript=``,this._conversationPartialMessage=null,this._conversationAudioCtx&&(this._conversationAudioCtx.close().catch(function(){}),this._conversationAudioCtx=null,this._conversationAnalyser=null),this._conversationAssistantMessage){var e=this.messages[this._conversationAssistantMessage.index];e&&(e.isStreaming=!1),this._conversationAssistantMessage=null}for(var t=0;t<this.messages.length;t++)this.messages[t].isStreaming&&(this.messages[t].isStreaming=!1);this.receiveNotification({type:`conversation-ended`,content:`Conversation ended.`,icon:`fa-solid fa-circle-check`,dismissible:!0,autoDismissMs:5e3})}},updateConversationButton(){if(this.conversationButton){if(this.isConversationMode){this.conversationButton.classList.add(`active`,`btn-primary`),this.conversationButton.classList.remove(`btn-dark`,`btn-outline-dark`,`btn-outline-secondary`),this.conversationButton.title=this.conversationButton.getAttribute(`data-end-title`)||`End Conversation`;var e=this.conversationButton.getAttribute(`data-end-html`);e&&this.conversationButton.replaceChildren(DOMPurify.sanitize(e,{RETURN_DOM_FRAGMENT:!0}))}else{this.conversationButton.classList.remove(`active`,`btn-primary`),this.conversationButton.classList.remove(`btn-dark`,`btn-outline-secondary`),this.conversationButton.classList.add(`btn-outline-dark`),this.conversationButton.blur(),this.conversationButton.title=this.conversationButton.getAttribute(`data-start-title`)||`Start Conversation`;var t=this.conversationButton.getAttribute(`data-start-html`);t&&this.conversationButton.replaceChildren(DOMPurify.sanitize(t,{RETURN_DOM_FRAGMENT:!0}))}}},conversationModeSendPrompt(){},conversationModeOnAudioEnded(){},showTypingIndicator(){this.addMessage({role:`indicator`,htmlContent:n.indicatorTemplate})},hideTypingIndicator(){let e=this.messages.length;return this.messages=this.messages.filter(e=>e.role!==`indicator`),e-this.messages.length},scrollToBottom(){this.autoScroll&&setTimeout(()=>{this.chatContainer.scrollTop=this.chatContainer.scrollHeight-this.chatContainer.clientHeight},50)},handleUserInput(e){this.prompt=e.target.value},getItemId(){return this.inputElement.getAttribute(`data-interaction-id`)||this.inputElement.getAttribute(`data-item-id`)},getSaveIndicatorElement(){return n.saveIndicatorElementSelector?document.querySelector(n.saveIndicatorElementSelector):document.querySelector(`[data-chat-interaction-save-indicator]`)},showSaveIndicator(e,t){let n=this.getSaveIndicatorElement();n&&(n.textContent=e||``,n.className=`settings-save-indicator `+(t||`text-muted`),this.saveIndicatorTimeout&&=(clearTimeout(this.saveIndicatorTimeout),null),e&&(this.saveIndicatorTimeout=setTimeout(()=>{n.textContent=``,this.saveIndicatorTimeout=null},3e3)))},clearPendingSettingsSave(){this.saveSettingsTimeout&&=(clearTimeout(this.saveSettingsTimeout),null)},getFieldLabel(e){let t=e.closest(`.mb-3, .col-6, .col, .form-group, .form-floating`)?.querySelector(`label`);return t?(t.textContent||``).replace(/\s+/g,` `).trim()||e.dataset.setting||`This field`:e.dataset.setting||`This field`},getValidationFeedbackElement(e){let t=e.nextElementSibling;return t&&t.classList.contains(`invalid-feedback`)||(t=document.createElement(`div`),t.className=`invalid-feedback`,e.insertAdjacentElement(`afterend`,t)),t},clearSettingValidationError(e){e.classList.remove(`is-invalid`),e.removeAttribute(`aria-invalid`);let t=e.nextElementSibling;t&&t.classList.contains(`invalid-feedback`)&&(t.textContent=``)},setSettingValidationError(e,t){let n=this.getValidationFeedbackElement(e);e.classList.add(`is-invalid`),e.setAttribute(`aria-invalid`,`true`),n.textContent=t},getSettingValidationMessage(e){if(!e||e.disabled||e.type!==`number`)return null;let t=(e.value||``).trim();if(!t)return null;let n=Number(t),r=this.getFieldLabel(e);if(Number.isNaN(n))return`${r} must be a valid number.`;let i=e.getAttribute(`min`);if(i!==null&&n<Number(i))return`${r} must be ${i} or greater.`;let a=e.getAttribute(`max`);return a!==null&&n>Number(a)?`${r} must be ${a} or less.`:null},validateSettingInput(e){let t=this.getSettingValidationMessage(e);return t?(this.setSettingValidationError(e,t),!1):(this.clearSettingValidationError(e),!0)},validateSettings(){let e=!0;return this.getSettingInputs().forEach(t=>{e=this.validateSettingInput(t)&&e}),e},queueSettingsSave(){this.validateSettings()?(this.settingsDirty=!0,this.showSaveIndicator(`Saving...`,`text-warning`),this.debouncedSaveSettings()):(this.clearPendingSettingsSave(),this.settingsDirty=!1,this.showSaveIndicator(`Fix errors`,`text-danger`))},getSettingInputs(){let e=document.querySelectorAll(`.setting-input[data-setting]`);return e.length>0?e:document.querySelectorAll(`input[name^="ChatInteraction."]:not([name*=".Tools["]):not([name*=".Connections["]), select[name^="ChatInteraction."]:not([name*=".Tools["]):not([name*=".Connections["]), textarea[name^="ChatInteraction."]:not([name*=".Tools["]):not([name*=".Connections["])`)},getSelectedGroupValues(e,t){let n=document.querySelectorAll(`.capability-checkbox[data-save-group="${e}"]:checked, .capability-checkbox[data-group="${e}"]:checked`);if(n.length>0){let e=[];return n.forEach(t=>{let n=t.getAttribute(`data-item-id`)||t.value;n&&e.push(n)}),e}if(!t)return[];let r=[];return document.querySelectorAll(t).forEach(e=>{let t=e.name.replace(`.IsSelected`,`.ItemId`),n=document.querySelector(`input[type="hidden"][name="${t}"]`);n&&n.value&&r.push(n.value)}),r},getPromptTemplateSelections(){let e=[];return document.querySelectorAll(`.prompt-template-card`).forEach(t=>{let n=t.querySelector(`.prompt-template-id-input`),r=t.querySelector(`.prompt-template-parameters-input`),i=n?n.value:t.getAttribute(`data-template-id`);i&&e.push({templateId:i,promptParameters:r?(r.value||``).trim():``})}),e},receiveNotification(e){if(e&&e.type){this.clearNotificationDismiss(e.type);var t=this.notifications.findIndex(t=>t.type===e.type);t>=0?this.notifications.splice(t,1,e):this.notifications.push(e),this.scheduleNotificationDismiss(e),this.scrollToBottom()}},updateNotification(e){if(e&&e.type){this.clearNotificationDismiss(e.type);var t=this.notifications.findIndex(t=>t.type===e.type);t>=0&&(this.notifications.splice(t,1,e),this.scheduleNotificationDismiss(e),this.scrollToBottom())}},scheduleNotificationDismiss(e){!e||!e.type||!e.autoDismissMs||e.autoDismissMs<=0||(this.notificationDismissTimers[e.type]=setTimeout(()=>{this.removeNotification(e.type)},e.autoDismissMs))},clearNotificationDismiss(e){var t=this.notificationDismissTimers[e];t&&(clearTimeout(t),delete this.notificationDismissTimers[e])},removeNotification(e){this.clearNotificationDismiss(e),this.notifications=this.notifications.filter(t=>t.type!==e)},dismissNotification(e){this.removeNotification(e)},handleNotificationAction(e,t){if(this.connection){var n=this.getItemId();this.connection.invoke(`HandleNotificationAction`,n,e,t).catch(e=>console.error(`Failed to handle notification action:`,e))}},setItemId(e){this.inputElement.setAttribute(`data-interaction-id`,e||``),this.inputElement.setAttribute(`data-item-id`,e||``)},resetInteraction(){this.setItemId(``),this.isInteractionStarted=!1,this.messages=[],this.showPlaceholder()},initializeApp(){this.inputElement=document.querySelector(n.inputElementSelector),this.buttonElement=document.querySelector(n.sendButtonElementSelector),this.chatContainer=document.querySelector(n.chatContainerElementSelector),this.placeholder=document.querySelector(n.placeholderElementSelector);let e=this.getItemId();e&&this.loadInteraction(e),this.chatContainer.addEventListener(`scroll`,()=>{if(!this.stream)return;let e=this.chatContainer.scrollHeight-this.chatContainer.clientHeight-this.chatContainer.scrollTop<=30;this.autoScroll=e}),this.inputElement.addEventListener(`keyup`,e=>{this.stream==null&&e.key===`Enter`&&!e.shiftKey&&this.buttonElement.click()}),this.inputElement.addEventListener(`input`,e=>{this.handleUserInput(e),e.target.value.trim()?this.buttonElement.removeAttribute(`disabled`):this.buttonElement.setAttribute(`disabled`,!0)}),this.inputElement.addEventListener(`paste`,e=>{setTimeout(()=>{this.prompt=this.inputElement.value,this.inputElement.value.trim()?this.buttonElement.removeAttribute(`disabled`):this.buttonElement.setAttribute(`disabled`,!0)},0)}),this.buttonElement.addEventListener(`click`,()=>{if(this.stream!=null){if(this.stream.dispose(),this.stream=null,this.streamingFinished(),this.hideTypingIndicator(),this.messages.length>0){let e=this.messages[this.messages.length-1];e.role===`assistant`&&!e.content?this.messages.pop():e.isStreaming&&=!1}}else this.sendMessage()});let t=document.getElementsByClassName(`chat-interaction-history-item`);for(var r=0;r<t.length;r++)t[r].addEventListener(`click`,e=>{e.preventDefault();var t=e.target.getAttribute(`data-interaction-id`);t?this.loadInteraction(t):console.error(`An element with the class chat-interaction-history-item with no data-interaction-id set.`)});let i=Array.isArray(n.messages)?n.messages:[];for(let e=0;e<i.length;e++)this.addMessage(i[e]);this.chatContainer&&this.chatContainer.addEventListener(`click`,e=>{var t=e.target.closest(`.ai-code-copy-btn`);if(t){var r=t.closest(`.ai-code-block`)||t.closest(`pre`);if(r){var i=r.querySelector(`code`);i&&(navigator.clipboard.writeText(i.textContent),t.innerHTML=`<i class="fa-solid fa-check"></i> `+(n.codeCopiedText||`Copied!`),setTimeout(()=>{t.innerHTML=`<i class="fa-regular fa-copy"></i>`},2e3))}}}),document.addEventListener(`input`,e=>{e.target.matches(`.setting-input[data-setting]`)&&(this.validateSettingInput(e.target),this.queueSettingsSave())}),document.addEventListener(`change`,e=>{e.target.matches(`.setting-input[data-setting], .capability-checkbox[data-save-group], .capability-checkbox[data-group], .group-toggle, .ci-agent-global-toggle`)?(e.target.matches(`.setting-input[data-setting]`)&&this.validateSettingInput(e.target),this.queueSettingsSave()):e.target.closest(`.prompt-template-parameters-input, .prompt-template-id-input`)&&this.queueSettingsSave()}),document.addEventListener(`click`,e=>{e.target.closest(`.prompt-template-add-btn, .remove-prompt-template-btn`)&&setTimeout(()=>{this.queueSettingsSave()},0)});let a=document.getElementById(`clearHistoryBtn`);a&&a.addEventListener(`click`,()=>{let e=a.getAttribute(`data-interaction-id`);e&&this.clearHistory(e)}),this.speechToTextEnabled&&n.micButtonElementSelector&&(this.micButton=document.querySelector(n.micButtonElementSelector),this.micButton&&(this.micButton.style.display=``,this.micButton.addEventListener(`click`,()=>{this.toggleRecording()}))),this.conversationModeEnabled&&n.conversationButtonElementSelector&&(this.conversationButton=document.querySelector(n.conversationButtonElementSelector),this.conversationButton&&this.conversationButton.addEventListener(`click`,()=>{this.toggleConversationMode()})),window.CoreAIRealtime&&n.realtimeButtonElementSelector&&(this.realtimeButton=document.querySelector(n.realtimeButtonElementSelector),this.realtimeController=window.CoreAIRealtime.attach({connection:this.connection,ensureConnected:()=>Promise.resolve(this.connection),sendStart:(e,t,n,r,i,a)=>{this.connection.send(`StartRealtimeConversation`,this.getItemId(),e,t,n,r,i,a)},webRtcEnabled:n.realtimeWebRtcEnabled===!0,sendStartWebRtc:(e,t,n,r,i,a)=>{this.connection.send(`StartRealtimeWebRtc`,this.getItemId(),e,t,n,r,i,a)},webRtcIceServers:Array.isArray(n.realtimeWebRtcIceServers)?n.realtimeWebRtcIceServers:void 0,voiceName:n.realtimeVoiceName||``,getVoiceName:()=>{var e=n.realtimeVoiceSelectElementSelector?document.querySelector(n.realtimeVoiceSelectElementSelector):null;return e?e.value:``},capableDeployments:n.realtimeCapableDeployments||[],realtimeEnabled:n.realtimeEnabled===!0,selectors:{realtimeButton:n.realtimeButtonElementSelector,micButton:n.micButtonElementSelector,conversationButton:n.conversationButtonElementSelector},onSessionStateChanged:e=>{this.setVoiceSessionLive(e)},onActivate:()=>{this.isConversationMode=!0,this._conversationPartialMessage=null,this._conversationAssistantMessage=null},onDeactivate:()=>{if(this.isConversationMode=!1,this._conversationAssistantMessage){var e=this.messages[this._conversationAssistantMessage.index];e&&(e.isStreaming=!1),this._conversationAssistantMessage=null}},onEnterRealtimeMode:()=>{this.isRecording&&this.stopRecording(),this.isConversationMode&&(!this.realtimeController||!this.realtimeController.isActive())&&this.stopConversationMode()},onUserTurnPending:e=>{if(e){var t={role:`user`,content:``,rawContent:``,references:{},isPartial:!0};y(t,t.references),this._realtimePendingTurns=this._realtimePendingTurns||{},this._realtimePendingTurns[e]=t,this.messages.push(t),this.scrollToBottom()}},onUserTurnDropped:e=>{if(e&&this._realtimePendingTurns){var t=this._realtimePendingTurns[e];if(t){delete this._realtimePendingTurns[e];var n=this.messages.indexOf(t);n>=0&&this.messages.splice(n,1)}}}}),this.setupRealtimeVoicePicker(n),this.setVoiceSessionLive(!1))},setupRealtimeVoicePicker(e){if(!e.realtimeVoiceSelectElementSelector||!e.realtimeVoicesUrl)return;var t=document.querySelector(e.realtimeVoiceSelectElementSelector);if(!t)return;var n=e.realtimeVoiceGroupElementSelector?document.querySelector(e.realtimeVoiceGroupElementSelector):null,r=e.conversationDeploymentSelectElementSelector?document.querySelector(e.conversationDeploymentSelectElementSelector):null,i=(e.realtimeCapableDeployments||[]).map(function(e){return(e||``).toLowerCase()}),a=e.realtimeVoiceName||``,o=this;function s(e){return e&&i.indexOf(e.toLowerCase())!==-1}function c(){if(!o.conversationModeEnabled)return``;var t=r&&r.value||e.defaultRealtimeDeploymentName||(i.length?i[0]:``);return s(t)?t:``}async function l(){var r=c(),i=!!r;if(n&&n.classList.toggle(`d-none`,!i),o.realtimeController&&o.realtimeController.applyMode(i),i){t.innerHTML=`<option value="">Default voice</option>`;try{let n=await fetch(e.realtimeVoicesUrl+`?deploymentName=`+encodeURIComponent(r),{credentials:`same-origin`}),i=(n.headers.get(`content-type`)||``).toLowerCase();if(!n.ok||i.indexOf(`json`)<0)return;let o=await n.json();if(!o||!Array.isArray(o.voices))return;let s=new Map;for(let e of o.voices){let t=e.gender||`Voices`;s.has(t)||s.set(t,[]),s.get(t).push(e)}Array.from(s.keys()).sort((e,t)=>e.localeCompare(t)).forEach(function(e){let n=document.createElement(`optgroup`);n.label=e,s.get(e).forEach(function(e){let t=document.createElement(`option`);t.value=e.id,t.textContent=e.name,t.selected=e.id===a,n.appendChild(t)}),t.appendChild(n)})}catch{}}}r&&r.addEventListener(`change`,l),l()},loadInteraction(e){this.connection.invoke(`LoadInteraction`,e).catch(e=>console.error(e))},reloadCurrentInteraction(){let e=this.getItemId();e&&this.loadInteraction(e)},clearHistory(e){let t=this,r=()=>{t.realtimeController&&t.realtimeController.isActive()&&t.realtimeController.stop(),t.stream&&(t.stream.dispose(),t.stream=null,t.hideTypingIndicator(),t.streamingFinished()),t.connection.invoke(`ClearHistory`,e).catch(e=>console.error(`Error clearing history:`,e))};typeof confirmDialog==`function`?confirmDialog({title:n.clearHistoryTitle,message:n.clearHistoryMessage,okText:n.clearHistoryOkText,cancelText:n.clearHistoryCancelText,callback:function(e){e&&r()}}):window.confirm(n.clearHistoryMessage||`Clear all messages?`)&&r()},debouncedSaveSettings(){this.clearPendingSettingsSave(),!this.stream&&(this.saveSettingsTimeout=setTimeout(()=>{this.settingsDirty&&=(this.saveSettings(),!1),this.saveSettingsTimeout=null},850))},getSelectedToolNames(){return this.getSelectedGroupValues(`toolNames`,`input[type="checkbox"][name$="].IsSelected"][name^="ChatInteraction.Tools["]:checked`)},getSelectedMcpConnectionIds(){return this.getSelectedGroupValues(`mcpConnectionIds`,`input[type="checkbox"][name$="].IsSelected"][name^="ChatInteraction.Connections["]:checked`)},getSelectedA2AConnectionIds(){return this.getSelectedGroupValues(`a2aConnectionIds`)},getSelectedAgentNames(){return this.getSelectedGroupValues(`agentNames`,`input[type="checkbox"][name$="].IsSelected"][name^="ChatInteraction.Agents["]:checked`)},saveSettings(){let e=this.getItemId();if(!e)return Promise.resolve();if(!this.validateSettings())return this.showSaveIndicator(`Fix errors`,`text-danger`),Promise.resolve();let t={};this.getSettingInputs().forEach(e=>{let n=e.dataset.setting||(e.name||``).replace(`ChatInteraction.`,``).replace(/^[A-Z]/,e=>e.toLowerCase());n&&(e.type===`checkbox`?t[n]=e.checked:e.type===`number`?t[n]=e.value?parseFloat(e.value):null:t[n]=e.value||null)}),t.toolNames=this.getSelectedToolNames(),t.mcpConnectionIds=this.getSelectedMcpConnectionIds(),t.a2aConnectionIds=this.getSelectedA2AConnectionIds(),t.agentNames=this.getSelectedAgentNames();let n=this.getPromptTemplateSelections();return n.length>0&&(t.promptTemplates=n,t.promptTemplateIds=n.map(e=>e.templateId)),this.connection.invoke(`SaveSettings`,e,t).catch(e=>{console.error(`Error saving settings:`,e),this.showSaveIndicator(`Save failed`,`text-danger`)})},flushPendingSave(){return this.saveSettingsTimeout&&=(clearTimeout(this.saveSettingsTimeout),null),this.settingsDirty?(this.settingsDirty=!1,this.saveSettings()):Promise.resolve()},initializeInteraction(e,t){(!this.isInteractionStarted||t)&&(this.fireEvent(new CustomEvent(`initializingChatInteraction`,{detail:{itemId:e}})),this.setItemId(e),this.isInteractionStarted=!0)},clearCopiedMessageState(){this.copyResetTimeoutId&&=(window.clearTimeout(this.copyResetTimeoutId),null),this.activeCopyButton&&=(this.setCopyButtonState(this.activeCopyButton,!1),null),this.copiedMessageIndex=-1},copyResponse(e,t,r){let i=e&&typeof e==`object`?e.copyContent??e.content??``:e??``,a=r?.currentTarget||r?.target?.closest?.(`[data-copy-message-index]`)||null;navigator.clipboard.writeText(i).then(()=>{this.clearCopiedMessageState(),this.copiedMessageIndex=typeof t==`number`?t:-1,this.activeCopyButton=a,a?this.setCopyButtonState(a,!0):this.$nextTick(()=>this.updateCopyButtons()),this.copyResetTimeoutId=window.setTimeout(()=>{this.clearCopiedMessageState(),this.$nextTick(()=>this.updateCopyButtons())},Number(n.copyResetDelayMs)||2e3)}).catch(e=>console.error(`Failed to copy response:`,e))},startRecording(){!this.isRecording&&this.connection&&navigator.mediaDevices.getUserMedia({audio:{echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0}}).then(e=>{var t=MediaRecorder.isTypeSupported(`audio/ogg;codecs=opus`)?`audio/ogg;codecs=opus`:MediaRecorder.isTypeSupported(`audio/webm;codecs=opus`)?`audio/webm;codecs=opus`:`audio/webm`;this.mediaRecorder=new MediaRecorder(e,{mimeType:t,audioBitsPerSecond:128e3}),this.preRecordingPrompt=this.prompt,this._audioInputSent=!1;var n=new signalR.Subject,r=this.getItemId(),i=Promise.resolve();this.mediaRecorder.addEventListener(`dataavailable`,e=>{e.data&&e.data.size>0&&(i=i.then(async()=>{var t=await e.data.arrayBuffer(),r=new Uint8Array(t).reduce(function(e,t){return e+String.fromCharCode(t)},``),i=btoa(r);n.next(i)}))}),this.mediaRecorder.addEventListener(`stop`,()=>{e.getTracks().forEach(e=>e.stop()),i.then(()=>n.complete())});var a=navigator.language||document.documentElement.lang||`en-US`;this.connection.send(`SendAudioStream`,r,n,t,a),this.mediaRecorder.start(250),this.isRecording=!0,this.updateMicButton()}).catch(e=>{console.error(`Microphone access denied:`,e)})},stopRecording(){this.isRecording&&this.mediaRecorder&&(this.mediaRecorder.stop(),this.isRecording=!1,this.updateMicButton())},toggleRecording(){this.isRecording?this.stopRecording():this.startRecording()},updateMicButton(){this.micButton&&(this.isRecording?(this.micButton.classList.add(`stt-recording`),this.micButton.innerHTML=`<i class="fa-solid fa-stop"></i>`):(this.micButton.classList.remove(`stt-recording`),this.micButton.innerHTML=`<i class="fa-solid fa-microphone"></i>`))}},watch:{isPlayingAudio(){},isConversationMode(e){this.micButton&&(this.micButton.style.display=e?`none`:this.speechToTextEnabled?``:`none`),this.realtimeEnabled||this.setVoiceSessionLive(e)},copiedMessageIndex(){this.$nextTick(()=>this.updateCopyButtons())}},mounted(){(async()=>{await this.startConnection(),this.initializeApp(),this.$nextTick(()=>{this.updateCopyButtons(),i(this.$el),this.fontAwesomeObserver=a(this.$el)})})(),window.addEventListener(`beforeunload`,this.handleBeforeUnload),window.addEventListener(`crestapps-ai-chat-stop-tts`,this.handleExternalTtsStop)},beforeUnmount(){window.removeEventListener(`beforeunload`,this.handleBeforeUnload),window.removeEventListener(`crestapps-ai-chat-stop-tts`,this.handleExternalTtsStop),this.fontAwesomeObserver&&=(this.fontAwesomeObserver.disconnect(),null),this.clearCopiedMessageState(),this.stopAudio(!1),this.stream&&=(this.stream.dispose(),null),this.connection&&this.connection.stop()},template:n.messageTemplate}).mount(n.appElementSelector)},N=`[data-chat-interaction-config]`;function P(e,t,n){let r=e.getAttribute(t);if(!r)return null;try{return JSON.parse(r)}catch(e){return console.error(`Failed to parse `+n+` JSON.`,e),null}}function F(e){if(!e||e.dataset.chatInteractionInitialized===`true`)return e&&e.__chatInteractionApp||null;let t=P(e,`data-chat-interaction-config`,`chat interaction config`);if(!t)return null;let n=M(t);return n?(e.dataset.chatInteractionInitialized=`true`,e.__chatInteractionApp=n,n):null}function I(e){e&&typeof e.querySelectorAll==`function`&&(typeof e.matches==`function`&&e.matches(N)&&F(e),e.querySelectorAll(N).forEach(F))}function L(){I(document),typeof MutationObserver<`u`&&new MutationObserver(e=>{e.forEach(e=>{e.addedNodes.forEach(e=>{e&&e.nodeType===1&&I(e)})})}).observe(document.body,{childList:!0,subtree:!0})}return document.readyState===`loading`?document.addEventListener(`DOMContentLoaded`,L,{once:!0}):L(),{initialize:M,initializeFromElement:F}}(),window.chatInteractionDocumentManager=function(){let e=`__chatInteractionDocumentManagerState`;function t(e){return!e||typeof e!=`object`?null:{documentId:e.documentId||e.DocumentId||``,fileName:e.fileName||e.FileName||``,fileSize:e.fileSize||e.FileSize||0}}function n(e){return!e||e<1024?(e||0)+` B`:e<1048576?(e/1024).toFixed(1)+` KB`:(e/1048576).toFixed(1)+` MB`}function r(e,t){return(e||``).trim().toLowerCase()+`::`+(t||0)}function i(e,t){return t.has(r(e.name,e.size))}function a(e){return e?Array.from(e.querySelectorAll(`[data-chat-document-id]`)).map(e=>t({documentId:e.dataset.chatDocumentId,fileName:e.dataset.chatDocumentName,fileSize:Number(e.dataset.chatDocumentSize||0)})).filter(e=>e&&e.documentId):[]}function o(o){if(!o||!o.itemId)return;let s=document.getElementById(`chat-doc-upload`),c=document.getElementById(`chat-documents-list`),l=document.getElementById(`chat-doc-upload-status`),u=document.getElementById(`chat-doc-upload-progress`),d=document.getElementById(`chat-doc-upload-progress-bar`),f=document.getElementById(`chat-doc-upload-queue`);if(!s||!c||!l||!u||!d||!f)return;let p=s[e];p&&typeof p.dispose==`function`&&p.dispose();let m=(Array.isArray(o.existingDocuments)?o.existingDocuments:[]).map(t).filter(e=>e&&e.documentId);m.length===0&&(m=a(c));let h=[],g=!1;function _(e,t,n){let r=document.createElement(e);return t&&(r.className=t),r.textContent=n,r}function v(){c.innerHTML=``,m.length===0?c.appendChild(_(`div`,`text-muted small`,`No documents uploaded yet.`)):m.forEach(e=>{let t=window.document.createElement(`div`);t.className=`d-flex align-items-center gap-2 border rounded px-2 py-2 bg-white chat-document-row`,t.dataset.chatDocumentId=e.documentId,t.dataset.chatDocumentName=e.fileName,t.dataset.chatDocumentSize=e.fileSize;let r=window.document.createElement(`div`);r.className=`d-flex gap-1`;let i=o.downloadDocumentBaseUrl||`/ai/documents/`,a=_(`a`,`btn btn-sm btn-outline-secondary`,``);a.title=`Download`,a.href=i+encodeURIComponent(e.documentId)+`/download`;let s=window.document.createElement(`i`);s.className=`fa-solid fa-download`,a.appendChild(s);let l=_(`button`,`btn btn-sm btn-outline-danger remove-chat-document-btn`,``);l.type=`button`,l.title=`Remove`,l.dataset.documentId=e.documentId;let u=window.document.createElement(`i`);u.className=`fa-solid fa-trash`,l.appendChild(u),l.addEventListener(`click`,()=>k(e.documentId)),r.appendChild(a),r.appendChild(l);let d=window.document.createElement(`div`);d.className=`min-w-0`;let f=_(`div`,`fw-semibold small text-truncate`,e.fileName||`Document`),p=window.document.createElement(`i`);p.className=`fa-solid fa-file-lines me-1`,f.prepend(p);let m=_(`div`,`text-muted small`,n(e.fileSize));d.appendChild(f),d.appendChild(m),t.appendChild(r),t.appendChild(d),c.appendChild(t)})}function y(e,t){e?(l.textContent=e,l.className=`small mt-2 `+(t||`text-muted`)):(l.textContent=``,l.className=`small mt-2 d-none`)}function b(e,t,n){if(e==null){u.className=`progress mt-2 d-none`,u.setAttribute(`aria-valuenow`,`0`),d.className=`progress-bar progress-bar-striped progress-bar-animated`,d.style.width=`0%`,d.textContent=`0%`;return}let r=Math.max(0,Math.min(100,Math.round(e)));u.className=`progress mt-2`,u.setAttribute(`aria-valuenow`,r.toString()),d.className=`progress-bar `+(n||`progress-bar-striped progress-bar-animated`),d.style.width=r+`%`,d.textContent=t||r+`%`}function x(e){switch(e){case`uploaded`:return{label:`Uploaded`,badgeClass:`text-bg-success`,progressClass:`bg-success`};case`failed`:return{label:`Failed`,badgeClass:`text-bg-danger`,progressClass:`bg-danger`};case`uploading`:return{label:`Uploading`,badgeClass:`text-bg-warning`,progressClass:`bg-warning progress-bar-striped progress-bar-animated`};default:return{label:`Queued`,badgeClass:`text-bg-secondary`,progressClass:`bg-secondary progress-bar-striped progress-bar-animated`}}}function S(e){return e.status===`failed`&&e.error?e.error:e.status===`uploaded`?`Upload completed successfully.`:e.status===`uploading`?e.progress+`% uploaded`:`Waiting to upload...`}function C(){f.innerHTML=``,h.forEach(e=>{let t=x(e.status),r=document.createElement(`div`);r.className=`border rounded px-2 py-2 bg-white`;let i=document.createElement(`div`);i.className=`d-flex justify-content-between align-items-start gap-2`;let a=document.createElement(`div`);a.className=`flex-grow-1 min-w-0`,a.appendChild(_(`div`,`fw-semibold small`,e.fileName)),a.appendChild(_(`div`,`text-muted small`,n(e.fileSize)));let o=_(`span`,`badge `+t.badgeClass,t.label);i.appendChild(a),i.appendChild(o);let s=document.createElement(`div`);s.className=`progress mt-2`,s.setAttribute(`role`,`progressbar`),s.setAttribute(`aria-valuemin`,`0`),s.setAttribute(`aria-valuemax`,`100`),s.setAttribute(`aria-valuenow`,e.progress.toString());let c=document.createElement(`div`);c.className=`progress-bar `+t.progressClass,c.style.width=e.progress+`%`,c.textContent=e.progress+`%`,s.appendChild(c);let l=_(`div`,e.status===`failed`?`small text-danger mt-2`:`small text-muted mt-2`,S(e));r.appendChild(i),r.appendChild(s),r.appendChild(l),f.appendChild(r)})}function w(e,t){return{id:e.name+`::`+e.size+`::`+e.lastModified+`::`+t+`::`+Date.now(),fileName:e.name,fileSize:e.size,status:`queued`,progress:0,error:null}}function T(e,t){h=h.map(n=>n.id===e?Object.assign({},n,t):n),C()}function E(e){h=h.filter(t=>!e(t)),C()}function D(e,t,n,r){return new Promise((i,a)=>{let s=new FormData;s.append(`chatInteractionId`,o.itemId),s.append(`files`,e);let c=new XMLHttpRequest;c.open(`POST`,o.uploadDocumentUrl,!0),c.upload.addEventListener(`progress`,e=>{e.lengthComputable&&(T(t,{status:`uploading`,progress:Math.round(e.loaded/e.total*100)}),b((n+e.loaded/e.total)/r*100,`Uploading `+(n+1)+` of `+r,`progress-bar-striped progress-bar-animated`))}),c.addEventListener(`load`,()=>{if(c.status>=200&&c.status<300)try{i(JSON.parse(c.responseText))}catch{a(Error(`Upload failed: invalid server response.`))}else a(Error((c.responseText||`Upload failed.`).trim()))}),c.addEventListener(`error`,()=>{a(Error(`Upload failed. Please check your connection and try again.`))}),c.send(s)})}async function O(e){if(!o.uploadDocumentUrl||!e||e.length===0)return;if(g){y(`A document upload is already in progress.`,`text-warning`);return}g=!0;let n=[],a=[],c=new Set(m.map(e=>r(e.fileName,e.fileSize)));if(Array.from(e).forEach(e=>{i(e,c)?a.push(e):(c.add(r(e.name,e.size)),n.push(e))}),a.length>0&&(h=h.concat(a.map((e,t)=>Object.assign(w(e,t),{status:`failed`,progress:100,error:`This document is already attached.`}))),C()),n.length===0){g=!1,y(a.map(e=>e.name+`: This document is already attached.`).join(` | `),`text-warning`),b(null);return}let l=n.map(w);h=h.concat(l),C(),b(0,`Preparing upload...`,`progress-bar-striped progress-bar-animated`),s.disabled=!0;try{let e=0,r=a.map(e=>e.name+`: This document is already attached.`);for(let i=0;i<n.length;i++){let a=n[i],o=l[i];T(o.id,{status:`uploading`,progress:0,error:null}),y(`Uploading `+(i+1)+` of `+n.length+` document(s)...`,`text-warning`);try{let s=await D(a,o.id,i,n.length),c=(Array.isArray(s.uploaded)?s.uploaded:[]).map(t).filter(e=>e&&e.documentId),l=Array.isArray(s.failed)?s.failed:[];if(c.length>0)e+=c.length,m=m.concat(c),T(o.id,{status:`uploaded`,progress:100,error:null});else{let e=l.length>0?l.map(e=>e.fileName+`: `+e.error).join(` | `):`The server did not confirm that the file was uploaded.`;l.length===0&&r.push(e),T(o.id,{status:`failed`,progress:100,error:e})}if(l.length>0){let e=l.map(e=>e.fileName+`: `+e.error).join(` | `);r.push(e),T(o.id,{status:`failed`,progress:100,error:e})}}catch(e){let t=e&&e.message?e.message:`Upload failed. Please try again.`;console.error(`Upload failed:`,e),r.push(a.name+`: `+t),T(o.id,{status:`failed`,progress:o.progress||0,error:t})}}if(v(),r.length>0){E(e=>e.status===`uploaded`),y((e>0?`Uploaded `+e+` document(s). `:``)+r.join(` | `),e>0?`text-warning`:`text-danger`),b(null);return}E(()=>!0),y(`Uploaded `+e+` document(s).`,`text-success`),b(null)}catch(e){console.error(`Upload failed:`,e),y(`Upload failed. Please try again.`,`text-danger`),b(null)}finally{g=!1,s.disabled=!1,s.value=``}}async function k(e){if(o.removeDocumentUrl&&e&&window.confirm(`Remove this document?`))try{let n=await fetch(o.removeDocumentUrl,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({itemId:o.itemId,documentId:e})});if(!n.ok){console.error(`Failed to remove document:`,await n.text()),y(`Failed to remove document.`,`text-danger`);return}if((n.headers.get(`content-type`)||``).toLowerCase().indexOf(`json`)<0){console.error(`Remove document: response was not JSON.`,{status:n.status,redirected:n.redirected}),y(n.redirected?`You may not be signed in, or you do not have permission for this. Please reload and try again.`:`Failed to remove document.`,`text-danger`);return}let r=await n.json(),i=(Array.isArray(r.documents)?r.documents:[]).map(t).filter(e=>e&&e.documentId);m=i.length>0?i:m.filter(t=>t.documentId!==e),v(),y(`Document removed.`,`text-success`)}catch(e){console.error(`Remove failed:`,e),y(`Failed to remove document.`,`text-danger`)}}let A=e=>{O(e.target.files?Array.from(e.target.files):[])};return s.addEventListener(`change`,A),s[e]={dispose:()=>{s.removeEventListener(`change`,A)}},v(),C(),y(null),b(null),s[e]}function s(e,t,n){let r=e.getAttribute(t);if(!r)return null;try{return JSON.parse(r)}catch(e){return console.error(`Failed to parse `+n+` JSON.`,e),null}}function c(t){if(!t||t.dataset.chatInteractionDocumentManagerInitialized===`true`)return t&&t[e]||null;let n=s(t,`data-chat-interaction-document-manager-config`,`chat interaction document manager config`);if(!n)return null;let r=o(n);return r?(t.dataset.chatInteractionDocumentManagerInitialized=`true`,r):null}function l(e){e&&typeof e.querySelectorAll==`function`&&(typeof e.matches==`function`&&e.matches(`[data-chat-interaction-document-manager-config]`)&&c(e),e.querySelectorAll(`[data-chat-interaction-document-manager-config]`).forEach(c))}function u(){l(document),typeof MutationObserver<`u`&&new MutationObserver(e=>{e.forEach(e=>{e.addedNodes.forEach(e=>{e&&e.nodeType===1&&l(e)})})}).observe(document.body,{childList:!0,subtree:!0})}return document.readyState===`loading`?document.addEventListener(`DOMContentLoaded`,u,{once:!0}):u(),{initialize:o,initializeFromElement:c}}(),document.addEventListener(`click`,function(e){let t=e.target.closest(`.download-chart-btn`);if(!t)return;let n=t.getAttribute(`data-chart-id`),r=n?document.getElementById(n):null;if(!r){console.error(`Chart canvas not found:`,n);return}let i=document.createElement(`a`);i.download=`chart-`+n+`.png`,i.href=r.toDataURL(`image/png`),i.click()}),document.addEventListener(`click`,function(e){let t=e.target.closest(`.ai-download-image`);if(!t)return;let n=t.closest(`.generated-image-container`)?.querySelector(`img`);if(!n)return;let r=n.src;r&&r.startsWith(`data:`)&&(e.preventDefault(),fetch(r).then(function(e){return e.blob()}).then(function(e){let n=URL.createObjectURL(e),r=document.createElement(`a`);r.href=n,r.download=t.getAttribute(`download`)||`generated-image.png`,document.body.appendChild(r),r.click(),document.body.removeChild(r),setTimeout(function(){URL.revokeObjectURL(n)},100)}).catch(function(e){console.error(`Failed to download image:`,e)}))})})();
|
|
62
|
+
`),e.responseId&&(r=e.responseId),t+=e.content),s.rawContent=t,y(s,n),this.messages[i]=s,this.$nextTick(()=>{O(s),this.scrollToBottom()})},complete:()=>{this.processReferences(n,i),this.streamingFinished();let e=this.messages[i];e&&(e.isStreaming=!1),(!e||!e.content)&&this.hideTypingIndicator(),this.isConversationMode&&this.textToSpeechEnabled&&e&&e.content&&this.synthesizeSpeech(e.content),this.stream?.dispose(),this.stream=null},error:e=>{this.processReferences(n,i),this.streamingFinished();let t=this.messages[i];t&&(t.isStreaming=!1),this.hideTypingIndicator(),this.isNavigatingAway||this.addMessage(this.getServiceDownMessage()),this.stream?.dispose(),this.stream=null,console.error(`Stream error:`,e)}})},getServiceDownMessage(){return{role:`assistant`,content:`Our service is currently unavailable. Please try again later. We apologize for the inconvenience.`,htmlContent:``}},processReferences(e,t){if(e=c(e),Object.keys(e).length){let n=this.messages[t];n.rawContent=n.rawContent??n.content??``,y(n,e),this.messages[t]=n,this.$nextTick(()=>{O(n),this.scrollToBottom()})}},streamingStarted(){var e=this.buttonElement.getAttribute(`data-stop-icon`);e&&this.buttonElement.replaceChildren(DOMPurify.sanitize(e,{RETURN_DOM_FRAGMENT:!0}))},streamingFinished(){var e=this.buttonElement.getAttribute(`data-start-icon`);if(e&&this.buttonElement.replaceChildren(DOMPurify.sanitize(e,{RETURN_DOM_FRAGMENT:!0})),this.chatContainer)for(var t=this.chatContainer.querySelectorAll(`.ai-streaming-icon`),n=0;n<t.length;n++)t[n].classList.remove(`ai-streaming-icon`),t[n].classList.add(`ai-bot-icon`);for(n=0;n<this.messages.length;n++)this.messages[n].isStreaming&&(this.messages[n].isStreaming=!1);this.settingsDirty&&this.debouncedSaveSettings()},handleExternalTtsStop(e){e?.detail?.sourceId!==this.ttsInstanceId&&this.stopAudio(!1)},updateTtsPlaybackButtons(){this.chatContainer&&this.chatContainer.querySelectorAll(`[data-tts-message-index]`).forEach(e=>{var t=Number(e.getAttribute(`data-tts-message-index`))===this.ttsPlayingMessageIndex,n=t?`<i class="fa-solid fa-circle-pause"></i>`:`<i class="fa-solid fa-circle-play"></i>`;e.classList.toggle(`tts-playing`,t),e.setAttribute(`title`,t?`Pause audio`:`Read aloud`),e.replaceChildren(DOMPurify.sanitize(n,{RETURN_DOM_FRAGMENT:!0}))})},updateCopyButtons(){this.chatContainer&&this.chatContainer.querySelectorAll(`[data-copy-message-index]`).forEach(e=>{var t=Number(e.getAttribute(`data-copy-message-index`))===this.copiedMessageIndex,n=t?`<i class="fa-solid fa-check"></i>`:`<i class="fa-solid fa-copy"></i>`;e.classList.toggle(`text-success`,t),e.classList.toggle(`text-secondary`,!t),e.setAttribute(`title`,t?this.copiedTitle:this.copyTitle),e.replaceChildren(DOMPurify.sanitize(n,{RETURN_DOM_FRAGMENT:!0}))})},setCopyButtonState(e,t){if(e){var n=t?`<i class="fa-solid fa-check"></i>`:`<i class="fa-solid fa-copy"></i>`;e.classList.toggle(`text-success`,t),e.classList.toggle(`text-secondary`,!t),e.setAttribute(`title`,t?this.copiedTitle:this.copyTitle),e.replaceChildren(DOMPurify.sanitize(n,{RETURN_DOM_FRAGMENT:!0}))}},synthesizeSpeech(e,t){this.textToSpeechEnabled&&e&&this.connection&&(this.audioChunks=[],this.isPlayingAudio=!0,this._ttsCacheIndex=t===void 0?-1:t,this.connection.invoke(`SynthesizeSpeech`,this.getItemId(),e,this.ttsVoiceName).catch(e=>{console.error(`TTS synthesis error:`,e),this.isPlayingAudio=!1,this.ttsPlayingMessageIndex=-1,this._ttsCacheIndex=-1,this.$nextTick(()=>this.updateTtsPlaybackButtons())}))},toggleMessageTts(e,t){this.ttsPlayingMessageIndex===t?this.stopAudio():(this.stopAudio(!1),window.dispatchEvent(new CustomEvent(`crestapps-ai-chat-stop-tts`,{detail:{sourceId:this.ttsInstanceId}})),this.ttsPlayingMessageIndex=t,this.$nextTick(()=>this.updateTtsPlaybackButtons()),this.ttsAudioCache[t]?this.playAudioBlob(this.ttsAudioCache[t]):this.synthesizeSpeech(e.content,t))},playCollectedAudio(){if(this.audioChunks.length===0){!this.isPlayingAudio&&this.audioPlayQueue.length===0&&(this.isPlayingAudio=!1,this.ttsPlayingMessageIndex=-1,this.$nextTick(()=>this.updateTtsPlaybackButtons()));return}let e=this.audioChunks.reduce((e,t)=>e+t.length,0),t=new Uint8Array(e),n=0;for(let e of this.audioChunks)t.set(e,n),n+=e.length;this.audioChunks=[];let r=new Blob([t],{type:`audio/mp3`});this._ttsCacheIndex>=0&&(this.ttsAudioCache[this._ttsCacheIndex]=r,this._ttsCacheIndex=-1),this.isPlayingAudio&&this.currentAudioElement?this.audioPlayQueue.push(r):this.playAudioBlob(r)},playAudioBlob(e){let t=URL.createObjectURL(e),n=new Audio(t);this.currentAudioUrl=t,this.currentAudioElement=n,this.isPlayingAudio=!0,n.addEventListener(`ended`,()=>{this.currentAudioElement=null,this.currentAudioUrl=null,URL.revokeObjectURL(t),this.playNextInQueue()}),n.addEventListener(`error`,()=>{this.currentAudioElement=null,this.currentAudioUrl=null,URL.revokeObjectURL(t),this.playNextInQueue()}),n.play().catch(e=>{console.error(`Audio playback error:`,e),this.currentAudioElement=null,this.currentAudioUrl=null,URL.revokeObjectURL(t),this.audioPlayQueue=[],this.isPlayingAudio=!1,this.ttsPlayingMessageIndex=-1,this.$nextTick(()=>this.updateTtsPlaybackButtons())})},playNextInQueue(){if(this.audioPlayQueue.length>0){let e=this.audioPlayQueue.shift();this.playAudioBlob(e)}else this.isPlayingAudio=!1,this.ttsPlayingMessageIndex=-1,this.$nextTick(()=>this.updateTtsPlaybackButtons()),this.conversationModeOnAudioEnded()},stopAudio(){this.currentAudioElement&&=(this.currentAudioElement.pause(),this.currentAudioElement.currentTime=0,null),this.currentAudioUrl&&=(URL.revokeObjectURL(this.currentAudioUrl),null),this.audioChunks=[],this.audioPlayQueue=[],this.isPlayingAudio=!1,this.ttsPlayingMessageIndex=-1,this.$nextTick(()=>this.updateTtsPlaybackButtons())},setVoiceSessionLive(e){this.inputElement&&(this.inputElement.hidden=e),this.buttonElement&&(this.buttonElement.hidden=e),[this.realtimeButton,this.conversationButton].forEach(function(t){t&&t.classList.toggle(`flex-grow-1`,e)});var t=this.realtimeButton&&this.realtimeButton.nextElementSibling,n=t&&t.id===`realtime-audio-settings`?t:null;n&&(n.hidden=!e)},toggleConversationMode(){this.isConversationMode?this.stopConversationMode():this.startConversationMode()},endActiveVoiceSession(){this.realtimeController&&this.realtimeController.isActive()?this.realtimeController.stop():this.isConversationMode&&this.stopConversationMode()},startConversationMode(){this.conversationModeEnabled&&!this.isConversationMode&&this.connection&&(this.isConversationMode=!0,this.updateConversationButton(),this._conversationPartialTranscript=``,this._conversationAssistantMessage=null,this._conversationPartialMessage=null,this.removeNotification(`conversation-ended`),navigator.mediaDevices.getUserMedia({audio:{echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0}}).then(e=>{var t=MediaRecorder.isTypeSupported(`audio/ogg;codecs=opus`)?`audio/ogg;codecs=opus`:MediaRecorder.isTypeSupported(`audio/webm;codecs=opus`)?`audio/webm;codecs=opus`:`audio/webm`;this.mediaRecorder=new MediaRecorder(e,{mimeType:t,audioBitsPerSecond:128e3}),this._conversationSubject=new signalR.Subject,this._conversationStream=e;var n=window.AudioContext||window.webkitAudioContext;n&&(this._conversationAudioCtx=new n,this._conversationAnalyser=this._conversationAudioCtx.createAnalyser(),this._conversationAnalyser.fftSize=256,this._conversationAudioCtx.createMediaStreamSource(e).connect(this._conversationAnalyser));var r=Promise.resolve(),i=this._conversationAnalyser,a=30;this.mediaRecorder.addEventListener(`dataavailable`,e=>{if(e.data&&e.data.size>0){if(this.isPlayingAudio&&i){var t=new Uint8Array(i.frequencyBinCount);i.getByteFrequencyData(t);for(var n=0,o=0;o<t.length;o++)n+=t[o];n/t.length>=a&&this.stopAudio()}r=r.then(async()=>{var t=await e.data.arrayBuffer(),n=new Uint8Array(t).reduce(function(e,t){return e+String.fromCharCode(t)},``),r=btoa(n);try{this._conversationSubject.next(r)}catch{}})}}),this.mediaRecorder.addEventListener(`stop`,()=>{e.getTracks().forEach(e=>e.stop()),r.then(()=>{try{this._conversationSubject.complete()}catch{}})});var o=this.getItemId(),s=navigator.language||document.documentElement.lang||`en-US`;this.connection.send(`StartConversation`,o,this._conversationSubject,t,s),this.mediaRecorder.start(250),this.isRecording=!0}).catch(e=>{console.error(`Microphone access denied:`,e),this.isConversationMode=!1,this.updateConversationButton()}))},stopConversationMode(){if(this.isConversationMode){if(this.isConversationMode=!1,this.updateConversationButton(),this.connection&&this.connection.invoke(`StopConversation`).catch(function(){}),this.isRecording&&this.mediaRecorder&&(this.mediaRecorder.stop(),this.isRecording=!1),this.stopAudio(),this._conversationPartialTranscript=``,this._conversationPartialMessage=null,this._conversationAudioCtx&&(this._conversationAudioCtx.close().catch(function(){}),this._conversationAudioCtx=null,this._conversationAnalyser=null),this._conversationAssistantMessage){var e=this.messages[this._conversationAssistantMessage.index];e&&(e.isStreaming=!1),this._conversationAssistantMessage=null}for(var t=0;t<this.messages.length;t++)this.messages[t].isStreaming&&(this.messages[t].isStreaming=!1);this.receiveNotification({type:`conversation-ended`,content:`Conversation ended.`,icon:`fa-solid fa-circle-check`,dismissible:!0,autoDismissMs:5e3})}},updateConversationButton(){if(this.conversationButton){if(this.isConversationMode){this.conversationButton.classList.add(`active`,`btn-primary`),this.conversationButton.classList.remove(`btn-dark`,`btn-outline-dark`,`btn-outline-secondary`),this.conversationButton.title=this.conversationButton.getAttribute(`data-end-title`)||`End Conversation`;var e=this.conversationButton.getAttribute(`data-end-html`);e&&this.conversationButton.replaceChildren(DOMPurify.sanitize(e,{RETURN_DOM_FRAGMENT:!0}))}else{this.conversationButton.classList.remove(`active`,`btn-primary`),this.conversationButton.classList.remove(`btn-dark`,`btn-outline-secondary`),this.conversationButton.classList.add(`btn-outline-dark`),this.conversationButton.blur(),this.conversationButton.title=this.conversationButton.getAttribute(`data-start-title`)||`Start Conversation`;var t=this.conversationButton.getAttribute(`data-start-html`);t&&this.conversationButton.replaceChildren(DOMPurify.sanitize(t,{RETURN_DOM_FRAGMENT:!0}))}}},conversationModeSendPrompt(){},conversationModeOnAudioEnded(){},showTypingIndicator(){this.addMessage({role:`indicator`,htmlContent:r.indicatorTemplate})},hideTypingIndicator(){let e=this.messages.length;return this.messages=this.messages.filter(e=>e.role!==`indicator`),e-this.messages.length},scrollToBottom(){this.autoScroll&&setTimeout(()=>{this.chatContainer.scrollTop=this.chatContainer.scrollHeight-this.chatContainer.clientHeight},50)},handleUserInput(e){this.prompt=e.target.value},getItemId(){return this.inputElement.getAttribute(`data-interaction-id`)||this.inputElement.getAttribute(`data-item-id`)},getSaveIndicatorElement(){return r.saveIndicatorElementSelector?document.querySelector(r.saveIndicatorElementSelector):document.querySelector(`[data-chat-interaction-save-indicator]`)},showSaveIndicator(e,t){let n=this.getSaveIndicatorElement();n&&(n.textContent=e||``,n.className=`settings-save-indicator `+(t||`text-muted`),this.saveIndicatorTimeout&&=(clearTimeout(this.saveIndicatorTimeout),null),e&&(this.saveIndicatorTimeout=setTimeout(()=>{n.textContent=``,this.saveIndicatorTimeout=null},3e3)))},clearPendingSettingsSave(){this.saveSettingsTimeout&&=(clearTimeout(this.saveSettingsTimeout),null)},getFieldLabel(e){let t=e.closest(`.mb-3, .col-6, .col, .form-group, .form-floating`)?.querySelector(`label`);return t?(t.textContent||``).replace(/\s+/g,` `).trim()||e.dataset.setting||`This field`:e.dataset.setting||`This field`},getValidationFeedbackElement(e){let t=e.nextElementSibling;return t&&t.classList.contains(`invalid-feedback`)||(t=document.createElement(`div`),t.className=`invalid-feedback`,e.insertAdjacentElement(`afterend`,t)),t},clearSettingValidationError(e){e.classList.remove(`is-invalid`),e.removeAttribute(`aria-invalid`);let t=e.nextElementSibling;t&&t.classList.contains(`invalid-feedback`)&&(t.textContent=``)},setSettingValidationError(e,t){let n=this.getValidationFeedbackElement(e);e.classList.add(`is-invalid`),e.setAttribute(`aria-invalid`,`true`),n.textContent=t},getSettingValidationMessage(e){if(!e||e.disabled||e.type!==`number`)return null;let t=(e.value||``).trim();if(!t)return null;let n=Number(t),r=this.getFieldLabel(e);if(Number.isNaN(n))return`${r} must be a valid number.`;let i=e.getAttribute(`min`);if(i!==null&&n<Number(i))return`${r} must be ${i} or greater.`;let a=e.getAttribute(`max`);return a!==null&&n>Number(a)?`${r} must be ${a} or less.`:null},validateSettingInput(e){let t=this.getSettingValidationMessage(e);return t?(this.setSettingValidationError(e,t),!1):(this.clearSettingValidationError(e),!0)},validateSettings(){let e=!0;return this.getSettingInputs().forEach(t=>{e=this.validateSettingInput(t)&&e}),e},queueSettingsSave(){this.validateSettings()?(this.settingsDirty=!0,this.showSaveIndicator(`Saving...`,`text-warning`),this.debouncedSaveSettings()):(this.clearPendingSettingsSave(),this.settingsDirty=!1,this.showSaveIndicator(`Fix errors`,`text-danger`))},getSettingInputs(){let e=document.querySelectorAll(`.setting-input[data-setting]`);return e.length>0?e:document.querySelectorAll(`input[name^="ChatInteraction."]:not([name*=".Tools["]):not([name*=".Connections["]):not([name*=".Instances["]), select[name^="ChatInteraction."]:not([name*=".Tools["]):not([name*=".Connections["]):not([name*=".Instances["]), textarea[name^="ChatInteraction."]:not([name*=".Tools["]):not([name*=".Connections["]):not([name*=".Instances["])`)},getSelectedGroupValues(e,t){let n=document.querySelectorAll(`.capability-checkbox[data-save-group="${e}"]:checked, .capability-checkbox[data-group="${e}"]:checked`);if(n.length>0){let e=[];return n.forEach(t=>{let n=t.getAttribute(`data-item-id`)||t.value;n&&e.push(n)}),e}if(!t)return[];let r=[];return document.querySelectorAll(t).forEach(e=>{let t=e.name.replace(`.IsSelected`,`.ItemId`),n=document.querySelector(`input[type="hidden"][name="${t}"]`);n&&n.value&&r.push(n.value)}),r},getPromptTemplateSelections(){let e=[];return document.querySelectorAll(`.prompt-template-card`).forEach(t=>{let n=t.querySelector(`.prompt-template-id-input`),r=t.querySelector(`.prompt-template-parameters-input`),i=n?n.value:t.getAttribute(`data-template-id`);i&&e.push({templateId:i,promptParameters:r?(r.value||``).trim():``})}),e},receiveNotification(e){if(e&&e.type){this.clearNotificationDismiss(e.type);var t=this.notifications.findIndex(t=>t.type===e.type);t>=0?this.notifications.splice(t,1,e):this.notifications.push(e),this.scheduleNotificationDismiss(e),this.scrollToBottom()}},updateNotification(e){if(e&&e.type){this.clearNotificationDismiss(e.type);var t=this.notifications.findIndex(t=>t.type===e.type);t>=0&&(this.notifications.splice(t,1,e),this.scheduleNotificationDismiss(e),this.scrollToBottom())}},scheduleNotificationDismiss(e){!e||!e.type||!e.autoDismissMs||e.autoDismissMs<=0||(this.notificationDismissTimers[e.type]=setTimeout(()=>{this.removeNotification(e.type)},e.autoDismissMs))},clearNotificationDismiss(e){var t=this.notificationDismissTimers[e];t&&(clearTimeout(t),delete this.notificationDismissTimers[e])},removeNotification(e){this.clearNotificationDismiss(e),this.notifications=this.notifications.filter(t=>t.type!==e)},dismissNotification(e){this.removeNotification(e)},handleNotificationAction(e,t){if(this.connection){var n=this.getItemId();this.connection.invoke(`HandleNotificationAction`,n,e,t).catch(e=>console.error(`Failed to handle notification action:`,e))}},setItemId(e){this.inputElement.setAttribute(`data-interaction-id`,e||``),this.inputElement.setAttribute(`data-item-id`,e||``)},resetInteraction(){this.setItemId(``),this.isInteractionStarted=!1,this.messages=[],this.showPlaceholder()},initializeApp(){this.inputElement=document.querySelector(r.inputElementSelector),this.buttonElement=document.querySelector(r.sendButtonElementSelector),this.chatContainer=document.querySelector(r.chatContainerElementSelector),this.placeholder=document.querySelector(r.placeholderElementSelector);let e=this.getItemId();e&&this.loadInteraction(e),this.chatContainer.addEventListener(`scroll`,()=>{if(!this.stream)return;let e=this.chatContainer.scrollHeight-this.chatContainer.clientHeight-this.chatContainer.scrollTop<=30;this.autoScroll=e}),this.inputElement.addEventListener(`keyup`,e=>{this.stream==null&&e.key===`Enter`&&!e.shiftKey&&this.buttonElement.click()}),this.inputElement.addEventListener(`input`,e=>{this.handleUserInput(e),e.target.value.trim()?this.buttonElement.removeAttribute(`disabled`):this.buttonElement.setAttribute(`disabled`,!0)}),this.inputElement.addEventListener(`paste`,()=>{setTimeout(()=>{this.prompt=this.inputElement.value,this.inputElement.value.trim()?this.buttonElement.removeAttribute(`disabled`):this.buttonElement.setAttribute(`disabled`,!0)},0)}),this.buttonElement.addEventListener(`click`,()=>{if(this.stream!=null){if(this.stream.dispose(),this.stream=null,this.streamingFinished(),this.hideTypingIndicator(),this.messages.length>0){let e=this.messages[this.messages.length-1];e.role===`assistant`&&!e.content?this.messages.pop():e.isStreaming&&=!1}}else this.sendMessage()});let t=document.getElementsByClassName(`chat-interaction-history-item`);for(var n=0;n<t.length;n++)t[n].addEventListener(`click`,e=>{e.preventDefault();var t=e.target.getAttribute(`data-interaction-id`);t?this.loadInteraction(t):console.error(`An element with the class chat-interaction-history-item with no data-interaction-id set.`)});let i=Array.isArray(r.messages)?r.messages:[];for(let e=0;e<i.length;e++)this.addMessage(i[e]);this.chatContainer&&this.chatContainer.addEventListener(`click`,e=>{var t=e.target.closest(`.ai-code-copy-btn`);if(t){var n=t.closest(`.ai-code-block`)||t.closest(`pre`);if(n){var i=n.querySelector(`code`);i&&(navigator.clipboard.writeText(i.textContent),t.innerHTML=`<i class="fa-solid fa-check"></i> `+(r.codeCopiedText||`Copied!`),setTimeout(()=>{t.innerHTML=`<i class="fa-regular fa-copy"></i>`},2e3))}}}),document.addEventListener(`input`,e=>{e.target.matches(`.setting-input[data-setting]`)&&(this.validateSettingInput(e.target),this.queueSettingsSave())}),document.addEventListener(`change`,e=>{e.target.matches(`.setting-input[data-setting], .capability-checkbox[data-save-group], .capability-checkbox[data-group], .group-toggle, .ci-agent-global-toggle`)?(e.target.matches(`.setting-input[data-setting]`)&&this.validateSettingInput(e.target),this.queueSettingsSave()):e.target.closest(`.prompt-template-parameters-input, .prompt-template-id-input`)&&this.queueSettingsSave()}),document.addEventListener(`click`,e=>{e.target.closest(`.prompt-template-add-btn, .remove-prompt-template-btn`)&&setTimeout(()=>{this.queueSettingsSave()},0)});let a=document.getElementById(`clearHistoryBtn`);a&&a.addEventListener(`click`,()=>{let e=a.getAttribute(`data-interaction-id`);e&&this.clearHistory(e)}),this.speechToTextEnabled&&r.micButtonElementSelector&&(this.micButton=document.querySelector(r.micButtonElementSelector),this.micButton&&(this.micButton.style.display=``,this.micButton.addEventListener(`click`,()=>{this.toggleRecording()}))),this.conversationModeEnabled&&r.conversationButtonElementSelector&&(this.conversationButton=document.querySelector(r.conversationButtonElementSelector),this.conversationButton&&this.conversationButton.addEventListener(`click`,()=>{this.toggleConversationMode()})),window.CoreAIRealtime&&r.realtimeButtonElementSelector&&(this.realtimeButton=document.querySelector(r.realtimeButtonElementSelector),this.realtimeController=window.CoreAIRealtime.attach({connection:this.connection,ensureConnected:()=>Promise.resolve(this.connection),sendStart:(e,t,n,r,i,a)=>{this.connection.send(`StartRealtimeConversation`,this.getItemId(),e,t,n,r,i,a)},webRtcEnabled:r.realtimeWebRtcEnabled===!0,sendStartWebRtc:(e,t,n,r,i,a)=>{this.connection.send(`StartRealtimeWebRtc`,this.getItemId(),e,t,n,r,i,a)},webRtcIceServers:Array.isArray(r.realtimeWebRtcIceServers)?r.realtimeWebRtcIceServers:void 0,voiceName:r.realtimeVoiceName||``,getVoiceName:()=>{var e=r.realtimeVoiceSelectElementSelector?document.querySelector(r.realtimeVoiceSelectElementSelector):null;return e?e.value:``},capableDeployments:r.realtimeCapableDeployments||[],realtimeEnabled:r.realtimeEnabled===!0,selectors:{realtimeButton:r.realtimeButtonElementSelector,micButton:r.micButtonElementSelector,conversationButton:r.conversationButtonElementSelector},onSessionStateChanged:e=>{this.setVoiceSessionLive(e)},onActivate:()=>{this.isConversationMode=!0,this._conversationPartialMessage=null,this._conversationAssistantMessage=null},onDeactivate:()=>{if(this.isConversationMode=!1,this._conversationAssistantMessage){var e=this.messages[this._conversationAssistantMessage.index];e&&(e.isStreaming=!1),this._conversationAssistantMessage=null}},onEnterRealtimeMode:()=>{this.isRecording&&this.stopRecording(),this.isConversationMode&&(!this.realtimeController||!this.realtimeController.isActive())&&this.stopConversationMode()},onUserTurnPending:e=>{if(e){var t={role:`user`,content:``,rawContent:``,references:{},isPartial:!0};y(t,t.references),this._realtimePendingTurns=this._realtimePendingTurns||{},this._realtimePendingTurns[e]=t,this.messages.push(t),this.scrollToBottom()}},onUserTurnDropped:e=>{if(e&&this._realtimePendingTurns){var t=this._realtimePendingTurns[e];if(t){delete this._realtimePendingTurns[e];var n=this.messages.indexOf(t);n>=0&&this.messages.splice(n,1)}}}}),this.setupRealtimeVoicePicker(r),this.setVoiceSessionLive(!1))},setupRealtimeVoicePicker(e){if(!e.realtimeVoiceSelectElementSelector||!e.realtimeVoicesUrl)return;var t=document.querySelector(e.realtimeVoiceSelectElementSelector);if(!t)return;var n=e.realtimeVoiceGroupElementSelector?document.querySelector(e.realtimeVoiceGroupElementSelector):null,r=e.conversationDeploymentSelectElementSelector?document.querySelector(e.conversationDeploymentSelectElementSelector):null,i=(e.realtimeCapableDeployments||[]).map(function(e){return(e||``).toLowerCase()}),a=e.realtimeVoiceName||``,o=this;function s(e){return e&&i.indexOf(e.toLowerCase())!==-1}function c(){if(!o.conversationModeEnabled)return``;var t=r&&r.value||e.defaultRealtimeDeploymentName||(i.length?i[0]:``);return s(t)?t:``}async function l(){var r=c(),i=!!r;if(n&&n.classList.toggle(`d-none`,!i),o.realtimeController&&o.realtimeController.applyMode(i),i){t.innerHTML=`<option value="">Default voice</option>`;try{let n=await fetch(e.realtimeVoicesUrl+`?deploymentName=`+encodeURIComponent(r),{credentials:`same-origin`}),i=(n.headers.get(`content-type`)||``).toLowerCase();if(!n.ok||i.indexOf(`json`)<0)return;let o=await n.json();if(!o||!Array.isArray(o.voices))return;let s=new Map;for(let e of o.voices){let t=e.gender||`Voices`;s.has(t)||s.set(t,[]),s.get(t).push(e)}Array.from(s.keys()).sort((e,t)=>e.localeCompare(t)).forEach(function(e){let n=document.createElement(`optgroup`);n.label=e,s.get(e).forEach(function(e){let t=document.createElement(`option`);t.value=e.id,t.textContent=e.name,t.selected=e.id===a,n.appendChild(t)}),t.appendChild(n)})}catch{}}}r&&r.addEventListener(`change`,l),l()},loadInteraction(e){this.connection.invoke(`LoadInteraction`,e).catch(e=>console.error(e))},reloadCurrentInteraction(){let e=this.getItemId();e&&this.loadInteraction(e)},clearHistory(e){let t=this,n=()=>{t.realtimeController&&t.realtimeController.isActive()&&t.realtimeController.stop(),t.stream&&(t.stream.dispose(),t.stream=null,t.hideTypingIndicator(),t.streamingFinished()),t.connection.invoke(`ClearHistory`,e).catch(e=>console.error(`Error clearing history:`,e))};typeof confirmDialog==`function`?confirmDialog({title:r.clearHistoryTitle,message:r.clearHistoryMessage,okText:r.clearHistoryOkText,cancelText:r.clearHistoryCancelText,callback:function(e){e&&n()}}):window.confirm(r.clearHistoryMessage||`Clear all messages?`)&&n()},debouncedSaveSettings(){this.clearPendingSettingsSave(),!this.stream&&(this.saveSettingsTimeout=setTimeout(()=>{this.settingsDirty&&=(this.saveSettings(),!1),this.saveSettingsTimeout=null},850))},getSelectedToolNames(){return this.getSelectedGroupValues(`toolNames`,`input[type="checkbox"][name$="].IsSelected"][name^="ChatInteraction.Tools["]:checked`)},getSelectedMcpConnectionIds(){return this.getSelectedGroupValues(`mcpConnectionIds`,`input[type="checkbox"][name$="].IsSelected"][name^="ChatInteraction.Connections["]:checked`)},getSelectedA2AConnectionIds(){return this.getSelectedGroupValues(`a2aConnectionIds`)},getSelectedAgentNames(){return this.getSelectedGroupValues(`agentNames`,`input[type="checkbox"][name$="].IsSelected"][name^="ChatInteraction.Agents["]:checked`)},hasToolInstanceSelector(){return document.querySelector(`.capability-checkbox[data-save-group="toolInstanceNames"], .capability-checkbox[data-group="toolInstanceNames"]`)!==null},getSelectedToolInstanceNames(){return this.getSelectedGroupValues(`toolInstanceNames`)},saveSettings(){let e=this.getItemId();if(!e)return Promise.resolve();if(!this.validateSettings())return this.showSaveIndicator(`Fix errors`,`text-danger`),Promise.resolve();let t={};this.getSettingInputs().forEach(e=>{let n=e.dataset.setting||(e.name||``).replace(`ChatInteraction.`,``).replace(/^[A-Z]/,e=>e.toLowerCase());n&&(e.type===`checkbox`?t[n]=e.checked:e.type===`number`?t[n]=e.value?parseFloat(e.value):null:t[n]=e.value||null)}),t.toolNames=this.getSelectedToolNames(),t.mcpConnectionIds=this.getSelectedMcpConnectionIds(),t.a2aConnectionIds=this.getSelectedA2AConnectionIds(),t.agentNames=this.getSelectedAgentNames(),this.hasToolInstanceSelector()&&(t.toolInstanceNames=this.getSelectedToolInstanceNames());let n=this.getPromptTemplateSelections();return n.length>0&&(t.promptTemplates=n,t.promptTemplateIds=n.map(e=>e.templateId)),this.connection.invoke(`SaveSettings`,e,t).catch(e=>{console.error(`Error saving settings:`,e),this.showSaveIndicator(`Save failed`,`text-danger`)})},flushPendingSave(){return this.saveSettingsTimeout&&=(clearTimeout(this.saveSettingsTimeout),null),this.settingsDirty?(this.settingsDirty=!1,this.saveSettings()):Promise.resolve()},initializeInteraction(e,t){(!this.isInteractionStarted||t)&&(this.fireEvent(new CustomEvent(`initializingChatInteraction`,{detail:{itemId:e}})),this.setItemId(e),this.isInteractionStarted=!0)},clearCopiedMessageState(){this.copyResetTimeoutId&&=(window.clearTimeout(this.copyResetTimeoutId),null),this.activeCopyButton&&=(this.setCopyButtonState(this.activeCopyButton,!1),null),this.copiedMessageIndex=-1},copyResponse(e,t,n){let i=e&&typeof e==`object`?e.copyContent??e.content??``:e??``,a=n?.currentTarget||n?.target?.closest?.(`[data-copy-message-index]`)||null;navigator.clipboard.writeText(i).then(()=>{this.clearCopiedMessageState(),this.copiedMessageIndex=typeof t==`number`?t:-1,this.activeCopyButton=a,a?this.setCopyButtonState(a,!0):this.$nextTick(()=>this.updateCopyButtons()),this.copyResetTimeoutId=window.setTimeout(()=>{this.clearCopiedMessageState(),this.$nextTick(()=>this.updateCopyButtons())},Number(r.copyResetDelayMs)||2e3)}).catch(e=>console.error(`Failed to copy response:`,e))},startRecording(){!this.isRecording&&this.connection&&navigator.mediaDevices.getUserMedia({audio:{echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0}}).then(e=>{var t=MediaRecorder.isTypeSupported(`audio/ogg;codecs=opus`)?`audio/ogg;codecs=opus`:MediaRecorder.isTypeSupported(`audio/webm;codecs=opus`)?`audio/webm;codecs=opus`:`audio/webm`;this.mediaRecorder=new MediaRecorder(e,{mimeType:t,audioBitsPerSecond:128e3}),this.preRecordingPrompt=this.prompt,this._audioInputSent=!1;var n=new signalR.Subject,r=this.getItemId(),i=Promise.resolve();this.mediaRecorder.addEventListener(`dataavailable`,e=>{e.data&&e.data.size>0&&(i=i.then(async()=>{var t=await e.data.arrayBuffer(),r=new Uint8Array(t).reduce(function(e,t){return e+String.fromCharCode(t)},``),i=btoa(r);n.next(i)}))}),this.mediaRecorder.addEventListener(`stop`,()=>{e.getTracks().forEach(e=>e.stop()),i.then(()=>n.complete())});var a=navigator.language||document.documentElement.lang||`en-US`;this.connection.send(`SendAudioStream`,r,n,t,a),this.mediaRecorder.start(250),this.isRecording=!0,this.updateMicButton()}).catch(e=>{console.error(`Microphone access denied:`,e)})},stopRecording(){this.isRecording&&this.mediaRecorder&&(this.mediaRecorder.stop(),this.isRecording=!1,this.updateMicButton())},toggleRecording(){this.isRecording?this.stopRecording():this.startRecording()},updateMicButton(){this.micButton&&(this.isRecording?(this.micButton.classList.add(`stt-recording`),this.micButton.innerHTML=`<i class="fa-solid fa-stop"></i>`):(this.micButton.classList.remove(`stt-recording`),this.micButton.innerHTML=`<i class="fa-solid fa-microphone"></i>`))}},watch:{isPlayingAudio(){},isConversationMode(e){this.micButton&&(this.micButton.style.display=e?`none`:this.speechToTextEnabled?``:`none`),this.realtimeEnabled||this.setVoiceSessionLive(e)},copiedMessageIndex(){this.$nextTick(()=>this.updateCopyButtons())}},mounted(){(async()=>{await this.startConnection(),this.initializeApp(),this.$nextTick(()=>{this.updateCopyButtons(),i(this.$el),this.fontAwesomeObserver=a(this.$el)})})(),window.addEventListener(`beforeunload`,this.handleBeforeUnload),window.addEventListener(`crestapps-ai-chat-stop-tts`,this.handleExternalTtsStop)},beforeUnmount(){window.removeEventListener(`beforeunload`,this.handleBeforeUnload),window.removeEventListener(`crestapps-ai-chat-stop-tts`,this.handleExternalTtsStop),this.fontAwesomeObserver&&=(this.fontAwesomeObserver.disconnect(),null),this.clearCopiedMessageState(),this.stopAudio(!1),this.stream&&=(this.stream.dispose(),null),this.connection&&this.connection.stop()},template:r.messageTemplate}).mount(r.appElementSelector)},F=`[data-chat-interaction-config]`;function I(e,t,n){let r=e.getAttribute(t);if(!r)return null;try{return JSON.parse(r)}catch(e){return console.error(`Failed to parse `+n+` JSON.`,e),null}}function L(e){if(!e||e.dataset.chatInteractionInitialized===`true`)return e&&e.__chatInteractionApp||null;let t=I(e,`data-chat-interaction-config`,`chat interaction config`);if(!t)return null;let n=P(t);return n?(e.dataset.chatInteractionInitialized=`true`,e.__chatInteractionApp=n,n):null}function R(e){e&&typeof e.querySelectorAll==`function`&&(typeof e.matches==`function`&&e.matches(F)&&L(e),e.querySelectorAll(F).forEach(L))}function z(){R(document),typeof MutationObserver<`u`&&new MutationObserver(e=>{e.forEach(e=>{e.addedNodes.forEach(e=>{e&&e.nodeType===1&&R(e)})})}).observe(document.body,{childList:!0,subtree:!0})}return document.readyState===`loading`?document.addEventListener(`DOMContentLoaded`,z,{once:!0}):z(),{initialize:P,initializeFromElement:L}}(),window.chatInteractionDocumentManager=function(){let e=`__chatInteractionDocumentManagerState`;function t(e){return!e||typeof e!=`object`?null:{documentId:e.documentId||e.DocumentId||``,fileName:e.fileName||e.FileName||``,fileSize:e.fileSize||e.FileSize||0}}function n(e){return!e||e<1024?(e||0)+` B`:e<1048576?(e/1024).toFixed(1)+` KB`:(e/1048576).toFixed(1)+` MB`}function r(e,t){return(e||``).trim().toLowerCase()+`::`+(t||0)}function i(e,t){return t.has(r(e.name,e.size))}function a(e){return e?Array.from(e.querySelectorAll(`[data-chat-document-id]`)).map(e=>t({documentId:e.dataset.chatDocumentId,fileName:e.dataset.chatDocumentName,fileSize:Number(e.dataset.chatDocumentSize||0)})).filter(e=>e&&e.documentId):[]}function o(o){if(!o||!o.itemId)return;let s=document.getElementById(`chat-doc-upload`),c=document.getElementById(`chat-documents-list`),l=document.getElementById(`chat-doc-upload-status`),u=document.getElementById(`chat-doc-upload-progress`),d=document.getElementById(`chat-doc-upload-progress-bar`),f=document.getElementById(`chat-doc-upload-queue`);if(!s||!c||!l||!u||!d||!f)return;let p=s[e];p&&typeof p.dispose==`function`&&p.dispose();let m=(Array.isArray(o.existingDocuments)?o.existingDocuments:[]).map(t).filter(e=>e&&e.documentId);m.length===0&&(m=a(c));let h=[],g=!1;function _(e,t,n){let r=document.createElement(e);return t&&(r.className=t),r.textContent=n,r}function v(){c.innerHTML=``,m.length===0?c.appendChild(_(`div`,`text-muted small`,`No documents uploaded yet.`)):m.forEach(e=>{let t=window.document.createElement(`div`);t.className=`d-flex align-items-center gap-2 border rounded px-2 py-2 bg-white chat-document-row`,t.dataset.chatDocumentId=e.documentId,t.dataset.chatDocumentName=e.fileName,t.dataset.chatDocumentSize=e.fileSize;let r=window.document.createElement(`div`);r.className=`d-flex gap-1`;let i=o.downloadDocumentBaseUrl||`/ai/documents/`,a=_(`a`,`btn btn-sm btn-outline-secondary`,``);a.title=`Download`,a.href=i+encodeURIComponent(e.documentId)+`/download`;let s=window.document.createElement(`i`);s.className=`fa-solid fa-download`,a.appendChild(s);let l=_(`button`,`btn btn-sm btn-outline-danger remove-chat-document-btn`,``);l.type=`button`,l.title=`Remove`,l.dataset.documentId=e.documentId;let u=window.document.createElement(`i`);u.className=`fa-solid fa-trash`,l.appendChild(u),l.addEventListener(`click`,()=>k(e.documentId)),r.appendChild(a),r.appendChild(l);let d=window.document.createElement(`div`);d.className=`min-w-0`;let f=_(`div`,`fw-semibold small text-truncate`,e.fileName||`Document`),p=window.document.createElement(`i`);p.className=`fa-solid fa-file-lines me-1`,f.prepend(p);let m=_(`div`,`text-muted small`,n(e.fileSize));d.appendChild(f),d.appendChild(m),t.appendChild(r),t.appendChild(d),c.appendChild(t)})}function y(e,t){e?(l.textContent=e,l.className=`small mt-2 `+(t||`text-muted`)):(l.textContent=``,l.className=`small mt-2 d-none`)}function b(e,t,n){if(e==null){u.className=`progress mt-2 d-none`,u.setAttribute(`aria-valuenow`,`0`),d.className=`progress-bar progress-bar-striped progress-bar-animated`,d.style.width=`0%`,d.textContent=`0%`;return}let r=Math.max(0,Math.min(100,Math.round(e)));u.className=`progress mt-2`,u.setAttribute(`aria-valuenow`,r.toString()),d.className=`progress-bar `+(n||`progress-bar-striped progress-bar-animated`),d.style.width=r+`%`,d.textContent=t||r+`%`}function x(e){switch(e){case`uploaded`:return{label:`Uploaded`,badgeClass:`text-bg-success`,progressClass:`bg-success`};case`failed`:return{label:`Failed`,badgeClass:`text-bg-danger`,progressClass:`bg-danger`};case`uploading`:return{label:`Uploading`,badgeClass:`text-bg-warning`,progressClass:`bg-warning progress-bar-striped progress-bar-animated`};default:return{label:`Queued`,badgeClass:`text-bg-secondary`,progressClass:`bg-secondary progress-bar-striped progress-bar-animated`}}}function S(e){return e.status===`failed`&&e.error?e.error:e.status===`uploaded`?`Upload completed successfully.`:e.status===`uploading`?e.progress+`% uploaded`:`Waiting to upload...`}function C(){f.innerHTML=``,h.forEach(e=>{let t=x(e.status),r=document.createElement(`div`);r.className=`border rounded px-2 py-2 bg-white`;let i=document.createElement(`div`);i.className=`d-flex justify-content-between align-items-start gap-2`;let a=document.createElement(`div`);a.className=`flex-grow-1 min-w-0`,a.appendChild(_(`div`,`fw-semibold small`,e.fileName)),a.appendChild(_(`div`,`text-muted small`,n(e.fileSize)));let o=_(`span`,`badge `+t.badgeClass,t.label);i.appendChild(a),i.appendChild(o);let s=document.createElement(`div`);s.className=`progress mt-2`,s.setAttribute(`role`,`progressbar`),s.setAttribute(`aria-valuemin`,`0`),s.setAttribute(`aria-valuemax`,`100`),s.setAttribute(`aria-valuenow`,e.progress.toString());let c=document.createElement(`div`);c.className=`progress-bar `+t.progressClass,c.style.width=e.progress+`%`,c.textContent=e.progress+`%`,s.appendChild(c);let l=_(`div`,e.status===`failed`?`small text-danger mt-2`:`small text-muted mt-2`,S(e));r.appendChild(i),r.appendChild(s),r.appendChild(l),f.appendChild(r)})}function w(e,t){return{id:e.name+`::`+e.size+`::`+e.lastModified+`::`+t+`::`+Date.now(),fileName:e.name,fileSize:e.size,status:`queued`,progress:0,error:null}}function T(e,t){h=h.map(n=>n.id===e?Object.assign({},n,t):n),C()}function E(e){h=h.filter(t=>!e(t)),C()}function D(e,t,n,r){return new Promise((i,a)=>{let s=new FormData;s.append(`chatInteractionId`,o.itemId),s.append(`files`,e);let c=new XMLHttpRequest;c.open(`POST`,o.uploadDocumentUrl,!0),c.upload.addEventListener(`progress`,e=>{e.lengthComputable&&(T(t,{status:`uploading`,progress:Math.round(e.loaded/e.total*100)}),b((n+e.loaded/e.total)/r*100,`Uploading `+(n+1)+` of `+r,`progress-bar-striped progress-bar-animated`))}),c.addEventListener(`load`,()=>{if(c.status>=200&&c.status<300)try{i(JSON.parse(c.responseText))}catch{a(Error(`Upload failed: invalid server response.`))}else a(Error((c.responseText||`Upload failed.`).trim()))}),c.addEventListener(`error`,()=>{a(Error(`Upload failed. Please check your connection and try again.`))}),c.send(s)})}async function O(e){if(!o.uploadDocumentUrl||!e||e.length===0)return;if(g){y(`A document upload is already in progress.`,`text-warning`);return}g=!0;let n=[],a=[],c=new Set(m.map(e=>r(e.fileName,e.fileSize)));if(Array.from(e).forEach(e=>{i(e,c)?a.push(e):(c.add(r(e.name,e.size)),n.push(e))}),a.length>0&&(h=h.concat(a.map((e,t)=>Object.assign(w(e,t),{status:`failed`,progress:100,error:`This document is already attached.`}))),C()),n.length===0){g=!1,y(a.map(e=>e.name+`: This document is already attached.`).join(` | `),`text-warning`),b(null);return}let l=n.map(w);h=h.concat(l),C(),b(0,`Preparing upload...`,`progress-bar-striped progress-bar-animated`),s.disabled=!0;try{let e=0,r=a.map(e=>e.name+`: This document is already attached.`);for(let i=0;i<n.length;i++){let a=n[i],o=l[i];T(o.id,{status:`uploading`,progress:0,error:null}),y(`Uploading `+(i+1)+` of `+n.length+` document(s)...`,`text-warning`);try{let s=await D(a,o.id,i,n.length),c=(Array.isArray(s.uploaded)?s.uploaded:[]).map(t).filter(e=>e&&e.documentId),l=Array.isArray(s.failed)?s.failed:[];if(c.length>0)e+=c.length,m=m.concat(c),T(o.id,{status:`uploaded`,progress:100,error:null});else{let e=l.length>0?l.map(e=>e.fileName+`: `+e.error).join(` | `):`The server did not confirm that the file was uploaded.`;l.length===0&&r.push(e),T(o.id,{status:`failed`,progress:100,error:e})}if(l.length>0){let e=l.map(e=>e.fileName+`: `+e.error).join(` | `);r.push(e),T(o.id,{status:`failed`,progress:100,error:e})}}catch(e){let t=e&&e.message?e.message:`Upload failed. Please try again.`;console.error(`Upload failed:`,e),r.push(a.name+`: `+t),T(o.id,{status:`failed`,progress:o.progress||0,error:t})}}if(v(),r.length>0){E(e=>e.status===`uploaded`),y((e>0?`Uploaded `+e+` document(s). `:``)+r.join(` | `),e>0?`text-warning`:`text-danger`),b(null);return}E(()=>!0),y(`Uploaded `+e+` document(s).`,`text-success`),b(null)}catch(e){console.error(`Upload failed:`,e),y(`Upload failed. Please try again.`,`text-danger`),b(null)}finally{g=!1,s.disabled=!1,s.value=``}}async function k(e){if(o.removeDocumentUrl&&e&&window.confirm(`Remove this document?`))try{let n=await fetch(o.removeDocumentUrl,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({itemId:o.itemId,documentId:e})});if(!n.ok){console.error(`Failed to remove document:`,await n.text()),y(`Failed to remove document.`,`text-danger`);return}if((n.headers.get(`content-type`)||``).toLowerCase().indexOf(`json`)<0){console.error(`Remove document: response was not JSON.`,{status:n.status,redirected:n.redirected}),y(n.redirected?`You may not be signed in, or you do not have permission for this. Please reload and try again.`:`Failed to remove document.`,`text-danger`);return}let r=await n.json(),i=(Array.isArray(r.documents)?r.documents:[]).map(t).filter(e=>e&&e.documentId);m=i.length>0?i:m.filter(t=>t.documentId!==e),v(),y(`Document removed.`,`text-success`)}catch(e){console.error(`Remove failed:`,e),y(`Failed to remove document.`,`text-danger`)}}let A=e=>{O(e.target.files?Array.from(e.target.files):[])};return s.addEventListener(`change`,A),s[e]={dispose:()=>{s.removeEventListener(`change`,A)}},v(),C(),y(null),b(null),s[e]}function s(e,t,n){let r=e.getAttribute(t);if(!r)return null;try{return JSON.parse(r)}catch(e){return console.error(`Failed to parse `+n+` JSON.`,e),null}}function c(t){if(!t||t.dataset.chatInteractionDocumentManagerInitialized===`true`)return t&&t[e]||null;let n=s(t,`data-chat-interaction-document-manager-config`,`chat interaction document manager config`);if(!n)return null;let r=o(n);return r?(t.dataset.chatInteractionDocumentManagerInitialized=`true`,r):null}function l(e){e&&typeof e.querySelectorAll==`function`&&(typeof e.matches==`function`&&e.matches(`[data-chat-interaction-document-manager-config]`)&&c(e),e.querySelectorAll(`[data-chat-interaction-document-manager-config]`).forEach(c))}function u(){l(document),typeof MutationObserver<`u`&&new MutationObserver(e=>{e.forEach(e=>{e.addedNodes.forEach(e=>{e&&e.nodeType===1&&l(e)})})}).observe(document.body,{childList:!0,subtree:!0})}return document.readyState===`loading`?document.addEventListener(`DOMContentLoaded`,u,{once:!0}):u(),{initialize:o,initializeFromElement:c}}(),document.addEventListener(`click`,function(e){let t=e.target.closest(`.download-chart-btn`);if(!t)return;let n=t.getAttribute(`data-chart-id`),r=n?document.getElementById(n):null;if(!r){console.error(`Chart canvas not found:`,n);return}let i=document.createElement(`a`);i.download=`chart-`+n+`.png`,i.href=r.toDataURL(`image/png`),i.click()}),document.addEventListener(`click`,function(e){let t=e.target.closest(`.ai-download-image`);if(!t)return;let n=t.closest(`.generated-image-container`)?.querySelector(`img`);if(!n)return;let r=n.src;r&&r.startsWith(`data:`)&&(e.preventDefault(),fetch(r).then(function(e){return e.blob()}).then(function(e){let n=URL.createObjectURL(e),r=document.createElement(`a`);r.href=n,r.download=t.getAttribute(`download`)||`generated-image.png`,document.body.appendChild(r),r.click(),document.body.removeChild(r),setTimeout(function(){URL.revokeObjectURL(n)},100)}).catch(function(e){console.error(`Failed to download image:`,e)}))})})();
|
|
63
63
|
//# sourceMappingURL=chat-interaction.min.js.map
|