@crestapps/ai-chat-ui 1.0.0-rc.7 → 1.0.0

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.
@@ -32,8 +32,11 @@ window.chatInteractionManager = function () {
32
32
  downloadChartTitle: 'Download chart as image',
33
33
  downloadChartButtonText: 'Download',
34
34
  codeCopiedText: 'Copied!',
35
+ copyTitle: 'Click here to copy response to clipboard.',
36
+ copiedTitle: 'Response copied to clipboard.',
37
+ copyResetDelayMs: 2000,
35
38
  assistantLabel: 'Assistant',
36
- messageTemplate: "\n <div class=\"ai-chat-messages\">\n <div v-for=\"(message, index) in messages\" :key=\"index\" class=\"ai-chat-message-item\">\n <div>\n <div v-if=\"message.role === 'user'\" class=\"ai-chat-msg-role ai-chat-msg-role-user\">You</div>\n <div v-else-if=\"message.role !== 'indicator'\" :class=\"getAssistantRoleClasses(message)\">\n <span :class=\"getAssistantIconClasses(message, index)\"><i :class=\"getAssistantIcon(message)\"></i></span>\n {{ getAssistantLabel(message) }}\n </div>\n <div class=\"ai-chat-message-body lh-base\">\n <h4 v-if=\"message.title\">{{ message.title }}</h4>\n <div v-html=\"message.htmlContent\"></div>\n <ol v-if=\"message.citationReferences && message.citationReferences.length\" class=\"ai-chat-citation-list\">\n <li v-for=\"citation in message.citationReferences\" :key=\"'citation-' + (citation.referenceKey || citation.displayIndex)\" class=\"ai-chat-citation-item\">\n <a v-if=\"citation.link\" :href=\"citation.link\" :target=\"citation.isDownload ? null : '_blank'\" :rel=\"citation.isDownload ? null : 'noopener noreferrer'\">{{ citation.label }}</a>\n <span v-else>{{ citation.label }}</span>\n </li>\n </ol>\n <span class=\"message-buttons-container\" v-if=\"!isIndicator(message)\">\n <button v-if=\"textToSpeechEnabled && !isConversationMode && message.role === 'assistant' && !message.isStreaming\" class=\"btn btn-sm btn-link text-secondary p-0 me-1 button-message-toolbox\" :class=\"{ 'tts-playing': ttsPlayingMessageIndex === index }\" :data-tts-message-index=\"index\" @click=\"toggleMessageTts(message, index)\" :title=\"ttsPlayingMessageIndex === index ? 'Pause audio' : 'Read aloud'\">\n <i :class=\"ttsPlayingMessageIndex === index ? 'fa-solid fa-circle-pause' : 'fa-solid fa-circle-play'\"></i>\n </button>\n <button class=\"btn btn-sm btn-link text-secondary p-0 button-message-toolbox\" @click=\"copyResponse(message)\" title=\"Click here to copy response to clipboard.\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n </span>\n </div>\n </div>\n </div>\n <div v-for=\"notification in notifications\" :key=\"'notif-' + notification.type\" class=\"ai-chat-notification\" :class=\"'ai-chat-notification-' + (notification.type || 'info') + ' ' + (notification.cssClass || '')\">\n <div class=\"ai-chat-notification-content\">\n <i v-if=\"notification.icon\" :class=\"notification.icon\" class=\"ai-chat-notification-icon\"></i>\n <span class=\"ai-chat-notification-text\">{{ notification.content }}</span>\n <button v-if=\"notification.dismissible\" class=\"btn btn-sm btn-link p-0 ms-2 ai-chat-notification-dismiss\" @click=\"dismissNotification(notification.type)\" title=\"Dismiss\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n <div v-if=\"notification.actions && notification.actions.length\" class=\"ai-chat-notification-actions\">\n <button v-for=\"action in notification.actions\" :key=\"action.name\" class=\"btn btn-sm\" :class=\"action.cssClass || 'btn-outline-secondary'\" @click=\"handleNotificationAction(notification.type, action.name)\">\n <i v-if=\"action.icon\" :class=\"action.icon\" class=\"me-1\"></i>\n {{ action.label }}\n </button>\n </div>\n </div>\n </div>\n ",
39
+ messageTemplate: "\n <div class=\"ai-chat-messages\">\n <div v-for=\"(message, index) in messages\" :key=\"index\" class=\"ai-chat-message-item\">\n <div>\n <div v-if=\"message.role === 'user'\" class=\"ai-chat-msg-role ai-chat-msg-role-user\">You</div>\n <div v-else-if=\"message.role !== 'indicator'\" :class=\"getAssistantRoleClasses(message)\">\n <span :class=\"getAssistantIconClasses(message, index)\"><i :class=\"getAssistantIcon(message)\"></i></span>\n {{ getAssistantLabel(message) }}\n </div>\n <div class=\"ai-chat-message-body lh-base\">\n <h4 v-if=\"message.title\">{{ message.title }}</h4>\n <div v-html=\"message.htmlContent\"></div>\n <ol v-if=\"message.citationReferences && message.citationReferences.length\" class=\"ai-chat-citation-list\">\n <li v-for=\"citation in message.citationReferences\" :key=\"'citation-' + (citation.referenceKey || citation.displayIndex)\" class=\"ai-chat-citation-item\">\n <a v-if=\"citation.link\" :href=\"citation.link\" :target=\"citation.isDownload ? null : '_blank'\" :rel=\"citation.isDownload ? null : 'noopener noreferrer'\">{{ citation.label }}</a>\n <span v-else>{{ citation.label }}</span>\n </li>\n </ol>\n <span class=\"message-buttons-container\" v-if=\"!isIndicator(message)\">\n <button v-if=\"textToSpeechEnabled && !isConversationMode && message.role === 'assistant' && !message.isStreaming\" class=\"btn btn-sm btn-link text-secondary p-0 me-1 button-message-toolbox\" :class=\"{ 'tts-playing': ttsPlayingMessageIndex === index }\" :data-tts-message-index=\"index\" @click=\"toggleMessageTts(message, index)\" :title=\"ttsPlayingMessageIndex === index ? 'Pause audio' : 'Read aloud'\">\n <i :class=\"ttsPlayingMessageIndex === index ? 'fa-solid fa-circle-pause' : 'fa-solid fa-circle-play'\"></i>\n </button>\n <button type=\"button\" class=\"btn btn-sm btn-link p-0 button-message-toolbox ai-response-copy-btn\" :class=\"copiedMessageIndex === index ? 'text-success' : 'text-secondary'\" :data-copy-message-index=\"index\" @click=\"copyResponse(message, index, $event)\" :title=\"copiedMessageIndex === index ? copiedTitle : copyTitle\">\n <i :class=\"copiedMessageIndex === index ? 'fa-solid fa-check' : 'fa-solid fa-copy'\"></i>\n </button>\n </span>\n </div>\n </div>\n </div>\n <div v-for=\"notification in notifications\" :key=\"'notif-' + notification.type\" class=\"ai-chat-notification\" :class=\"'ai-chat-notification-' + (notification.type || 'info') + ' ' + (notification.cssClass || '')\">\n <div class=\"ai-chat-notification-content\">\n <i v-if=\"notification.icon\" :class=\"notification.icon\" class=\"ai-chat-notification-icon\"></i>\n <span class=\"ai-chat-notification-text\">{{ notification.content }}</span>\n <button v-if=\"notification.dismissible\" class=\"btn btn-sm btn-link p-0 ms-2 ai-chat-notification-dismiss\" @click=\"dismissNotification(notification.type)\" title=\"Dismiss\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n <div v-if=\"notification.actions && notification.actions.length\" class=\"ai-chat-notification-actions\">\n <button v-for=\"action in notification.actions\" :key=\"action.name\" class=\"btn btn-sm\" :class=\"action.cssClass || 'btn-outline-secondary'\" @click=\"handleNotificationAction(notification.type, action.name)\">\n <i v-if=\"action.icon\" :class=\"action.icon\" class=\"me-1\"></i>\n {{ action.label }}\n </button>\n </div>\n </div>\n </div>\n ",
37
40
  indicatorTemplate: "\n <div class=\"ai-chat-msg-role ai-chat-msg-role-assistant\">\n <span class=\"ai-streaming-icon\"><i class=\"fa fa-robot\" style=\"display: inline-block;\"></i></span>\n Assistant\n </div>\n ",
38
41
  // Localizable strings
39
42
  untitledText: 'Untitled',
@@ -96,7 +99,7 @@ window.chatInteractionManager = function () {
96
99
  return observer;
97
100
  }
98
101
  function normalizeReference(reference) {
99
- var _ref, _normalized$index, _ref2, _normalized$text, _ref3, _normalized$title, _ref4, _normalized$link, _ref5, _normalized$reference;
102
+ var _ref, _normalized$index, _ref2, _normalized$text, _ref3, _normalized$title, _ref4, _normalized$link, _ref5, _normalized$reference, _normalized$isGenerat;
100
103
  if (!reference || _typeof(reference) !== 'object') {
101
104
  return null;
102
105
  }
@@ -106,6 +109,7 @@ window.chatInteractionManager = function () {
106
109
  normalized.title = (_ref3 = (_normalized$title = normalized.title) !== null && _normalized$title !== void 0 ? _normalized$title : normalized.Title) !== null && _ref3 !== void 0 ? _ref3 : null;
107
110
  normalized.link = sanitizeUrl((_ref4 = (_normalized$link = normalized.link) !== null && _normalized$link !== void 0 ? _normalized$link : normalized.Link) !== null && _ref4 !== void 0 ? _ref4 : null);
108
111
  normalized.referenceType = (_ref5 = (_normalized$reference = normalized.referenceType) !== null && _normalized$reference !== void 0 ? _normalized$reference : normalized.ReferenceType) !== null && _ref5 !== void 0 ? _ref5 : null;
112
+ normalized.isGenerated = ((_normalized$isGenerat = normalized.isGenerated) !== null && _normalized$isGenerat !== void 0 ? _normalized$isGenerat : normalized.IsGenerated) === true;
109
113
  return normalized;
110
114
  }
111
115
  function isDownloadCitationReference(reference) {
@@ -140,28 +144,42 @@ window.chatInteractionManager = function () {
140
144
  function buildCitationDisplay(content, references) {
141
145
  var processedContent = (content || '').trim();
142
146
  var messageReferences = normalizeReferences(references);
143
- if (!processedContent || !Object.keys(messageReferences).length) {
147
+ var referenceEntries = Object.entries(messageReferences);
148
+ if (!referenceEntries.length) {
144
149
  return {
145
150
  content: processedContent,
146
151
  citations: []
147
152
  };
148
153
  }
149
- var citedRefs = Object.entries(messageReferences).filter(function (_ref6) {
154
+ var citedRefs = referenceEntries.filter(function (_ref6) {
150
155
  var _ref7 = _slicedToArray(_ref6, 1),
151
156
  key = _ref7[0];
152
157
  return processedContent.includes(key);
153
158
  });
154
- if (!citedRefs.length) {
159
+ var generatedRefs = referenceEntries.filter(function (_ref8) {
160
+ var _ref9 = _slicedToArray(_ref8, 2),
161
+ key = _ref9[0],
162
+ value = _ref9[1];
163
+ return value.isGenerated && !processedContent.includes(key);
164
+ });
165
+ if (!citedRefs.length && !generatedRefs.length) {
155
166
  return {
156
167
  content: processedContent,
157
168
  citations: []
158
169
  };
159
170
  }
160
- citedRefs.sort(function (_ref8, _ref9) {
161
- var _ref0 = _slicedToArray(_ref8, 2),
162
- a = _ref0[1];
163
- var _ref1 = _slicedToArray(_ref9, 2),
164
- b = _ref1[1];
171
+ citedRefs.sort(function (_ref0, _ref1) {
172
+ var _ref10 = _slicedToArray(_ref0, 2),
173
+ a = _ref10[1];
174
+ var _ref11 = _slicedToArray(_ref1, 2),
175
+ b = _ref11[1];
176
+ return a.index - b.index;
177
+ });
178
+ generatedRefs.sort(function (_ref12, _ref13) {
179
+ var _ref14 = _slicedToArray(_ref12, 2),
180
+ a = _ref14[1];
181
+ var _ref15 = _slicedToArray(_ref13, 2),
182
+ b = _ref15[1];
165
183
  return a.index - b.index;
166
184
  });
167
185
  var citations = [];
@@ -195,11 +213,36 @@ window.chatInteractionManager = function () {
195
213
  processedContent = processedContent.replaceAll(citation.placeholder, "<sup>".concat(citation.displayIndex, "</sup>"));
196
214
  }
197
215
  processedContent = processedContent.replaceAll('</sup><sup>', '</sup><sup>,</sup><sup>');
216
+
217
+ // Generated files (such as exported tabular data) are always offered as a download even when
218
+ // the model does not cite them inline, so the user never loses access to the produced file.
219
+ var _iterator2 = _createForOfIteratorHelper(generatedRefs),
220
+ _step2;
221
+ try {
222
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
223
+ var _step2$value = _slicedToArray(_step2.value, 2),
224
+ _key = _step2$value[0],
225
+ _value = _step2$value[1];
226
+ citations.push({
227
+ referenceKey: _key,
228
+ displayIndex: displayIndex,
229
+ label: getCitationLabel(_value, _key),
230
+ link: _value.link || null,
231
+ isDownload: true,
232
+ placeholder: null
233
+ });
234
+ displayIndex++;
235
+ }
236
+ } catch (err) {
237
+ _iterator2.e(err);
238
+ } finally {
239
+ _iterator2.f();
240
+ }
198
241
  return {
199
242
  content: processedContent,
200
- citations: citations.map(function (_ref10) {
201
- var placeholder = _ref10.placeholder,
202
- citation = _objectWithoutProperties(_ref10, _excluded);
243
+ citations: citations.map(function (_ref16) {
244
+ var placeholder = _ref16.placeholder,
245
+ citation = _objectWithoutProperties(_ref16, _excluded);
203
246
  return citation;
204
247
  })
205
248
  };
@@ -209,24 +252,24 @@ window.chatInteractionManager = function () {
209
252
  if (!copyContent || !Array.isArray(citations) || citations.length === 0) {
210
253
  return copyContent;
211
254
  }
212
- var _iterator2 = _createForOfIteratorHelper(citations),
213
- _step2;
255
+ var _iterator3 = _createForOfIteratorHelper(citations),
256
+ _step3;
214
257
  try {
215
- for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
216
- var citation = _step2.value;
258
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
259
+ var citation = _step3.value;
217
260
  copyContent = copyContent.replaceAll(citation.referenceKey, "[".concat(citation.displayIndex, "]"));
218
261
  }
219
262
  } catch (err) {
220
- _iterator2.e(err);
263
+ _iterator3.e(err);
221
264
  } finally {
222
- _iterator2.f();
265
+ _iterator3.f();
223
266
  }
224
267
  copyContent += '\n\nReferences:\n';
225
- var _iterator3 = _createForOfIteratorHelper(citations),
226
- _step3;
268
+ var _iterator4 = _createForOfIteratorHelper(citations),
269
+ _step4;
227
270
  try {
228
- for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
229
- var _citation = _step3.value;
271
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
272
+ var _citation = _step4.value;
230
273
  copyContent += "".concat(_citation.displayIndex, ". ").concat(_citation.label);
231
274
  if (_citation.link) {
232
275
  copyContent += " - ".concat(_citation.link);
@@ -234,9 +277,9 @@ window.chatInteractionManager = function () {
234
277
  copyContent += '\n';
235
278
  }
236
279
  } catch (err) {
237
- _iterator3.e(err);
280
+ _iterator4.e(err);
238
281
  } finally {
239
- _iterator3.f();
282
+ _iterator4.f();
240
283
  }
241
284
  return copyContent.trimEnd();
242
285
  }
@@ -416,11 +459,11 @@ window.chatInteractionManager = function () {
416
459
  // Defer to requestAnimationFrame so the browser has fully laid out the
417
460
  // canvas elements before Chart.js reads their dimensions.
418
461
  requestAnimationFrame(function () {
419
- var _iterator4 = _createForOfIteratorHelper(charts),
420
- _step4;
462
+ var _iterator5 = _createForOfIteratorHelper(charts),
463
+ _step5;
421
464
  try {
422
- for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
423
- var c = _step4.value;
465
+ for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
466
+ var c = _step5.value;
424
467
  var canvas = document.getElementById(c.chartId);
425
468
  if (!canvas) {
426
469
  continue;
@@ -453,9 +496,9 @@ window.chatInteractionManager = function () {
453
496
  }
454
497
  }
455
498
  } catch (err) {
456
- _iterator4.e(err);
499
+ _iterator5.e(err);
457
500
  } finally {
458
- _iterator4.f();
501
+ _iterator5.f();
459
502
  }
460
503
  });
461
504
  }
@@ -474,8 +517,18 @@ window.chatInteractionManager = function () {
474
517
  ADD_ATTR: ['target']
475
518
  });
476
519
  }
520
+ function compactObject(source) {
521
+ if (!source || _typeof(source) !== 'object') {
522
+ return {};
523
+ }
524
+ return Object.fromEntries(Object.entries(source).filter(function (_ref17) {
525
+ var _ref18 = _slicedToArray(_ref17, 2),
526
+ value = _ref18[1];
527
+ return value !== undefined;
528
+ }));
529
+ }
477
530
  var initialize = function initialize(instanceConfig) {
478
- var config = Object.assign({}, defaultConfig, instanceConfig);
531
+ var config = Object.assign({}, defaultConfig, compactObject(instanceConfig));
479
532
  // Keep defaultConfig in sync so renderers use overridden values
480
533
  defaultConfig = config;
481
534
  if (!config.signalRHubUrl) {
@@ -536,7 +589,12 @@ window.chatInteractionManager = function () {
536
589
  conversationButton: null,
537
590
  isConversationMode: false,
538
591
  notifications: [],
539
- notificationDismissTimers: {}
592
+ notificationDismissTimers: {},
593
+ copyTitle: config.copyTitle,
594
+ copiedTitle: config.copiedTitle,
595
+ copiedMessageIndex: -1,
596
+ copyResetTimeoutId: null,
597
+ activeCopyButton: null
540
598
  };
541
599
  },
542
600
  computed: {
@@ -1035,9 +1093,9 @@ window.chatInteractionManager = function () {
1035
1093
  var _this6 = this;
1036
1094
  references = normalizeReferences(references);
1037
1095
  if (Object.keys(references).length) {
1038
- var _ref11, _message$rawContent2;
1096
+ var _ref19, _message$rawContent2;
1039
1097
  var message = this.messages[messageIndex];
1040
- message.rawContent = (_ref11 = (_message$rawContent2 = message.rawContent) !== null && _message$rawContent2 !== void 0 ? _message$rawContent2 : message.content) !== null && _ref11 !== void 0 ? _ref11 : '';
1098
+ message.rawContent = (_ref19 = (_message$rawContent2 = message.rawContent) !== null && _message$rawContent2 !== void 0 ? _message$rawContent2 : message.content) !== null && _ref19 !== void 0 ? _ref19 : '';
1041
1099
  updateMessagePresentation(message, references);
1042
1100
  this.messages[messageIndex] = message;
1043
1101
  this.$nextTick(function () {
@@ -1107,8 +1165,38 @@ window.chatInteractionManager = function () {
1107
1165
  }));
1108
1166
  });
1109
1167
  },
1110
- synthesizeSpeech: function synthesizeSpeech(text, cacheIndex) {
1168
+ updateCopyButtons: function updateCopyButtons() {
1111
1169
  var _this8 = this;
1170
+ if (!this.chatContainer) {
1171
+ return;
1172
+ }
1173
+ var buttons = this.chatContainer.querySelectorAll('[data-copy-message-index]');
1174
+ buttons.forEach(function (button) {
1175
+ var buttonIndex = Number(button.getAttribute('data-copy-message-index'));
1176
+ var isCopied = buttonIndex === _this8.copiedMessageIndex;
1177
+ var iconHtml = isCopied ? '<i class="fa-solid fa-check"></i>' : '<i class="fa-solid fa-copy"></i>';
1178
+ button.classList.toggle('text-success', isCopied);
1179
+ button.classList.toggle('text-secondary', !isCopied);
1180
+ button.setAttribute('title', isCopied ? _this8.copiedTitle : _this8.copyTitle);
1181
+ button.replaceChildren(DOMPurify.sanitize(iconHtml, {
1182
+ RETURN_DOM_FRAGMENT: true
1183
+ }));
1184
+ });
1185
+ },
1186
+ setCopyButtonState: function setCopyButtonState(button, isCopied) {
1187
+ if (!button) {
1188
+ return;
1189
+ }
1190
+ var iconHtml = isCopied ? '<i class="fa-solid fa-check"></i>' : '<i class="fa-solid fa-copy"></i>';
1191
+ button.classList.toggle('text-success', isCopied);
1192
+ button.classList.toggle('text-secondary', !isCopied);
1193
+ button.setAttribute('title', isCopied ? this.copiedTitle : this.copyTitle);
1194
+ button.replaceChildren(DOMPurify.sanitize(iconHtml, {
1195
+ RETURN_DOM_FRAGMENT: true
1196
+ }));
1197
+ },
1198
+ synthesizeSpeech: function synthesizeSpeech(text, cacheIndex) {
1199
+ var _this9 = this;
1112
1200
  if (!this.textToSpeechEnabled || !text || !this.connection) {
1113
1201
  return;
1114
1202
  }
@@ -1117,16 +1205,16 @@ window.chatInteractionManager = function () {
1117
1205
  this._ttsCacheIndex = cacheIndex !== undefined ? cacheIndex : -1;
1118
1206
  this.connection.invoke("SynthesizeSpeech", this.getItemId(), text, this.ttsVoiceName)["catch"](function (err) {
1119
1207
  console.error("TTS synthesis error:", err);
1120
- _this8.isPlayingAudio = false;
1121
- _this8.ttsPlayingMessageIndex = -1;
1122
- _this8._ttsCacheIndex = -1;
1123
- _this8.$nextTick(function () {
1124
- return _this8.updateTtsPlaybackButtons();
1208
+ _this9.isPlayingAudio = false;
1209
+ _this9.ttsPlayingMessageIndex = -1;
1210
+ _this9._ttsCacheIndex = -1;
1211
+ _this9.$nextTick(function () {
1212
+ return _this9.updateTtsPlaybackButtons();
1125
1213
  });
1126
1214
  });
1127
1215
  },
1128
1216
  toggleMessageTts: function toggleMessageTts(message, index) {
1129
- var _this9 = this;
1217
+ var _this0 = this;
1130
1218
  if (this.ttsPlayingMessageIndex === index) {
1131
1219
  this.stopAudio();
1132
1220
  return;
@@ -1139,7 +1227,7 @@ window.chatInteractionManager = function () {
1139
1227
  }));
1140
1228
  this.ttsPlayingMessageIndex = index;
1141
1229
  this.$nextTick(function () {
1142
- return _this9.updateTtsPlaybackButtons();
1230
+ return _this0.updateTtsPlaybackButtons();
1143
1231
  });
1144
1232
  if (this.ttsAudioCache[index]) {
1145
1233
  this.playAudioBlob(this.ttsAudioCache[index]);
@@ -1148,13 +1236,13 @@ window.chatInteractionManager = function () {
1148
1236
  this.synthesizeSpeech(message.content, index);
1149
1237
  },
1150
1238
  playCollectedAudio: function playCollectedAudio() {
1151
- var _this0 = this;
1239
+ var _this1 = this;
1152
1240
  if (this.audioChunks.length === 0) {
1153
1241
  if (!this.isPlayingAudio && this.audioPlayQueue.length === 0) {
1154
1242
  this.isPlayingAudio = false;
1155
1243
  this.ttsPlayingMessageIndex = -1;
1156
1244
  this.$nextTick(function () {
1157
- return _this0.updateTtsPlaybackButtons();
1245
+ return _this1.updateTtsPlaybackButtons();
1158
1246
  });
1159
1247
  }
1160
1248
  return;
@@ -1164,18 +1252,18 @@ window.chatInteractionManager = function () {
1164
1252
  }, 0);
1165
1253
  var combined = new Uint8Array(totalLength);
1166
1254
  var offset = 0;
1167
- var _iterator5 = _createForOfIteratorHelper(this.audioChunks),
1168
- _step5;
1255
+ var _iterator6 = _createForOfIteratorHelper(this.audioChunks),
1256
+ _step6;
1169
1257
  try {
1170
- for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
1171
- var chunk = _step5.value;
1258
+ for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
1259
+ var chunk = _step6.value;
1172
1260
  combined.set(chunk, offset);
1173
1261
  offset += chunk.length;
1174
1262
  }
1175
1263
  } catch (err) {
1176
- _iterator5.e(err);
1264
+ _iterator6.e(err);
1177
1265
  } finally {
1178
- _iterator5.f();
1266
+ _iterator6.f();
1179
1267
  }
1180
1268
  this.audioChunks = [];
1181
1269
  var blob = new Blob([combined], {
@@ -1194,39 +1282,39 @@ window.chatInteractionManager = function () {
1194
1282
  this.playAudioBlob(blob);
1195
1283
  },
1196
1284
  playAudioBlob: function playAudioBlob(blob) {
1197
- var _this1 = this;
1285
+ var _this10 = this;
1198
1286
  var url = URL.createObjectURL(blob);
1199
1287
  var audio = new Audio(url);
1200
1288
  this.currentAudioUrl = url;
1201
1289
  this.currentAudioElement = audio;
1202
1290
  this.isPlayingAudio = true;
1203
1291
  audio.addEventListener('ended', function () {
1204
- _this1.currentAudioElement = null;
1205
- _this1.currentAudioUrl = null;
1292
+ _this10.currentAudioElement = null;
1293
+ _this10.currentAudioUrl = null;
1206
1294
  URL.revokeObjectURL(url);
1207
- _this1.playNextInQueue();
1295
+ _this10.playNextInQueue();
1208
1296
  });
1209
1297
  audio.addEventListener('error', function () {
1210
- _this1.currentAudioElement = null;
1211
- _this1.currentAudioUrl = null;
1298
+ _this10.currentAudioElement = null;
1299
+ _this10.currentAudioUrl = null;
1212
1300
  URL.revokeObjectURL(url);
1213
- _this1.playNextInQueue();
1301
+ _this10.playNextInQueue();
1214
1302
  });
1215
1303
  audio.play()["catch"](function (err) {
1216
1304
  console.error("Audio playback error:", err);
1217
- _this1.currentAudioElement = null;
1218
- _this1.currentAudioUrl = null;
1305
+ _this10.currentAudioElement = null;
1306
+ _this10.currentAudioUrl = null;
1219
1307
  URL.revokeObjectURL(url);
1220
- _this1.audioPlayQueue = [];
1221
- _this1.isPlayingAudio = false;
1222
- _this1.ttsPlayingMessageIndex = -1;
1223
- _this1.$nextTick(function () {
1224
- return _this1.updateTtsPlaybackButtons();
1308
+ _this10.audioPlayQueue = [];
1309
+ _this10.isPlayingAudio = false;
1310
+ _this10.ttsPlayingMessageIndex = -1;
1311
+ _this10.$nextTick(function () {
1312
+ return _this10.updateTtsPlaybackButtons();
1225
1313
  });
1226
1314
  });
1227
1315
  },
1228
1316
  playNextInQueue: function playNextInQueue() {
1229
- var _this10 = this;
1317
+ var _this11 = this;
1230
1318
  if (this.audioPlayQueue.length > 0) {
1231
1319
  var nextBlob = this.audioPlayQueue.shift();
1232
1320
  this.playAudioBlob(nextBlob);
@@ -1234,13 +1322,13 @@ window.chatInteractionManager = function () {
1234
1322
  this.isPlayingAudio = false;
1235
1323
  this.ttsPlayingMessageIndex = -1;
1236
1324
  this.$nextTick(function () {
1237
- return _this10.updateTtsPlaybackButtons();
1325
+ return _this11.updateTtsPlaybackButtons();
1238
1326
  });
1239
1327
  this.conversationModeOnAudioEnded();
1240
1328
  }
1241
1329
  },
1242
1330
  stopAudio: function stopAudio() {
1243
- var _this11 = this;
1331
+ var _this12 = this;
1244
1332
  if (this.currentAudioElement) {
1245
1333
  this.currentAudioElement.pause();
1246
1334
  this.currentAudioElement.currentTime = 0;
@@ -1255,7 +1343,7 @@ window.chatInteractionManager = function () {
1255
1343
  this.isPlayingAudio = false;
1256
1344
  this.ttsPlayingMessageIndex = -1;
1257
1345
  this.$nextTick(function () {
1258
- return _this11.updateTtsPlaybackButtons();
1346
+ return _this12.updateTtsPlaybackButtons();
1259
1347
  });
1260
1348
  },
1261
1349
  toggleConversationMode: function toggleConversationMode() {
@@ -1266,7 +1354,7 @@ window.chatInteractionManager = function () {
1266
1354
  }
1267
1355
  },
1268
1356
  startConversationMode: function startConversationMode() {
1269
- var _this12 = this;
1357
+ var _this13 = this;
1270
1358
  if (!this.conversationModeEnabled || this.isConversationMode || !this.connection) {
1271
1359
  return;
1272
1360
  }
@@ -1286,30 +1374,30 @@ window.chatInteractionManager = function () {
1286
1374
  }
1287
1375
  }).then(function (stream) {
1288
1376
  var mimeType = MediaRecorder.isTypeSupported('audio/ogg;codecs=opus') ? 'audio/ogg;codecs=opus' : MediaRecorder.isTypeSupported('audio/webm;codecs=opus') ? 'audio/webm;codecs=opus' : 'audio/webm';
1289
- _this12.mediaRecorder = new MediaRecorder(stream, {
1377
+ _this13.mediaRecorder = new MediaRecorder(stream, {
1290
1378
  mimeType: mimeType,
1291
1379
  audioBitsPerSecond: 128000
1292
1380
  });
1293
- _this12._conversationSubject = new signalR.Subject();
1294
- _this12._conversationStream = stream;
1381
+ _this13._conversationSubject = new signalR.Subject();
1382
+ _this13._conversationStream = stream;
1295
1383
 
1296
1384
  // Create an AnalyserNode for volume-based interrupt detection.
1297
1385
  var AudioCtx = window.AudioContext || window.webkitAudioContext;
1298
1386
  if (AudioCtx) {
1299
- _this12._conversationAudioCtx = new AudioCtx();
1300
- _this12._conversationAnalyser = _this12._conversationAudioCtx.createAnalyser();
1301
- _this12._conversationAnalyser.fftSize = 256;
1302
- var micSource = _this12._conversationAudioCtx.createMediaStreamSource(stream);
1303
- micSource.connect(_this12._conversationAnalyser);
1387
+ _this13._conversationAudioCtx = new AudioCtx();
1388
+ _this13._conversationAnalyser = _this13._conversationAudioCtx.createAnalyser();
1389
+ _this13._conversationAnalyser.fftSize = 256;
1390
+ var micSource = _this13._conversationAudioCtx.createMediaStreamSource(stream);
1391
+ micSource.connect(_this13._conversationAnalyser);
1304
1392
  }
1305
1393
  var pendingChunk = Promise.resolve();
1306
- var analyser = _this12._conversationAnalyser;
1394
+ var analyser = _this13._conversationAnalyser;
1307
1395
  var interruptVolumeThreshold = 30;
1308
- _this12.mediaRecorder.addEventListener('dataavailable', function (e) {
1396
+ _this13.mediaRecorder.addEventListener('dataavailable', function (e) {
1309
1397
  if (e.data && e.data.size > 0) {
1310
1398
  // During TTS playback, check mic volume to detect
1311
1399
  // user interruption (speaking above threshold).
1312
- if (_this12.isPlayingAudio && analyser) {
1400
+ if (_this13.isPlayingAudio && analyser) {
1313
1401
  var freqData = new Uint8Array(analyser.frequencyBinCount);
1314
1402
  analyser.getByteFrequencyData(freqData);
1315
1403
  var sum = 0;
@@ -1319,7 +1407,7 @@ window.chatInteractionManager = function () {
1319
1407
  var avg = sum / freqData.length;
1320
1408
  if (avg >= interruptVolumeThreshold) {
1321
1409
  // User is speaking — interrupt TTS playback.
1322
- _this12.stopAudio();
1410
+ _this13.stopAudio();
1323
1411
  }
1324
1412
  }
1325
1413
 
@@ -1341,7 +1429,7 @@ window.chatInteractionManager = function () {
1341
1429
  }, '');
1342
1430
  base64 = btoa(binaryString);
1343
1431
  try {
1344
- _this12._conversationSubject.next(base64);
1432
+ _this13._conversationSubject.next(base64);
1345
1433
  } catch (err) {
1346
1434
  // Subject may have been completed already.
1347
1435
  }
@@ -1352,27 +1440,27 @@ window.chatInteractionManager = function () {
1352
1440
  })));
1353
1441
  }
1354
1442
  });
1355
- _this12.mediaRecorder.addEventListener('stop', function () {
1443
+ _this13.mediaRecorder.addEventListener('stop', function () {
1356
1444
  stream.getTracks().forEach(function (track) {
1357
1445
  return track.stop();
1358
1446
  });
1359
1447
  pendingChunk.then(function () {
1360
1448
  try {
1361
- _this12._conversationSubject.complete();
1449
+ _this13._conversationSubject.complete();
1362
1450
  } catch (err) {
1363
1451
  // Already completed.
1364
1452
  }
1365
1453
  });
1366
1454
  });
1367
- var itemId = _this12.getItemId();
1455
+ var itemId = _this13.getItemId();
1368
1456
  var language = navigator.language || document.documentElement.lang || 'en-US';
1369
- _this12.connection.send("StartConversation", itemId, _this12._conversationSubject, mimeType, language);
1370
- _this12.mediaRecorder.start(250);
1371
- _this12.isRecording = true;
1457
+ _this13.connection.send("StartConversation", itemId, _this13._conversationSubject, mimeType, language);
1458
+ _this13.mediaRecorder.start(250);
1459
+ _this13.isRecording = true;
1372
1460
  })["catch"](function (err) {
1373
1461
  console.error('Microphone access denied:', err);
1374
- _this12.isConversationMode = false;
1375
- _this12.updateConversationButton();
1462
+ _this13.isConversationMode = false;
1463
+ _this13.updateConversationButton();
1376
1464
  });
1377
1465
  },
1378
1466
  stopConversationMode: function stopConversationMode() {
@@ -1476,12 +1564,12 @@ window.chatInteractionManager = function () {
1476
1564
  return removedCount;
1477
1565
  },
1478
1566
  scrollToBottom: function scrollToBottom() {
1479
- var _this13 = this;
1567
+ var _this14 = this;
1480
1568
  if (!this.autoScroll) {
1481
1569
  return;
1482
1570
  }
1483
1571
  setTimeout(function () {
1484
- _this13.chatContainer.scrollTop = _this13.chatContainer.scrollHeight - _this13.chatContainer.clientHeight;
1572
+ _this14.chatContainer.scrollTop = _this14.chatContainer.scrollHeight - _this14.chatContainer.clientHeight;
1485
1573
  }, 50);
1486
1574
  },
1487
1575
  handleUserInput: function handleUserInput(event) {
@@ -1497,7 +1585,7 @@ window.chatInteractionManager = function () {
1497
1585
  return document.querySelector('[data-chat-interaction-save-indicator]');
1498
1586
  },
1499
1587
  showSaveIndicator: function showSaveIndicator(text, className) {
1500
- var _this14 = this;
1588
+ var _this15 = this;
1501
1589
  var indicator = this.getSaveIndicatorElement();
1502
1590
  if (!indicator) {
1503
1591
  return;
@@ -1513,7 +1601,7 @@ window.chatInteractionManager = function () {
1513
1601
  }
1514
1602
  this.saveIndicatorTimeout = setTimeout(function () {
1515
1603
  indicator.textContent = '';
1516
- _this14.saveIndicatorTimeout = null;
1604
+ _this15.saveIndicatorTimeout = null;
1517
1605
  }, 3000);
1518
1606
  },
1519
1607
  clearPendingSettingsSave: function clearPendingSettingsSave() {
@@ -1587,10 +1675,10 @@ window.chatInteractionManager = function () {
1587
1675
  return false;
1588
1676
  },
1589
1677
  validateSettings: function validateSettings() {
1590
- var _this15 = this;
1678
+ var _this16 = this;
1591
1679
  var isValid = true;
1592
1680
  this.getSettingInputs().forEach(function (input) {
1593
- isValid = _this15.validateSettingInput(input) && isValid;
1681
+ isValid = _this16.validateSettingInput(input) && isValid;
1594
1682
  });
1595
1683
  return isValid;
1596
1684
  },
@@ -1686,12 +1774,12 @@ window.chatInteractionManager = function () {
1686
1774
  }
1687
1775
  },
1688
1776
  scheduleNotificationDismiss: function scheduleNotificationDismiss(notification) {
1689
- var _this16 = this;
1777
+ var _this17 = this;
1690
1778
  if (!notification || !notification.type || !notification.autoDismissMs || notification.autoDismissMs <= 0) {
1691
1779
  return;
1692
1780
  }
1693
1781
  this.notificationDismissTimers[notification.type] = setTimeout(function () {
1694
- _this16.removeNotification(notification.type);
1782
+ _this17.removeNotification(notification.type);
1695
1783
  }, notification.autoDismissMs);
1696
1784
  },
1697
1785
  clearNotificationDismiss: function clearNotificationDismiss(notificationType) {
@@ -1731,7 +1819,7 @@ window.chatInteractionManager = function () {
1731
1819
  this.showPlaceholder();
1732
1820
  },
1733
1821
  initializeApp: function initializeApp() {
1734
- var _this17 = this;
1822
+ var _this18 = this;
1735
1823
  this.inputElement = document.querySelector(config.inputElementSelector);
1736
1824
  this.buttonElement = document.querySelector(config.sendButtonElementSelector);
1737
1825
  this.chatContainer = document.querySelector(config.chatContainerElementSelector);
@@ -1743,59 +1831,59 @@ window.chatInteractionManager = function () {
1743
1831
 
1744
1832
  // Pause auto-scroll when the user manually scrolls up during streaming.
1745
1833
  this.chatContainer.addEventListener('scroll', function () {
1746
- if (!_this17.stream) {
1834
+ if (!_this18.stream) {
1747
1835
  return;
1748
1836
  }
1749
1837
  var threshold = 30;
1750
- var atBottom = _this17.chatContainer.scrollHeight - _this17.chatContainer.clientHeight - _this17.chatContainer.scrollTop <= threshold;
1751
- _this17.autoScroll = atBottom;
1838
+ var atBottom = _this18.chatContainer.scrollHeight - _this18.chatContainer.clientHeight - _this18.chatContainer.scrollTop <= threshold;
1839
+ _this18.autoScroll = atBottom;
1752
1840
  });
1753
1841
  this.inputElement.addEventListener('keyup', function (event) {
1754
- if (_this17.stream != null) {
1842
+ if (_this18.stream != null) {
1755
1843
  return;
1756
1844
  }
1757
1845
  if (event.key === "Enter" && !event.shiftKey) {
1758
- _this17.buttonElement.click();
1846
+ _this18.buttonElement.click();
1759
1847
  }
1760
1848
  });
1761
1849
  this.inputElement.addEventListener('input', function (e) {
1762
- _this17.handleUserInput(e);
1850
+ _this18.handleUserInput(e);
1763
1851
  if (e.target.value.trim()) {
1764
- _this17.buttonElement.removeAttribute('disabled');
1852
+ _this18.buttonElement.removeAttribute('disabled');
1765
1853
  } else {
1766
- _this17.buttonElement.setAttribute('disabled', true);
1854
+ _this18.buttonElement.setAttribute('disabled', true);
1767
1855
  }
1768
1856
  });
1769
1857
  this.inputElement.addEventListener('paste', function (e) {
1770
1858
  // Use setTimeout to allow the paste to complete before checking the value
1771
1859
  setTimeout(function () {
1772
- _this17.prompt = _this17.inputElement.value;
1773
- if (_this17.inputElement.value.trim()) {
1774
- _this17.buttonElement.removeAttribute('disabled');
1860
+ _this18.prompt = _this18.inputElement.value;
1861
+ if (_this18.inputElement.value.trim()) {
1862
+ _this18.buttonElement.removeAttribute('disabled');
1775
1863
  } else {
1776
- _this17.buttonElement.setAttribute('disabled', true);
1864
+ _this18.buttonElement.setAttribute('disabled', true);
1777
1865
  }
1778
1866
  }, 0);
1779
1867
  });
1780
1868
  this.buttonElement.addEventListener('click', function () {
1781
- if (_this17.stream != null) {
1782
- _this17.stream.dispose();
1783
- _this17.stream = null;
1784
- _this17.streamingFinished();
1785
- _this17.hideTypingIndicator();
1869
+ if (_this18.stream != null) {
1870
+ _this18.stream.dispose();
1871
+ _this18.stream = null;
1872
+ _this18.streamingFinished();
1873
+ _this18.hideTypingIndicator();
1786
1874
 
1787
1875
  // Clean up: remove empty assistant message or stop streaming animation.
1788
- if (_this17.messages.length > 0) {
1789
- var lastMsg = _this17.messages[_this17.messages.length - 1];
1876
+ if (_this18.messages.length > 0) {
1877
+ var lastMsg = _this18.messages[_this18.messages.length - 1];
1790
1878
  if (lastMsg.role === 'assistant' && !lastMsg.content) {
1791
- _this17.messages.pop();
1879
+ _this18.messages.pop();
1792
1880
  } else if (lastMsg.isStreaming) {
1793
1881
  lastMsg.isStreaming = false;
1794
1882
  }
1795
1883
  }
1796
1884
  return;
1797
1885
  }
1798
- _this17.sendMessage();
1886
+ _this18.sendMessage();
1799
1887
  });
1800
1888
  var chatInteractionItems = document.getElementsByClassName('chat-interaction-history-item');
1801
1889
  for (var i = 0; i < chatInteractionItems.length; i++) {
@@ -1806,11 +1894,12 @@ window.chatInteractionManager = function () {
1806
1894
  console.error('An element with the class chat-interaction-history-item with no data-interaction-id set.');
1807
1895
  return;
1808
1896
  }
1809
- _this17.loadInteraction(itemId);
1897
+ _this18.loadInteraction(itemId);
1810
1898
  });
1811
1899
  }
1812
- for (var _i4 = 0; _i4 < config.messages.length; _i4++) {
1813
- this.addMessage(config.messages[_i4]);
1900
+ var initialMessages = Array.isArray(config.messages) ? config.messages : [];
1901
+ for (var _i4 = 0; _i4 < initialMessages.length; _i4++) {
1902
+ this.addMessage(initialMessages[_i4]);
1814
1903
  }
1815
1904
 
1816
1905
  // Delegate click for code block copy buttons.
@@ -1837,20 +1926,20 @@ window.chatInteractionManager = function () {
1837
1926
  }
1838
1927
  document.addEventListener('input', function (event) {
1839
1928
  if (event.target.matches('.setting-input[data-setting]')) {
1840
- _this17.validateSettingInput(event.target);
1841
- _this17.queueSettingsSave();
1929
+ _this18.validateSettingInput(event.target);
1930
+ _this18.queueSettingsSave();
1842
1931
  }
1843
1932
  });
1844
1933
  document.addEventListener('change', function (event) {
1845
1934
  if (event.target.matches('.setting-input[data-setting], .capability-checkbox[data-save-group], .capability-checkbox[data-group], .group-toggle, .ci-agent-global-toggle')) {
1846
1935
  if (event.target.matches('.setting-input[data-setting]')) {
1847
- _this17.validateSettingInput(event.target);
1936
+ _this18.validateSettingInput(event.target);
1848
1937
  }
1849
- _this17.queueSettingsSave();
1938
+ _this18.queueSettingsSave();
1850
1939
  return;
1851
1940
  }
1852
1941
  if (event.target.closest('.prompt-template-parameters-input, .prompt-template-id-input')) {
1853
- _this17.queueSettingsSave();
1942
+ _this18.queueSettingsSave();
1854
1943
  }
1855
1944
  });
1856
1945
  document.addEventListener('click', function (event) {
@@ -1858,7 +1947,7 @@ window.chatInteractionManager = function () {
1858
1947
  return;
1859
1948
  }
1860
1949
  setTimeout(function () {
1861
- _this17.queueSettingsSave();
1950
+ _this18.queueSettingsSave();
1862
1951
  }, 0);
1863
1952
  });
1864
1953
 
@@ -1868,7 +1957,7 @@ window.chatInteractionManager = function () {
1868
1957
  clearHistoryBtn.addEventListener('click', function () {
1869
1958
  var itemId = clearHistoryBtn.getAttribute('data-interaction-id');
1870
1959
  if (itemId) {
1871
- _this17.clearHistory(itemId);
1960
+ _this18.clearHistory(itemId);
1872
1961
  }
1873
1962
  });
1874
1963
  }
@@ -1879,7 +1968,7 @@ window.chatInteractionManager = function () {
1879
1968
  if (this.micButton) {
1880
1969
  this.micButton.style.display = '';
1881
1970
  this.micButton.addEventListener('click', function () {
1882
- _this17.toggleRecording();
1971
+ _this18.toggleRecording();
1883
1972
  });
1884
1973
  }
1885
1974
  }
@@ -1889,7 +1978,7 @@ window.chatInteractionManager = function () {
1889
1978
  this.conversationButton = document.querySelector(config.conversationButtonElementSelector);
1890
1979
  if (this.conversationButton) {
1891
1980
  this.conversationButton.addEventListener('click', function () {
1892
- _this17.toggleConversationMode();
1981
+ _this18.toggleConversationMode();
1893
1982
  });
1894
1983
  }
1895
1984
  }
@@ -1938,7 +2027,7 @@ window.chatInteractionManager = function () {
1938
2027
  }
1939
2028
  },
1940
2029
  debouncedSaveSettings: function debouncedSaveSettings() {
1941
- var _this18 = this;
2030
+ var _this19 = this;
1942
2031
  // Clear any existing timeout to reset the debounce timer
1943
2032
  this.clearPendingSettingsSave();
1944
2033
 
@@ -1949,11 +2038,11 @@ window.chatInteractionManager = function () {
1949
2038
 
1950
2039
  // Set a new timeout to save after 850ms of no changes
1951
2040
  this.saveSettingsTimeout = setTimeout(function () {
1952
- if (_this18.settingsDirty) {
1953
- _this18.saveSettings();
1954
- _this18.settingsDirty = false;
2041
+ if (_this19.settingsDirty) {
2042
+ _this19.saveSettings();
2043
+ _this19.settingsDirty = false;
1955
2044
  }
1956
- _this18.saveSettingsTimeout = null;
2045
+ _this19.saveSettingsTimeout = null;
1957
2046
  }, 850);
1958
2047
  },
1959
2048
  getSelectedToolNames: function getSelectedToolNames() {
@@ -1969,7 +2058,7 @@ window.chatInteractionManager = function () {
1969
2058
  return this.getSelectedGroupValues('agentNames', 'input[type="checkbox"][name$="].IsSelected"][name^="ChatInteraction.Agents["]:checked');
1970
2059
  },
1971
2060
  saveSettings: function saveSettings() {
1972
- var _this19 = this;
2061
+ var _this20 = this;
1973
2062
  var itemId = this.getItemId();
1974
2063
  if (!itemId) {
1975
2064
  return Promise.resolve();
@@ -2014,7 +2103,7 @@ window.chatInteractionManager = function () {
2014
2103
  }
2015
2104
  return this.connection.invoke("SaveSettings", itemId, settings)["catch"](function (err) {
2016
2105
  console.error('Error saving settings:', err);
2017
- _this19.showSaveIndicator('Save failed', 'text-danger');
2106
+ _this20.showSaveIndicator('Save failed', 'text-danger');
2018
2107
  });
2019
2108
  },
2020
2109
  flushPendingSave: function flushPendingSave() {
@@ -2040,13 +2129,48 @@ window.chatInteractionManager = function () {
2040
2129
  this.setItemId(itemId);
2041
2130
  this.isInteractionStarted = true;
2042
2131
  },
2043
- copyResponse: function copyResponse(message) {
2044
- var _ref13, _message$copyContent;
2045
- var text = message && _typeof(message) === 'object' ? (_ref13 = (_message$copyContent = message.copyContent) !== null && _message$copyContent !== void 0 ? _message$copyContent : message.content) !== null && _ref13 !== void 0 ? _ref13 : '' : message !== null && message !== void 0 ? message : '';
2046
- navigator.clipboard.writeText(text);
2132
+ clearCopiedMessageState: function clearCopiedMessageState() {
2133
+ if (this.copyResetTimeoutId) {
2134
+ window.clearTimeout(this.copyResetTimeoutId);
2135
+ this.copyResetTimeoutId = null;
2136
+ }
2137
+ if (this.activeCopyButton) {
2138
+ this.setCopyButtonState(this.activeCopyButton, false);
2139
+ this.activeCopyButton = null;
2140
+ }
2141
+ this.copiedMessageIndex = -1;
2142
+ },
2143
+ copyResponse: function copyResponse(message, index, event) {
2144
+ var _ref21,
2145
+ _message$copyContent,
2146
+ _event$target,
2147
+ _event$target$closest,
2148
+ _this21 = this;
2149
+ var text = message && _typeof(message) === 'object' ? (_ref21 = (_message$copyContent = message.copyContent) !== null && _message$copyContent !== void 0 ? _message$copyContent : message.content) !== null && _ref21 !== void 0 ? _ref21 : '' : message !== null && message !== void 0 ? message : '';
2150
+ var button = (event === null || event === void 0 ? void 0 : event.currentTarget) || (event === null || event === void 0 || (_event$target = event.target) === null || _event$target === void 0 || (_event$target$closest = _event$target.closest) === null || _event$target$closest === void 0 ? void 0 : _event$target$closest.call(_event$target, '[data-copy-message-index]')) || null;
2151
+ navigator.clipboard.writeText(text).then(function () {
2152
+ _this21.clearCopiedMessageState();
2153
+ _this21.copiedMessageIndex = typeof index === 'number' ? index : -1;
2154
+ _this21.activeCopyButton = button;
2155
+ if (button) {
2156
+ _this21.setCopyButtonState(button, true);
2157
+ } else {
2158
+ _this21.$nextTick(function () {
2159
+ return _this21.updateCopyButtons();
2160
+ });
2161
+ }
2162
+ _this21.copyResetTimeoutId = window.setTimeout(function () {
2163
+ _this21.clearCopiedMessageState();
2164
+ _this21.$nextTick(function () {
2165
+ return _this21.updateCopyButtons();
2166
+ });
2167
+ }, Number(config.copyResetDelayMs) || 2000);
2168
+ })["catch"](function (err) {
2169
+ return console.error('Failed to copy response:', err);
2170
+ });
2047
2171
  },
2048
2172
  startRecording: function startRecording() {
2049
- var _this20 = this;
2173
+ var _this22 = this;
2050
2174
  if (this.isRecording || !this.connection) {
2051
2175
  return;
2052
2176
  }
@@ -2058,16 +2182,16 @@ window.chatInteractionManager = function () {
2058
2182
  }
2059
2183
  }).then(function (stream) {
2060
2184
  var mimeType = MediaRecorder.isTypeSupported('audio/ogg;codecs=opus') ? 'audio/ogg;codecs=opus' : MediaRecorder.isTypeSupported('audio/webm;codecs=opus') ? 'audio/webm;codecs=opus' : 'audio/webm';
2061
- _this20.mediaRecorder = new MediaRecorder(stream, {
2185
+ _this22.mediaRecorder = new MediaRecorder(stream, {
2062
2186
  mimeType: mimeType,
2063
2187
  audioBitsPerSecond: 128000
2064
2188
  });
2065
- _this20.preRecordingPrompt = _this20.prompt;
2066
- _this20._audioInputSent = false;
2189
+ _this22.preRecordingPrompt = _this22.prompt;
2190
+ _this22._audioInputSent = false;
2067
2191
  var subject = new signalR.Subject();
2068
- var itemId = _this20.getItemId();
2192
+ var itemId = _this22.getItemId();
2069
2193
  var pendingChunk = Promise.resolve();
2070
- _this20.mediaRecorder.addEventListener('dataavailable', function (e) {
2194
+ _this22.mediaRecorder.addEventListener('dataavailable', function (e) {
2071
2195
  if (e.data && e.data.size > 0) {
2072
2196
  pendingChunk = pendingChunk.then(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4() {
2073
2197
  var data, uint8Array, binaryString, base64;
@@ -2091,7 +2215,7 @@ window.chatInteractionManager = function () {
2091
2215
  })));
2092
2216
  }
2093
2217
  });
2094
- _this20.mediaRecorder.addEventListener('stop', function () {
2218
+ _this22.mediaRecorder.addEventListener('stop', function () {
2095
2219
  stream.getTracks().forEach(function (track) {
2096
2220
  return track.stop();
2097
2221
  });
@@ -2100,10 +2224,10 @@ window.chatInteractionManager = function () {
2100
2224
  });
2101
2225
  });
2102
2226
  var language = navigator.language || document.documentElement.lang || 'en-US';
2103
- _this20.connection.send("SendAudioStream", itemId, subject, mimeType, language);
2104
- _this20.mediaRecorder.start(250);
2105
- _this20.isRecording = true;
2106
- _this20.updateMicButton();
2227
+ _this22.connection.send("SendAudioStream", itemId, subject, mimeType, language);
2228
+ _this22.mediaRecorder.start(250);
2229
+ _this22.isRecording = true;
2230
+ _this22.updateMicButton();
2107
2231
  })["catch"](function (err) {
2108
2232
  console.error('Microphone access denied:', err);
2109
2233
  });
@@ -2154,21 +2278,28 @@ window.chatInteractionManager = function () {
2154
2278
  this.inputElement.placeholder = '';
2155
2279
  }
2156
2280
  }
2281
+ },
2282
+ copiedMessageIndex: function copiedMessageIndex() {
2283
+ var _this23 = this;
2284
+ this.$nextTick(function () {
2285
+ return _this23.updateCopyButtons();
2286
+ });
2157
2287
  }
2158
2288
  },
2159
2289
  mounted: function mounted() {
2160
- var _this21 = this;
2290
+ var _this24 = this;
2161
2291
  _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee5() {
2162
2292
  return _regenerator().w(function (_context5) {
2163
2293
  while (1) switch (_context5.n) {
2164
2294
  case 0:
2165
2295
  _context5.n = 1;
2166
- return _this21.startConnection();
2296
+ return _this24.startConnection();
2167
2297
  case 1:
2168
- _this21.initializeApp();
2169
- _this21.$nextTick(function () {
2170
- refreshFontAwesomeIcons(_this21.$el);
2171
- _this21.fontAwesomeObserver = observeFontAwesomeIcons(_this21.$el);
2298
+ _this24.initializeApp();
2299
+ _this24.$nextTick(function () {
2300
+ _this24.updateCopyButtons();
2301
+ refreshFontAwesomeIcons(_this24.$el);
2302
+ _this24.fontAwesomeObserver = observeFontAwesomeIcons(_this24.$el);
2172
2303
  });
2173
2304
  case 2:
2174
2305
  return _context5.a(2);
@@ -2185,6 +2316,7 @@ window.chatInteractionManager = function () {
2185
2316
  this.fontAwesomeObserver.disconnect();
2186
2317
  this.fontAwesomeObserver = null;
2187
2318
  }
2319
+ this.clearCopiedMessageState();
2188
2320
  this.stopAudio(false);
2189
2321
  if (this.stream) {
2190
2322
  this.stream.dispose();
@@ -2198,8 +2330,73 @@ window.chatInteractionManager = function () {
2198
2330
  }).mount(config.appElementSelector);
2199
2331
  return app;
2200
2332
  };
2333
+ var autoInitializeSelector = '[data-chat-interaction-config]';
2334
+ function parseJsonAttribute(element, attributeName, description) {
2335
+ var rawValue = element.getAttribute(attributeName);
2336
+ if (!rawValue) {
2337
+ return null;
2338
+ }
2339
+ try {
2340
+ return JSON.parse(rawValue);
2341
+ } catch (error) {
2342
+ console.error('Failed to parse ' + description + ' JSON.', error);
2343
+ return null;
2344
+ }
2345
+ }
2346
+ function initializeFromElement(element) {
2347
+ if (!element || element.dataset.chatInteractionInitialized === 'true') {
2348
+ return element ? element.__chatInteractionApp || null : null;
2349
+ }
2350
+ var config = parseJsonAttribute(element, 'data-chat-interaction-config', 'chat interaction config');
2351
+ if (!config) {
2352
+ return null;
2353
+ }
2354
+ var app = initialize(config);
2355
+ if (!app) {
2356
+ return null;
2357
+ }
2358
+ element.dataset.chatInteractionInitialized = 'true';
2359
+ element.__chatInteractionApp = app;
2360
+ return app;
2361
+ }
2362
+ function scanForAutoInitialization(root) {
2363
+ if (!root || typeof root.querySelectorAll !== 'function') {
2364
+ return;
2365
+ }
2366
+ if (typeof root.matches === 'function' && root.matches(autoInitializeSelector)) {
2367
+ initializeFromElement(root);
2368
+ }
2369
+ root.querySelectorAll(autoInitializeSelector).forEach(initializeFromElement);
2370
+ }
2371
+ function startAutoInitialization() {
2372
+ scanForAutoInitialization(document);
2373
+ if (typeof MutationObserver === 'undefined') {
2374
+ return;
2375
+ }
2376
+ var observer = new MutationObserver(function (mutations) {
2377
+ mutations.forEach(function (mutation) {
2378
+ mutation.addedNodes.forEach(function (node) {
2379
+ if (node && node.nodeType === 1) {
2380
+ scanForAutoInitialization(node);
2381
+ }
2382
+ });
2383
+ });
2384
+ });
2385
+ observer.observe(document.body, {
2386
+ childList: true,
2387
+ subtree: true
2388
+ });
2389
+ }
2390
+ if (document.readyState === 'loading') {
2391
+ document.addEventListener('DOMContentLoaded', startAutoInitialization, {
2392
+ once: true
2393
+ });
2394
+ } else {
2395
+ startAutoInitialization();
2396
+ }
2201
2397
  return {
2202
- initialize: initialize
2398
+ initialize: initialize,
2399
+ initializeFromElement: initializeFromElement
2203
2400
  };
2204
2401
  }();
2205
2402
  window.chatInteractionDocumentManager = function () {
@@ -2726,9 +2923,73 @@ window.chatInteractionDocumentManager = function () {
2726
2923
  renderUploadQueue();
2727
2924
  showUploadStatus(null);
2728
2925
  showUploadProgress(null);
2926
+ return fileInput[managerStateKey];
2927
+ }
2928
+ function parseJsonAttribute(element, attributeName, description) {
2929
+ var rawValue = element.getAttribute(attributeName);
2930
+ if (!rawValue) {
2931
+ return null;
2932
+ }
2933
+ try {
2934
+ return JSON.parse(rawValue);
2935
+ } catch (error) {
2936
+ console.error('Failed to parse ' + description + ' JSON.', error);
2937
+ return null;
2938
+ }
2939
+ }
2940
+ function initializeFromElement(element) {
2941
+ if (!element || element.dataset.chatInteractionDocumentManagerInitialized === 'true') {
2942
+ return element ? element[managerStateKey] || null : null;
2943
+ }
2944
+ var config = parseJsonAttribute(element, 'data-chat-interaction-document-manager-config', 'chat interaction document manager config');
2945
+ if (!config) {
2946
+ return null;
2947
+ }
2948
+ var state = initialize(config);
2949
+ if (!state) {
2950
+ return null;
2951
+ }
2952
+ element.dataset.chatInteractionDocumentManagerInitialized = 'true';
2953
+ return state;
2954
+ }
2955
+ function scanForAutoInitialization(root) {
2956
+ if (!root || typeof root.querySelectorAll !== 'function') {
2957
+ return;
2958
+ }
2959
+ if (typeof root.matches === 'function' && root.matches('[data-chat-interaction-document-manager-config]')) {
2960
+ initializeFromElement(root);
2961
+ }
2962
+ root.querySelectorAll('[data-chat-interaction-document-manager-config]').forEach(initializeFromElement);
2963
+ }
2964
+ function startAutoInitialization() {
2965
+ scanForAutoInitialization(document);
2966
+ if (typeof MutationObserver === 'undefined') {
2967
+ return;
2968
+ }
2969
+ var observer = new MutationObserver(function (mutations) {
2970
+ mutations.forEach(function (mutation) {
2971
+ mutation.addedNodes.forEach(function (node) {
2972
+ if (node && node.nodeType === 1) {
2973
+ scanForAutoInitialization(node);
2974
+ }
2975
+ });
2976
+ });
2977
+ });
2978
+ observer.observe(document.body, {
2979
+ childList: true,
2980
+ subtree: true
2981
+ });
2982
+ }
2983
+ if (document.readyState === 'loading') {
2984
+ document.addEventListener('DOMContentLoaded', startAutoInitialization, {
2985
+ once: true
2986
+ });
2987
+ } else {
2988
+ startAutoInitialization();
2729
2989
  }
2730
2990
  return {
2731
- initialize: initialize
2991
+ initialize: initialize,
2992
+ initializeFromElement: initializeFromElement
2732
2993
  };
2733
2994
  }();
2734
2995