@crestapps/ai-chat-ui 1.0.0-preview.14 → 1.0.0-preview.153

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/ai-chat-widget.js +158 -12
  2. package/dist/ai-chat-widget.js.map +1 -1
  3. package/dist/ai-chat-widget.min.js +1 -1
  4. package/dist/ai-chat-widget.min.js.map +1 -1
  5. package/dist/ai-chat.css +67 -17
  6. package/dist/ai-chat.css.map +1 -1
  7. package/dist/ai-chat.js +683 -328
  8. package/dist/ai-chat.js.map +1 -1
  9. package/dist/ai-chat.min.css +1 -1
  10. package/dist/ai-chat.min.js +1 -1
  11. package/dist/ai-chat.min.js.map +1 -1
  12. package/dist/chat-interaction-settings.js +297 -0
  13. package/dist/chat-interaction-settings.js.map +1 -0
  14. package/dist/chat-interaction-settings.min.js +2 -0
  15. package/dist/chat-interaction-settings.min.js.map +1 -0
  16. package/dist/chat-interaction.js +1198 -338
  17. package/dist/chat-interaction.js.map +1 -1
  18. package/dist/chat-interaction.min.js +1 -1
  19. package/dist/chat-interaction.min.js.map +1 -1
  20. package/dist/chat-widget.css +86 -35
  21. package/dist/chat-widget.css.map +1 -1
  22. package/dist/chat-widget.min.css +1 -1
  23. package/dist/document-drop-zone.css +10 -10
  24. package/dist/document-drop-zone.css.map +1 -1
  25. package/dist/document-drop-zone.js +92 -14
  26. package/dist/document-drop-zone.js.map +1 -1
  27. package/dist/document-drop-zone.min.css +1 -1
  28. package/dist/document-drop-zone.min.js +1 -1
  29. package/dist/document-drop-zone.min.js.map +1 -1
  30. package/dist/technical-name-generator.js +36 -8
  31. package/dist/technical-name-generator.js.map +1 -1
  32. package/dist/technical-name-generator.min.js +1 -1
  33. package/dist/technical-name-generator.min.js.map +1 -1
  34. package/package.json +5 -1
  35. package/README.md +0 -145
@@ -3,22 +3,25 @@
3
3
  ** Any changes made directly to this file will be overwritten next time its asset group is processed by Gulp.
4
4
  */
5
5
 
6
- function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
7
- function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
8
- function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
9
- function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
10
- function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
6
+ var _excluded = ["placeholder"];
11
7
  function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i["return"]) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
12
8
  function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); }
13
9
  function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
14
10
  function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
15
- function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
16
11
  function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
17
12
  function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
18
- function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
19
13
  function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
20
14
  function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }
15
+ function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
16
+ function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
17
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
18
+ function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
19
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
20
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
21
21
  function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
22
+ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
23
+ function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
24
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
22
25
  window.chatInteractionManager = function () {
23
26
  // Defaults (can be overridden by instanceConfig)
24
27
  var defaultConfig = {
@@ -29,9 +32,12 @@ window.chatInteractionManager = function () {
29
32
  downloadChartTitle: 'Download chart as image',
30
33
  downloadChartButtonText: 'Download',
31
34
  codeCopiedText: 'Copied!',
35
+ copyTitle: 'Click here to copy response to clipboard.',
36
+ copiedTitle: 'Response copied to clipboard.',
37
+ copyResetDelayMs: 2000,
32
38
  assistantLabel: 'Assistant',
33
- messageTemplate: "\n <div class=\"ai-chat-messages\">\n <div v-for=\"(message, index) in messages\" :key=\"index\" class=\"ai-chat-message-item\">\n <div>\n <div v-if=\"message.role === 'user'\" class=\"ai-chat-msg-role ai-chat-msg-role-user\">You</div>\n <div v-else-if=\"message.role !== 'indicator'\" :class=\"getAssistantRoleClasses(message)\">\n <span :class=\"getAssistantIconClasses(message, index)\"><span :class=\"getAssistantIcon(message)\"></span></span>\n {{ getAssistantLabel(message) }}\n </div>\n <div class=\"ai-chat-message-body lh-base\">\n <h4 v-if=\"message.title\">{{ message.title }}</h4>\n <div v-html=\"message.htmlContent\"></div>\n <span class=\"message-buttons-container\" v-if=\"!isIndicator(message)\">\n <button v-if=\"textToSpeechEnabled && !isConversationMode && message.role === 'assistant' && !message.isStreaming\" class=\"btn btn-sm btn-link text-secondary p-0 me-1 button-message-toolbox\" :class=\"{ 'tts-playing': ttsPlayingMessageIndex === index }\" :data-tts-message-index=\"index\" @click=\"toggleMessageTts(message, index)\" :title=\"ttsPlayingMessageIndex === index ? 'Pause audio' : 'Read aloud'\">\n <span :class=\"ttsPlayingMessageIndex === index ? 'fa-solid fa-circle-pause' : 'fa-solid fa-circle-play'\"></span>\n </button>\n <button class=\"btn btn-sm btn-link text-secondary p-0 button-message-toolbox\" @click=\"copyResponse(message.content)\" title=\"Click here to copy response to clipboard.\">\n <span class=\"fa-solid fa-copy\"></span>\n </button>\n </span>\n </div>\n </div>\n </div>\n <div v-for=\"notification in notifications\" :key=\"'notif-' + notification.type\" class=\"ai-chat-notification\" :class=\"'ai-chat-notification-' + (notification.type || 'info') + ' ' + (notification.cssClass || '')\">\n <div class=\"ai-chat-notification-content\">\n <span v-if=\"notification.icon\" :class=\"notification.icon\" class=\"ai-chat-notification-icon\"></span>\n <span class=\"ai-chat-notification-text\">{{ notification.content }}</span>\n <button v-if=\"notification.dismissible\" class=\"btn btn-sm btn-link p-0 ms-2 ai-chat-notification-dismiss\" @click=\"dismissNotification(notification.type)\" title=\"Dismiss\">\n <span class=\"fa-solid fa-xmark\"></span>\n </button>\n </div>\n <div v-if=\"notification.actions && notification.actions.length\" class=\"ai-chat-notification-actions\">\n <button v-for=\"action in notification.actions\" :key=\"action.name\" class=\"btn btn-sm\" :class=\"action.cssClass || 'btn-outline-secondary'\" @click=\"handleNotificationAction(notification.type, action.name)\">\n <span v-if=\"action.icon\" :class=\"action.icon\" class=\"me-1\"></span>\n {{ action.label }}\n </button>\n </div>\n </div>\n </div>\n ",
34
- indicatorTemplate: "\n <div class=\"ai-chat-msg-role ai-chat-msg-role-assistant\">\n <span class=\"ai-streaming-icon\"><span class=\"fa fa-robot\" style=\"display: inline-block;\"></span></span>\n Assistant\n </div>\n ",
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 ",
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 ",
35
41
  // Localizable strings
36
42
  untitledText: 'Untitled',
37
43
  clearHistoryTitle: 'Clear History',
@@ -56,6 +62,240 @@ window.chatInteractionManager = function () {
56
62
  span.textContent = text;
57
63
  return span.innerHTML;
58
64
  }
65
+ function containsFontAwesomePlaceholders(root) {
66
+ if (!root || root.nodeType !== 1) {
67
+ return false;
68
+ }
69
+ var selector = 'i[class*="fa-"],i.fa,i.fas,i.far,i.fab';
70
+ if (typeof root.matches === 'function' && root.matches(selector)) {
71
+ return true;
72
+ }
73
+ return typeof root.querySelector === 'function' && !!root.querySelector(selector);
74
+ }
75
+ function refreshFontAwesomeIcons(root) {
76
+ var fontAwesome = window.FontAwesome;
77
+ if (!containsFontAwesomePlaceholders(root) || !fontAwesome || !fontAwesome.dom || typeof fontAwesome.dom.i2svg !== 'function') {
78
+ return;
79
+ }
80
+ fontAwesome.dom.i2svg({
81
+ node: root
82
+ });
83
+ }
84
+ function observeFontAwesomeIcons(root) {
85
+ if (!root || typeof MutationObserver === 'undefined') {
86
+ return null;
87
+ }
88
+ var observer = new MutationObserver(function (mutations) {
89
+ mutations.forEach(function (mutation) {
90
+ mutation.addedNodes.forEach(function (node) {
91
+ refreshFontAwesomeIcons(node);
92
+ });
93
+ });
94
+ });
95
+ observer.observe(root, {
96
+ childList: true,
97
+ subtree: true
98
+ });
99
+ return observer;
100
+ }
101
+ function normalizeReference(reference) {
102
+ var _ref, _normalized$index, _ref2, _normalized$text, _ref3, _normalized$title, _ref4, _normalized$link, _ref5, _normalized$reference, _normalized$isGenerat;
103
+ if (!reference || _typeof(reference) !== 'object') {
104
+ return null;
105
+ }
106
+ var normalized = Object.assign({}, reference);
107
+ normalized.index = (_ref = (_normalized$index = normalized.index) !== null && _normalized$index !== void 0 ? _normalized$index : normalized.Index) !== null && _ref !== void 0 ? _ref : 0;
108
+ normalized.text = (_ref2 = (_normalized$text = normalized.text) !== null && _normalized$text !== void 0 ? _normalized$text : normalized.Text) !== null && _ref2 !== void 0 ? _ref2 : null;
109
+ normalized.title = (_ref3 = (_normalized$title = normalized.title) !== null && _normalized$title !== void 0 ? _normalized$title : normalized.Title) !== null && _ref3 !== void 0 ? _ref3 : null;
110
+ normalized.link = sanitizeUrl((_ref4 = (_normalized$link = normalized.link) !== null && _normalized$link !== void 0 ? _normalized$link : normalized.Link) !== null && _ref4 !== void 0 ? _ref4 : null);
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;
113
+ return normalized;
114
+ }
115
+ function isDownloadCitationReference(reference) {
116
+ if (!reference || _typeof(reference) !== 'object') {
117
+ return false;
118
+ }
119
+ if (typeof reference.referenceType === 'string' && reference.referenceType.toLowerCase() === 'document') {
120
+ return true;
121
+ }
122
+ if (typeof reference.link === 'string' && /\/ai\/documents\/.+\/download(?:$|\?)/i.test(reference.link)) {
123
+ return true;
124
+ }
125
+ return false;
126
+ }
127
+ function normalizeReferences(references) {
128
+ if (!references || _typeof(references) !== 'object') {
129
+ return {};
130
+ }
131
+ var normalized = {};
132
+ for (var _i = 0, _Object$entries = Object.entries(references); _i < _Object$entries.length; _i++) {
133
+ var _normalizeReference;
134
+ var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
135
+ key = _Object$entries$_i[0],
136
+ value = _Object$entries$_i[1];
137
+ normalized[key] = (_normalizeReference = normalizeReference(value)) !== null && _normalizeReference !== void 0 ? _normalizeReference : {};
138
+ }
139
+ return normalized;
140
+ }
141
+ function getCitationLabel(reference, key) {
142
+ return reference.title || reference.text || key;
143
+ }
144
+ function buildCitationDisplay(content, references) {
145
+ var processedContent = (content || '').trim();
146
+ var messageReferences = normalizeReferences(references);
147
+ var referenceEntries = Object.entries(messageReferences);
148
+ if (!referenceEntries.length) {
149
+ return {
150
+ content: processedContent,
151
+ citations: []
152
+ };
153
+ }
154
+ var citedRefs = referenceEntries.filter(function (_ref6) {
155
+ var _ref7 = _slicedToArray(_ref6, 1),
156
+ key = _ref7[0];
157
+ return processedContent.includes(key);
158
+ });
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) {
166
+ return {
167
+ content: processedContent,
168
+ citations: []
169
+ };
170
+ }
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];
183
+ return a.index - b.index;
184
+ });
185
+ var citations = [];
186
+ var displayIndex = 1;
187
+ var _iterator = _createForOfIteratorHelper(citedRefs),
188
+ _step;
189
+ try {
190
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
191
+ var _step$value = _slicedToArray(_step.value, 2),
192
+ key = _step$value[0],
193
+ value = _step$value[1];
194
+ var placeholder = "__CITE_".concat(displayIndex, "_").concat(value.index || displayIndex, "__");
195
+ processedContent = processedContent.replaceAll(key, placeholder);
196
+ citations.push({
197
+ referenceKey: key,
198
+ displayIndex: displayIndex,
199
+ label: getCitationLabel(value, key),
200
+ link: value.link || null,
201
+ isDownload: isDownloadCitationReference(value),
202
+ placeholder: placeholder
203
+ });
204
+ displayIndex++;
205
+ }
206
+ } catch (err) {
207
+ _iterator.e(err);
208
+ } finally {
209
+ _iterator.f();
210
+ }
211
+ for (var _i2 = 0, _citations = citations; _i2 < _citations.length; _i2++) {
212
+ var citation = _citations[_i2];
213
+ processedContent = processedContent.replaceAll(citation.placeholder, "<sup>".concat(citation.displayIndex, "</sup>"));
214
+ }
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
+ }
241
+ return {
242
+ content: processedContent,
243
+ citations: citations.map(function (_ref16) {
244
+ var placeholder = _ref16.placeholder,
245
+ citation = _objectWithoutProperties(_ref16, _excluded);
246
+ return citation;
247
+ })
248
+ };
249
+ }
250
+ function buildCopyContent(content, citations) {
251
+ var copyContent = (content || '').trim();
252
+ if (!copyContent || !Array.isArray(citations) || citations.length === 0) {
253
+ return copyContent;
254
+ }
255
+ var _iterator3 = _createForOfIteratorHelper(citations),
256
+ _step3;
257
+ try {
258
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
259
+ var citation = _step3.value;
260
+ copyContent = copyContent.replaceAll(citation.referenceKey, "[".concat(citation.displayIndex, "]"));
261
+ }
262
+ } catch (err) {
263
+ _iterator3.e(err);
264
+ } finally {
265
+ _iterator3.f();
266
+ }
267
+ copyContent += '\n\nReferences:\n';
268
+ var _iterator4 = _createForOfIteratorHelper(citations),
269
+ _step4;
270
+ try {
271
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
272
+ var _citation = _step4.value;
273
+ copyContent += "".concat(_citation.displayIndex, ". ").concat(_citation.label);
274
+ if (_citation.link) {
275
+ copyContent += " - ".concat(_citation.link);
276
+ }
277
+ copyContent += '\n';
278
+ }
279
+ } catch (err) {
280
+ _iterator4.e(err);
281
+ } finally {
282
+ _iterator4.f();
283
+ }
284
+ return copyContent.trimEnd();
285
+ }
286
+ function updateMessagePresentation(message, references) {
287
+ var messageReferences = normalizeReferences(references !== null && references !== void 0 ? references : message.references);
288
+ var rawContent = typeof message.rawContent === 'string' ? message.rawContent : typeof message.content === 'string' ? message.content : '';
289
+ var citationDisplay = buildCitationDisplay(rawContent, messageReferences);
290
+ message.rawContent = rawContent;
291
+ message.content = rawContent;
292
+ message.displayContent = citationDisplay.content;
293
+ message.references = messageReferences;
294
+ message.citationReferences = citationDisplay.citations;
295
+ message.copyContent = buildCopyContent(rawContent, citationDisplay.citations);
296
+ message.htmlContent = parseMarkdownContent(citationDisplay.content, message);
297
+ return message;
298
+ }
59
299
  var renderer = new marked.Renderer();
