@crestapps/ai-chat-ui 1.0.0-preview.9 → 1.0.0-preview.95
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai-chat-widget.js +962 -0
- package/dist/ai-chat-widget.js.map +1 -0
- package/dist/ai-chat-widget.min.js +2 -0
- package/dist/ai-chat-widget.min.js.map +1 -0
- package/dist/ai-chat.css +45 -14
- package/dist/ai-chat.css.map +1 -1
- package/dist/ai-chat.js +1076 -1019
- package/dist/ai-chat.js.map +1 -1
- package/dist/ai-chat.min.css +1 -1
- package/dist/ai-chat.min.js +1 -1
- package/dist/ai-chat.min.js.map +1 -1
- package/dist/chat-interaction-settings.js +297 -0
- package/dist/chat-interaction-settings.js.map +1 -0
- package/dist/chat-interaction-settings.min.js +2 -0
- package/dist/chat-interaction-settings.min.js.map +1 -0
- package/dist/chat-interaction.js +1224 -325
- package/dist/chat-interaction.js.map +1 -1
- package/dist/chat-interaction.min.js +1 -1
- package/dist/chat-interaction.min.js.map +1 -1
- package/dist/chat-widget.css +48 -26
- package/dist/chat-widget.css.map +1 -1
- package/dist/chat-widget.min.css +1 -1
- package/dist/document-drop-zone.css +10 -10
- package/dist/document-drop-zone.css.map +1 -1
- package/dist/document-drop-zone.js +92 -14
- package/dist/document-drop-zone.js.map +1 -1
- package/dist/document-drop-zone.min.css +1 -1
- package/dist/document-drop-zone.min.js +1 -1
- package/dist/document-drop-zone.min.js.map +1 -1
- package/dist/technical-name-generator.js +36 -8
- package/dist/technical-name-generator.js.map +1 -1
- package/dist/technical-name-generator.min.js +1 -1
- package/dist/technical-name-generator.min.js.map +1 -1
- package/package.json +9 -1
- package/README.md +0 -145
package/dist/chat-interaction.js
CHANGED
|
@@ -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
|
-
|
|
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)\"><
|
|
34
|
-
indicatorTemplate: "\n <div class=\"ai-chat-msg-role ai-chat-msg-role-assistant\">\n <span class=\"ai-streaming-icon\"><
|
|
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\"><
|
|
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 <
|
|
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, "\">") + "<
|
|
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
|
|
223
|
-
|
|
462
|
+
var _iterator5 = _createForOfIteratorHelper(charts),
|
|
463
|
+
_step5;
|
|
224
464
|
try {
|
|
225
|
-
for (
|
|
226
|
-
var c =
|
|
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
|
-
|
|
499
|
+
_iterator5.e(err);
|
|
260
500
|
} finally {
|
|
261
|
-
|
|
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.
|
|
503
|
-
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
|
|
609
|
-
|
|
610
|
-
|
|
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
|
|
832
|
-
var
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
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
|
-
|
|
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.
|
|
857
|
-
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
|
-
|
|
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);
|
|
@@ -1039,8 +1148,55 @@ window.chatInteractionManager = function () {
|
|
|
1039
1148
|
}
|
|
1040
1149
|
this.stopAudio(false);
|
|
1041
1150
|
},
|
|
1042
|
-
|
|
1151
|
+
updateTtsPlaybackButtons: function updateTtsPlaybackButtons() {
|
|
1043
1152
|
var _this7 = this;
|
|
1153
|
+
if (!this.chatContainer) {
|
|
1154
|
+
return;
|
|
1155
|
+
}
|
|
1156
|
+
var buttons = this.chatContainer.querySelectorAll('[data-tts-message-index]');
|
|
1157
|
+
buttons.forEach(function (button) {
|
|
1158
|
+
var buttonIndex = Number(button.getAttribute('data-tts-message-index'));
|
|
1159
|
+
var isPlaying = buttonIndex === _this7.ttsPlayingMessageIndex;
|
|
1160
|
+
var iconHtml = isPlaying ? '<i class="fa-solid fa-circle-pause"></i>' : '<i class="fa-solid fa-circle-play"></i>';
|
|
1161
|
+
button.classList.toggle('tts-playing', isPlaying);
|
|
1162
|
+
button.setAttribute('title', isPlaying ? 'Pause audio' : 'Read aloud');
|
|
1163
|
+
button.replaceChildren(DOMPurify.sanitize(iconHtml, {
|
|
1164
|
+
RETURN_DOM_FRAGMENT: true
|
|
1165
|
+
}));
|
|
1166
|
+
});
|
|
1167
|
+
},
|
|
1168
|
+
updateCopyButtons: function updateCopyButtons() {
|
|
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;
|
|
1044
1200
|
if (!this.textToSpeechEnabled || !text || !this.connection) {
|
|
1045
1201
|
return;
|
|
1046
1202
|
}
|
|
@@ -1049,12 +1205,16 @@ window.chatInteractionManager = function () {
|
|
|
1049
1205
|
this._ttsCacheIndex = cacheIndex !== undefined ? cacheIndex : -1;
|
|
1050
1206
|
this.connection.invoke("SynthesizeSpeech", this.getItemId(), text, this.ttsVoiceName)["catch"](function (err) {
|
|
1051
1207
|
console.error("TTS synthesis error:", err);
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1208
|
+
_this9.isPlayingAudio = false;
|
|
1209
|
+
_this9.ttsPlayingMessageIndex = -1;
|
|
1210
|
+
_this9._ttsCacheIndex = -1;
|
|
1211
|
+
_this9.$nextTick(function () {
|
|
1212
|
+
return _this9.updateTtsPlaybackButtons();
|
|
1213
|
+
});
|
|
1055
1214
|
});
|
|
1056
1215
|
},
|
|
1057
1216
|
toggleMessageTts: function toggleMessageTts(message, index) {
|
|
1217
|
+
var _this0 = this;
|
|
1058
1218
|
if (this.ttsPlayingMessageIndex === index) {
|
|
1059
1219
|
this.stopAudio();
|
|
1060
1220
|
return;
|
|
@@ -1066,6 +1226,9 @@ window.chatInteractionManager = function () {
|
|
|
1066
1226
|
}
|
|
1067
1227
|
}));
|
|
1068
1228
|
this.ttsPlayingMessageIndex = index;
|
|
1229
|
+
this.$nextTick(function () {
|
|
1230
|
+
return _this0.updateTtsPlaybackButtons();
|
|
1231
|
+
});
|
|
1069
1232
|
if (this.ttsAudioCache[index]) {
|
|
1070
1233
|
this.playAudioBlob(this.ttsAudioCache[index]);
|
|
1071
1234
|
return;
|
|
@@ -1073,10 +1236,14 @@ window.chatInteractionManager = function () {
|
|
|
1073
1236
|
this.synthesizeSpeech(message.content, index);
|
|
1074
1237
|
},
|
|
1075
1238
|
playCollectedAudio: function playCollectedAudio() {
|
|
1239
|
+
var _this1 = this;
|
|
1076
1240
|
if (this.audioChunks.length === 0) {
|
|
1077
1241
|
if (!this.isPlayingAudio && this.audioPlayQueue.length === 0) {
|
|
1078
1242
|
this.isPlayingAudio = false;
|
|
1079
1243
|
this.ttsPlayingMessageIndex = -1;
|
|
1244
|
+
this.$nextTick(function () {
|
|
1245
|
+
return _this1.updateTtsPlaybackButtons();
|
|
1246
|
+
});
|
|
1080
1247
|
}
|
|
1081
1248
|
return;
|
|
1082
1249
|
}
|
|
@@ -1085,18 +1252,18 @@ window.chatInteractionManager = function () {
|
|
|
1085
1252
|
}, 0);
|
|
1086
1253
|
var combined = new Uint8Array(totalLength);
|
|
1087
1254
|
var offset = 0;
|
|
1088
|
-
var
|
|
1089
|
-
|
|
1255
|
+
var _iterator6 = _createForOfIteratorHelper(this.audioChunks),
|
|
1256
|
+
_step6;
|
|
1090
1257
|
try {
|
|
1091
|
-
for (
|
|
1092
|
-
var chunk =
|
|
1258
|
+
for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
|
|
1259
|
+
var chunk = _step6.value;
|
|
1093
1260
|
combined.set(chunk, offset);
|
|
1094
1261
|
offset += chunk.length;
|
|
1095
1262
|
}
|
|
1096
1263
|
} catch (err) {
|
|
1097
|
-
|
|
1264
|
+
_iterator6.e(err);
|
|
1098
1265
|
} finally {
|
|
1099
|
-
|
|
1266
|
+
_iterator6.f();
|
|
1100
1267
|
}
|
|
1101
1268
|
this.audioChunks = [];
|
|
1102
1269
|
var blob = new Blob([combined], {
|
|
@@ -1115,45 +1282,53 @@ window.chatInteractionManager = function () {
|
|
|
1115
1282
|
this.playAudioBlob(blob);
|
|
1116
1283
|
},
|
|
1117
1284
|
playAudioBlob: function playAudioBlob(blob) {
|
|
1118
|
-
var
|
|
1285
|
+
var _this10 = this;
|
|
1119
1286
|
var url = URL.createObjectURL(blob);
|
|
1120
1287
|
var audio = new Audio(url);
|
|
1121
1288
|
this.currentAudioUrl = url;
|
|
1122
1289
|
this.currentAudioElement = audio;
|
|
1123
1290
|
this.isPlayingAudio = true;
|
|
1124
1291
|
audio.addEventListener('ended', function () {
|
|
1125
|
-
|
|
1126
|
-
|
|
1292
|
+
_this10.currentAudioElement = null;
|
|
1293
|
+
_this10.currentAudioUrl = null;
|
|
1127
1294
|
URL.revokeObjectURL(url);
|
|
1128
|
-
|
|
1295
|
+
_this10.playNextInQueue();
|
|
1129
1296
|
});
|
|
1130
1297
|
audio.addEventListener('error', function () {
|
|
1131
|
-
|
|
1132
|
-
|
|
1298
|
+
_this10.currentAudioElement = null;
|
|
1299
|
+
_this10.currentAudioUrl = null;
|
|
1133
1300
|
URL.revokeObjectURL(url);
|
|
1134
|
-
|
|
1301
|
+
_this10.playNextInQueue();
|
|
1135
1302
|
});
|
|
1136
1303
|
audio.play()["catch"](function (err) {
|
|
1137
1304
|
console.error("Audio playback error:", err);
|
|
1138
|
-
|
|
1139
|
-
|
|
1305
|
+
_this10.currentAudioElement = null;
|
|
1306
|
+
_this10.currentAudioUrl = null;
|
|
1140
1307
|
URL.revokeObjectURL(url);
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1308
|
+
_this10.audioPlayQueue = [];
|
|
1309
|
+
_this10.isPlayingAudio = false;
|
|
1310
|
+
_this10.ttsPlayingMessageIndex = -1;
|
|
1311
|
+
_this10.$nextTick(function () {
|
|
1312
|
+
return _this10.updateTtsPlaybackButtons();
|
|
1313
|
+
});
|
|
1144
1314
|
});
|
|
1145
1315
|
},
|
|
1146
1316
|
playNextInQueue: function playNextInQueue() {
|
|
1317
|
+
var _this11 = this;
|
|
1147
1318
|
if (this.audioPlayQueue.length > 0) {
|
|
1148
1319
|
var nextBlob = this.audioPlayQueue.shift();
|
|
1149
1320
|
this.playAudioBlob(nextBlob);
|
|
1150
1321
|
} else {
|
|
1151
1322
|
this.isPlayingAudio = false;
|
|
1152
1323
|
this.ttsPlayingMessageIndex = -1;
|
|
1324
|
+
this.$nextTick(function () {
|
|
1325
|
+
return _this11.updateTtsPlaybackButtons();
|
|
1326
|
+
});
|
|
1153
1327
|
this.conversationModeOnAudioEnded();
|
|
1154
1328
|
}
|
|
1155
1329
|
},
|
|
1156
1330
|
stopAudio: function stopAudio() {
|
|
1331
|
+
var _this12 = this;
|
|
1157
1332
|
if (this.currentAudioElement) {
|
|
1158
1333
|
this.currentAudioElement.pause();
|
|
1159
1334
|
this.currentAudioElement.currentTime = 0;
|
|
@@ -1167,6 +1342,9 @@ window.chatInteractionManager = function () {
|
|
|
1167
1342
|
this.audioPlayQueue = [];
|
|
1168
1343
|
this.isPlayingAudio = false;
|
|
1169
1344
|
this.ttsPlayingMessageIndex = -1;
|
|
1345
|
+
this.$nextTick(function () {
|
|
1346
|
+
return _this12.updateTtsPlaybackButtons();
|
|
1347
|
+
});
|
|
1170
1348
|
},
|
|
1171
1349
|
toggleConversationMode: function toggleConversationMode() {
|
|
1172
1350
|
if (this.isConversationMode) {
|
|
@@ -1176,7 +1354,7 @@ window.chatInteractionManager = function () {
|
|
|
1176
1354
|
}
|
|
1177
1355
|
},
|
|
1178
1356
|
startConversationMode: function startConversationMode() {
|
|
1179
|
-
var
|
|
1357
|
+
var _this13 = this;
|
|
1180
1358
|
if (!this.conversationModeEnabled || this.isConversationMode || !this.connection) {
|
|
1181
1359
|
return;
|
|
1182
1360
|
}
|
|
@@ -1196,30 +1374,30 @@ window.chatInteractionManager = function () {
|
|
|
1196
1374
|
}
|
|
1197
1375
|
}).then(function (stream) {
|
|
1198
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';
|
|
1199
|
-
|
|
1377
|
+
_this13.mediaRecorder = new MediaRecorder(stream, {
|
|
1200
1378
|
mimeType: mimeType,
|
|
1201
1379
|
audioBitsPerSecond: 128000
|
|
1202
1380
|
});
|
|
1203
|
-
|
|
1204
|
-
|
|
1381
|
+
_this13._conversationSubject = new signalR.Subject();
|
|
1382
|
+
_this13._conversationStream = stream;
|
|
1205
1383
|
|
|
1206
1384
|
// Create an AnalyserNode for volume-based interrupt detection.
|
|
1207
1385
|
var AudioCtx = window.AudioContext || window.webkitAudioContext;
|
|
1208
1386
|
if (AudioCtx) {
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
var micSource =
|
|
1213
|
-
micSource.connect(
|
|
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);
|
|
1214
1392
|
}
|
|
1215
1393
|
var pendingChunk = Promise.resolve();
|
|
1216
|
-
var analyser =
|
|
1394
|
+
var analyser = _this13._conversationAnalyser;
|
|
1217
1395
|
var interruptVolumeThreshold = 30;
|
|
1218
|
-
|
|
1396
|
+
_this13.mediaRecorder.addEventListener('dataavailable', function (e) {
|
|
1219
1397
|
if (e.data && e.data.size > 0) {
|
|
1220
1398
|
// During TTS playback, check mic volume to detect
|
|
1221
1399
|
// user interruption (speaking above threshold).
|
|
1222
|
-
if (
|
|
1400
|
+
if (_this13.isPlayingAudio && analyser) {
|
|
1223
1401
|
var freqData = new Uint8Array(analyser.frequencyBinCount);
|
|
1224
1402
|
analyser.getByteFrequencyData(freqData);
|
|
1225
1403
|
var sum = 0;
|
|
@@ -1229,7 +1407,7 @@ window.chatInteractionManager = function () {
|
|
|
1229
1407
|
var avg = sum / freqData.length;
|
|
1230
1408
|
if (avg >= interruptVolumeThreshold) {
|
|
1231
1409
|
// User is speaking — interrupt TTS playback.
|
|
1232
|
-
|
|
1410
|
+
_this13.stopAudio();
|
|
1233
1411
|
}
|
|
1234
1412
|
}
|
|
1235
1413
|
|
|
@@ -1251,7 +1429,7 @@ window.chatInteractionManager = function () {
|
|
|
1251
1429
|
}, '');
|
|
1252
1430
|
base64 = btoa(binaryString);
|
|
1253
1431
|
try {
|
|
1254
|
-
|
|
1432
|
+
_this13._conversationSubject.next(base64);
|
|
1255
1433
|
} catch (err) {
|
|
1256
1434
|
// Subject may have been completed already.
|
|
1257
1435
|
}
|
|
@@ -1262,27 +1440,27 @@ window.chatInteractionManager = function () {
|
|
|
1262
1440
|
})));
|
|
1263
1441
|
}
|
|
1264
1442
|
});
|
|
1265
|
-
|
|
1443
|
+
_this13.mediaRecorder.addEventListener('stop', function () {
|
|
1266
1444
|
stream.getTracks().forEach(function (track) {
|
|
1267
1445
|
return track.stop();
|
|
1268
1446
|
});
|
|
1269
1447
|
pendingChunk.then(function () {
|
|
1270
1448
|
try {
|
|
1271
|
-
|
|
1449
|
+
_this13._conversationSubject.complete();
|
|
1272
1450
|
} catch (err) {
|
|
1273
1451
|
// Already completed.
|
|
1274
1452
|
}
|
|
1275
1453
|
});
|
|
1276
1454
|
});
|
|
1277
|
-
var itemId =
|
|
1455
|
+
var itemId = _this13.getItemId();
|
|
1278
1456
|
var language = navigator.language || document.documentElement.lang || 'en-US';
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1457
|
+
_this13.connection.send("StartConversation", itemId, _this13._conversationSubject, mimeType, language);
|
|
1458
|
+
_this13.mediaRecorder.start(250);
|
|
1459
|
+
_this13.isRecording = true;
|
|
1282
1460
|
})["catch"](function (err) {
|
|
1283
1461
|
console.error('Microphone access denied:', err);
|
|
1284
|
-
|
|
1285
|
-
|
|
1462
|
+
_this13.isConversationMode = false;
|
|
1463
|
+
_this13.updateConversationButton();
|
|
1286
1464
|
});
|
|
1287
1465
|
},
|
|
1288
1466
|
stopConversationMode: function stopConversationMode() {
|
|
@@ -1386,12 +1564,12 @@ window.chatInteractionManager = function () {
|
|
|
1386
1564
|
return removedCount;
|
|
1387
1565
|
},
|
|
1388
1566
|
scrollToBottom: function scrollToBottom() {
|
|
1389
|
-
var
|
|
1567
|
+
var _this14 = this;
|
|
1390
1568
|
if (!this.autoScroll) {
|
|
1391
1569
|
return;
|
|
1392
1570
|
}
|
|
1393
1571
|
setTimeout(function () {
|
|
1394
|
-
|
|
1572
|
+
_this14.chatContainer.scrollTop = _this14.chatContainer.scrollHeight - _this14.chatContainer.clientHeight;
|
|
1395
1573
|
}, 50);
|
|
1396
1574
|
},
|
|
1397
1575
|
handleUserInput: function handleUserInput(event) {
|
|
@@ -1407,7 +1585,7 @@ window.chatInteractionManager = function () {
|
|
|
1407
1585
|
return document.querySelector('[data-chat-interaction-save-indicator]');
|
|
1408
1586
|
},
|
|
1409
1587
|
showSaveIndicator: function showSaveIndicator(text, className) {
|
|
1410
|
-
var
|
|
1588
|
+
var _this15 = this;
|
|
1411
1589
|
var indicator = this.getSaveIndicatorElement();
|
|
1412
1590
|
if (!indicator) {
|
|
1413
1591
|
return;
|
|
@@ -1423,7 +1601,7 @@ window.chatInteractionManager = function () {
|
|
|
1423
1601
|
}
|
|
1424
1602
|
this.saveIndicatorTimeout = setTimeout(function () {
|
|
1425
1603
|
indicator.textContent = '';
|
|
1426
|
-
|
|
1604
|
+
_this15.saveIndicatorTimeout = null;
|
|
1427
1605
|
}, 3000);
|
|
1428
1606
|
},
|
|
1429
1607
|
clearPendingSettingsSave: function clearPendingSettingsSave() {
|
|
@@ -1497,10 +1675,10 @@ window.chatInteractionManager = function () {
|
|
|
1497
1675
|
return false;
|
|
1498
1676
|
},
|
|
1499
1677
|
validateSettings: function validateSettings() {
|
|
1500
|
-
var
|
|
1678
|
+
var _this16 = this;
|
|
1501
1679
|
var isValid = true;
|
|
1502
1680
|
this.getSettingInputs().forEach(function (input) {
|
|
1503
|
-
isValid =
|
|
1681
|
+
isValid = _this16.validateSettingInput(input) && isValid;
|
|
1504
1682
|
});
|
|
1505
1683
|
return isValid;
|
|
1506
1684
|
},
|
|
@@ -1523,7 +1701,7 @@ window.chatInteractionManager = function () {
|
|
|
1523
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["])');
|
|
1524
1702
|
},
|
|
1525
1703
|
getSelectedGroupValues: function getSelectedGroupValues(groupName, fallbackSelector) {
|
|
1526
|
-
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"));
|
|
1527
1705
|
if (explicitSelections.length > 0) {
|
|
1528
1706
|
var _values = [];
|
|
1529
1707
|
explicitSelections.forEach(function (checkbox) {
|
|
@@ -1596,12 +1774,12 @@ window.chatInteractionManager = function () {
|
|
|
1596
1774
|
}
|
|
1597
1775
|
},
|
|
1598
1776
|
scheduleNotificationDismiss: function scheduleNotificationDismiss(notification) {
|
|
1599
|
-
var
|
|
1777
|
+
var _this17 = this;
|
|
1600
1778
|
if (!notification || !notification.type || !notification.autoDismissMs || notification.autoDismissMs <= 0) {
|
|
1601
1779
|
return;
|
|
1602
1780
|
}
|
|
1603
1781
|
this.notificationDismissTimers[notification.type] = setTimeout(function () {
|
|
1604
|
-
|
|
1782
|
+
_this17.removeNotification(notification.type);
|
|
1605
1783
|
}, notification.autoDismissMs);
|
|
1606
1784
|
},
|
|
1607
1785
|
clearNotificationDismiss: function clearNotificationDismiss(notificationType) {
|
|
@@ -1641,7 +1819,7 @@ window.chatInteractionManager = function () {
|
|
|
1641
1819
|
this.showPlaceholder();
|
|
1642
1820
|
},
|
|
1643
1821
|
initializeApp: function initializeApp() {
|
|
1644
|
-
var
|
|
1822
|
+
var _this18 = this;
|
|
1645
1823
|
this.inputElement = document.querySelector(config.inputElementSelector);
|
|
1646
1824
|
this.buttonElement = document.querySelector(config.sendButtonElementSelector);
|
|
1647
1825
|
this.chatContainer = document.querySelector(config.chatContainerElementSelector);
|
|
@@ -1653,59 +1831,59 @@ window.chatInteractionManager = function () {
|
|
|
1653
1831
|
|
|
1654
1832
|
// Pause auto-scroll when the user manually scrolls up during streaming.
|
|
1655
1833
|
this.chatContainer.addEventListener('scroll', function () {
|
|
1656
|
-
if (!
|
|
1834
|
+
if (!_this18.stream) {
|
|
1657
1835
|
return;
|
|
1658
1836
|
}
|
|
1659
1837
|
var threshold = 30;
|
|
1660
|
-
var atBottom =
|
|
1661
|
-
|
|
1838
|
+
var atBottom = _this18.chatContainer.scrollHeight - _this18.chatContainer.clientHeight - _this18.chatContainer.scrollTop <= threshold;
|
|
1839
|
+
_this18.autoScroll = atBottom;
|
|
1662
1840
|
});
|
|
1663
1841
|
this.inputElement.addEventListener('keyup', function (event) {
|
|
1664
|
-
if (
|
|
1842
|
+
if (_this18.stream != null) {
|
|
1665
1843
|
return;
|
|
1666
1844
|
}
|
|
1667
1845
|
if (event.key === "Enter" && !event.shiftKey) {
|
|
1668
|
-
|
|
1846
|
+
_this18.buttonElement.click();
|
|
1669
1847
|
}
|
|
1670
1848
|
});
|
|
1671
1849
|
this.inputElement.addEventListener('input', function (e) {
|
|
1672
|
-
|
|
1850
|
+
_this18.handleUserInput(e);
|
|
1673
1851
|
if (e.target.value.trim()) {
|
|
1674
|
-
|
|
1852
|
+
_this18.buttonElement.removeAttribute('disabled');
|
|
1675
1853
|
} else {
|
|
1676
|
-
|
|
1854
|
+
_this18.buttonElement.setAttribute('disabled', true);
|
|
1677
1855
|
}
|
|
1678
1856
|
});
|
|
1679
1857
|
this.inputElement.addEventListener('paste', function (e) {
|
|
1680
1858
|
// Use setTimeout to allow the paste to complete before checking the value
|
|
1681
1859
|
setTimeout(function () {
|
|
1682
|
-
|
|
1683
|
-
if (
|
|
1684
|
-
|
|
1860
|
+
_this18.prompt = _this18.inputElement.value;
|
|
1861
|
+
if (_this18.inputElement.value.trim()) {
|
|
1862
|
+
_this18.buttonElement.removeAttribute('disabled');
|
|
1685
1863
|
} else {
|
|
1686
|
-
|
|
1864
|
+
_this18.buttonElement.setAttribute('disabled', true);
|
|
1687
1865
|
}
|
|
1688
1866
|
}, 0);
|
|
1689
1867
|
});
|
|
1690
1868
|
this.buttonElement.addEventListener('click', function () {
|
|
1691
|
-
if (
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1869
|
+
if (_this18.stream != null) {
|
|
1870
|
+
_this18.stream.dispose();
|
|
1871
|
+
_this18.stream = null;
|
|
1872
|
+
_this18.streamingFinished();
|
|
1873
|
+
_this18.hideTypingIndicator();
|
|
1696
1874
|
|
|
1697
1875
|
// Clean up: remove empty assistant message or stop streaming animation.
|
|
1698
|
-
if (
|
|
1699
|
-
var lastMsg =
|
|
1876
|
+
if (_this18.messages.length > 0) {
|
|
1877
|
+
var lastMsg = _this18.messages[_this18.messages.length - 1];
|
|
1700
1878
|
if (lastMsg.role === 'assistant' && !lastMsg.content) {
|
|
1701
|
-
|
|
1879
|
+
_this18.messages.pop();
|
|
1702
1880
|
} else if (lastMsg.isStreaming) {
|
|
1703
1881
|
lastMsg.isStreaming = false;
|
|
1704
1882
|
}
|
|
1705
1883
|
}
|
|
1706
1884
|
return;
|
|
1707
1885
|
}
|
|
1708
|
-
|
|
1886
|
+
_this18.sendMessage();
|
|
1709
1887
|
});
|
|
1710
1888
|
var chatInteractionItems = document.getElementsByClassName('chat-interaction-history-item');
|
|
1711
1889
|
for (var i = 0; i < chatInteractionItems.length; i++) {
|
|
@@ -1716,11 +1894,12 @@ window.chatInteractionManager = function () {
|
|
|
1716
1894
|
console.error('An element with the class chat-interaction-history-item with no data-interaction-id set.');
|
|
1717
1895
|
return;
|
|
1718
1896
|
}
|
|
1719
|
-
|
|
1897
|
+
_this18.loadInteraction(itemId);
|
|
1720
1898
|
});
|
|
1721
1899
|
}
|
|
1722
|
-
|
|
1723
|
-
|
|
1900
|
+
var initialMessages = Array.isArray(config.messages) ? config.messages : [];
|
|
1901
|
+
for (var _i4 = 0; _i4 < initialMessages.length; _i4++) {
|
|
1902
|
+
this.addMessage(initialMessages[_i4]);
|
|
1724
1903
|
}
|
|
1725
1904
|
|
|
1726
1905
|
// Delegate click for code block copy buttons.
|
|
@@ -1738,29 +1917,29 @@ window.chatInteractionManager = function () {
|
|
|
1738
1917
|
if (codeEl) {
|
|
1739
1918
|
navigator.clipboard.writeText(codeEl.textContent);
|
|
1740
1919
|
var copiedText = config.codeCopiedText || 'Copied!';
|
|
1741
|
-
btn.innerHTML = '<
|
|
1920
|
+
btn.innerHTML = '<i class="fa-solid fa-check"></i> ' + copiedText;
|
|
1742
1921
|
setTimeout(function () {
|
|
1743
|
-
btn.innerHTML = '<
|
|
1922
|
+
btn.innerHTML = '<i class="fa-regular fa-copy"></i>';
|
|
1744
1923
|
}, 2000);
|
|
1745
1924
|
}
|
|
1746
1925
|
});
|
|
1747
1926
|
}
|
|
1748
1927
|
document.addEventListener('input', function (event) {
|
|
1749
1928
|
if (event.target.matches('.setting-input[data-setting]')) {
|
|
1750
|
-
|
|
1751
|
-
|
|
1929
|
+
_this18.validateSettingInput(event.target);
|
|
1930
|
+
_this18.queueSettingsSave();
|
|
1752
1931
|
}
|
|
1753
1932
|
});
|
|
1754
1933
|
document.addEventListener('change', function (event) {
|
|
1755
|
-
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')) {
|
|
1756
1935
|
if (event.target.matches('.setting-input[data-setting]')) {
|
|
1757
|
-
|
|
1936
|
+
_this18.validateSettingInput(event.target);
|
|
1758
1937
|
}
|
|
1759
|
-
|
|
1938
|
+
_this18.queueSettingsSave();
|
|
1760
1939
|
return;
|
|
1761
1940
|
}
|
|
1762
1941
|
if (event.target.closest('.prompt-template-parameters-input, .prompt-template-id-input')) {
|
|
1763
|
-
|
|
1942
|
+
_this18.queueSettingsSave();
|
|
1764
1943
|
}
|
|
1765
1944
|
});
|
|
1766
1945
|
document.addEventListener('click', function (event) {
|
|
@@ -1768,7 +1947,7 @@ window.chatInteractionManager = function () {
|
|
|
1768
1947
|
return;
|
|
1769
1948
|
}
|
|
1770
1949
|
setTimeout(function () {
|
|
1771
|
-
|
|
1950
|
+
_this18.queueSettingsSave();
|
|
1772
1951
|
}, 0);
|
|
1773
1952
|
});
|
|
1774
1953
|
|
|
@@ -1778,7 +1957,7 @@ window.chatInteractionManager = function () {
|
|
|
1778
1957
|
clearHistoryBtn.addEventListener('click', function () {
|
|
1779
1958
|
var itemId = clearHistoryBtn.getAttribute('data-interaction-id');
|
|
1780
1959
|
if (itemId) {
|
|
1781
|
-
|
|
1960
|
+
_this18.clearHistory(itemId);
|
|
1782
1961
|
}
|
|
1783
1962
|
});
|
|
1784
1963
|
}
|
|
@@ -1789,7 +1968,7 @@ window.chatInteractionManager = function () {
|
|
|
1789
1968
|
if (this.micButton) {
|
|
1790
1969
|
this.micButton.style.display = '';
|
|
1791
1970
|
this.micButton.addEventListener('click', function () {
|
|
1792
|
-
|
|
1971
|
+
_this18.toggleRecording();
|
|
1793
1972
|
});
|
|
1794
1973
|
}
|
|
1795
1974
|
}
|
|
@@ -1799,7 +1978,7 @@ window.chatInteractionManager = function () {
|
|
|
1799
1978
|
this.conversationButton = document.querySelector(config.conversationButtonElementSelector);
|
|
1800
1979
|
if (this.conversationButton) {
|
|
1801
1980
|
this.conversationButton.addEventListener('click', function () {
|
|
1802
|
-
|
|
1981
|
+
_this18.toggleConversationMode();
|
|
1803
1982
|
});
|
|
1804
1983
|
}
|
|
1805
1984
|
}
|
|
@@ -1817,29 +1996,38 @@ window.chatInteractionManager = function () {
|
|
|
1817
1996
|
},
|
|
1818
1997
|
clearHistory: function clearHistory(itemId) {
|
|
1819
1998
|
var self = this;
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
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();
|
|
1833
2020
|
}
|
|
1834
|
-
self.connection.invoke("ClearHistory", itemId)["catch"](function (err) {
|
|
1835
|
-
return console.error('Error clearing history:', err);
|
|
1836
|
-
});
|
|
1837
2021
|
}
|
|
1838
|
-
}
|
|
1839
|
-
|
|
2022
|
+
});
|
|
2023
|
+
return;
|
|
2024
|
+
}
|
|
2025
|
+
if (window.confirm(config.clearHistoryMessage || 'Clear all messages?')) {
|
|
2026
|
+
clearHistoryConfirmed();
|
|
2027
|
+
}
|
|
1840
2028
|
},
|
|
1841
2029
|
debouncedSaveSettings: function debouncedSaveSettings() {
|
|
1842
|
-
var
|
|
2030
|
+
var _this19 = this;
|
|
1843
2031
|
// Clear any existing timeout to reset the debounce timer
|
|
1844
2032
|
this.clearPendingSettingsSave();
|
|
1845
2033
|
|
|
@@ -1850,11 +2038,11 @@ window.chatInteractionManager = function () {
|
|
|
1850
2038
|
|
|
1851
2039
|
// Set a new timeout to save after 850ms of no changes
|
|
1852
2040
|
this.saveSettingsTimeout = setTimeout(function () {
|
|
1853
|
-
if (
|
|
1854
|
-
|
|
1855
|
-
|
|
2041
|
+
if (_this19.settingsDirty) {
|
|
2042
|
+
_this19.saveSettings();
|
|
2043
|
+
_this19.settingsDirty = false;
|
|
1856
2044
|
}
|
|
1857
|
-
|
|
2045
|
+
_this19.saveSettingsTimeout = null;
|
|
1858
2046
|
}, 850);
|
|
1859
2047
|
},
|
|
1860
2048
|
getSelectedToolNames: function getSelectedToolNames() {
|
|
@@ -1870,7 +2058,7 @@ window.chatInteractionManager = function () {
|
|
|
1870
2058
|
return this.getSelectedGroupValues('agentNames', 'input[type="checkbox"][name$="].IsSelected"][name^="ChatInteraction.Agents["]:checked');
|
|
1871
2059
|
},
|
|
1872
2060
|
saveSettings: function saveSettings() {
|
|
1873
|
-
var
|
|
2061
|
+
var _this20 = this;
|
|
1874
2062
|
var itemId = this.getItemId();
|
|
1875
2063
|
if (!itemId) {
|
|
1876
2064
|
return Promise.resolve();
|
|
@@ -1915,7 +2103,7 @@ window.chatInteractionManager = function () {
|
|
|
1915
2103
|
}
|
|
1916
2104
|
return this.connection.invoke("SaveSettings", itemId, settings)["catch"](function (err) {
|
|
1917
2105
|
console.error('Error saving settings:', err);
|
|
1918
|
-
|
|
2106
|
+
_this20.showSaveIndicator('Save failed', 'text-danger');
|
|
1919
2107
|
});
|
|
1920
2108
|
},
|
|
1921
2109
|
flushPendingSave: function flushPendingSave() {
|
|
@@ -1941,11 +2129,48 @@ window.chatInteractionManager = function () {
|
|
|
1941
2129
|
this.setItemId(itemId);
|
|
1942
2130
|
this.isInteractionStarted = true;
|
|
1943
2131
|
},
|
|
1944
|
-
|
|
1945
|
-
|
|
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
|
+
});
|
|
1946
2171
|
},
|
|
1947
2172
|
startRecording: function startRecording() {
|
|
1948
|
-
var
|
|
2173
|
+
var _this22 = this;
|
|
1949
2174
|
if (this.isRecording || !this.connection) {
|
|
1950
2175
|
return;
|
|
1951
2176
|
}
|
|
@@ -1957,16 +2182,16 @@ window.chatInteractionManager = function () {
|
|
|
1957
2182
|
}
|
|
1958
2183
|
}).then(function (stream) {
|
|
1959
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';
|
|
1960
|
-
|
|
2185
|
+
_this22.mediaRecorder = new MediaRecorder(stream, {
|
|
1961
2186
|
mimeType: mimeType,
|
|
1962
2187
|
audioBitsPerSecond: 128000
|
|
1963
2188
|
});
|
|
1964
|
-
|
|
1965
|
-
|
|
2189
|
+
_this22.preRecordingPrompt = _this22.prompt;
|
|
2190
|
+
_this22._audioInputSent = false;
|
|
1966
2191
|
var subject = new signalR.Subject();
|
|
1967
|
-
var itemId =
|
|
2192
|
+
var itemId = _this22.getItemId();
|
|
1968
2193
|
var pendingChunk = Promise.resolve();
|
|
1969
|
-
|
|
2194
|
+
_this22.mediaRecorder.addEventListener('dataavailable', function (e) {
|
|
1970
2195
|
if (e.data && e.data.size > 0) {
|
|
1971
2196
|
pendingChunk = pendingChunk.then(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4() {
|
|
1972
2197
|
var data, uint8Array, binaryString, base64;
|
|
@@ -1990,7 +2215,7 @@ window.chatInteractionManager = function () {
|
|
|
1990
2215
|
})));
|
|
1991
2216
|
}
|
|
1992
2217
|
});
|
|
1993
|
-
|
|
2218
|
+
_this22.mediaRecorder.addEventListener('stop', function () {
|
|
1994
2219
|
stream.getTracks().forEach(function (track) {
|
|
1995
2220
|
return track.stop();
|
|
1996
2221
|
});
|
|
@@ -1999,10 +2224,10 @@ window.chatInteractionManager = function () {
|
|
|
1999
2224
|
});
|
|
2000
2225
|
});
|
|
2001
2226
|
var language = navigator.language || document.documentElement.lang || 'en-US';
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2227
|
+
_this22.connection.send("SendAudioStream", itemId, subject, mimeType, language);
|
|
2228
|
+
_this22.mediaRecorder.start(250);
|
|
2229
|
+
_this22.isRecording = true;
|
|
2230
|
+
_this22.updateMicButton();
|
|
2006
2231
|
})["catch"](function (err) {
|
|
2007
2232
|
console.error('Microphone access denied:', err);
|
|
2008
2233
|
});
|
|
@@ -2028,10 +2253,10 @@ window.chatInteractionManager = function () {
|
|
|
2028
2253
|
}
|
|
2029
2254
|
if (this.isRecording) {
|
|
2030
2255
|
this.micButton.classList.add('stt-recording');
|
|
2031
|
-
this.micButton.innerHTML = '<
|
|
2256
|
+
this.micButton.innerHTML = '<i class="fa-solid fa-stop"></i>';
|
|
2032
2257
|
} else {
|
|
2033
2258
|
this.micButton.classList.remove('stt-recording');
|
|
2034
|
-
this.micButton.innerHTML = '<
|
|
2259
|
+
this.micButton.innerHTML = '<i class="fa-solid fa-microphone"></i>';
|
|
2035
2260
|
}
|
|
2036
2261
|
}
|
|
2037
2262
|
},
|
|
@@ -2053,18 +2278,29 @@ window.chatInteractionManager = function () {
|
|
|
2053
2278
|
this.inputElement.placeholder = '';
|
|
2054
2279
|
}
|
|
2055
2280
|
}
|
|
2281
|
+
},
|
|
2282
|
+
copiedMessageIndex: function copiedMessageIndex() {
|
|
2283
|
+
var _this23 = this;
|
|
2284
|
+
this.$nextTick(function () {
|
|
2285
|
+
return _this23.updateCopyButtons();
|
|
2286
|
+
});
|
|
2056
2287
|
}
|
|
2057
2288
|
},
|
|
2058
2289
|
mounted: function mounted() {
|
|
2059
|
-
var
|
|
2290
|
+
var _this24 = this;
|
|
2060
2291
|
_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee5() {
|
|
2061
2292
|
return _regenerator().w(function (_context5) {
|
|
2062
2293
|
while (1) switch (_context5.n) {
|
|
2063
2294
|
case 0:
|
|
2064
2295
|
_context5.n = 1;
|
|
2065
|
-
return
|
|
2296
|
+
return _this24.startConnection();
|
|
2066
2297
|
case 1:
|
|
2067
|
-
|
|
2298
|
+
_this24.initializeApp();
|
|
2299
|
+
_this24.$nextTick(function () {
|
|
2300
|
+
_this24.updateCopyButtons();
|
|
2301
|
+
refreshFontAwesomeIcons(_this24.$el);
|
|
2302
|
+
_this24.fontAwesomeObserver = observeFontAwesomeIcons(_this24.$el);
|
|
2303
|
+
});
|
|
2068
2304
|
case 2:
|
|
2069
2305
|
return _context5.a(2);
|
|
2070
2306
|
}
|
|
@@ -2076,6 +2312,11 @@ window.chatInteractionManager = function () {
|
|
|
2076
2312
|
beforeUnmount: function beforeUnmount() {
|
|
2077
2313
|
window.removeEventListener('beforeunload', this.handleBeforeUnload);
|
|
2078
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();
|
|
2079
2320
|
this.stopAudio(false);
|
|
2080
2321
|
if (this.stream) {
|
|
2081
2322
|
this.stream.dispose();
|
|
@@ -2089,8 +2330,666 @@ window.chatInteractionManager = function () {
|
|
|
2089
2330
|
}).mount(config.appElementSelector);
|
|
2090
2331
|
return app;
|
|
2091
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
|
+
}
|
|
2092
2990
|
return {
|
|
2093
|
-
initialize: initialize
|
|
2991
|
+
initialize: initialize,
|
|
2992
|
+
initializeFromElement: initializeFromElement
|
|
2094
2993
|
};
|
|
2095
2994
|
}();
|
|
2096
2995
|
|