60
300
 
61
301
  // Modify the link rendering to open in a new tab
@@ -86,7 +326,7 @@ window.chatInteractionManager = function () {
86
326
  highlighted = escapeHtmlEntities(code);
87
327
  }
88
328
  var langDisplay = lang ? escapeHtmlEntities(lang) : 'code';
89
- return "<div class=\"ai-code-block\"><div class=\"ai-code-header\"><span class=\"ai-code-lang\"><span class=\"fa-solid fa-code\"></span> ".concat(langDisplay, "</span><button type=\"button\" class=\"ai-code-copy-btn\" title=\"Copy code\"><span class=\"fa-regular fa-copy\"></span></button></div><pre><code class=\"hljs").concat(lang ? ' language-' + lang : '', "\">").concat(highlighted, "</code></pre></div>");
329
+ return "<div class=\"ai-code-block\"><div class=\"ai-code-header\"><span class=\"ai-code-lang\"><i class=\"fa-solid fa-code\"></i> ".concat(langDisplay, "</span><button type=\"button\" class=\"ai-code-copy-btn\" title=\"Copy code\"><i class=\"fa-regular fa-copy\"></i></button></div><pre><code class=\"hljs").concat(lang ? ' language-' + lang : '', "\">").concat(highlighted, "</code></pre></div>");
90
330
  };
91
331
 
92
332
  // Custom image renderer for generated images with thumbnail styling and download button.
@@ -96,7 +336,7 @@ window.chatInteractionManager = function () {
96
336
  if (!src) return '';
97
337
  var alt = data.text || defaultConfig.generatedImageAltText;
98
338
  var maxWidth = defaultConfig.generatedImageMaxWidth;
99
- return "<div class=\"generated-image-container\">\n <img src=\"".concat(src, "\" alt=\"").concat(alt, "\" class=\"img-thumbnail\" style=\"max-width: ").concat(maxWidth, "px; height: auto;\" />\n <div class=\"mt-2\">\n <a href=\"").concat(src, "\" target=\"_blank\" download=\"").concat(alt, "\" title=\"").concat(defaultConfig.downloadImageTitle, "\" class=\"btn btn-sm btn-outline-secondary ai-download-image\">\n <span class=\"fa-solid fa-download\"></span>\n </a>\n </div>\n </div>");
339
+ return "<div class=\"generated-image-container\">\n <img src=\"".concat(src, "\" alt=\"").concat(alt, "\" class=\"img-thumbnail\" style=\"max-width: ").concat(maxWidth, "px; height: auto;\" />\n <div class=\"mt-2\">\n <a href=\"").concat(src, "\" target=\"_blank\" download=\"").concat(alt, "\" title=\"").concat(defaultConfig.downloadImageTitle, "\" class=\"btn btn-sm btn-outline-secondary ai-download-image\">\n <i class=\"fa-solid fa-download\"></i>\n </a>\n </div>\n </div>");
100
340
  };
101
341
 
102
342
  // Chart counter for unique IDs
@@ -108,7 +348,7 @@ window.chatInteractionManager = function () {
108
348
  // Global chart config map shared with ai-chat.js
109
349
  window.__chartConfigs = window.__chartConfigs || {};
110
350
  function createChartHtml(chartId) {
111
- return "<div class=\"chart-container\" style=\"position: relative; width: 100%; max-width: 560px; min-height: 420px;\">" + "<canvas id=\"".concat(chartId, "\"></canvas>") + "</div>" + "<div class=\"mt-2\">" + "<button type=\"button\" class=\"btn btn-sm btn-outline-secondary download-chart-btn\" data-chart-id=\"".concat(chartId, "\" title=\"").concat(defaultConfig.downloadChartTitle, "\">") + "<span class=\"fa-solid fa-download\"></span> ".concat(defaultConfig.downloadChartButtonText) + "</button>" + "</div>";
351
+ return "<div class=\"chart-container\" style=\"position: relative; width: 100%; max-width: 560px; min-height: 420px;\">" + "<canvas id=\"".concat(chartId, "\"></canvas>") + "</div>" + "<div class=\"mt-2\">" + "<button type=\"button\" class=\"btn btn-sm btn-outline-secondary download-chart-btn\" data-chart-id=\"".concat(chartId, "\" title=\"").concat(defaultConfig.downloadChartTitle, "\">") + "<i class=\"fa-solid fa-download\"></i> ".concat(defaultConfig.downloadChartButtonText) + "</button>" + "</div>";
112
352
  }
113
353
 
114
354
  // Register [chart:{...json...}] as a native marked block extension so the
@@ -219,11 +459,11 @@ window.chatInteractionManager = function () {
219
459
  // Defer to requestAnimationFrame so the browser has fully laid out the
220
460
  // canvas elements before Chart.js reads their dimensions.
221
461
  requestAnimationFrame(function () {
222
- var _iterator = _createForOfIteratorHelper(charts),
223
- _step;
462
+ var _iterator5 = _createForOfIteratorHelper(charts),
463
+ _step5;
224
464
  try {
225
- for (_iterator.s(); !(_step = _iterator.n()).done;) {
226
- var c = _step.value;
465
+ for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
466
+ var c = _step5.value;
227
467
  var canvas = document.getElementById(c.chartId);
228
468
  if (!canvas) {
229
469
  continue;
@@ -256,9 +496,9 @@ window.chatInteractionManager = function () {
256
496
  }
257
497
  }
258
498
  } catch (err) {
259
- _iterator.e(err);
499
+ _iterator5.e(err);
260
500
  } finally {
261
- _iterator.f();
501
+ _iterator5.f();
262
502
  }
263
503
  });
264
504
  }
@@ -277,8 +517,18 @@ window.chatInteractionManager = function () {
277
517
  ADD_ATTR: ['target']
278
518
  });
279
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
+ }
280
530
  var initialize = function initialize(instanceConfig) {
281
- var config = Object.assign({}, defaultConfig, instanceConfig);
531
+ var config = Object.assign({}, defaultConfig, compactObject(instanceConfig));
282
532
  // Keep defaultConfig in sync so renderers use overridden values
283
533
  defaultConfig = config;
284
534
  if (!config.signalRHubUrl) {
@@ -339,7 +589,12 @@ window.chatInteractionManager = function () {
339
589
  conversationButton: null,
340
590
  isConversationMode: false,
341
591
  notifications: [],
342
- notificationDismissTimers: {}
592
+ notificationDismissTimers: {},
593
+ copyTitle: config.copyTitle,
594
+ copiedTitle: config.copiedTitle,
595
+ copiedMessageIndex: -1,
596
+ copyResetTimeoutId: null,
597
+ activeCopyButton: null
343
598
  };
344
599
  },
345
600
  computed: {
@@ -467,7 +722,7 @@ window.chatInteractionManager = function () {
467
722
  _this.scrollToBottom();
468
723
  }
469
724
  });
470
- _this.connection.on("ReceiveConversationAssistantToken", function (itemId, messageId, token, responseId, appearance) {
725
+ _this.connection.on("ReceiveConversationAssistantToken", function (itemId, messageId, token, responseId, references, appearance) {
471
726
  if (!_this._conversationAssistantMessage) {
472
727
  _this.stopAudio();
473
728
  _this.hideTypingIndicator();
@@ -485,7 +740,8 @@ window.chatInteractionManager = function () {
485
740
  content: "",
486
741
  htmlContent: "",
487
742
  isStreaming: true,
488
- appearance: _this.normalizeAssistantAppearance(appearance)
743
+ appearance: _this.normalizeAssistantAppearance(appearance),
744
+ references: {}
489
745
  };
490
746
  _this.messages.push(newMessage);
491
747
  _this._conversationAssistantMessage = {
@@ -499,19 +755,22 @@ window.chatInteractionManager = function () {
499
755
  if (!msg.appearance) {
500
756
  msg.appearance = _this.normalizeAssistantAppearance(appearance);
501
757
  }
502
- msg.content = _this._conversationAssistantMessage.content;
503
- msg.htmlContent = parseMarkdownContent(msg.content, msg);
758
+ msg.rawContent = _this._conversationAssistantMessage.content;
759
+ msg.references = normalizeReferences(Object.assign({}, msg.references || {}, references || {}));
760
+ updateMessagePresentation(msg, msg.references);
504
761
  _this.$nextTick(function () {
505
762
  renderChartsInMessage(msg);
506
763
  _this.scrollToBottom();
507
764
  });
508
765
  }
509
766
  });
510
- _this.connection.on("ReceiveConversationAssistantComplete", function (itemId, messageId) {
767
+ _this.connection.on("ReceiveConversationAssistantComplete", function (itemId, messageId, references) {
511
768
  if (_this._conversationAssistantMessage) {
512
769
  var msg = _this.messages[_this._conversationAssistantMessage.index];
513
770
  if (msg) {
514
771
  msg.isStreaming = false;
772
+ msg.references = normalizeReferences(Object.assign({}, msg.references || {}, references || {}));
773
+ updateMessagePresentation(msg, msg.references);
515
774
  }
516
775
  _this._conversationAssistantMessage = null;
517
776
  }
@@ -605,79 +864,9 @@ window.chatInteractionManager = function () {
605
864
  addMessage: function addMessage(message) {
606
865
  var _this3 = this;
607
866
  if (message.content) {
608
- var processedContent = message.content.trim();
609
- if (message.references && _typeof(message.references) === "object" && Object.keys(message.references).length) {
610
- // Only include references that were actually cited in the response.
611
- var citedRefs = Object.entries(message.references).filter(function (_ref) {
612
- var _ref2 = _slicedToArray(_ref, 1),
613
- key = _ref2[0];
614
- return processedContent.includes(key);
615
- });
616
- if (citedRefs.length) {
617
- // Sort by original index so display indices follow a natural order.
618
- citedRefs.sort(function (_ref3, _ref4) {
619
- var _ref5 = _slicedToArray(_ref3, 2),
620
- a = _ref5[1];
621
- var _ref6 = _slicedToArray(_ref4, 2),
622
- b = _ref6[1];
623
- return a.index - b.index;
624
- });
625
-
626
- // Phase 1: Replace all markers with unique placeholders.
627
- var displayIndex = 1;
628
- var _iterator2 = _createForOfIteratorHelper(citedRefs),
629
- _step2;
630
- try {
631
- for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
632
- var _step2$value = _slicedToArray(_step2.value, 2),
633
- key = _step2$value[0],
634
- value = _step2$value[1];
635
- var placeholder = "__CITE_".concat(value.index, "__");
636
- processedContent = processedContent.replaceAll(key, placeholder);
637
- value._displayIndex = displayIndex++;
638
- value._placeholder = placeholder;
639
- }
640
-
641
- // Phase 2: Replace placeholders with sequential display indices.
642
- } catch (err) {
643
- _iterator2.e(err);
644
- } finally {
645
- _iterator2.f();
646
- }
647
- var _iterator3 = _createForOfIteratorHelper(citedRefs),
648
- _step3;
649
- try {
650
- for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
651
- var _step3$value = _slicedToArray(_step3.value, 2),
652
- _value = _step3$value[1];
653
- processedContent = processedContent.replaceAll(_value._placeholder, "<sup><strong>".concat(_value._displayIndex, "</strong></sup>"));
654
- }
655
- } catch (err) {
656
- _iterator3.e(err);
657
- } finally {
658
- _iterator3.f();
659
- }
660
- processedContent = processedContent.replaceAll('</strong></sup><sup>', '</strong></sup><sup>,</sup><sup>');
661
- processedContent += '<br><br>';
662
- var _iterator4 = _createForOfIteratorHelper(citedRefs),
663
- _step4;
664
- try {
665
- for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
666
- var _step4$value = _slicedToArray(_step4.value, 2),
667
- _key = _step4$value[0],
668
- _value2 = _step4$value[1];
669
- var label = _value2.text || "[doc:".concat(_value2.index, "]");
670
- processedContent += _value2.link ? "**".concat(_value2._displayIndex, "**. [").concat(label, "](").concat(_value2.link, ")<br>") : "**".concat(_value2._displayIndex, "**. ").concat(label, "<br>");
671
- }
672
- } catch (err) {
673
- _iterator4.e(err);
674
- } finally {
675
- _iterator4.f();
676
- }
677
- }
678
- }
679
- message.content = processedContent;
680
- message.htmlContent = parseMarkdownContent(processedContent, message);
867
+ var _message$rawContent;
868
+ message.rawContent = (_message$rawContent = message.rawContent) !== null && _message$rawContent !== void 0 ? _message$rawContent : message.content;
869
+ updateMessagePresentation(message, message.references);
681
870
  }
682
871
  this.addMessageInternal(message);
683
872
  this.hidePlaceholder();
@@ -828,11 +1017,12 @@ window.chatInteractionManager = function () {
828
1017
  message = newMessage;
829
1018
  }
830
1019
  if (chunk.references && _typeof(chunk.references) === "object" && Object.keys(chunk.references).length) {
831
- for (var _i = 0, _Object$entries = Object.entries(chunk.references); _i < _Object$entries.length; _i++) {
832
- var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
833
- key = _Object$entries$_i[0],
834
- value = _Object$entries$_i[1];
835
- references[key] = value;
1020
+ for (var _i3 = 0, _Object$entries2 = Object.entries(chunk.references); _i3 < _Object$entries2.length; _i3++) {
1021
+ var _normalizeReference2;
1022
+ var _Object$entries2$_i = _slicedToArray(_Object$entries2[_i3], 2),
1023
+ key = _Object$entries2$_i[0],
1024
+ value = _Object$entries2$_i[1];
1025
+ references[key] = (_normalizeReference2 = normalizeReference(value)) !== null && _normalizeReference2 !== void 0 ? _normalizeReference2 : {};
836
1026
  }
837
1027
  }
838
1028
  if (chunk.content) {
@@ -844,17 +1034,10 @@ window.chatInteractionManager = function () {
844
1034
  if (chunk.responseId) {
845
1035
  lastResponseId = chunk.responseId;
846
1036
  }
847
- var processedContent = chunk.content;
848
- for (var _i2 = 0, _Object$entries2 = Object.entries(references); _i2 < _Object$entries2.length; _i2++) {
849
- var _Object$entries2$_i = _slicedToArray(_Object$entries2[_i2], 2),
850
- _key2 = _Object$entries2$_i[0],
851
- _value3 = _Object$entries2$_i[1];
852
- processedContent = processedContent.replaceAll(_key2, "<sup><strong>".concat(_value3.index, "</strong></sup>"));
853
- }
854
- content += processedContent.replaceAll('</strong></sup><sup>', '</strong></sup><sup>,</sup><sup>');
1037
+ content += chunk.content;
855
1038
  }
856
- message.content = content;
857
- message.htmlContent = parseMarkdownContent(content, message);
1039
+ message.rawContent = content;
1040
+ updateMessagePresentation(message, references);
858
1041
  _this5.messages[messageIndex] = message;
859
1042
  _this5.$nextTick(function () {
860
1043
  renderChartsInMessage(message);
@@ -908,86 +1091,12 @@ window.chatInteractionManager = function () {
908
1091
  },
909
1092
  processReferences: function processReferences(references, messageIndex) {
910
1093
  var _this6 = this;
1094
+ references = normalizeReferences(references);
911
1095
  if (Object.keys(references).length) {
1096
+ var _ref19, _message$rawContent2;
912
1097
  var message = this.messages[messageIndex];
913
- var content = message.content || '';
914
-
915
- // Only include references that were actually cited in the response.
916
- // Check both raw [doc:N] markers and already-rendered <sup> tags from streaming.
917
- var citedRefs = Object.entries(references).filter(function (_ref7) {
918
- var _ref8 = _slicedToArray(_ref7, 2),
919
- key = _ref8[0],
920
- value = _ref8[1];
921
- return content.includes(key) || content.includes("<sup><strong>".concat(value.index, "</strong></sup>"));
922
- });
923
- if (!citedRefs.length) {
924
- return;
925
- }
926
-
927
- // Sort by original index so display indices follow a natural order.
928
- citedRefs.sort(function (_ref9, _ref0) {
929
- var _ref1 = _slicedToArray(_ref9, 2),
930
- a = _ref1[1];
931
- var _ref10 = _slicedToArray(_ref0, 2),
932
- b = _ref10[1];
933
- return a.index - b.index;
934
- });
935
-
936
- // Phase 1: Replace all markers with unique placeholders to avoid collisions during remapping.
937
- var processed = content.trim();
938
- var displayIndex = 1;
939
- var _iterator5 = _createForOfIteratorHelper(citedRefs),
940
- _step5;
941
- try {
942
- for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
943
- var _step5$value = _slicedToArray(_step5.value, 2),
944
- key = _step5$value[0],
945
- value = _step5$value[1];
946
- var placeholder = "__CITE_".concat(value.index, "__");
947
- processed = processed.replaceAll(key, placeholder);
948
- processed = processed.replaceAll("<sup><strong>".concat(value.index, "</strong></sup>"), placeholder);
949
- value._displayIndex = displayIndex++;
950
- value._placeholder = placeholder;
951
- }
952
-
953
- // Phase 2: Replace placeholders with sequential display indices.
954
- } catch (err) {
955
- _iterator5.e(err);
956
- } finally {
957
- _iterator5.f();
958
- }
959
- var _iterator6 = _createForOfIteratorHelper(citedRefs),
960
- _step6;
961
- try {
962
- for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
963
- var _step6$value = _slicedToArray(_step6.value, 2),
964
- _value4 = _step6$value[1];
965
- processed = processed.replaceAll(_value4._placeholder, "<sup><strong>".concat(_value4._displayIndex, "</strong></sup>"));
966
- }
967
- } catch (err) {
968
- _iterator6.e(err);
969
- } finally {
970
- _iterator6.f();
971
- }
972
- processed = processed.replaceAll('</strong></sup><sup>', '</strong></sup><sup>,</sup><sup>');
973
- processed += '<br><br>';
974
- var _iterator7 = _createForOfIteratorHelper(citedRefs),
975
- _step7;
976
- try {
977
- for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
978
- var _step7$value = _slicedToArray(_step7.value, 2),
979
- _key3 = _step7$value[0],
980
- _value5 = _step7$value[1];
981
- var label = _value5.text || "[doc:".concat(_value5.index, "]");
982
- processed += _value5.link ? "**".concat(_value5._displayIndex, "**. [").concat(label, "](").concat(_value5.link, ")<br>") : "**".concat(_value5._displayIndex, "**. ").concat(label, "<br>");
983
- }
984
- } catch (err) {
985
- _iterator7.e(err);
986
- } finally {
987
- _iterator7.f();
988
- }
989
- message.content = processed;
990
- message.htmlContent = parseMarkdownContent(processed, message);
1098
+ message.rawContent = (_ref19 = (_message$rawContent2 = message.rawContent) !== null && _message$rawContent2 !== void 0 ? _message$rawContent2 : message.content) !== null && _ref19 !== void 0 ? _ref19 : '';
1099
+ updateMessagePresentation(message, references);
991
1100
  this.messages[messageIndex] = message;
992
1101
  this.$nextTick(function () {
993
1102
  renderChartsInMessage(message);
@@ -1048,7 +1157,7 @@ window.chatInteractionManager = function () {
1048
1157
  buttons.forEach(function (button) {
1049
1158
  var buttonIndex = Number(button.getAttribute('data-tts-message-index'));
1050
1159
  var isPlaying = buttonIndex === _this7.ttsPlayingMessageIndex;
1051
- var iconHtml = isPlaying ? '<span class="fa-solid fa-circle-pause"></span>' : '<span class="fa-solid fa-circle-play"></span>';
1160
+ var iconHtml = isPlaying ? '<i class="fa-solid fa-circle-pause"></i>' : '<i class="fa-solid fa-circle-play"></i>';
1052
1161
  button.classList.toggle('tts-playing', isPlaying);
1053
1162
  button.setAttribute('title', isPlaying ? 'Pause audio' : 'Read aloud');
1054
1163
  button.replaceChildren(DOMPurify.sanitize(iconHtml, {
@@ -1056,8 +1165,38 @@ window.chatInteractionManager = function () {
1056
1165
  }));
1057
1166
  });
1058
1167
  },
1059
- synthesizeSpeech: function synthesizeSpeech(text, cacheIndex) {
1168
+ updateCopyButtons: function updateCopyButtons() {
1060
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;
1061
1200
  if (!this.textToSpeechEnabled || !text || !this.connection) {
1062
1201
  return;
1063
1202
  }
@@ -1066,16 +1205,16 @@ window.chatInteractionManager = function () {
1066
1205
  this._ttsCacheIndex = cacheIndex !== undefined ? cacheIndex : -1;
1067
1206
  this.connection.invoke("SynthesizeSpeech", this.getItemId(), text, this.ttsVoiceName)["catch"](function (err) {
1068
1207
  console.error("TTS synthesis error:", err);
1069
- _this8.isPlayingAudio = false;
1070
- _this8.ttsPlayingMessageIndex = -1;
1071
- _this8._ttsCacheIndex = -1;
1072
- _this8.$nextTick(function () {
1073
- return _this8.updateTtsPlaybackButtons();
1208
+ _this9.isPlayingAudio = false;
1209
+ _this9.ttsPlayingMessageIndex = -1;
1210
+ _this9._ttsCacheIndex = -1;
1211
+ _this9.$nextTick(function () {
1212
+ return _this9.updateTtsPlaybackButtons();
1074
1213
  });
1075
1214
  });
1076
1215
  },
1077
1216
  toggleMessageTts: function toggleMessageTts(message, index) {
1078
- var _this9 = this;
1217
+ var _this0 = this;
1079
1218
  if (this.ttsPlayingMessageIndex === index) {
1080
1219
  this.stopAudio();
1081
1220
  return;
@@ -1088,7 +1227,7 @@ window.chatInteractionManager = function () {
1088
1227
  }));
1089
1228
  this.ttsPlayingMessageIndex = index;
1090
1229
  this.$nextTick(function () {
1091
- return _this9.updateTtsPlaybackButtons();
1230
+ return _this0.updateTtsPlaybackButtons();
1092
1231
  });
1093
1232
  if (this.ttsAudioCache[index]) {
1094
1233
  this.playAudioBlob(this.ttsAudioCache[index]);
@@ -1097,13 +1236,13 @@ window.chatInteractionManager = function () {
1097
1236
  this.synthesizeSpeech(message.content, index);
1098
1237
  },
1099
1238
  playCollectedAudio: function playCollectedAudio() {
1100
- var _this0 = this;
1239
+ var _this1 = this;
1101
1240
  if (this.audioChunks.length === 0) {
1102
1241
  if (!this.isPlayingAudio && this.audioPlayQueue.length === 0) {
1103
1242
  this.isPlayingAudio = false;
1104
1243
  this.ttsPlayingMessageIndex = -1;
1105
1244
  this.$nextTick(function () {
1106
- return _this0.updateTtsPlaybackButtons();
1245
+ return _this1.updateTtsPlaybackButtons();
1107
1246
  });
1108
1247
  }
1109
1248
  return;
@@ -1113,18 +1252,18 @@ window.chatInteractionManager = function () {
1113
1252
  }, 0);
1114
1253
  var combined = new Uint8Array(totalLength);
1115
1254
  var offset = 0;
1116
- var _iterator8 = _createForOfIteratorHelper(this.audioChunks),
1117
- _step8;
1255
+ var _iterator6 = _createForOfIteratorHelper(this.audioChunks),
1256
+ _step6;
1118
1257
  try {
1119
- for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
1120
- var chunk = _step8.value;
1258
+ for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
1259
+ var chunk = _step6.value;
1121
1260
  combined.set(chunk, offset);
1122
1261
  offset += chunk.length;
1123
1262
  }
1124
1263
  } catch (err) {
1125
- _iterator8.e(err);
1264
+ _iterator6.e(err);
1126
1265
  } finally {
1127
- _iterator8.f();
1266
+ _iterator6.f();
1128
1267
  }
1129
1268
  this.audioChunks = [];
1130
1269
  var blob = new Blob([combined], {
@@ -1143,39 +1282,39 @@ window.chatInteractionManager = function () {
1143
1282
  this.playAudioBlob(blob);
1144
1283
  },
1145
1284
  playAudioBlob: function playAudioBlob(blob) {
1146
- var _this1 = this;
1285
+ var _this10 = this;
1147
1286
  var url = URL.createObjectURL(blob);
1148
1287
  var audio = new Audio(url);
1149
1288
  this.currentAudioUrl = url;
1150
1289
  this.currentAudioElement = audio;
1151
1290
  this.isPlayingAudio = true;
1152
1291
  audio.addEventListener('ended', function () {
1153
- _this1.currentAudioElement = null;
1154
- _this1.currentAudioUrl = null;
1292
+ _this10.currentAudioElement = null;
1293
+ _this10.currentAudioUrl = null;
1155
1294
  URL.revokeObjectURL(url);
1156
- _this1.playNextInQueue();
1295
+ _this10.playNextInQueue();
1157
1296
  });
1158
1297
  audio.addEventListener('error', function () {
1159
- _this1.currentAudioElement = null;
1160
- _this1.currentAudioUrl = null;
1298
+ _this10.currentAudioElement = null;
1299
+ _this10.currentAudioUrl = null;
1161
1300
  URL.revokeObjectURL(url);
1162
- _this1.playNextInQueue();
1301
+ _this10.playNextInQueue();
1163
1302
  });
1164
1303
  audio.play()["catch"](function (err) {
1165
1304
  console.error("Audio playback error:", err);
1166
- _this1.currentAudioElement = null;
1167
- _this1.currentAudioUrl = null;
1305
+ _this10.currentAudioElement = null;
1306
+ _this10.currentAudioUrl = null;
1168
1307
  URL.revokeObjectURL(url);
1169
- _this1.audioPlayQueue = [];
1170
- _this1.isPlayingAudio = false;
1171
- _this1.ttsPlayingMessageIndex = -1;
1172
- _this1.$nextTick(function () {
1173
- return _this1.updateTtsPlaybackButtons();
1308
+ _this10.audioPlayQueue = [];
1309
+ _this10.isPlayingAudio = false;
1310
+ _this10.ttsPlayingMessageIndex = -1;
1311
+ _this10.$nextTick(function () {
1312
+ return _this10.updateTtsPlaybackButtons();
1174
1313
  });
1175
1314
  });
1176
1315
  },
1177
1316
  playNextInQueue: function playNextInQueue() {
1178
- var _this10 = this;
1317
+ var _this11 = this;
1179
1318
  if (this.audioPlayQueue.length > 0) {
1180
1319
  var nextBlob = this.audioPlayQueue.shift();
1181
1320
  this.playAudioBlob(nextBlob);
@@ -1183,13 +1322,13 @@ window.chatInteractionManager = function () {
1183
1322
  this.isPlayingAudio = false;
1184
1323
  this.ttsPlayingMessageIndex = -1;
1185
1324
  this.$nextTick(function () {
1186
- return _this10.updateTtsPlaybackButtons();
1325
+ return _this11.updateTtsPlaybackButtons();
1187
1326
  });
1188
1327
  this.conversationModeOnAudioEnded();
1189
1328
  }
1190
1329
  },
1191
1330
  stopAudio: function stopAudio() {
1192
- var _this11 = this;
1331
+ var _this12 = this;
1193
1332
  if (this.currentAudioElement) {
1194
1333
  this.currentAudioElement.pause();
1195
1334
  this.currentAudioElement.currentTime = 0;
@@ -1204,7 +1343,7 @@ window.chatInteractionManager = function () {
1204
1343
  this.isPlayingAudio = false;
1205
1344
  this.ttsPlayingMessageIndex = -1;
1206
1345
  this.$nextTick(function () {
1207
- return _this11.updateTtsPlaybackButtons();
1346
+ return _this12.updateTtsPlaybackButtons();
1208
1347
  });
1209
1348
  },
1210
1349
  toggleConversationMode: function toggleConversationMode() {
@@ -1215,7 +1354,7 @@ window.chatInteractionManager = function () {
1215
1354
  }
1216
1355
  },
1217
1356
  startConversationMode: function startConversationMode() {
1218
- var _this12 = this;
1357
+ var _this13 = this;
1219
1358
  if (!this.conversationModeEnabled || this.isConversationMode || !this.connection) {
1220
1359
  return;
1221
1360
  }
@@ -1235,30 +1374,30 @@ window.chatInteractionManager = function () {
1235
1374
  }
1236
1375
  }).then(function (stream) {
1237
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';
1238
- _this12.mediaRecorder = new MediaRecorder(stream, {
1377
+ _this13.mediaRecorder = new MediaRecorder(stream, {
1239
1378
  mimeType: mimeType,
1240
1379
  audioBitsPerSecond: 128000
1241
1380
  });
1242
- _this12._conversationSubject = new signalR.Subject();
1243
- _this12._conversationStream = stream;
1381
+ _this13._conversationSubject = new signalR.Subject();
1382
+ _this13._conversationStream = stream;
1244
1383
 
1245
1384
  // Create an AnalyserNode for volume-based interrupt detection.
1246
1385
  var AudioCtx = window.AudioContext || window.webkitAudioContext;
1247
1386
  if (AudioCtx) {
1248
- _this12._conversationAudioCtx = new AudioCtx();
1249
- _this12._conversationAnalyser = _this12._conversationAudioCtx.createAnalyser();
1250
- _this12._conversationAnalyser.fftSize = 256;
1251
- var micSource = _this12._conversationAudioCtx.createMediaStreamSource(stream);
1252
- 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);
1253
1392
  }
1254
1393
  var pendingChunk = Promise.resolve();
1255
- var analyser = _this12._conversationAnalyser;
1394
+ var analyser = _this13._conversationAnalyser;
1256
1395
  var interruptVolumeThreshold = 30;
1257
- _this12.mediaRecorder.addEventListener('dataavailable', function (e) {
1396
+ _this13.mediaRecorder.addEventListener('dataavailable', function (e) {
1258
1397
  if (e.data && e.data.size > 0) {
1259
1398
  // During TTS playback, check mic volume to detect
1260
1399
  // user interruption (speaking above threshold).
1261
- if (_this12.isPlayingAudio && analyser) {
1400
+ if (_this13.isPlayingAudio && analyser) {
1262
1401
  var freqData = new Uint8Array(analyser.frequencyBinCount);
1263
1402
  analyser.getByteFrequencyData(freqData);
1264
1403
  var sum = 0;
@@ -1268,7 +1407,7 @@ window.chatInteractionManager = function () {
1268
1407
  var avg = sum / freqData.length;
1269
1408
  if (avg >= interruptVolumeThreshold) {
1270
1409
  // User is speaking — interrupt TTS playback.
1271
- _this12.stopAudio();
1410
+ _this13.stopAudio();
1272
1411
  }
1273
1412
  }
1274
1413
 
@@ -1290,7 +1429,7 @@ window.chatInteractionManager = function () {
1290
1429
  }, '');
1291
1430
  base64 = btoa(binaryString);
1292
1431
  try {
1293
- _this12._conversationSubject.next(base64);
1432
+ _this13._conversationSubject.next(base64);
1294
1433
  } catch (err) {
1295
1434
  // Subject may have been completed already.
1296
1435
  }
@@ -1301,27 +1440,27 @@ window.chatInteractionManager = function () {
1301
1440
  })));
1302
1441
  }
1303
1442
  });
1304
- _this12.mediaRecorder.addEventListener('stop', function () {
1443
+ _this13.mediaRecorder.addEventListener('stop', function () {
1305
1444
  stream.getTracks().forEach(function (track) {
1306
1445
  return track.stop();
1307
1446
  });
1308
1447
  pendingChunk.then(function () {
1309
1448
  try {
1310
- _this12._conversationSubject.complete();
1449
+ _this13._conversationSubject.complete();
1311
1450
  } catch (err) {
1312
1451
  // Already completed.
1313
1452
  }
1314
1453
  });
1315
1454
  });
1316
- var itemId = _this12.getItemId();
1455
+ var itemId = _this13.getItemId();
1317
1456
  var language = navigator.language || document.documentElement.lang || 'en-US';
1318
- _this12.connection.send("StartConversation", itemId, _this12._conversationSubject, mimeType, language);
1319
- _this12.mediaRecorder.start(250);
1320
- _this12.isRecording = true;
1457
+ _this13.connection.send("StartConversation", itemId, _this13._conversationSubject, mimeType, language);
1458
+ _this13.mediaRecorder.start(250);
1459
+ _this13.isRecording = true;
1321
1460
  })["catch"](function (err) {
1322
1461
  console.error('Microphone access denied:', err);
1323
- _this12.isConversationMode = false;
1324
- _this12.updateConversationButton();
1462
+ _this13.isConversationMode = false;
1463
+ _this13.updateConversationButton();
1325
1464
  });
1326
1465
  },
1327
1466
  stopConversationMode: function stopConversationMode() {
@@ -1425,12 +1564,12 @@ window.chatInteractionManager = function () {
1425
1564
  return removedCount;
1426
1565
  },
1427
1566
  scrollToBottom: function scrollToBottom() {
1428
- var _this13 = this;
1567
+ var _this14 = this;
1429
1568
  if (!this.autoScroll) {
1430
1569
  return;
1431
1570
  }
1432
1571
  setTimeout(function () {
1433
- _this13.chatContainer.scrollTop = _this13.chatContainer.scrollHeight - _this13.chatContainer.clientHeight;
1572
+ _this14.chatContainer.scrollTop = _this14.chatContainer.scrollHeight - _this14.chatContainer.clientHeight;
1434
1573
  }, 50);
1435
1574
  },
1436
1575
  handleUserInput: function handleUserInput(event) {
@@ -1446,7 +1585,7 @@ window.chatInteractionManager = function () {
1446
1585
  return document.querySelector('[data-chat-interaction-save-indicator]');
1447
1586
  },
1448
1587
  showSaveIndicator: function showSaveIndicator(text, className) {
1449
- var _this14 = this;
1588
+ var _this15 = this;
1450
1589
  var indicator = this.getSaveIndicatorElement();
1451
1590
  if (!indicator) {
1452
1591
  return;
@@ -1462,7 +1601,7 @@ window.chatInteractionManager = function () {
1462
1601
  }
1463
1602
  this.saveIndicatorTimeout = setTimeout(function () {
1464
1603
  indicator.textContent = '';
1465
- _this14.saveIndicatorTimeout = null;
1604
+ _this15.saveIndicatorTimeout = null;
1466
1605
  }, 3000);
1467
1606
  },
1468
1607
  clearPendingSettingsSave: function clearPendingSettingsSave() {
@@ -1536,10 +1675,10 @@ window.chatInteractionManager = function () {
1536
1675
  return false;
1537
1676
  },
1538
1677
  validateSettings: function validateSettings() {
1539
- var _this15 = this;
1678
+ var _this16 = this;
1540
1679
  var isValid = true;
1541
1680
  this.getSettingInputs().forEach(function (input) {
1542
- isValid = _this15.validateSettingInput(input) && isValid;
1681
+ isValid = _this16.validateSettingInput(input) && isValid;
1543
1682
  });
1544
1683
  return isValid;
1545
1684
  },
@@ -1562,7 +1701,7 @@ window.chatInteractionManager = function () {
1562
1701
  return 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["])');
1563
1702
  },
1564
1703
  getSelectedGroupValues: function getSelectedGroupValues(groupName, fallbackSelector) {
1565
- var explicitSelections = document.querySelectorAll(".capability-checkbox[data-save-group=\"".concat(groupName, "\"]:checked"));
1704
+ var explicitSelections = document.querySelectorAll(".capability-checkbox[data-save-group=\"".concat(groupName, "\"]:checked, .capability-checkbox[data-group=\"").concat(groupName, "\"]:checked"));
1566
1705
  if (explicitSelections.length > 0) {
1567
1706
  var _values = [];
1568
1707
  explicitSelections.forEach(function (checkbox) {
@@ -1635,12 +1774,12 @@ window.chatInteractionManager = function () {
1635
1774
  }
1636
1775
  },
1637
1776
  scheduleNotificationDismiss: function scheduleNotificationDismiss(notification) {
1638
- var _this16 = this;
1777
+ var _this17 = this;
1639
1778
  if (!notification || !notification.type || !notification.autoDismissMs || notification.autoDismissMs <= 0) {
1640
1779
  return;
1641
1780
  }
1642
1781
  this.notificationDismissTimers[notification.type] = setTimeout(function () {
1643
- _this16.removeNotification(notification.type);
1782
+ _this17.removeNotification(notification.type);
1644
1783
  }, notification.autoDismissMs);
1645
1784
  },
1646
1785
  clearNotificationDismiss: function clearNotificationDismiss(notificationType) {
@@ -1680,7 +1819,7 @@ window.chatInteractionManager = function () {
1680
1819
  this.showPlaceholder();
1681
1820
  },
1682
1821
  initializeApp: function initializeApp() {
1683
- var _this17 = this;
1822
+ var _this18 = this;
1684
1823
  this.inputElement = document.querySelector(config.inputElementSelector);
1685
1824
  this.buttonElement = document.querySelector(config.sendButtonElementSelector);
1686
1825
  this.chatContainer = document.querySelector(config.chatContainerElementSelector);
@@ -1692,59 +1831,59 @@ window.chatInteractionManager = function () {
1692
1831
 
1693
1832
  // Pause auto-scroll when the user manually scrolls up during streaming.
1694
1833
  this.chatContainer.addEventListener('scroll', function () {
1695
- if (!_this17.stream) {
1834
+ if (!_this18.stream) {
1696
1835
  return;
1697
1836
  }
1698
1837
  var threshold = 30;
1699
- var atBottom = _this17.chatContainer.scrollHeight - _this17.chatContainer.clientHeight - _this17.chatContainer.scrollTop <= threshold;
1700
- _this17.autoScroll = atBottom;
1838
+ var atBottom = _this18.chatContainer.scrollHeight - _this18.chatContainer.clientHeight - _this18.chatContainer.scrollTop <= threshold;
1839
+ _this18.autoScroll = atBottom;
1701
1840
  });
1702
1841
  this.inputElement.addEventListener('keyup', function (event) {
1703
- if (_this17.stream != null) {
1842
+ if (_this18.stream != null) {
1704
1843
  return;
1705
1844
  }
1706
1845
  if (event.key === "Enter" && !event.shiftKey) {
1707
- _this17.buttonElement.click();
1846
+ _this18.buttonElement.click();
1708
1847
  }
1709
1848
  });
1710
1849
  this.inputElement.addEventListener('input', function (e) {
1711
- _this17.handleUserInput(e);
1850
+ _this18.handleUserInput(e);
1712
1851
  if (e.target.value.trim()) {
1713
- _this17.buttonElement.removeAttribute('disabled');
1852
+ _this18.buttonElement.removeAttribute('disabled');
1714
1853
  } else {
1715
- _this17.buttonElement.setAttribute('disabled', true);
1854
+ _this18.buttonElement.setAttribute('disabled', true);
1716
1855
  }
1717
1856
  });
1718
1857
  this.inputElement.addEventListener('paste', function (e) {
1719
1858
  // Use setTimeout to allow the paste to complete before checking the value
1720
1859
  setTimeout(function () {
1721
- _this17.prompt = _this17.inputElement.value;
1722
- if (_this17.inputElement.value.trim()) {
1723
- _this17.buttonElement.removeAttribute('disabled');
1860
+ _this18.prompt = _this18.inputElement.value;
1861
+ if (_this18.inputElement.value.trim()) {
1862
+ _this18.buttonElement.removeAttribute('disabled');
1724
1863
  } else {
1725
- _this17.buttonElement.setAttribute('disabled', true);
1864
+ _this18.buttonElement.setAttribute('disabled', true);
1726
1865
  }
1727
1866
  }, 0);
1728
1867
  });
1729
1868
  this.buttonElement.addEventListener('click', function () {
1730
- if (_this17.stream != null) {
1731
- _this17.stream.dispose();
1732
- _this17.stream = null;
1733
- _this17.streamingFinished();
1734
- _this17.hideTypingIndicator();
1869
+ if (_this18.stream != null) {
1870
+ _this18.stream.dispose();
1871
+ _this18.stream = null;
1872
+ _this18.streamingFinished();
1873
+ _this18.hideTypingIndicator();
1735
1874
 
1736
1875
  // Clean up: remove empty assistant message or stop streaming animation.
1737
- if (_this17.messages.length > 0) {
1738
- var lastMsg = _this17.messages[_this17.messages.length - 1];
1876
+ if (_this18.messages.length > 0) {
1877
+ var lastMsg = _this18.messages[_this18.messages.length - 1];
1739
1878
  if (lastMsg.role === 'assistant' && !lastMsg.content) {
1740
- _this17.messages.pop();
1879
+ _this18.messages.pop();
1741
1880
  } else if (lastMsg.isStreaming) {
1742
1881
  lastMsg.isStreaming = false;
1743
1882
  }
1744
1883
  }
1745
1884
  return;
1746
1885
  }
1747
- _this17.sendMessage();
1886
+ _this18.sendMessage();
1748
1887
  });
1749
1888
  var chatInteractionItems = document.getElementsByClassName('chat-interaction-history-item');
1750
1889
  for (var i = 0; i < chatInteractionItems.length; i++) {
@@ -1755,11 +1894,12 @@ window.chatInteractionManager = function () {
1755
1894
  console.error('An element with the class chat-interaction-history-item with no data-interaction-id set.');
1756
1895
  return;
1757
1896
  }
1758
- _this17.loadInteraction(itemId);
1897
+ _this18.loadInteraction(itemId);
1759
1898
  });
1760
1899
  }
1761
- for (var _i3 = 0; _i3 < config.messages.length; _i3++) {
1762
- this.addMessage(config.messages[_i3]);
1900
+ var initialMessages = Array.isArray(config.messages) ? config.messages : [];
1901
+ for (var _i4 = 0; _i4 < initialMessages.length; _i4++) {
1902
+ this.addMessage(initialMessages[_i4]);
1763
1903
  }
1764
1904
 
1765
1905
  // Delegate click for code block copy buttons.
@@ -1777,29 +1917,29 @@ window.chatInteractionManager = function () {
1777
1917
  if (codeEl) {
1778
1918
  navigator.clipboard.writeText(codeEl.textContent);
1779
1919
  var copiedText = config.codeCopiedText || 'Copied!';
1780
- btn.innerHTML = '<span class="fa-solid fa-check"></span> ' + copiedText;
1920
+ btn.innerHTML = '<i class="fa-solid fa-check"></i> ' + copiedText;
1781
1921
  setTimeout(function () {
1782
- btn.innerHTML = '<span class="fa-regular fa-copy"></span>';
1922
+ btn.innerHTML = '<i class="fa-regular fa-copy"></i>';
1783
1923
  }, 2000);
1784
1924
  }
1785
1925
  });
1786
1926
  }
1787
1927
  document.addEventListener('input', function (event) {
1788
1928
  if (event.target.matches('.setting-input[data-setting]')) {
1789
- _this17.validateSettingInput(event.target);
1790
- _this17.queueSettingsSave();
1929
+ _this18.validateSettingInput(event.target);
1930
+ _this18.queueSettingsSave();
1791
1931
  }
1792
1932
  });
1793
1933
  document.addEventListener('change', function (event) {
1794
- if (event.target.matches('.setting-input[data-setting], .capability-checkbox[data-save-group], .group-toggle, .ci-agent-global-toggle')) {
1934
+ if (event.target.matches('.setting-input[data-setting], .capability-checkbox[data-save-group], .capability-checkbox[data-group], .group-toggle, .ci-agent-global-toggle')) {
1795
1935
  if (event.target.matches('.setting-input[data-setting]')) {
1796
- _this17.validateSettingInput(event.target);
1936
+ _this18.validateSettingInput(event.target);
1797
1937
  }
1798
- _this17.queueSettingsSave();
1938
+ _this18.queueSettingsSave();
1799
1939
  return;
1800
1940
  }
1801
1941
  if (event.target.closest('.prompt-template-parameters-input, .prompt-template-id-input')) {
1802
- _this17.queueSettingsSave();
1942
+ _this18.queueSettingsSave();
1803
1943
  }
1804
1944
  });
1805
1945
  document.addEventListener('click', function (event) {
@@ -1807,7 +1947,7 @@ window.chatInteractionManager = function () {
1807
1947
  return;
1808
1948
  }
1809
1949
  setTimeout(function () {
1810
- _this17.queueSettingsSave();
1950
+ _this18.queueSettingsSave();
1811
1951
  }, 0);
1812
1952
  });
1813
1953
 
@@ -1817,7 +1957,7 @@ window.chatInteractionManager = function () {
1817
1957
  clearHistoryBtn.addEventListener('click', function () {
1818
1958
  var itemId = clearHistoryBtn.getAttribute('data-interaction-id');
1819
1959
  if (itemId) {
1820
- _this17.clearHistory(itemId);
1960
+ _this18.clearHistory(itemId);
1821
1961
  }
1822
1962
  });
1823
1963
  }
@@ -1828,7 +1968,7 @@ window.chatInteractionManager = function () {
1828
1968
  if (this.micButton) {
1829
1969
  this.micButton.style.display = '';
1830
1970
  this.micButton.addEventListener('click', function () {
1831
- _this17.toggleRecording();
1971
+ _this18.toggleRecording();
1832
1972
  });
1833
1973
  }
1834
1974
  }
@@ -1838,7 +1978,7 @@ window.chatInteractionManager = function () {
1838
1978
  this.conversationButton = document.querySelector(config.conversationButtonElementSelector);
1839
1979
  if (this.conversationButton) {
1840
1980
  this.conversationButton.addEventListener('click', function () {
1841
- _this17.toggleConversationMode();
1981
+ _this18.toggleConversationMode();
1842
1982
  });
1843
1983
  }
1844
1984
  }
@@ -1856,29 +1996,38 @@ window.chatInteractionManager = function () {
1856
1996
  },
1857
1997
  clearHistory: function clearHistory(itemId) {
1858
1998
  var self = this;
1859
- confirmDialog({
1860
- title: config.clearHistoryTitle,
1861
- message: config.clearHistoryMessage,
1862
- okText: config.clearHistoryOkText,
1863
- cancelText: config.clearHistoryCancelText,
1864
- callback: function callback(confirmed) {
1865
- if (confirmed) {
1866
- // Cancel any active stream before clearing history.
1867
- if (self.stream) {
1868
- self.stream.dispose();
1869
- self.stream = null;
1870
- self.hideTypingIndicator();
1871
- self.streamingFinished();
1999
+ var clearHistoryConfirmed = function clearHistoryConfirmed() {
2000
+ // Cancel any active stream before clearing history.
2001
+ if (self.stream) {
2002
+ self.stream.dispose();
2003
+ self.stream = null;
2004
+ self.hideTypingIndicator();
2005
+ self.streamingFinished();
2006
+ }
2007
+ self.connection.invoke("ClearHistory", itemId)["catch"](function (err) {
2008
+ return console.error('Error clearing history:', err);
2009
+ });
2010
+ };
2011
+ if (typeof confirmDialog === 'function') {
2012
+ confirmDialog({
2013
+ title: config.clearHistoryTitle,
2014
+ message: config.clearHistoryMessage,
2015
+ okText: config.clearHistoryOkText,
2016
+ cancelText: config.clearHistoryCancelText,
2017
+ callback: function callback(confirmed) {
2018
+ if (confirmed) {
2019
+ clearHistoryConfirmed();
1872
2020
  }
1873
- self.connection.invoke("ClearHistory", itemId)["catch"](function (err) {
1874
- return console.error('Error clearing history:', err);
1875
- });
1876
2021
  }
1877
- }
1878
- });
2022
+ });
2023
+ return;
2024
+ }
2025
+ if (window.confirm(config.clearHistoryMessage || 'Clear all messages?')) {
2026
+ clearHistoryConfirmed();
2027
+ }
1879
2028
  },
1880
2029
  debouncedSaveSettings: function debouncedSaveSettings() {
1881
- var _this18 = this;
2030
+ var _this19 = this;
1882
2031
  // Clear any existing timeout to reset the debounce timer
1883
2032
  this.clearPendingSettingsSave();
1884
2033
 
@@ -1889,11 +2038,11 @@ window.chatInteractionManager = function () {
1889
2038
 
1890
2039
  // Set a new timeout to save after 850ms of no changes
1891
2040
  this.saveSettingsTimeout = setTimeout(function () {
1892
- if (_this18.settingsDirty) {
1893
- _this18.saveSettings();
1894
- _this18.settingsDirty = false;
2041
+ if (_this19.settingsDirty) {
2042
+ _this19.saveSettings();
2043
+ _this19.settingsDirty = false;
1895
2044
  }
1896
- _this18.saveSettingsTimeout = null;
2045
+ _this19.saveSettingsTimeout = null;
1897
2046
  }, 850);
1898
2047
  },
1899
2048
  getSelectedToolNames: function getSelectedToolNames() {
@@ -1909,7 +2058,7 @@ window.chatInteractionManager = function () {
1909
2058
  return this.getSelectedGroupValues('agentNames', 'input[type="checkbox"][name$="].IsSelected"][name^="ChatInteraction.Agents["]:checked');
1910
2059
  },
1911
2060
  saveSettings: function saveSettings() {
1912
- var _this19 = this;
2061
+ var _this20 = this;
1913
2062
  var itemId = this.getItemId();
1914
2063
  if (!itemId) {
1915
2064
  return Promise.resolve();
@@ -1954,7 +2103,7 @@ window.chatInteractionManager = function () {
1954
2103
  }
1955
2104
  return this.connection.invoke("SaveSettings", itemId, settings)["catch"](function (err) {
1956
2105
  console.error('Error saving settings:', err);
1957
- _this19.showSaveIndicator('Save failed', 'text-danger');
2106
+ _this20.showSaveIndicator('Save failed', 'text-danger');
1958
2107
  });
1959
2108
  },
1960
2109
  flushPendingSave: function flushPendingSave() {
@@ -1980,11 +2129,48 @@ window.chatInteractionManager = function () {
1980
2129
  this.setItemId(itemId);
1981
2130
  this.isInteractionStarted = true;
1982
2131
  },
1983
- copyResponse: function copyResponse(message) {
1984
- navigator.clipboard.writeText(message);
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
+ });
1985
2171
  },
1986
2172
  startRecording: function startRecording() {
1987
- var _this20 = this;
2173
+ var _this22 = this;
1988
2174
  if (this.isRecording || !this.connection) {
1989
2175
  return;
1990
2176
  }
@@ -1996,16 +2182,16 @@ window.chatInteractionManager = function () {
1996
2182
  }
1997
2183
  }).then(function (stream) {
1998
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';
1999
- _this20.mediaRecorder = new MediaRecorder(stream, {
2185
+ _this22.mediaRecorder = new MediaRecorder(stream, {
2000
2186
  mimeType: mimeType,
2001
2187
  audioBitsPerSecond: 128000
2002
2188
  });
2003
- _this20.preRecordingPrompt = _this20.prompt;
2004
- _this20._audioInputSent = false;
2189
+ _this22.preRecordingPrompt = _this22.prompt;
2190
+ _this22._audioInputSent = false;
2005
2191
  var subject = new signalR.Subject();
2006
- var itemId = _this20.getItemId();
2192
+ var itemId = _this22.getItemId();
2007
2193
  var pendingChunk = Promise.resolve();
2008
- _this20.mediaRecorder.addEventListener('dataavailable', function (e) {
2194
+ _this22.mediaRecorder.addEventListener('dataavailable', function (e) {
2009
2195
  if (e.data && e.data.size > 0) {
2010
2196
  pendingChunk = pendingChunk.then(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4() {
2011
2197
  var data, uint8Array, binaryString, base64;
@@ -2029,7 +2215,7 @@ window.chatInteractionManager = function () {
2029
2215
  })));
2030
2216
  }
2031
2217
  });
2032
- _this20.mediaRecorder.addEventListener('stop', function () {
2218
+ _this22.mediaRecorder.addEventListener('stop', function () {
2033
2219
  stream.getTracks().forEach(function (track) {
2034
2220
  return track.stop();
2035
2221
  });
@@ -2038,10 +2224,10 @@ window.chatInteractionManager = function () {
2038
2224
  });
2039
2225
  });
2040
2226
  var language = navigator.language || document.documentElement.lang || 'en-US';
2041
- _this20.connection.send("SendAudioStream", itemId, subject, mimeType, language);
2042
- _this20.mediaRecorder.start(250);
2043
- _this20.isRecording = true;
2044
- _this20.updateMicButton();
2227
+ _this22.connection.send("SendAudioStream", itemId, subject, mimeType, language);
2228
+ _this22.mediaRecorder.start(250);
2229
+ _this22.isRecording = true;
2230
+ _this22.updateMicButton();
2045
2231
  })["catch"](function (err) {
2046
2232
  console.error('Microphone access denied:', err);
2047
2233
  });
@@ -2067,10 +2253,10 @@ window.chatInteractionManager = function () {
2067
2253
  }
2068
2254
  if (this.isRecording) {
2069
2255
  this.micButton.classList.add('stt-recording');
2070
- this.micButton.innerHTML = '<span class="fa-solid fa-stop"></span>';
2256
+ this.micButton.innerHTML = '<i class="fa-solid fa-stop"></i>';
2071
2257
  } else {
2072
2258
  this.micButton.classList.remove('stt-recording');
2073
- this.micButton.innerHTML = '<span class="fa-solid fa-microphone"></span>';
2259
+ this.micButton.innerHTML = '<i class="fa-solid fa-microphone"></i>';
2074
2260
  }
2075
2261
  }
2076
2262
  },
@@ -2092,18 +2278,29 @@ window.chatInteractionManager = function () {
2092
2278
  this.inputElement.placeholder = '';
2093
2279
  }
2094
2280
  }
2281
+ },
2282
+ copiedMessageIndex: function copiedMessageIndex() {
2283
+ var _this23 = this;
2284
+ this.$nextTick(function () {
2285
+ return _this23.updateCopyButtons();
2286
+ });
2095
2287
  }
2096
2288
  },
2097
2289
  mounted: function mounted() {
2098
- var _this21 = this;
2290
+ var _this24 = this;
2099
2291
  _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee5() {
2100
2292
  return _regenerator().w(function (_context5) {
2101
2293
  while (1) switch (_context5.n) {
2102
2294
  case 0:
2103
2295
  _context5.n = 1;
2104
- return _this21.startConnection();
2296
+ return _this24.startConnection();
2105
2297
  case 1:
2106
- _this21.initializeApp();
2298
+ _this24.initializeApp();
2299
+ _this24.$nextTick(function () {
2300
+ _this24.updateCopyButtons();
2301
+ refreshFontAwesomeIcons(_this24.$el);
2302
+ _this24.fontAwesomeObserver = observeFontAwesomeIcons(_this24.$el);
2303
+ });
2107
2304
  case 2:
2108
2305
  return _context5.a(2);
2109
2306
  }
@@ -2115,6 +2312,11 @@ window.chatInteractionManager = function () {
2115
2312
  beforeUnmount: function beforeUnmount() {
2116
2313
  window.removeEventListener('beforeunload', this.handleBeforeUnload);
2117
2314
  window.removeEventListener('crestapps-ai-chat-stop-tts', this.handleExternalTtsStop);
2315
+ if (this.fontAwesomeObserver) {
2316
+ this.fontAwesomeObserver.disconnect();
2317
+ this.fontAwesomeObserver = null;
2318
+ }
2319
+ this.clearCopiedMessageState();
2118
2320
  this.stopAudio(false);
2119
2321
  if (this.stream) {
2120
2322
  this.stream.dispose();
@@ -2128,8 +2330,666 @@ window.chatInteractionManager = function () {
2128
2330
  }).mount(config.appElementSelector);
2129
2331
  return app;
2130
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
+ }
2397
+ return {
2398
+ initialize: initialize,
2399
+ initializeFromElement: initializeFromElement
2400
+ };
2401
+ }();
2402
+ window.chatInteractionDocumentManager = function () {
2403
+ var managerStateKey = '__chatInteractionDocumentManagerState';
2404
+ function normalizeDocumentInfo(document) {
2405
+ if (!document || _typeof(document) !== 'object') {
2406
+ return null;
2407
+ }
2408
+ return {
2409
+ documentId: document.documentId || document.DocumentId || '',
2410
+ fileName: document.fileName || document.FileName || '',
2411
+ fileSize: document.fileSize || document.FileSize || 0
2412
+ };
2413
+ }
2414
+ function formatFileSize(bytes) {
2415
+ if (!bytes || bytes < 1024) {
2416
+ return (bytes || 0) + ' B';
2417
+ }
2418
+ if (bytes < 1024 * 1024) {
2419
+ return (bytes / 1024).toFixed(1) + ' KB';
2420
+ }
2421
+ return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
2422
+ }
2423
+ function getDocumentKey(fileName, fileSize) {
2424
+ return (fileName || '').trim().toLowerCase() + '::' + (fileSize || 0);
2425
+ }
2426
+ function isDuplicateFile(file, knownKeys) {
2427
+ return knownKeys.has(getDocumentKey(file.name, file.size));
2428
+ }
2429
+ function getDocumentsFromDom(container) {
2430
+ if (!container) {
2431
+ return [];
2432
+ }
2433
+ return Array.from(container.querySelectorAll('[data-chat-document-id]')).map(function (element) {
2434
+ return normalizeDocumentInfo({
2435
+ documentId: element.dataset.chatDocumentId,
2436
+ fileName: element.dataset.chatDocumentName,
2437
+ fileSize: Number(element.dataset.chatDocumentSize || 0)
2438
+ });
2439
+ }).filter(function (document) {
2440
+ return document && document.documentId;
2441
+ });
2442
+ }
2443
+ function initialize(config) {
2444
+ if (!config || !config.itemId) {
2445
+ return;
2446
+ }
2447
+ var fileInput = document.getElementById('chat-doc-upload');
2448
+ var documentsList = document.getElementById('chat-documents-list');
2449
+ var status = document.getElementById('chat-doc-upload-status');
2450
+ var progressContainer = document.getElementById('chat-doc-upload-progress');
2451
+ var progressBar = document.getElementById('chat-doc-upload-progress-bar');
2452
+ var uploadQueue = document.getElementById('chat-doc-upload-queue');
2453
+ if (!fileInput || !documentsList || !status || !progressContainer || !progressBar || !uploadQueue) {
2454
+ return;
2455
+ }
2456
+ var previousState = fileInput[managerStateKey];
2457
+ if (previousState && typeof previousState.dispose === 'function') {
2458
+ previousState.dispose();
2459
+ }
2460
+ var interactionDocuments = (Array.isArray(config.existingDocuments) ? config.existingDocuments : []).map(normalizeDocumentInfo).filter(function (document) {
2461
+ return document && document.documentId;
2462
+ });
2463
+ if (interactionDocuments.length === 0) {
2464
+ interactionDocuments = getDocumentsFromDom(documentsList);
2465
+ }
2466
+ var uploadItems = [];
2467
+ var isUploadingDocuments = false;
2468
+ function createTextElement(tagName, className, text) {
2469
+ var element = document.createElement(tagName);
2470
+ if (className) {
2471
+ element.className = className;
2472
+ }
2473
+ element.textContent = text;
2474
+ return element;
2475
+ }
2476
+ function renderDocuments() {
2477
+ documentsList.innerHTML = '';
2478
+ if (interactionDocuments.length === 0) {
2479
+ documentsList.appendChild(createTextElement('div', 'text-muted small', 'No documents uploaded yet.'));
2480
+ return;
2481
+ }
2482
+ interactionDocuments.forEach(function (documentInfo) {
2483
+ var row = window.document.createElement('div');
2484
+ row.className = 'd-flex justify-content-between align-items-start gap-2 border rounded px-2 py-2 bg-white chat-document-row';
2485
+ row.dataset.chatDocumentId = documentInfo.documentId;
2486
+ row.dataset.chatDocumentName = documentInfo.fileName;
2487
+ row.dataset.chatDocumentSize = documentInfo.fileSize;
2488
+ var details = window.document.createElement('div');
2489
+ details.className = 'me-2 min-w-0';
2490
+ var name = createTextElement('div', 'fw-semibold small', documentInfo.fileName || 'Document');
2491
+ var icon = window.document.createElement('i');
2492
+ icon.className = 'bi bi-file-earmark-text me-1';
2493
+ name.prepend(icon);
2494
+ var size = createTextElement('div', 'text-muted small', formatFileSize(documentInfo.fileSize));
2495
+ details.appendChild(name);
2496
+ details.appendChild(size);
2497
+ var removeButton = createTextElement('button', 'btn btn-sm btn-outline-danger remove-chat-document-btn', ' Remove');
2498
+ removeButton.type = 'button';
2499
+ removeButton.dataset.documentId = documentInfo.documentId;
2500
+ var removeIcon = window.document.createElement('i');
2501
+ removeIcon.className = 'bi bi-trash';
2502
+ removeButton.prepend(removeIcon);
2503
+ removeButton.addEventListener('click', function () {
2504
+ return removeDocument(documentInfo.documentId);
2505
+ });
2506
+ row.appendChild(details);
2507
+ row.appendChild(removeButton);
2508
+ documentsList.appendChild(row);
2509
+ });
2510
+ }
2511
+ function showUploadStatus(message, cssClass) {
2512
+ if (!message) {
2513
+ status.textContent = '';
2514
+ status.className = 'small mt-2 d-none';
2515
+ return;
2516
+ }
2517
+ status.textContent = message;
2518
+ status.className = 'small mt-2 ' + (cssClass || 'text-muted');
2519
+ }
2520
+ function showUploadProgress(progress, message, cssClass) {
2521
+ if (progress === null || progress === undefined) {
2522
+ progressContainer.className = 'progress mt-2 d-none';
2523
+ progressContainer.setAttribute('aria-valuenow', '0');
2524
+ progressBar.className = 'progress-bar progress-bar-striped progress-bar-animated';
2525
+ progressBar.style.width = '0%';
2526
+ progressBar.textContent = '0%';
2527
+ return;
2528
+ }
2529
+ var roundedProgress = Math.max(0, Math.min(100, Math.round(progress)));
2530
+ progressContainer.className = 'progress mt-2';
2531
+ progressContainer.setAttribute('aria-valuenow', roundedProgress.toString());
2532
+ progressBar.className = 'progress-bar ' + (cssClass || 'progress-bar-striped progress-bar-animated');
2533
+ progressBar.style.width = roundedProgress + '%';
2534
+ progressBar.textContent = message || roundedProgress + '%';
2535
+ }
2536
+ function getUploadStatePresentation(state) {
2537
+ switch (state) {
2538
+ case 'uploaded':
2539
+ return {
2540
+ label: 'Uploaded',
2541
+ badgeClass: 'text-bg-success',
2542
+ progressClass: 'bg-success'
2543
+ };
2544
+ case 'failed':
2545
+ return {
2546
+ label: 'Failed',
2547
+ badgeClass: 'text-bg-danger',
2548
+ progressClass: 'bg-danger'
2549
+ };
2550
+ case 'uploading':
2551
+ return {
2552
+ label: 'Uploading',
2553
+ badgeClass: 'text-bg-warning',
2554
+ progressClass: 'bg-warning progress-bar-striped progress-bar-animated'
2555
+ };
2556
+ default:
2557
+ return {
2558
+ label: 'Queued',
2559
+ badgeClass: 'text-bg-secondary',
2560
+ progressClass: 'bg-secondary progress-bar-striped progress-bar-animated'
2561
+ };
2562
+ }
2563
+ }
2564
+ function formatUploadMessage(item) {
2565
+ if (item.status === 'failed' && item.error) {
2566
+ return item.error;
2567
+ }
2568
+ if (item.status === 'uploaded') {
2569
+ return 'Upload completed successfully.';
2570
+ }
2571
+ if (item.status === 'uploading') {
2572
+ return item.progress + '% uploaded';
2573
+ }
2574
+ return 'Waiting to upload...';
2575
+ }
2576
+ function renderUploadQueue() {
2577
+ uploadQueue.innerHTML = '';
2578
+ uploadItems.forEach(function (item) {
2579
+ var presentation = getUploadStatePresentation(item.status);
2580
+ var card = document.createElement('div');
2581
+ card.className = 'border rounded px-2 py-2 bg-white';
2582
+ var header = document.createElement('div');
2583
+ header.className = 'd-flex justify-content-between align-items-start gap-2';
2584
+ var fileDetails = document.createElement('div');
2585
+ fileDetails.className = 'flex-grow-1 min-w-0';
2586
+ fileDetails.appendChild(createTextElement('div', 'fw-semibold small', item.fileName));
2587
+ fileDetails.appendChild(createTextElement('div', 'text-muted small', formatFileSize(item.fileSize)));
2588
+ var badge = createTextElement('span', 'badge ' + presentation.badgeClass, presentation.label);
2589
+ header.appendChild(fileDetails);
2590
+ header.appendChild(badge);
2591
+ var progress = document.createElement('div');
2592
+ progress.className = 'progress mt-2';
2593
+ progress.setAttribute('role', 'progressbar');
2594
+ progress.setAttribute('aria-valuemin', '0');
2595
+ progress.setAttribute('aria-valuemax', '100');
2596
+ progress.setAttribute('aria-valuenow', item.progress.toString());
2597
+ var progressState = document.createElement('div');
2598
+ progressState.className = 'progress-bar ' + presentation.progressClass;
2599
+ progressState.style.width = item.progress + '%';
2600
+ progressState.textContent = item.progress + '%';
2601
+ progress.appendChild(progressState);
2602
+ var message = createTextElement('div', item.status === 'failed' ? 'small text-danger mt-2' : 'small text-muted mt-2', formatUploadMessage(item));
2603
+ card.appendChild(header);
2604
+ card.appendChild(progress);
2605
+ card.appendChild(message);
2606
+ uploadQueue.appendChild(card);
2607
+ });
2608
+ }
2609
+ function createUploadItem(file, index) {
2610
+ return {
2611
+ id: file.name + '::' + file.size + '::' + file.lastModified + '::' + index + '::' + Date.now(),
2612
+ fileName: file.name,
2613
+ fileSize: file.size,
2614
+ status: 'queued',
2615
+ progress: 0,
2616
+ error: null
2617
+ };
2618
+ }
2619
+ function updateUploadItem(itemId, updates) {
2620
+ uploadItems = uploadItems.map(function (item) {
2621
+ return item.id === itemId ? Object.assign({}, item, updates) : item;
2622
+ });
2623
+ renderUploadQueue();
2624
+ }
2625
+ function removeUploadItems(predicate) {
2626
+ uploadItems = uploadItems.filter(function (item) {
2627
+ return !predicate(item);
2628
+ });
2629
+ renderUploadQueue();
2630
+ }
2631
+ function uploadSingleDocument(file, itemIdToUpdate, fileIndex, totalFiles) {
2632
+ return new Promise(function (resolve, reject) {
2633
+ var formData = new FormData();
2634
+ formData.append('chatInteractionId', config.itemId);
2635
+ formData.append('files', file);
2636
+ var xhr = new XMLHttpRequest();
2637
+ xhr.open('POST', config.uploadDocumentUrl, true);
2638
+ xhr.upload.addEventListener('progress', function (event) {
2639
+ if (!event.lengthComputable) {
2640
+ return;
2641
+ }
2642
+ var fileProgress = Math.round(event.loaded / event.total * 100);
2643
+ updateUploadItem(itemIdToUpdate, {
2644
+ status: 'uploading',
2645
+ progress: fileProgress
2646
+ });
2647
+ var overallProgress = (fileIndex + event.loaded / event.total) / totalFiles * 100;
2648
+ showUploadProgress(overallProgress, 'Uploading ' + (fileIndex + 1) + ' of ' + totalFiles, 'progress-bar-striped progress-bar-animated');
2649
+ });
2650
+ xhr.addEventListener('load', function () {
2651
+ if (xhr.status >= 200 && xhr.status < 300) {
2652
+ try {
2653
+ resolve(JSON.parse(xhr.responseText));
2654
+ } catch (error) {
2655
+ reject(new Error('Upload failed: invalid server response.'));
2656
+ }
2657
+ return;
2658
+ }
2659
+ reject(new Error((xhr.responseText || 'Upload failed.').trim()));
2660
+ });
2661
+ xhr.addEventListener('error', function () {
2662
+ reject(new Error('Upload failed. Please check your connection and try again.'));
2663
+ });
2664
+ xhr.send(formData);
2665
+ });
2666
+ }
2667
+ function uploadDocuments(_x) {
2668
+ return _uploadDocuments.apply(this, arguments);
2669
+ }
2670
+ function _uploadDocuments() {
2671
+ _uploadDocuments = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee6(files) {
2672
+ var filesToUpload, duplicateItems, knownDocumentKeys, pendingItems, uploadedCount, failedUploads, i, file, pendingItem, result, uploaded, failed, missingUploadMessage, failedMessage, errorMessage, _t2, _t3;
2673
+ return _regenerator().w(function (_context6) {
2674
+ while (1) switch (_context6.p = _context6.n) {
2675
+ case 0:
2676
+ if (!(!config.uploadDocumentUrl || !files || files.length === 0)) {
2677
+ _context6.n = 1;
2678
+ break;
2679
+ }
2680
+ return _context6.a(2);
2681
+ case 1:
2682
+ if (!isUploadingDocuments) {
2683
+ _context6.n = 2;
2684
+ break;
2685
+ }
2686
+ showUploadStatus('A document upload is already in progress.', 'text-warning');
2687
+ return _context6.a(2);
2688
+ case 2:
2689
+ isUploadingDocuments = true;
2690
+ filesToUpload = [];
2691
+ duplicateItems = [];
2692
+ knownDocumentKeys = new Set(interactionDocuments.map(function (document) {
2693
+ return getDocumentKey(document.fileName, document.fileSize);
2694
+ }));
2695
+ Array.from(files).forEach(function (file) {
2696
+ if (isDuplicateFile(file, knownDocumentKeys)) {
2697
+ duplicateItems.push(file);
2698
+ return;
2699
+ }
2700
+ knownDocumentKeys.add(getDocumentKey(file.name, file.size));
2701
+ filesToUpload.push(file);
2702
+ });
2703
+ if (duplicateItems.length > 0) {
2704
+ uploadItems = uploadItems.concat(duplicateItems.map(function (file, index) {
2705
+ return Object.assign(createUploadItem(file, index), {
2706
+ status: 'failed',
2707
+ progress: 100,
2708
+ error: 'This document is already attached.'
2709
+ });
2710
+ }));
2711
+ renderUploadQueue();
2712
+ }
2713
+ if (!(filesToUpload.length === 0)) {
2714
+ _context6.n = 3;
2715
+ break;
2716
+ }
2717
+ isUploadingDocuments = false;
2718
+ showUploadStatus(duplicateItems.map(function (file) {
2719
+ return file.name + ': This document is already attached.';
2720
+ }).join(' | '), 'text-warning');
2721
+ showUploadProgress(null);
2722
+ return _context6.a(2);
2723
+ case 3:
2724
+ pendingItems = filesToUpload.map(createUploadItem);
2725
+ uploadItems = uploadItems.concat(pendingItems);
2726
+ renderUploadQueue();
2727
+ showUploadProgress(0, 'Preparing upload...', 'progress-bar-striped progress-bar-animated');
2728
+ fileInput.disabled = true;
2729
+ _context6.p = 4;
2730
+ uploadedCount = 0;
2731
+ failedUploads = duplicateItems.map(function (file) {
2732
+ return file.name + ': This document is already attached.';
2733
+ });
2734
+ i = 0;
2735
+ case 5:
2736
+ if (!(i < filesToUpload.length)) {
2737
+ _context6.n = 10;
2738
+ break;
2739
+ }
2740
+ file = filesToUpload[i];
2741
+ pendingItem = pendingItems[i];
2742
+ updateUploadItem(pendingItem.id, {
2743
+ status: 'uploading',
2744
+ progress: 0,
2745
+ error: null
2746
+ });
2747
+ showUploadStatus('Uploading ' + (i + 1) + ' of ' + filesToUpload.length + ' document(s)...', 'text-warning');
2748
+ _context6.p = 6;
2749
+ _context6.n = 7;
2750
+ return uploadSingleDocument(file, pendingItem.id, i, filesToUpload.length);
2751
+ case 7:
2752
+ result = _context6.v;
2753
+ uploaded = (Array.isArray(result.uploaded) ? result.uploaded : []).map(normalizeDocumentInfo).filter(function (document) {
2754
+ return document && document.documentId;
2755
+ });
2756
+ failed = Array.isArray(result.failed) ? result.failed : [];
2757
+ if (uploaded.length > 0) {
2758
+ uploadedCount += uploaded.length;
2759
+ interactionDocuments = interactionDocuments.concat(uploaded);
2760
+ updateUploadItem(pendingItem.id, {
2761
+ status: 'uploaded',
2762
+ progress: 100,
2763
+ error: null
2764
+ });
2765
+ } else {
2766
+ missingUploadMessage = failed.length > 0 ? failed.map(function (entry) {
2767
+ return entry.fileName + ': ' + entry.error;
2768
+ }).join(' | ') : 'The server did not confirm that the file was uploaded.';
2769
+ if (failed.length === 0) {
2770
+ failedUploads.push(missingUploadMessage);
2771
+ }
2772
+ updateUploadItem(pendingItem.id, {
2773
+ status: 'failed',
2774
+ progress: 100,
2775
+ error: missingUploadMessage
2776
+ });
2777
+ }
2778
+ if (failed.length > 0) {
2779
+ failedMessage = failed.map(function (entry) {
2780
+ return entry.fileName + ': ' + entry.error;
2781
+ }).join(' | ');
2782
+ failedUploads.push(failedMessage);
2783
+ updateUploadItem(pendingItem.id, {
2784
+ status: 'failed',
2785
+ progress: 100,
2786
+ error: failedMessage
2787
+ });
2788
+ }
2789
+ _context6.n = 9;
2790
+ break;
2791
+ case 8:
2792
+ _context6.p = 8;
2793
+ _t2 = _context6.v;
2794
+ errorMessage = _t2 && _t2.message ? _t2.message : 'Upload failed. Please try again.';
2795
+ console.error('Upload failed:', _t2);
2796
+ failedUploads.push(file.name + ': ' + errorMessage);
2797
+ updateUploadItem(pendingItem.id, {
2798
+ status: 'failed',
2799
+ progress: pendingItem.progress || 0,
2800
+ error: errorMessage
2801
+ });
2802
+ case 9:
2803
+ i++;
2804
+ _context6.n = 5;
2805
+ break;
2806
+ case 10:
2807
+ renderDocuments();
2808
+ if (!(failedUploads.length > 0)) {
2809
+ _context6.n = 11;
2810
+ break;
2811
+ }
2812
+ removeUploadItems(function (item) {
2813
+ return item.status === 'uploaded';
2814
+ });
2815
+ showUploadStatus((uploadedCount > 0 ? 'Uploaded ' + uploadedCount + ' document(s). ' : '') + failedUploads.join(' | '), uploadedCount > 0 ? 'text-warning' : 'text-danger');
2816
+ showUploadProgress(null);
2817
+ return _context6.a(2);
2818
+ case 11:
2819
+ removeUploadItems(function () {
2820
+ return true;
2821
+ });
2822
+ showUploadStatus('Uploaded ' + uploadedCount + ' document(s).', 'text-success');
2823
+ showUploadProgress(null);
2824
+ _context6.n = 13;
2825
+ break;
2826
+ case 12:
2827
+ _context6.p = 12;
2828
+ _t3 = _context6.v;
2829
+ console.error('Upload failed:', _t3);
2830
+ showUploadStatus('Upload failed. Please try again.', 'text-danger');
2831
+ showUploadProgress(null);
2832
+ case 13:
2833
+ _context6.p = 13;
2834
+ isUploadingDocuments = false;
2835
+ fileInput.disabled = false;
2836
+ fileInput.value = '';
2837
+ return _context6.f(13);
2838
+ case 14:
2839
+ return _context6.a(2);
2840
+ }
2841
+ }, _callee6, null, [[6, 8], [4, 12, 13, 14]]);
2842
+ }));
2843
+ return _uploadDocuments.apply(this, arguments);
2844
+ }
2845
+ function removeDocument(_x2) {
2846
+ return _removeDocument.apply(this, arguments);
2847
+ }
2848
+ function _removeDocument() {
2849
+ _removeDocument = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee7(documentId) {
2850
+ var response, result, serverDocuments, _t4, _t5;
2851
+ return _regenerator().w(function (_context7) {
2852
+ while (1) switch (_context7.p = _context7.n) {
2853
+ case 0:
2854
+ if (!(!config.removeDocumentUrl || !documentId || !window.confirm('Remove this document?'))) {
2855
+ _context7.n = 1;
2856
+ break;
2857
+ }
2858
+ return _context7.a(2);
2859
+ case 1:
2860
+ _context7.p = 1;
2861
+ _context7.n = 2;
2862
+ return fetch(config.removeDocumentUrl, {
2863
+ method: 'POST',
2864
+ headers: {
2865
+ 'Content-Type': 'application/json'
2866
+ },
2867
+ body: JSON.stringify({
2868
+ itemId: config.itemId,
2869
+ documentId: documentId
2870
+ })
2871
+ });
2872
+ case 2:
2873
+ response = _context7.v;
2874
+ if (response.ok) {
2875
+ _context7.n = 4;
2876
+ break;
2877
+ }
2878
+ _t4 = console;
2879
+ _context7.n = 3;
2880
+ return response.text();
2881
+ case 3:
2882
+ _t4.error.call(_t4, 'Failed to remove document:', _context7.v);
2883
+ showUploadStatus('Failed to remove document.', 'text-danger');
2884
+ return _context7.a(2);
2885
+ case 4:
2886
+ _context7.n = 5;
2887
+ return response.json();
2888
+ case 5:
2889
+ result = _context7.v;
2890
+ serverDocuments = (Array.isArray(result.documents) ? result.documents : []).map(normalizeDocumentInfo).filter(function (document) {
2891
+ return document && document.documentId;
2892
+ });
2893
+ interactionDocuments = serverDocuments.length > 0 ? serverDocuments : interactionDocuments.filter(function (document) {
2894
+ return document.documentId !== documentId;
2895
+ });
2896
+ renderDocuments();
2897
+ showUploadStatus('Document removed.', 'text-success');
2898
+ _context7.n = 7;
2899
+ break;
2900
+ case 6:
2901
+ _context7.p = 6;
2902
+ _t5 = _context7.v;
2903
+ console.error('Remove failed:', _t5);
2904
+ showUploadStatus('Failed to remove document.', 'text-danger');
2905
+ case 7:
2906
+ return _context7.a(2);
2907
+ }
2908
+ }, _callee7, null, [[1, 6]]);
2909
+ }));
2910
+ return _removeDocument.apply(this, arguments);
2911
+ }
2912
+ var onFileInputChange = function onFileInputChange(event) {
2913
+ var selectedFiles = event.target.files ? Array.from(event.target.files) : [];
2914
+ uploadDocuments(selectedFiles);
2915
+ };
2916
+ fileInput.addEventListener('change', onFileInputChange);
2917
+ fileInput[managerStateKey] = {
2918
+ dispose: function dispose() {
2919
+ fileInput.removeEventListener('change', onFileInputChange);
2920
+ }
2921
+ };
2922
+ renderDocuments();
2923
+ renderUploadQueue();
2924
+ showUploadStatus(null);
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();
2989
+ }
2131
2990
  return {
2132
- initialize: initialize
2991
+ initialize: initialize,
2992
+ initializeFromElement: initializeFromElement
2133
2993
  };
2134
2994
  }();
2135
2995