@crestapps/ai-chat-ui 1.0.0-preview.14 → 1.0.0-preview.153
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai-chat-widget.js +158 -12
- package/dist/ai-chat-widget.js.map +1 -1
- package/dist/ai-chat-widget.min.js +1 -1
- package/dist/ai-chat-widget.min.js.map +1 -1
- package/dist/ai-chat.css +67 -17
- package/dist/ai-chat.css.map +1 -1
- package/dist/ai-chat.js +683 -328
- 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 +1198 -338
- 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 +86 -35
- 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 +5 -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);
|
|
@@ -1048,7 +1157,7 @@ window.chatInteractionManager = function () {
|
|
|
1048
1157
|
buttons.forEach(function (button) {
|
|
1049
1158
|
var buttonIndex = Number(button.getAttribute('data-tts-message-index'));
|
|
1050
1159
|
var isPlaying = buttonIndex === _this7.ttsPlayingMessageIndex;
|
|
1051
|
-
var iconHtml = isPlaying ? '<
|
|
1160
|
+
var iconHtml = isPlaying ? '<i class="fa-solid fa-circle-pause"></i>' : '<i class="fa-solid fa-circle-play"></i>';
|
|
1052
1161
|
button.classList.toggle('tts-playing', isPlaying);
|
|
1053
1162
|
button.setAttribute('title', isPlaying ? 'Pause audio' : 'Read aloud');
|
|
1054
1163
|
button.replaceChildren(DOMPurify.sanitize(iconHtml, {
|
|
@@ -1056,8 +1165,38 @@ window.chatInteractionManager = function () {
|
|
|
1056
1165
|
}));
|
|
1057
1166
|
});
|
|
1058
1167
|
},
|
|
1059
|
-
|
|
1168
|
+
updateCopyButtons: function updateCopyButtons() {
|
|
1060
1169
|
var _this8 = this;
|
|
1170
|
+
if (!this.chatContainer) {
|
|
1171
|
+
return;
|
|
1172
|
+
}
|
|
1173
|
+
var buttons = this.chatContainer.querySelectorAll('[data-copy-message-index]');
|
|
1174
|
+
buttons.forEach(function (button) {
|
|
1175
|
+
var buttonIndex = Number(button.getAttribute('data-copy-message-index'));
|
|
1176
|
+
var isCopied = buttonIndex === _this8.copiedMessageIndex;
|
|
1177
|
+
var iconHtml = isCopied ? '<i class="fa-solid fa-check"></i>' : '<i class="fa-solid fa-copy"></i>';
|
|
1178
|
+
button.classList.toggle('text-success', isCopied);
|
|
1179
|
+
button.classList.toggle('text-secondary', !isCopied);
|
|
1180
|
+
button.setAttribute('title', isCopied ? _this8.copiedTitle : _this8.copyTitle);
|
|
1181
|
+
button.replaceChildren(DOMPurify.sanitize(iconHtml, {
|
|
1182
|
+
RETURN_DOM_FRAGMENT: true
|
|
1183
|
+
}));
|
|
1184
|
+
});
|
|
1185
|
+
},
|
|
1186
|
+
setCopyButtonState: function setCopyButtonState(button, isCopied) {
|
|
1187
|
+
if (!button) {
|
|
1188
|
+
return;
|
|
1189
|
+
}
|
|
1190
|
+
var iconHtml = isCopied ? '<i class="fa-solid fa-check"></i>' : '<i class="fa-solid fa-copy"></i>';
|
|
1191
|
+
button.classList.toggle('text-success', isCopied);
|
|
1192
|
+
button.classList.toggle('text-secondary', !isCopied);
|
|
1193
|
+
button.setAttribute('title', isCopied ? this.copiedTitle : this.copyTitle);
|
|
1194
|
+
button.replaceChildren(DOMPurify.sanitize(iconHtml, {
|
|
1195
|
+
RETURN_DOM_FRAGMENT: true
|
|
1196
|
+
}));
|
|
1197
|
+
},
|
|
1198
|
+
synthesizeSpeech: function synthesizeSpeech(text, cacheIndex) {
|
|
1199
|
+
var _this9 = this;
|
|
1061
1200
|
if (!this.textToSpeechEnabled || !text || !this.connection) {
|
|
1062
1201
|
return;
|
|
1063
1202
|
}
|
|
@@ -1066,16 +1205,16 @@ window.chatInteractionManager = function () {
|
|
|
1066
1205
|
this._ttsCacheIndex = cacheIndex !== undefined ? cacheIndex : -1;
|
|
1067
1206
|
this.connection.invoke("SynthesizeSpeech", this.getItemId(), text, this.ttsVoiceName)["catch"](function (err) {
|
|
1068
1207
|
console.error("TTS synthesis error:", err);
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
return
|
|
1208
|
+
_this9.isPlayingAudio = false;
|
|
1209
|
+
_this9.ttsPlayingMessageIndex = -1;
|
|
1210
|
+
_this9._ttsCacheIndex = -1;
|
|
1211
|
+
_this9.$nextTick(function () {
|
|
1212
|
+
return _this9.updateTtsPlaybackButtons();
|
|
1074
1213
|
});
|
|
1075
1214
|
});
|
|
1076
1215
|
},
|
|
1077
1216
|
toggleMessageTts: function toggleMessageTts(message, index) {
|
|
1078
|
-
var
|
|
1217
|
+
var _this0 = this;
|
|
1079
1218
|
if (this.ttsPlayingMessageIndex === index) {
|
|
1080
1219
|
this.stopAudio();
|
|
1081
1220
|
return;
|
|
@@ -1088,7 +1227,7 @@ window.chatInteractionManager = function () {
|
|
|
1088
1227
|
}));
|
|
1089
1228
|
this.ttsPlayingMessageIndex = index;
|
|
1090
1229
|
this.$nextTick(function () {
|
|
1091
|
-
return
|
|
1230
|
+
return _this0.updateTtsPlaybackButtons();
|
|
1092
1231
|
});
|
|
1093
1232
|
if (this.ttsAudioCache[index]) {
|
|
1094
1233
|
this.playAudioBlob(this.ttsAudioCache[index]);
|
|
@@ -1097,13 +1236,13 @@ window.chatInteractionManager = function () {
|
|
|
1097
1236
|
this.synthesizeSpeech(message.content, index);
|
|
1098
1237
|
},
|
|
1099
1238
|
playCollectedAudio: function playCollectedAudio() {
|
|
1100
|
-
var
|
|
1239
|
+
var _this1 = this;
|
|
1101
1240
|
if (this.audioChunks.length === 0) {
|
|
1102
1241
|
if (!this.isPlayingAudio && this.audioPlayQueue.length === 0) {
|
|
1103
1242
|
this.isPlayingAudio = false;
|
|
1104
1243
|
this.ttsPlayingMessageIndex = -1;
|
|
1105
1244
|
this.$nextTick(function () {
|
|
1106
|
-
return
|
|
1245
|
+
return _this1.updateTtsPlaybackButtons();
|
|
1107
1246
|
});
|
|
1108
1247
|
}
|
|
1109
1248
|
return;
|
|
@@ -1113,18 +1252,18 @@ window.chatInteractionManager = function () {
|
|
|
1113
1252
|
}, 0);
|
|
1114
1253
|
var combined = new Uint8Array(totalLength);
|
|
1115
1254
|
var offset = 0;
|
|
1116
|
-
var
|
|
1117
|
-
|
|
1255
|
+
var _iterator6 = _createForOfIteratorHelper(this.audioChunks),
|
|
1256
|
+
_step6;
|
|
1118
1257
|
try {
|
|
1119
|
-
for (
|
|
1120
|
-
var chunk =
|
|
1258
|
+
for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
|
|
1259
|
+
var chunk = _step6.value;
|
|
1121
1260
|
combined.set(chunk, offset);
|
|
1122
1261
|
offset += chunk.length;
|
|
1123
1262
|
}
|
|
1124
1263
|
} catch (err) {
|
|
1125
|
-
|
|
1264
|
+
_iterator6.e(err);
|
|
1126
1265
|
} finally {
|
|
1127
|
-
|
|
1266
|
+
_iterator6.f();
|
|
1128
1267
|
}
|
|
1129
1268
|
this.audioChunks = [];
|
|
1130
1269
|
var blob = new Blob([combined], {
|
|
@@ -1143,39 +1282,39 @@ window.chatInteractionManager = function () {
|
|
|
1143
1282
|
this.playAudioBlob(blob);
|
|
1144
1283
|
},
|
|
1145
1284
|
playAudioBlob: function playAudioBlob(blob) {
|
|
1146
|
-
var
|
|
1285
|
+
var _this10 = this;
|
|
1147
1286
|
var url = URL.createObjectURL(blob);
|
|
1148
1287
|
var audio = new Audio(url);
|
|
1149
1288
|
this.currentAudioUrl = url;
|
|
1150
1289
|
this.currentAudioElement = audio;
|
|
1151
1290
|
this.isPlayingAudio = true;
|
|
1152
1291
|
audio.addEventListener('ended', function () {
|
|
1153
|
-
|
|
1154
|
-
|
|
1292
|
+
_this10.currentAudioElement = null;
|
|
1293
|
+
_this10.currentAudioUrl = null;
|
|
1155
1294
|
URL.revokeObjectURL(url);
|
|
1156
|
-
|
|
1295
|
+
_this10.playNextInQueue();
|
|
1157
1296
|
});
|
|
1158
1297
|
audio.addEventListener('error', function () {
|
|
1159
|
-
|
|
1160
|
-
|
|
1298
|
+
_this10.currentAudioElement = null;
|
|
1299
|
+
_this10.currentAudioUrl = null;
|
|
1161
1300
|
URL.revokeObjectURL(url);
|
|
1162
|
-
|
|
1301
|
+
_this10.playNextInQueue();
|
|
1163
1302
|
});
|
|
1164
1303
|
audio.play()["catch"](function (err) {
|
|
1165
1304
|
console.error("Audio playback error:", err);
|
|
1166
|
-
|
|
1167
|
-
|
|
1305
|
+
_this10.currentAudioElement = null;
|
|
1306
|
+
_this10.currentAudioUrl = null;
|
|
1168
1307
|
URL.revokeObjectURL(url);
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
return
|
|
1308
|
+
_this10.audioPlayQueue = [];
|
|
1309
|
+
_this10.isPlayingAudio = false;
|
|
1310
|
+
_this10.ttsPlayingMessageIndex = -1;
|
|
1311
|
+
_this10.$nextTick(function () {
|
|
1312
|
+
return _this10.updateTtsPlaybackButtons();
|
|
1174
1313
|
});
|
|
1175
1314
|
});
|
|
1176
1315
|
},
|
|
1177
1316
|
playNextInQueue: function playNextInQueue() {
|
|
1178
|
-
var
|
|
1317
|
+
var _this11 = this;
|
|
1179
1318
|
if (this.audioPlayQueue.length > 0) {
|
|
1180
1319
|
var nextBlob = this.audioPlayQueue.shift();
|
|
1181
1320
|
this.playAudioBlob(nextBlob);
|
|
@@ -1183,13 +1322,13 @@ window.chatInteractionManager = function () {
|
|
|
1183
1322
|
this.isPlayingAudio = false;
|
|
1184
1323
|
this.ttsPlayingMessageIndex = -1;
|
|
1185
1324
|
this.$nextTick(function () {
|
|
1186
|
-
return
|
|
1325
|
+
return _this11.updateTtsPlaybackButtons();
|
|
1187
1326
|
});
|
|
1188
1327
|
this.conversationModeOnAudioEnded();
|
|
1189
1328
|
}
|
|
1190
1329
|
},
|
|
1191
1330
|
stopAudio: function stopAudio() {
|
|
1192
|
-
var
|
|
1331
|
+
var _this12 = this;
|
|
1193
1332
|
if (this.currentAudioElement) {
|
|
1194
1333
|
this.currentAudioElement.pause();
|
|
1195
1334
|
this.currentAudioElement.currentTime = 0;
|
|
@@ -1204,7 +1343,7 @@ window.chatInteractionManager = function () {
|
|
|
1204
1343
|
this.isPlayingAudio = false;
|
|
1205
1344
|
this.ttsPlayingMessageIndex = -1;
|
|
1206
1345
|
this.$nextTick(function () {
|
|
1207
|
-
return
|
|
1346
|
+
return _this12.updateTtsPlaybackButtons();
|
|
1208
1347
|
});
|
|
1209
1348
|
},
|
|
1210
1349
|
toggleConversationMode: function toggleConversationMode() {
|
|
@@ -1215,7 +1354,7 @@ window.chatInteractionManager = function () {
|
|
|
1215
1354
|
}
|
|
1216
1355
|
},
|
|
1217
1356
|
startConversationMode: function startConversationMode() {
|
|
1218
|
-
var
|
|
1357
|
+
var _this13 = this;
|
|
1219
1358
|
if (!this.conversationModeEnabled || this.isConversationMode || !this.connection) {
|
|
1220
1359
|
return;
|
|
1221
1360
|
}
|
|
@@ -1235,30 +1374,30 @@ window.chatInteractionManager = function () {
|
|
|
1235
1374
|
}
|
|
1236
1375
|
}).then(function (stream) {
|
|
1237
1376
|
var mimeType = MediaRecorder.isTypeSupported('audio/ogg;codecs=opus') ? 'audio/ogg;codecs=opus' : MediaRecorder.isTypeSupported('audio/webm;codecs=opus') ? 'audio/webm;codecs=opus' : 'audio/webm';
|
|
1238
|
-
|
|
1377
|
+
_this13.mediaRecorder = new MediaRecorder(stream, {
|
|
1239
1378
|
mimeType: mimeType,
|
|
1240
1379
|
audioBitsPerSecond: 128000
|
|
1241
1380
|
});
|
|
1242
|
-
|
|
1243
|
-
|
|
1381
|
+
_this13._conversationSubject = new signalR.Subject();
|
|
1382
|
+
_this13._conversationStream = stream;
|
|
1244
1383
|
|
|
1245
1384
|
// Create an AnalyserNode for volume-based interrupt detection.
|
|
1246
1385
|
var AudioCtx = window.AudioContext || window.webkitAudioContext;
|
|
1247
1386
|
if (AudioCtx) {
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
var micSource =
|
|
1252
|
-
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);
|
|
1253
1392
|
}
|
|
1254
1393
|
var pendingChunk = Promise.resolve();
|
|
1255
|
-
var analyser =
|
|
1394
|
+
var analyser = _this13._conversationAnalyser;
|
|
1256
1395
|
var interruptVolumeThreshold = 30;
|
|
1257
|
-
|
|
1396
|
+
_this13.mediaRecorder.addEventListener('dataavailable', function (e) {
|
|
1258
1397
|
if (e.data && e.data.size > 0) {
|
|
1259
1398
|
// During TTS playback, check mic volume to detect
|
|
1260
1399
|
// user interruption (speaking above threshold).
|
|
1261
|
-
if (
|
|
1400
|
+
if (_this13.isPlayingAudio && analyser) {
|
|
1262
1401
|
var freqData = new Uint8Array(analyser.frequencyBinCount);
|
|
1263
1402
|
analyser.getByteFrequencyData(freqData);
|
|
1264
1403
|
var sum = 0;
|
|
@@ -1268,7 +1407,7 @@ window.chatInteractionManager = function () {
|
|
|
1268
1407
|
var avg = sum / freqData.length;
|
|
1269
1408
|
if (avg >= interruptVolumeThreshold) {
|
|
1270
1409
|
// User is speaking — interrupt TTS playback.
|
|
1271
|
-
|
|
1410
|
+
_this13.stopAudio();
|
|
1272
1411
|
}
|
|
1273
1412
|
}
|
|
1274
1413
|
|
|
@@ -1290,7 +1429,7 @@ window.chatInteractionManager = function () {
|
|
|
1290
1429
|
}, '');
|
|
1291
1430
|
base64 = btoa(binaryString);
|
|
1292
1431
|
try {
|
|
1293
|
-
|
|
1432
|
+
_this13._conversationSubject.next(base64);
|
|
1294
1433
|
} catch (err) {
|
|
1295
1434
|
// Subject may have been completed already.
|
|
1296
1435
|
}
|
|
@@ -1301,27 +1440,27 @@ window.chatInteractionManager = function () {
|
|
|
1301
1440
|
})));
|
|
1302
1441
|
}
|
|
1303
1442
|
});
|
|
1304
|
-
|
|
1443
|
+
_this13.mediaRecorder.addEventListener('stop', function () {
|
|
1305
1444
|
stream.getTracks().forEach(function (track) {
|
|
1306
1445
|
return track.stop();
|
|
1307
1446
|
});
|
|
1308
1447
|
pendingChunk.then(function () {
|
|
1309
1448
|
try {
|
|
1310
|
-
|
|
1449
|
+
_this13._conversationSubject.complete();
|
|
1311
1450
|
} catch (err) {
|
|
1312
1451
|
// Already completed.
|
|
1313
1452
|
}
|
|
1314
1453
|
});
|
|
1315
1454
|
});
|
|
1316
|
-
var itemId =
|
|
1455
|
+
var itemId = _this13.getItemId();
|
|
1317
1456
|
var language = navigator.language || document.documentElement.lang || 'en-US';
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1457
|
+
_this13.connection.send("StartConversation", itemId, _this13._conversationSubject, mimeType, language);
|
|
1458
|
+
_this13.mediaRecorder.start(250);
|
|
1459
|
+
_this13.isRecording = true;
|
|
1321
1460
|
})["catch"](function (err) {
|
|
1322
1461
|
console.error('Microphone access denied:', err);
|
|
1323
|
-
|
|
1324
|
-
|
|
1462
|
+
_this13.isConversationMode = false;
|
|
1463
|
+
_this13.updateConversationButton();
|
|
1325
1464
|
});
|
|
1326
1465
|
},
|
|
1327
1466
|
stopConversationMode: function stopConversationMode() {
|
|
@@ -1425,12 +1564,12 @@ window.chatInteractionManager = function () {
|
|
|
1425
1564
|
return removedCount;
|
|
1426
1565
|
},
|
|
1427
1566
|
scrollToBottom: function scrollToBottom() {
|
|
1428
|
-
var
|
|
1567
|
+
var _this14 = this;
|
|
1429
1568
|
if (!this.autoScroll) {
|
|
1430
1569
|
return;
|
|
1431
1570
|
}
|
|
1432
1571
|
setTimeout(function () {
|
|
1433
|
-
|
|
1572
|
+
_this14.chatContainer.scrollTop = _this14.chatContainer.scrollHeight - _this14.chatContainer.clientHeight;
|
|
1434
1573
|
}, 50);
|
|
1435
1574
|
},
|
|
1436
1575
|
handleUserInput: function handleUserInput(event) {
|
|
@@ -1446,7 +1585,7 @@ window.chatInteractionManager = function () {
|
|
|
1446
1585
|
return document.querySelector('[data-chat-interaction-save-indicator]');
|
|
1447
1586
|
},
|
|
1448
1587
|
showSaveIndicator: function showSaveIndicator(text, className) {
|
|
1449
|
-
var
|
|
1588
|
+
var _this15 = this;
|
|
1450
1589
|
var indicator = this.getSaveIndicatorElement();
|
|
1451
1590
|
if (!indicator) {
|
|
1452
1591
|
return;
|
|
@@ -1462,7 +1601,7 @@ window.chatInteractionManager = function () {
|
|
|
1462
1601
|
}
|
|
1463
1602
|
this.saveIndicatorTimeout = setTimeout(function () {
|
|
1464
1603
|
indicator.textContent = '';
|
|
1465
|
-
|
|
1604
|
+
_this15.saveIndicatorTimeout = null;
|
|
1466
1605
|
}, 3000);
|
|
1467
1606
|
},
|
|
1468
1607
|
clearPendingSettingsSave: function clearPendingSettingsSave() {
|
|
@@ -1536,10 +1675,10 @@ window.chatInteractionManager = function () {
|
|
|
1536
1675
|
return false;
|
|
1537
1676
|
},
|
|
1538
1677
|
validateSettings: function validateSettings() {
|
|
1539
|
-
var
|
|
1678
|
+
var _this16 = this;
|
|
1540
1679
|
var isValid = true;
|
|
1541
1680
|
this.getSettingInputs().forEach(function (input) {
|
|
1542
|
-
isValid =
|
|
1681
|
+
isValid = _this16.validateSettingInput(input) && isValid;
|
|
1543
1682
|
});
|
|
1544
1683
|
return isValid;
|
|
1545
1684
|
},
|
|
@@ -1562,7 +1701,7 @@ window.chatInteractionManager = function () {
|
|
|
1562
1701
|
return document.querySelectorAll('input[name^="ChatInteraction."]:not([name*=".Tools["]):not([name*=".Connections["]), ' + 'select[name^="ChatInteraction."]:not([name*=".Tools["]):not([name*=".Connections["]), ' + 'textarea[name^="ChatInteraction."]:not([name*=".Tools["]):not([name*=".Connections["])');
|
|
1563
1702
|
},
|
|
1564
1703
|
getSelectedGroupValues: function getSelectedGroupValues(groupName, fallbackSelector) {
|
|
1565
|
-
var explicitSelections = document.querySelectorAll(".capability-checkbox[data-save-group=\"".concat(groupName, "\"]:checked"));
|
|
1704
|
+
var explicitSelections = document.querySelectorAll(".capability-checkbox[data-save-group=\"".concat(groupName, "\"]:checked, .capability-checkbox[data-group=\"").concat(groupName, "\"]:checked"));
|
|
1566
1705
|
if (explicitSelections.length > 0) {
|
|
1567
1706
|
var _values = [];
|
|
1568
1707
|
explicitSelections.forEach(function (checkbox) {
|
|
@@ -1635,12 +1774,12 @@ window.chatInteractionManager = function () {
|
|
|
1635
1774
|
}
|
|
1636
1775
|
},
|
|
1637
1776
|
scheduleNotificationDismiss: function scheduleNotificationDismiss(notification) {
|
|
1638
|
-
var
|
|
1777
|
+
var _this17 = this;
|
|
1639
1778
|
if (!notification || !notification.type || !notification.autoDismissMs || notification.autoDismissMs <= 0) {
|
|
1640
1779
|
return;
|
|
1641
1780
|
}
|
|
1642
1781
|
this.notificationDismissTimers[notification.type] = setTimeout(function () {
|
|
1643
|
-
|
|
1782
|
+
_this17.removeNotification(notification.type);
|
|
1644
1783
|
}, notification.autoDismissMs);
|
|
1645
1784
|
},
|
|
1646
1785
|
clearNotificationDismiss: function clearNotificationDismiss(notificationType) {
|
|
@@ -1680,7 +1819,7 @@ window.chatInteractionManager = function () {
|
|
|
1680
1819
|
this.showPlaceholder();
|
|
1681
1820
|
},
|
|
1682
1821
|
initializeApp: function initializeApp() {
|
|
1683
|
-
var
|
|
1822
|
+
var _this18 = this;
|
|
1684
1823
|
this.inputElement = document.querySelector(config.inputElementSelector);
|
|
1685
1824
|
this.buttonElement = document.querySelector(config.sendButtonElementSelector);
|
|
1686
1825
|
this.chatContainer = document.querySelector(config.chatContainerElementSelector);
|
|
@@ -1692,59 +1831,59 @@ window.chatInteractionManager = function () {
|
|
|
1692
1831
|
|
|
1693
1832
|
// Pause auto-scroll when the user manually scrolls up during streaming.
|
|
1694
1833
|
this.chatContainer.addEventListener('scroll', function () {
|
|
1695
|
-
if (!
|
|
1834
|
+
if (!_this18.stream) {
|
|
1696
1835
|
return;
|
|
1697
1836
|
}
|
|
1698
1837
|
var threshold = 30;
|
|
1699
|
-
var atBottom =
|
|
1700
|
-
|
|
1838
|
+
var atBottom = _this18.chatContainer.scrollHeight - _this18.chatContainer.clientHeight - _this18.chatContainer.scrollTop <= threshold;
|
|
1839
|
+
_this18.autoScroll = atBottom;
|
|
1701
1840
|
});
|
|
1702
1841
|
this.inputElement.addEventListener('keyup', function (event) {
|
|
1703
|
-
if (
|
|
1842
|
+
if (_this18.stream != null) {
|
|
1704
1843
|
return;
|
|
1705
1844
|
}
|
|
1706
1845
|
if (event.key === "Enter" && !event.shiftKey) {
|
|
1707
|
-
|
|
1846
|
+
_this18.buttonElement.click();
|
|
1708
1847
|
}
|
|
1709
1848
|
});
|
|
1710
1849
|
this.inputElement.addEventListener('input', function (e) {
|
|
1711
|
-
|
|
1850
|
+
_this18.handleUserInput(e);
|
|
1712
1851
|
if (e.target.value.trim()) {
|
|
1713
|
-
|
|
1852
|
+
_this18.buttonElement.removeAttribute('disabled');
|
|
1714
1853
|
} else {
|
|
1715
|
-
|
|
1854
|
+
_this18.buttonElement.setAttribute('disabled', true);
|
|
1716
1855
|
}
|
|
1717
1856
|
});
|
|
1718
1857
|
this.inputElement.addEventListener('paste', function (e) {
|
|
1719
1858
|
// Use setTimeout to allow the paste to complete before checking the value
|
|
1720
1859
|
setTimeout(function () {
|
|
1721
|
-
|
|
1722
|
-
if (
|
|
1723
|
-
|
|
1860
|
+
_this18.prompt = _this18.inputElement.value;
|
|
1861
|
+
if (_this18.inputElement.value.trim()) {
|
|
1862
|
+
_this18.buttonElement.removeAttribute('disabled');
|
|
1724
1863
|
} else {
|
|
1725
|
-
|
|
1864
|
+
_this18.buttonElement.setAttribute('disabled', true);
|
|
1726
1865
|
}
|
|
1727
1866
|
}, 0);
|
|
1728
1867
|
});
|
|
1729
1868
|
this.buttonElement.addEventListener('click', function () {
|
|
1730
|
-
if (
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1869
|
+
if (_this18.stream != null) {
|
|
1870
|
+
_this18.stream.dispose();
|
|
1871
|
+
_this18.stream = null;
|
|
1872
|
+
_this18.streamingFinished();
|
|
1873
|
+
_this18.hideTypingIndicator();
|
|
1735
1874
|
|
|
1736
1875
|
// Clean up: remove empty assistant message or stop streaming animation.
|
|
1737
|
-
if (
|
|
1738
|
-
var lastMsg =
|
|
1876
|
+
if (_this18.messages.length > 0) {
|
|
1877
|
+
var lastMsg = _this18.messages[_this18.messages.length - 1];
|
|
1739
1878
|
if (lastMsg.role === 'assistant' && !lastMsg.content) {
|
|
1740
|
-
|
|
1879
|
+
_this18.messages.pop();
|
|
1741
1880
|
} else if (lastMsg.isStreaming) {
|
|
1742
1881
|
lastMsg.isStreaming = false;
|
|
1743
1882
|
}
|
|
1744
1883
|
}
|
|
1745
1884
|
return;
|
|
1746
1885
|
}
|
|
1747
|
-
|
|
1886
|
+
_this18.sendMessage();
|
|
1748
1887
|
});
|
|
1749
1888
|
var chatInteractionItems = document.getElementsByClassName('chat-interaction-history-item');
|
|
1750
1889
|
for (var i = 0; i < chatInteractionItems.length; i++) {
|
|
@@ -1755,11 +1894,12 @@ window.chatInteractionManager = function () {
|
|
|
1755
1894
|
console.error('An element with the class chat-interaction-history-item with no data-interaction-id set.');
|
|
1756
1895
|
return;
|
|
1757
1896
|
}
|
|
1758
|
-
|
|
1897
|
+
_this18.loadInteraction(itemId);
|
|
1759
1898
|
});
|
|
1760
1899
|
}
|
|
1761
|
-
|
|
1762
|
-
|
|
1900
|
+
var initialMessages = Array.isArray(config.messages) ? config.messages : [];
|
|
1901
|
+
for (var _i4 = 0; _i4 < initialMessages.length; _i4++) {
|
|
1902
|
+
this.addMessage(initialMessages[_i4]);
|
|
1763
1903
|
}
|
|
1764
1904
|
|
|
1765
1905
|
// Delegate click for code block copy buttons.
|
|
@@ -1777,29 +1917,29 @@ window.chatInteractionManager = function () {
|
|
|
1777
1917
|
if (codeEl) {
|
|
1778
1918
|
navigator.clipboard.writeText(codeEl.textContent);
|
|
1779
1919
|
var copiedText = config.codeCopiedText || 'Copied!';
|
|
1780
|
-
btn.innerHTML = '<
|
|
1920
|
+
btn.innerHTML = '<i class="fa-solid fa-check"></i> ' + copiedText;
|
|
1781
1921
|
setTimeout(function () {
|
|
1782
|
-
btn.innerHTML = '<
|
|
1922
|
+
btn.innerHTML = '<i class="fa-regular fa-copy"></i>';
|
|
1783
1923
|
}, 2000);
|
|
1784
1924
|
}
|
|
1785
1925
|
});
|
|
1786
1926
|
}
|
|
1787
1927
|
document.addEventListener('input', function (event) {
|
|
1788
1928
|
if (event.target.matches('.setting-input[data-setting]')) {
|
|
1789
|
-
|
|
1790
|
-
|
|
1929
|
+
_this18.validateSettingInput(event.target);
|
|
1930
|
+
_this18.queueSettingsSave();
|
|
1791
1931
|
}
|
|
1792
1932
|
});
|
|
1793
1933
|
document.addEventListener('change', function (event) {
|
|
1794
|
-
if (event.target.matches('.setting-input[data-setting], .capability-checkbox[data-save-group], .group-toggle, .ci-agent-global-toggle')) {
|
|
1934
|
+
if (event.target.matches('.setting-input[data-setting], .capability-checkbox[data-save-group], .capability-checkbox[data-group], .group-toggle, .ci-agent-global-toggle')) {
|
|
1795
1935
|
if (event.target.matches('.setting-input[data-setting]')) {
|
|
1796
|
-
|
|
1936
|
+
_this18.validateSettingInput(event.target);
|
|
1797
1937
|
}
|
|
1798
|
-
|
|
1938
|
+
_this18.queueSettingsSave();
|
|
1799
1939
|
return;
|
|
1800
1940
|
}
|
|
1801
1941
|
if (event.target.closest('.prompt-template-parameters-input, .prompt-template-id-input')) {
|
|
1802
|
-
|
|
1942
|
+
_this18.queueSettingsSave();
|
|
1803
1943
|
}
|
|
1804
1944
|
});
|
|
1805
1945
|
document.addEventListener('click', function (event) {
|
|
@@ -1807,7 +1947,7 @@ window.chatInteractionManager = function () {
|
|
|
1807
1947
|
return;
|
|
1808
1948
|
}
|
|
1809
1949
|
setTimeout(function () {
|
|
1810
|
-
|
|
1950
|
+
_this18.queueSettingsSave();
|
|
1811
1951
|
}, 0);
|
|
1812
1952
|
});
|
|
1813
1953
|
|
|
@@ -1817,7 +1957,7 @@ window.chatInteractionManager = function () {
|
|
|
1817
1957
|
clearHistoryBtn.addEventListener('click', function () {
|
|
1818
1958
|
var itemId = clearHistoryBtn.getAttribute('data-interaction-id');
|
|
1819
1959
|
if (itemId) {
|
|
1820
|
-
|
|
1960
|
+
_this18.clearHistory(itemId);
|
|
1821
1961
|
}
|
|
1822
1962
|
});
|
|
1823
1963
|
}
|
|
@@ -1828,7 +1968,7 @@ window.chatInteractionManager = function () {
|
|
|
1828
1968
|
if (this.micButton) {
|
|
1829
1969
|
this.micButton.style.display = '';
|
|
1830
1970
|
this.micButton.addEventListener('click', function () {
|
|
1831
|
-
|
|
1971
|
+
_this18.toggleRecording();
|
|
1832
1972
|
});
|
|
1833
1973
|
}
|
|
1834
1974
|
}
|
|
@@ -1838,7 +1978,7 @@ window.chatInteractionManager = function () {
|
|
|
1838
1978
|
this.conversationButton = document.querySelector(config.conversationButtonElementSelector);
|
|
1839
1979
|
if (this.conversationButton) {
|
|
1840
1980
|
this.conversationButton.addEventListener('click', function () {
|
|
1841
|
-
|
|
1981
|
+
_this18.toggleConversationMode();
|
|
1842
1982
|
});
|
|
1843
1983
|
}
|
|
1844
1984
|
}
|
|
@@ -1856,29 +1996,38 @@ window.chatInteractionManager = function () {
|
|
|
1856
1996
|
},
|
|
1857
1997
|
clearHistory: function clearHistory(itemId) {
|
|
1858
1998
|
var self = this;
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1999
|
+
var clearHistoryConfirmed = function clearHistoryConfirmed() {
|
|
2000
|
+
// Cancel any active stream before clearing history.
|
|
2001
|
+
if (self.stream) {
|
|
2002
|
+
self.stream.dispose();
|
|
2003
|
+
self.stream = null;
|
|
2004
|
+
self.hideTypingIndicator();
|
|
2005
|
+
self.streamingFinished();
|
|
2006
|
+
}
|
|
2007
|
+
self.connection.invoke("ClearHistory", itemId)["catch"](function (err) {
|
|
2008
|
+
return console.error('Error clearing history:', err);
|
|
2009
|
+
});
|
|
2010
|
+
};
|
|
2011
|
+
if (typeof confirmDialog === 'function') {
|
|
2012
|
+
confirmDialog({
|
|
2013
|
+
title: config.clearHistoryTitle,
|
|
2014
|
+
message: config.clearHistoryMessage,
|
|
2015
|
+
okText: config.clearHistoryOkText,
|
|
2016
|
+
cancelText: config.clearHistoryCancelText,
|
|
2017
|
+
callback: function callback(confirmed) {
|
|
2018
|
+
if (confirmed) {
|
|
2019
|
+
clearHistoryConfirmed();
|
|
1872
2020
|
}
|
|
1873
|
-
self.connection.invoke("ClearHistory", itemId)["catch"](function (err) {
|
|
1874
|
-
return console.error('Error clearing history:', err);
|
|
1875
|
-
});
|
|
1876
2021
|
}
|
|
1877
|
-
}
|
|
1878
|
-
|
|
2022
|
+
});
|
|
2023
|
+
return;
|
|
2024
|
+
}
|
|
2025
|
+
if (window.confirm(config.clearHistoryMessage || 'Clear all messages?')) {
|
|
2026
|
+
clearHistoryConfirmed();
|
|
2027
|
+
}
|
|
1879
2028
|
},
|
|
1880
2029
|
debouncedSaveSettings: function debouncedSaveSettings() {
|
|
1881
|
-
var
|
|
2030
|
+
var _this19 = this;
|
|
1882
2031
|
// Clear any existing timeout to reset the debounce timer
|
|
1883
2032
|
this.clearPendingSettingsSave();
|
|
1884
2033
|
|
|
@@ -1889,11 +2038,11 @@ window.chatInteractionManager = function () {
|
|
|
1889
2038
|
|
|
1890
2039
|
// Set a new timeout to save after 850ms of no changes
|
|
1891
2040
|
this.saveSettingsTimeout = setTimeout(function () {
|
|
1892
|
-
if (
|
|
1893
|
-
|
|
1894
|
-
|
|
2041
|
+
if (_this19.settingsDirty) {
|
|
2042
|
+
_this19.saveSettings();
|
|
2043
|
+
_this19.settingsDirty = false;
|
|
1895
2044
|
}
|
|
1896
|
-
|
|
2045
|
+
_this19.saveSettingsTimeout = null;
|
|
1897
2046
|
}, 850);
|
|
1898
2047
|
},
|
|
1899
2048
|
getSelectedToolNames: function getSelectedToolNames() {
|
|
@@ -1909,7 +2058,7 @@ window.chatInteractionManager = function () {
|
|
|
1909
2058
|
return this.getSelectedGroupValues('agentNames', 'input[type="checkbox"][name$="].IsSelected"][name^="ChatInteraction.Agents["]:checked');
|
|
1910
2059
|
},
|
|
1911
2060
|
saveSettings: function saveSettings() {
|
|
1912
|
-
var
|
|
2061
|
+
var _this20 = this;
|
|
1913
2062
|
var itemId = this.getItemId();
|
|
1914
2063
|
if (!itemId) {
|
|
1915
2064
|
return Promise.resolve();
|
|
@@ -1954,7 +2103,7 @@ window.chatInteractionManager = function () {
|
|
|
1954
2103
|
}
|
|
1955
2104
|
return this.connection.invoke("SaveSettings", itemId, settings)["catch"](function (err) {
|
|
1956
2105
|
console.error('Error saving settings:', err);
|
|
1957
|
-
|
|
2106
|
+
_this20.showSaveIndicator('Save failed', 'text-danger');
|
|
1958
2107
|
});
|
|
1959
2108
|
},
|
|
1960
2109
|
flushPendingSave: function flushPendingSave() {
|
|
@@ -1980,11 +2129,48 @@ window.chatInteractionManager = function () {
|
|
|
1980
2129
|
this.setItemId(itemId);
|
|
1981
2130
|
this.isInteractionStarted = true;
|
|
1982
2131
|
},
|
|
1983
|
-
|
|
1984
|
-
|
|
2132
|
+
clearCopiedMessageState: function clearCopiedMessageState() {
|
|
2133
|
+
if (this.copyResetTimeoutId) {
|
|
2134
|
+
window.clearTimeout(this.copyResetTimeoutId);
|
|
2135
|
+
this.copyResetTimeoutId = null;
|
|
2136
|
+
}
|
|
2137
|
+
if (this.activeCopyButton) {
|
|
2138
|
+
this.setCopyButtonState(this.activeCopyButton, false);
|
|
2139
|
+
this.activeCopyButton = null;
|
|
2140
|
+
}
|
|
2141
|
+
this.copiedMessageIndex = -1;
|
|
2142
|
+
},
|
|
2143
|
+
copyResponse: function copyResponse(message, index, event) {
|
|
2144
|
+
var _ref21,
|
|
2145
|
+
_message$copyContent,
|
|
2146
|
+
_event$target,
|
|
2147
|
+
_event$target$closest,
|
|
2148
|
+
_this21 = this;
|
|
2149
|
+
var text = message && _typeof(message) === 'object' ? (_ref21 = (_message$copyContent = message.copyContent) !== null && _message$copyContent !== void 0 ? _message$copyContent : message.content) !== null && _ref21 !== void 0 ? _ref21 : '' : message !== null && message !== void 0 ? message : '';
|
|
2150
|
+
var button = (event === null || event === void 0 ? void 0 : event.currentTarget) || (event === null || event === void 0 || (_event$target = event.target) === null || _event$target === void 0 || (_event$target$closest = _event$target.closest) === null || _event$target$closest === void 0 ? void 0 : _event$target$closest.call(_event$target, '[data-copy-message-index]')) || null;
|
|
2151
|
+
navigator.clipboard.writeText(text).then(function () {
|
|
2152
|
+
_this21.clearCopiedMessageState();
|
|
2153
|
+
_this21.copiedMessageIndex = typeof index === 'number' ? index : -1;
|
|
2154
|
+
_this21.activeCopyButton = button;
|
|
2155
|
+
if (button) {
|
|
2156
|
+
_this21.setCopyButtonState(button, true);
|
|
2157
|
+
} else {
|
|
2158
|
+
_this21.$nextTick(function () {
|
|
2159
|
+
return _this21.updateCopyButtons();
|
|
2160
|
+
});
|
|
2161
|
+
}
|
|
2162
|
+
_this21.copyResetTimeoutId = window.setTimeout(function () {
|
|
2163
|
+
_this21.clearCopiedMessageState();
|
|
2164
|
+
_this21.$nextTick(function () {
|
|
2165
|
+
return _this21.updateCopyButtons();
|
|
2166
|
+
});
|
|
2167
|
+
}, Number(config.copyResetDelayMs) || 2000);
|
|
2168
|
+
})["catch"](function (err) {
|
|
2169
|
+
return console.error('Failed to copy response:', err);
|
|
2170
|
+
});
|
|
1985
2171
|
},
|
|
1986
2172
|
startRecording: function startRecording() {
|
|
1987
|
-
var
|
|
2173
|
+
var _this22 = this;
|
|
1988
2174
|
if (this.isRecording || !this.connection) {
|
|
1989
2175
|
return;
|
|
1990
2176
|
}
|
|
@@ -1996,16 +2182,16 @@ window.chatInteractionManager = function () {
|
|
|
1996
2182
|
}
|
|
1997
2183
|
}).then(function (stream) {
|
|
1998
2184
|
var mimeType = MediaRecorder.isTypeSupported('audio/ogg;codecs=opus') ? 'audio/ogg;codecs=opus' : MediaRecorder.isTypeSupported('audio/webm;codecs=opus') ? 'audio/webm;codecs=opus' : 'audio/webm';
|
|
1999
|
-
|
|
2185
|
+
_this22.mediaRecorder = new MediaRecorder(stream, {
|
|
2000
2186
|
mimeType: mimeType,
|
|
2001
2187
|
audioBitsPerSecond: 128000
|
|
2002
2188
|
});
|
|
2003
|
-
|
|
2004
|
-
|
|
2189
|
+
_this22.preRecordingPrompt = _this22.prompt;
|
|
2190
|
+
_this22._audioInputSent = false;
|
|
2005
2191
|
var subject = new signalR.Subject();
|
|
2006
|
-
var itemId =
|
|
2192
|
+
var itemId = _this22.getItemId();
|
|
2007
2193
|
var pendingChunk = Promise.resolve();
|
|
2008
|
-
|
|
2194
|
+
_this22.mediaRecorder.addEventListener('dataavailable', function (e) {
|
|
2009
2195
|
if (e.data && e.data.size > 0) {
|
|
2010
2196
|
pendingChunk = pendingChunk.then(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4() {
|
|
2011
2197
|
var data, uint8Array, binaryString, base64;
|
|
@@ -2029,7 +2215,7 @@ window.chatInteractionManager = function () {
|
|
|
2029
2215
|
})));
|
|
2030
2216
|
}
|
|
2031
2217
|
});
|
|
2032
|
-
|
|
2218
|
+
_this22.mediaRecorder.addEventListener('stop', function () {
|
|
2033
2219
|
stream.getTracks().forEach(function (track) {
|
|
2034
2220
|
return track.stop();
|
|
2035
2221
|
});
|
|
@@ -2038,10 +2224,10 @@ window.chatInteractionManager = function () {
|
|
|
2038
2224
|
});
|
|
2039
2225
|
});
|
|
2040
2226
|
var language = navigator.language || document.documentElement.lang || 'en-US';
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2227
|
+
_this22.connection.send("SendAudioStream", itemId, subject, mimeType, language);
|
|
2228
|
+
_this22.mediaRecorder.start(250);
|
|
2229
|
+
_this22.isRecording = true;
|
|
2230
|
+
_this22.updateMicButton();
|
|
2045
2231
|
})["catch"](function (err) {
|
|
2046
2232
|
console.error('Microphone access denied:', err);
|
|
2047
2233
|
});
|
|
@@ -2067,10 +2253,10 @@ window.chatInteractionManager = function () {
|
|
|
2067
2253
|
}
|
|
2068
2254
|
if (this.isRecording) {
|
|
2069
2255
|
this.micButton.classList.add('stt-recording');
|
|
2070
|
-
this.micButton.innerHTML = '<
|
|
2256
|
+
this.micButton.innerHTML = '<i class="fa-solid fa-stop"></i>';
|
|
2071
2257
|
} else {
|
|
2072
2258
|
this.micButton.classList.remove('stt-recording');
|
|
2073
|
-
this.micButton.innerHTML = '<
|
|
2259
|
+
this.micButton.innerHTML = '<i class="fa-solid fa-microphone"></i>';
|
|
2074
2260
|
}
|
|
2075
2261
|
}
|
|
2076
2262
|
},
|
|
@@ -2092,18 +2278,29 @@ window.chatInteractionManager = function () {
|
|
|
2092
2278
|
this.inputElement.placeholder = '';
|
|
2093
2279
|
}
|
|
2094
2280
|
}
|
|
2281
|
+
},
|
|
2282
|
+
copiedMessageIndex: function copiedMessageIndex() {
|
|
2283
|
+
var _this23 = this;
|
|
2284
|
+
this.$nextTick(function () {
|
|
2285
|
+
return _this23.updateCopyButtons();
|
|
2286
|
+
});
|
|
2095
2287
|
}
|
|
2096
2288
|
},
|
|
2097
2289
|
mounted: function mounted() {
|
|
2098
|
-
var
|
|
2290
|
+
var _this24 = this;
|
|
2099
2291
|
_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee5() {
|
|
2100
2292
|
return _regenerator().w(function (_context5) {
|
|
2101
2293
|
while (1) switch (_context5.n) {
|
|
2102
2294
|
case 0:
|
|
2103
2295
|
_context5.n = 1;
|
|
2104
|
-
return
|
|
2296
|
+
return _this24.startConnection();
|
|
2105
2297
|
case 1:
|
|
2106
|
-
|
|
2298
|
+
_this24.initializeApp();
|
|
2299
|
+
_this24.$nextTick(function () {
|
|
2300
|
+
_this24.updateCopyButtons();
|
|
2301
|
+
refreshFontAwesomeIcons(_this24.$el);
|
|
2302
|
+
_this24.fontAwesomeObserver = observeFontAwesomeIcons(_this24.$el);
|
|
2303
|
+
});
|
|
2107
2304
|
case 2:
|
|
2108
2305
|
return _context5.a(2);
|
|
2109
2306
|
}
|
|
@@ -2115,6 +2312,11 @@ window.chatInteractionManager = function () {
|
|
|
2115
2312
|
beforeUnmount: function beforeUnmount() {
|
|
2116
2313
|
window.removeEventListener('beforeunload', this.handleBeforeUnload);
|
|
2117
2314
|
window.removeEventListener('crestapps-ai-chat-stop-tts', this.handleExternalTtsStop);
|
|
2315
|
+
if (this.fontAwesomeObserver) {
|
|
2316
|
+
this.fontAwesomeObserver.disconnect();
|
|
2317
|
+
this.fontAwesomeObserver = null;
|
|
2318
|
+
}
|
|
2319
|
+
this.clearCopiedMessageState();
|
|
2118
2320
|
this.stopAudio(false);
|
|
2119
2321
|
if (this.stream) {
|
|
2120
2322
|
this.stream.dispose();
|
|
@@ -2128,8 +2330,666 @@ window.chatInteractionManager = function () {
|
|
|
2128
2330
|
}).mount(config.appElementSelector);
|
|
2129
2331
|
return app;
|
|
2130
2332
|
};
|
|
2333
|
+
var autoInitializeSelector = '[data-chat-interaction-config]';
|
|
2334
|
+
function parseJsonAttribute(element, attributeName, description) {
|
|
2335
|
+
var rawValue = element.getAttribute(attributeName);
|
|
2336
|
+
if (!rawValue) {
|
|
2337
|
+
return null;
|
|
2338
|
+
}
|
|
2339
|
+
try {
|
|
2340
|
+
return JSON.parse(rawValue);
|
|
2341
|
+
} catch (error) {
|
|
2342
|
+
console.error('Failed to parse ' + description + ' JSON.', error);
|
|
2343
|
+
return null;
|
|
2344
|
+
}
|
|
2345
|
+
}
|
|
2346
|
+
function initializeFromElement(element) {
|
|
2347
|
+
if (!element || element.dataset.chatInteractionInitialized === 'true') {
|
|
2348
|
+
return element ? element.__chatInteractionApp || null : null;
|
|
2349
|
+
}
|
|
2350
|
+
var config = parseJsonAttribute(element, 'data-chat-interaction-config', 'chat interaction config');
|
|
2351
|
+
if (!config) {
|
|
2352
|
+
return null;
|
|
2353
|
+
}
|
|
2354
|
+
var app = initialize(config);
|
|
2355
|
+
if (!app) {
|
|
2356
|
+
return null;
|
|
2357
|
+
}
|
|
2358
|
+
element.dataset.chatInteractionInitialized = 'true';
|
|
2359
|
+
element.__chatInteractionApp = app;
|
|
2360
|
+
return app;
|
|
2361
|
+
}
|
|
2362
|
+
function scanForAutoInitialization(root) {
|
|
2363
|
+
if (!root || typeof root.querySelectorAll !== 'function') {
|
|
2364
|
+
return;
|
|
2365
|
+
}
|
|
2366
|
+
if (typeof root.matches === 'function' && root.matches(autoInitializeSelector)) {
|
|
2367
|
+
initializeFromElement(root);
|
|
2368
|
+
}
|
|
2369
|
+
root.querySelectorAll(autoInitializeSelector).forEach(initializeFromElement);
|
|
2370
|
+
}
|
|
2371
|
+
function startAutoInitialization() {
|
|
2372
|
+
scanForAutoInitialization(document);
|
|
2373
|
+
if (typeof MutationObserver === 'undefined') {
|
|
2374
|
+
return;
|
|
2375
|
+
}
|
|
2376
|
+
var observer = new MutationObserver(function (mutations) {
|
|
2377
|
+
mutations.forEach(function (mutation) {
|
|
2378
|
+
mutation.addedNodes.forEach(function (node) {
|
|
2379
|
+
if (node && node.nodeType === 1) {
|
|
2380
|
+
scanForAutoInitialization(node);
|
|
2381
|
+
}
|
|
2382
|
+
});
|
|
2383
|
+
});
|
|
2384
|
+
});
|
|
2385
|
+
observer.observe(document.body, {
|
|
2386
|
+
childList: true,
|
|
2387
|
+
subtree: true
|
|
2388
|
+
});
|
|
2389
|
+
}
|
|
2390
|
+
if (document.readyState === 'loading') {
|
|
2391
|
+
document.addEventListener('DOMContentLoaded', startAutoInitialization, {
|
|
2392
|
+
once: true
|
|
2393
|
+
});
|
|
2394
|
+
} else {
|
|
2395
|
+
startAutoInitialization();
|
|
2396
|
+
}
|
|
2397
|
+
return {
|
|
2398
|
+
initialize: initialize,
|
|
2399
|
+
initializeFromElement: initializeFromElement
|
|
2400
|
+
};
|
|
2401
|
+
}();
|
|
2402
|
+
window.chatInteractionDocumentManager = function () {
|
|
2403
|
+
var managerStateKey = '__chatInteractionDocumentManagerState';
|
|
2404
|
+
function normalizeDocumentInfo(document) {
|
|
2405
|
+
if (!document || _typeof(document) !== 'object') {
|
|
2406
|
+
return null;
|
|
2407
|
+
}
|
|
2408
|
+
return {
|
|
2409
|
+
documentId: document.documentId || document.DocumentId || '',
|
|
2410
|
+
fileName: document.fileName || document.FileName || '',
|
|
2411
|
+
fileSize: document.fileSize || document.FileSize || 0
|
|
2412
|
+
};
|
|
2413
|
+
}
|
|
2414
|
+
function formatFileSize(bytes) {
|
|
2415
|
+
if (!bytes || bytes < 1024) {
|
|
2416
|
+
return (bytes || 0) + ' B';
|
|
2417
|
+
}
|
|
2418
|
+
if (bytes < 1024 * 1024) {
|
|
2419
|
+
return (bytes / 1024).toFixed(1) + ' KB';
|
|
2420
|
+
}
|
|
2421
|
+
return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
|
|
2422
|
+
}
|
|
2423
|
+
function getDocumentKey(fileName, fileSize) {
|
|
2424
|
+
return (fileName || '').trim().toLowerCase() + '::' + (fileSize || 0);
|
|
2425
|
+
}
|
|
2426
|
+
function isDuplicateFile(file, knownKeys) {
|
|
2427
|
+
return knownKeys.has(getDocumentKey(file.name, file.size));
|
|
2428
|
+
}
|
|
2429
|
+
function getDocumentsFromDom(container) {
|
|
2430
|
+
if (!container) {
|
|
2431
|
+
return [];
|
|
2432
|
+
}
|
|
2433
|
+
return Array.from(container.querySelectorAll('[data-chat-document-id]')).map(function (element) {
|
|
2434
|
+
return normalizeDocumentInfo({
|
|
2435
|
+
documentId: element.dataset.chatDocumentId,
|
|
2436
|
+
fileName: element.dataset.chatDocumentName,
|
|
2437
|
+
fileSize: Number(element.dataset.chatDocumentSize || 0)
|
|
2438
|
+
});
|
|
2439
|
+
}).filter(function (document) {
|
|
2440
|
+
return document && document.documentId;
|
|
2441
|
+
});
|
|
2442
|
+
}
|
|
2443
|
+
function initialize(config) {
|
|
2444
|
+
if (!config || !config.itemId) {
|
|
2445
|
+
return;
|
|
2446
|
+
}
|
|
2447
|
+
var fileInput = document.getElementById('chat-doc-upload');
|
|
2448
|
+
var documentsList = document.getElementById('chat-documents-list');
|
|
2449
|
+
var status = document.getElementById('chat-doc-upload-status');
|
|
2450
|
+
var progressContainer = document.getElementById('chat-doc-upload-progress');
|
|
2451
|
+
var progressBar = document.getElementById('chat-doc-upload-progress-bar');
|
|
2452
|
+
var uploadQueue = document.getElementById('chat-doc-upload-queue');
|
|
2453
|
+
if (!fileInput || !documentsList || !status || !progressContainer || !progressBar || !uploadQueue) {
|
|
2454
|
+
return;
|
|
2455
|
+
}
|
|
2456
|
+
var previousState = fileInput[managerStateKey];
|
|
2457
|
+
if (previousState && typeof previousState.dispose === 'function') {
|
|
2458
|
+
previousState.dispose();
|
|
2459
|
+
}
|
|
2460
|
+
var interactionDocuments = (Array.isArray(config.existingDocuments) ? config.existingDocuments : []).map(normalizeDocumentInfo).filter(function (document) {
|
|
2461
|
+
return document && document.documentId;
|
|
2462
|
+
});
|
|
2463
|
+
if (interactionDocuments.length === 0) {
|
|
2464
|
+
interactionDocuments = getDocumentsFromDom(documentsList);
|
|
2465
|
+
}
|
|
2466
|
+
var uploadItems = [];
|
|
2467
|
+
var isUploadingDocuments = false;
|
|
2468
|
+
function createTextElement(tagName, className, text) {
|
|
2469
|
+
var element = document.createElement(tagName);
|
|
2470
|
+
if (className) {
|
|
2471
|
+
element.className = className;
|
|
2472
|
+
}
|
|
2473
|
+
element.textContent = text;
|
|
2474
|
+
return element;
|
|
2475
|
+
}
|
|
2476
|
+
function renderDocuments() {
|
|
2477
|
+
documentsList.innerHTML = '';
|
|
2478
|
+
if (interactionDocuments.length === 0) {
|
|
2479
|
+
documentsList.appendChild(createTextElement('div', 'text-muted small', 'No documents uploaded yet.'));
|
|
2480
|
+
return;
|
|
2481
|
+
}
|
|
2482
|
+
interactionDocuments.forEach(function (documentInfo) {
|
|
2483
|
+
var row = window.document.createElement('div');
|
|
2484
|
+
row.className = 'd-flex justify-content-between align-items-start gap-2 border rounded px-2 py-2 bg-white chat-document-row';
|
|
2485
|
+
row.dataset.chatDocumentId = documentInfo.documentId;
|
|
2486
|
+
row.dataset.chatDocumentName = documentInfo.fileName;
|
|
2487
|
+
row.dataset.chatDocumentSize = documentInfo.fileSize;
|
|
2488
|
+
var details = window.document.createElement('div');
|
|
2489
|
+
details.className = 'me-2 min-w-0';
|
|
2490
|
+
var name = createTextElement('div', 'fw-semibold small', documentInfo.fileName || 'Document');
|
|
2491
|
+
var icon = window.document.createElement('i');
|
|
2492
|
+
icon.className = 'bi bi-file-earmark-text me-1';
|
|
2493
|
+
name.prepend(icon);
|
|
2494
|
+
var size = createTextElement('div', 'text-muted small', formatFileSize(documentInfo.fileSize));
|
|
2495
|
+
details.appendChild(name);
|
|
2496
|
+
details.appendChild(size);
|
|
2497
|
+
var removeButton = createTextElement('button', 'btn btn-sm btn-outline-danger remove-chat-document-btn', ' Remove');
|
|
2498
|
+
removeButton.type = 'button';
|
|
2499
|
+
removeButton.dataset.documentId = documentInfo.documentId;
|
|
2500
|
+
var removeIcon = window.document.createElement('i');
|
|
2501
|
+
removeIcon.className = 'bi bi-trash';
|
|
2502
|
+
removeButton.prepend(removeIcon);
|
|
2503
|
+
removeButton.addEventListener('click', function () {
|
|
2504
|
+
return removeDocument(documentInfo.documentId);
|
|
2505
|
+
});
|
|
2506
|
+
row.appendChild(details);
|
|
2507
|
+
row.appendChild(removeButton);
|
|
2508
|
+
documentsList.appendChild(row);
|
|
2509
|
+
});
|
|
2510
|
+
}
|
|
2511
|
+
function showUploadStatus(message, cssClass) {
|
|
2512
|
+
if (!message) {
|
|
2513
|
+
status.textContent = '';
|
|
2514
|
+
status.className = 'small mt-2 d-none';
|
|
2515
|
+
return;
|
|
2516
|
+
}
|
|
2517
|
+
status.textContent = message;
|
|
2518
|
+
status.className = 'small mt-2 ' + (cssClass || 'text-muted');
|
|
2519
|
+
}
|
|
2520
|
+
function showUploadProgress(progress, message, cssClass) {
|
|
2521
|
+
if (progress === null || progress === undefined) {
|
|
2522
|
+
progressContainer.className = 'progress mt-2 d-none';
|
|
2523
|
+
progressContainer.setAttribute('aria-valuenow', '0');
|
|
2524
|
+
progressBar.className = 'progress-bar progress-bar-striped progress-bar-animated';
|
|
2525
|
+
progressBar.style.width = '0%';
|
|
2526
|
+
progressBar.textContent = '0%';
|
|
2527
|
+
return;
|
|
2528
|
+
}
|
|
2529
|
+
var roundedProgress = Math.max(0, Math.min(100, Math.round(progress)));
|
|
2530
|
+
progressContainer.className = 'progress mt-2';
|
|
2531
|
+
progressContainer.setAttribute('aria-valuenow', roundedProgress.toString());
|
|
2532
|
+
progressBar.className = 'progress-bar ' + (cssClass || 'progress-bar-striped progress-bar-animated');
|
|
2533
|
+
progressBar.style.width = roundedProgress + '%';
|
|
2534
|
+
progressBar.textContent = message || roundedProgress + '%';
|
|
2535
|
+
}
|
|
2536
|
+
function getUploadStatePresentation(state) {
|
|
2537
|
+
switch (state) {
|
|
2538
|
+
case 'uploaded':
|
|
2539
|
+
return {
|
|
2540
|
+
label: 'Uploaded',
|
|
2541
|
+
badgeClass: 'text-bg-success',
|
|
2542
|
+
progressClass: 'bg-success'
|
|
2543
|
+
};
|
|
2544
|
+
case 'failed':
|
|
2545
|
+
return {
|
|
2546
|
+
label: 'Failed',
|
|
2547
|
+
badgeClass: 'text-bg-danger',
|
|
2548
|
+
progressClass: 'bg-danger'
|
|
2549
|
+
};
|
|
2550
|
+
case 'uploading':
|
|
2551
|
+
return {
|
|
2552
|
+
label: 'Uploading',
|
|
2553
|
+
badgeClass: 'text-bg-warning',
|
|
2554
|
+
progressClass: 'bg-warning progress-bar-striped progress-bar-animated'
|
|
2555
|
+
};
|
|
2556
|
+
default:
|
|
2557
|
+
return {
|
|
2558
|
+
label: 'Queued',
|
|
2559
|
+
badgeClass: 'text-bg-secondary',
|
|
2560
|
+
progressClass: 'bg-secondary progress-bar-striped progress-bar-animated'
|
|
2561
|
+
};
|
|
2562
|
+
}
|
|
2563
|
+
}
|
|
2564
|
+
function formatUploadMessage(item) {
|
|
2565
|
+
if (item.status === 'failed' && item.error) {
|
|
2566
|
+
return item.error;
|
|
2567
|
+
}
|
|
2568
|
+
if (item.status === 'uploaded') {
|
|
2569
|
+
return 'Upload completed successfully.';
|
|
2570
|
+
}
|
|
2571
|
+
if (item.status === 'uploading') {
|
|
2572
|
+
return item.progress + '% uploaded';
|
|
2573
|
+
}
|
|
2574
|
+
return 'Waiting to upload...';
|
|
2575
|
+
}
|
|
2576
|
+
function renderUploadQueue() {
|
|
2577
|
+
uploadQueue.innerHTML = '';
|
|
2578
|
+
uploadItems.forEach(function (item) {
|
|
2579
|
+
var presentation = getUploadStatePresentation(item.status);
|
|
2580
|
+
var card = document.createElement('div');
|
|
2581
|
+
card.className = 'border rounded px-2 py-2 bg-white';
|
|
2582
|
+
var header = document.createElement('div');
|
|
2583
|
+
header.className = 'd-flex justify-content-between align-items-start gap-2';
|
|
2584
|
+
var fileDetails = document.createElement('div');
|
|
2585
|
+
fileDetails.className = 'flex-grow-1 min-w-0';
|
|
2586
|
+
fileDetails.appendChild(createTextElement('div', 'fw-semibold small', item.fileName));
|
|
2587
|
+
fileDetails.appendChild(createTextElement('div', 'text-muted small', formatFileSize(item.fileSize)));
|
|
2588
|
+
var badge = createTextElement('span', 'badge ' + presentation.badgeClass, presentation.label);
|
|
2589
|
+
header.appendChild(fileDetails);
|
|
2590
|
+
header.appendChild(badge);
|
|
2591
|
+
var progress = document.createElement('div');
|
|
2592
|
+
progress.className = 'progress mt-2';
|
|
2593
|
+
progress.setAttribute('role', 'progressbar');
|
|
2594
|
+
progress.setAttribute('aria-valuemin', '0');
|
|
2595
|
+
progress.setAttribute('aria-valuemax', '100');
|
|
2596
|
+
progress.setAttribute('aria-valuenow', item.progress.toString());
|
|
2597
|
+
var progressState = document.createElement('div');
|
|
2598
|
+
progressState.className = 'progress-bar ' + presentation.progressClass;
|
|
2599
|
+
progressState.style.width = item.progress + '%';
|
|
2600
|
+
progressState.textContent = item.progress + '%';
|
|
2601
|
+
progress.appendChild(progressState);
|
|
2602
|
+
var message = createTextElement('div', item.status === 'failed' ? 'small text-danger mt-2' : 'small text-muted mt-2', formatUploadMessage(item));
|
|
2603
|
+
card.appendChild(header);
|
|
2604
|
+
card.appendChild(progress);
|
|
2605
|
+
card.appendChild(message);
|
|
2606
|
+
uploadQueue.appendChild(card);
|
|
2607
|
+
});
|
|
2608
|
+
}
|
|
2609
|
+
function createUploadItem(file, index) {
|
|
2610
|
+
return {
|
|
2611
|
+
id: file.name + '::' + file.size + '::' + file.lastModified + '::' + index + '::' + Date.now(),
|
|
2612
|
+
fileName: file.name,
|
|
2613
|
+
fileSize: file.size,
|
|
2614
|
+
status: 'queued',
|
|
2615
|
+
progress: 0,
|
|
2616
|
+
error: null
|
|
2617
|
+
};
|
|
2618
|
+
}
|
|
2619
|
+
function updateUploadItem(itemId, updates) {
|
|
2620
|
+
uploadItems = uploadItems.map(function (item) {
|
|
2621
|
+
return item.id === itemId ? Object.assign({}, item, updates) : item;
|
|
2622
|
+
});
|
|
2623
|
+
renderUploadQueue();
|
|
2624
|
+
}
|
|
2625
|
+
function removeUploadItems(predicate) {
|
|
2626
|
+
uploadItems = uploadItems.filter(function (item) {
|
|
2627
|
+
return !predicate(item);
|
|
2628
|
+
});
|
|
2629
|
+
renderUploadQueue();
|
|
2630
|
+
}
|
|
2631
|
+
function uploadSingleDocument(file, itemIdToUpdate, fileIndex, totalFiles) {
|
|
2632
|
+
return new Promise(function (resolve, reject) {
|
|
2633
|
+
var formData = new FormData();
|
|
2634
|
+
formData.append('chatInteractionId', config.itemId);
|
|
2635
|
+
formData.append('files', file);
|
|
2636
|
+
var xhr = new XMLHttpRequest();
|
|
2637
|
+
xhr.open('POST', config.uploadDocumentUrl, true);
|
|
2638
|
+
xhr.upload.addEventListener('progress', function (event) {
|
|
2639
|
+
if (!event.lengthComputable) {
|
|
2640
|
+
return;
|
|
2641
|
+
}
|
|
2642
|
+
var fileProgress = Math.round(event.loaded / event.total * 100);
|
|
2643
|
+
updateUploadItem(itemIdToUpdate, {
|
|
2644
|
+
status: 'uploading',
|
|
2645
|
+
progress: fileProgress
|
|
2646
|
+
});
|
|
2647
|
+
var overallProgress = (fileIndex + event.loaded / event.total) / totalFiles * 100;
|
|
2648
|
+
showUploadProgress(overallProgress, 'Uploading ' + (fileIndex + 1) + ' of ' + totalFiles, 'progress-bar-striped progress-bar-animated');
|
|
2649
|
+
});
|
|
2650
|
+
xhr.addEventListener('load', function () {
|
|
2651
|
+
if (xhr.status >= 200 && xhr.status < 300) {
|
|
2652
|
+
try {
|
|
2653
|
+
resolve(JSON.parse(xhr.responseText));
|
|
2654
|
+
} catch (error) {
|
|
2655
|
+
reject(new Error('Upload failed: invalid server response.'));
|
|
2656
|
+
}
|
|
2657
|
+
return;
|
|
2658
|
+
}
|
|
2659
|
+
reject(new Error((xhr.responseText || 'Upload failed.').trim()));
|
|
2660
|
+
});
|
|
2661
|
+
xhr.addEventListener('error', function () {
|
|
2662
|
+
reject(new Error('Upload failed. Please check your connection and try again.'));
|
|
2663
|
+
});
|
|
2664
|
+
xhr.send(formData);
|
|
2665
|
+
});
|
|
2666
|
+
}
|
|
2667
|
+
function uploadDocuments(_x) {
|
|
2668
|
+
return _uploadDocuments.apply(this, arguments);
|
|
2669
|
+
}
|
|
2670
|
+
function _uploadDocuments() {
|
|
2671
|
+
_uploadDocuments = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee6(files) {
|
|
2672
|
+
var filesToUpload, duplicateItems, knownDocumentKeys, pendingItems, uploadedCount, failedUploads, i, file, pendingItem, result, uploaded, failed, missingUploadMessage, failedMessage, errorMessage, _t2, _t3;
|
|
2673
|
+
return _regenerator().w(function (_context6) {
|
|
2674
|
+
while (1) switch (_context6.p = _context6.n) {
|
|
2675
|
+
case 0:
|
|
2676
|
+
if (!(!config.uploadDocumentUrl || !files || files.length === 0)) {
|
|
2677
|
+
_context6.n = 1;
|
|
2678
|
+
break;
|
|
2679
|
+
}
|
|
2680
|
+
return _context6.a(2);
|
|
2681
|
+
case 1:
|
|
2682
|
+
if (!isUploadingDocuments) {
|
|
2683
|
+
_context6.n = 2;
|
|
2684
|
+
break;
|
|
2685
|
+
}
|
|
2686
|
+
showUploadStatus('A document upload is already in progress.', 'text-warning');
|
|
2687
|
+
return _context6.a(2);
|
|
2688
|
+
case 2:
|
|
2689
|
+
isUploadingDocuments = true;
|
|
2690
|
+
filesToUpload = [];
|
|
2691
|
+
duplicateItems = [];
|
|
2692
|
+
knownDocumentKeys = new Set(interactionDocuments.map(function (document) {
|
|
2693
|
+
return getDocumentKey(document.fileName, document.fileSize);
|
|
2694
|
+
}));
|
|
2695
|
+
Array.from(files).forEach(function (file) {
|
|
2696
|
+
if (isDuplicateFile(file, knownDocumentKeys)) {
|
|
2697
|
+
duplicateItems.push(file);
|
|
2698
|
+
return;
|
|
2699
|
+
}
|
|
2700
|
+
knownDocumentKeys.add(getDocumentKey(file.name, file.size));
|
|
2701
|
+
filesToUpload.push(file);
|
|
2702
|
+
});
|
|
2703
|
+
if (duplicateItems.length > 0) {
|
|
2704
|
+
uploadItems = uploadItems.concat(duplicateItems.map(function (file, index) {
|
|
2705
|
+
return Object.assign(createUploadItem(file, index), {
|
|
2706
|
+
status: 'failed',
|
|
2707
|
+
progress: 100,
|
|
2708
|
+
error: 'This document is already attached.'
|
|
2709
|
+
});
|
|
2710
|
+
}));
|
|
2711
|
+
renderUploadQueue();
|
|
2712
|
+
}
|
|
2713
|
+
if (!(filesToUpload.length === 0)) {
|
|
2714
|
+
_context6.n = 3;
|
|
2715
|
+
break;
|
|
2716
|
+
}
|
|
2717
|
+
isUploadingDocuments = false;
|
|
2718
|
+
showUploadStatus(duplicateItems.map(function (file) {
|
|
2719
|
+
return file.name + ': This document is already attached.';
|
|
2720
|
+
}).join(' | '), 'text-warning');
|
|
2721
|
+
showUploadProgress(null);
|
|
2722
|
+
return _context6.a(2);
|
|
2723
|
+
case 3:
|
|
2724
|
+
pendingItems = filesToUpload.map(createUploadItem);
|
|
2725
|
+
uploadItems = uploadItems.concat(pendingItems);
|
|
2726
|
+
renderUploadQueue();
|
|
2727
|
+
showUploadProgress(0, 'Preparing upload...', 'progress-bar-striped progress-bar-animated');
|
|
2728
|
+
fileInput.disabled = true;
|
|
2729
|
+
_context6.p = 4;
|
|
2730
|
+
uploadedCount = 0;
|
|
2731
|
+
failedUploads = duplicateItems.map(function (file) {
|
|
2732
|
+
return file.name + ': This document is already attached.';
|
|
2733
|
+
});
|
|
2734
|
+
i = 0;
|
|
2735
|
+
case 5:
|
|
2736
|
+
if (!(i < filesToUpload.length)) {
|
|
2737
|
+
_context6.n = 10;
|
|
2738
|
+
break;
|
|
2739
|
+
}
|
|
2740
|
+
file = filesToUpload[i];
|
|
2741
|
+
pendingItem = pendingItems[i];
|
|
2742
|
+
updateUploadItem(pendingItem.id, {
|
|
2743
|
+
status: 'uploading',
|
|
2744
|
+
progress: 0,
|
|
2745
|
+
error: null
|
|
2746
|
+
});
|
|
2747
|
+
showUploadStatus('Uploading ' + (i + 1) + ' of ' + filesToUpload.length + ' document(s)...', 'text-warning');
|
|
2748
|
+
_context6.p = 6;
|
|
2749
|
+
_context6.n = 7;
|
|
2750
|
+
return uploadSingleDocument(file, pendingItem.id, i, filesToUpload.length);
|
|
2751
|
+
case 7:
|
|
2752
|
+
result = _context6.v;
|
|
2753
|
+
uploaded = (Array.isArray(result.uploaded) ? result.uploaded : []).map(normalizeDocumentInfo).filter(function (document) {
|
|
2754
|
+
return document && document.documentId;
|
|
2755
|
+
});
|
|
2756
|
+
failed = Array.isArray(result.failed) ? result.failed : [];
|
|
2757
|
+
if (uploaded.length > 0) {
|
|
2758
|
+
uploadedCount += uploaded.length;
|
|
2759
|
+
interactionDocuments = interactionDocuments.concat(uploaded);
|
|
2760
|
+
updateUploadItem(pendingItem.id, {
|
|
2761
|
+
status: 'uploaded',
|
|
2762
|
+
progress: 100,
|
|
2763
|
+
error: null
|
|
2764
|
+
});
|
|
2765
|
+
} else {
|
|
2766
|
+
missingUploadMessage = failed.length > 0 ? failed.map(function (entry) {
|
|
2767
|
+
return entry.fileName + ': ' + entry.error;
|
|
2768
|
+
}).join(' | ') : 'The server did not confirm that the file was uploaded.';
|
|
2769
|
+
if (failed.length === 0) {
|
|
2770
|
+
failedUploads.push(missingUploadMessage);
|
|
2771
|
+
}
|
|
2772
|
+
updateUploadItem(pendingItem.id, {
|
|
2773
|
+
status: 'failed',
|
|
2774
|
+
progress: 100,
|
|
2775
|
+
error: missingUploadMessage
|
|
2776
|
+
});
|
|
2777
|
+
}
|
|
2778
|
+
if (failed.length > 0) {
|
|
2779
|
+
failedMessage = failed.map(function (entry) {
|
|
2780
|
+
return entry.fileName + ': ' + entry.error;
|
|
2781
|
+
}).join(' | ');
|
|
2782
|
+
failedUploads.push(failedMessage);
|
|
2783
|
+
updateUploadItem(pendingItem.id, {
|
|
2784
|
+
status: 'failed',
|
|
2785
|
+
progress: 100,
|
|
2786
|
+
error: failedMessage
|
|
2787
|
+
});
|
|
2788
|
+
}
|
|
2789
|
+
_context6.n = 9;
|
|
2790
|
+
break;
|
|
2791
|
+
case 8:
|
|
2792
|
+
_context6.p = 8;
|
|
2793
|
+
_t2 = _context6.v;
|
|
2794
|
+
errorMessage = _t2 && _t2.message ? _t2.message : 'Upload failed. Please try again.';
|
|
2795
|
+
console.error('Upload failed:', _t2);
|
|
2796
|
+
failedUploads.push(file.name + ': ' + errorMessage);
|
|
2797
|
+
updateUploadItem(pendingItem.id, {
|
|
2798
|
+
status: 'failed',
|
|
2799
|
+
progress: pendingItem.progress || 0,
|
|
2800
|
+
error: errorMessage
|
|
2801
|
+
});
|
|
2802
|
+
case 9:
|
|
2803
|
+
i++;
|
|
2804
|
+
_context6.n = 5;
|
|
2805
|
+
break;
|
|
2806
|
+
case 10:
|
|
2807
|
+
renderDocuments();
|
|
2808
|
+
if (!(failedUploads.length > 0)) {
|
|
2809
|
+
_context6.n = 11;
|
|
2810
|
+
break;
|
|
2811
|
+
}
|
|
2812
|
+
removeUploadItems(function (item) {
|
|
2813
|
+
return item.status === 'uploaded';
|
|
2814
|
+
});
|
|
2815
|
+
showUploadStatus((uploadedCount > 0 ? 'Uploaded ' + uploadedCount + ' document(s). ' : '') + failedUploads.join(' | '), uploadedCount > 0 ? 'text-warning' : 'text-danger');
|
|
2816
|
+
showUploadProgress(null);
|
|
2817
|
+
return _context6.a(2);
|
|
2818
|
+
case 11:
|
|
2819
|
+
removeUploadItems(function () {
|
|
2820
|
+
return true;
|
|
2821
|
+
});
|
|
2822
|
+
showUploadStatus('Uploaded ' + uploadedCount + ' document(s).', 'text-success');
|
|
2823
|
+
showUploadProgress(null);
|
|
2824
|
+
_context6.n = 13;
|
|
2825
|
+
break;
|
|
2826
|
+
case 12:
|
|
2827
|
+
_context6.p = 12;
|
|
2828
|
+
_t3 = _context6.v;
|
|
2829
|
+
console.error('Upload failed:', _t3);
|
|
2830
|
+
showUploadStatus('Upload failed. Please try again.', 'text-danger');
|
|
2831
|
+
showUploadProgress(null);
|
|
2832
|
+
case 13:
|
|
2833
|
+
_context6.p = 13;
|
|
2834
|
+
isUploadingDocuments = false;
|
|
2835
|
+
fileInput.disabled = false;
|
|
2836
|
+
fileInput.value = '';
|
|
2837
|
+
return _context6.f(13);
|
|
2838
|
+
case 14:
|
|
2839
|
+
return _context6.a(2);
|
|
2840
|
+
}
|
|
2841
|
+
}, _callee6, null, [[6, 8], [4, 12, 13, 14]]);
|
|
2842
|
+
}));
|
|
2843
|
+
return _uploadDocuments.apply(this, arguments);
|
|
2844
|
+
}
|
|
2845
|
+
function removeDocument(_x2) {
|
|
2846
|
+
return _removeDocument.apply(this, arguments);
|
|
2847
|
+
}
|
|
2848
|
+
function _removeDocument() {
|
|
2849
|
+
_removeDocument = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee7(documentId) {
|
|
2850
|
+
var response, result, serverDocuments, _t4, _t5;
|
|
2851
|
+
return _regenerator().w(function (_context7) {
|
|
2852
|
+
while (1) switch (_context7.p = _context7.n) {
|
|
2853
|
+
case 0:
|
|
2854
|
+
if (!(!config.removeDocumentUrl || !documentId || !window.confirm('Remove this document?'))) {
|
|
2855
|
+
_context7.n = 1;
|
|
2856
|
+
break;
|
|
2857
|
+
}
|
|
2858
|
+
return _context7.a(2);
|
|
2859
|
+
case 1:
|
|
2860
|
+
_context7.p = 1;
|
|
2861
|
+
_context7.n = 2;
|
|
2862
|
+
return fetch(config.removeDocumentUrl, {
|
|
2863
|
+
method: 'POST',
|
|
2864
|
+
headers: {
|
|
2865
|
+
'Content-Type': 'application/json'
|
|
2866
|
+
},
|
|
2867
|
+
body: JSON.stringify({
|
|
2868
|
+
itemId: config.itemId,
|
|
2869
|
+
documentId: documentId
|
|
2870
|
+
})
|
|
2871
|
+
});
|
|
2872
|
+
case 2:
|
|
2873
|
+
response = _context7.v;
|
|
2874
|
+
if (response.ok) {
|
|
2875
|
+
_context7.n = 4;
|
|
2876
|
+
break;
|
|
2877
|
+
}
|
|
2878
|
+
_t4 = console;
|
|
2879
|
+
_context7.n = 3;
|
|
2880
|
+
return response.text();
|
|
2881
|
+
case 3:
|
|
2882
|
+
_t4.error.call(_t4, 'Failed to remove document:', _context7.v);
|
|
2883
|
+
showUploadStatus('Failed to remove document.', 'text-danger');
|
|
2884
|
+
return _context7.a(2);
|
|
2885
|
+
case 4:
|
|
2886
|
+
_context7.n = 5;
|
|
2887
|
+
return response.json();
|
|
2888
|
+
case 5:
|
|
2889
|
+
result = _context7.v;
|
|
2890
|
+
serverDocuments = (Array.isArray(result.documents) ? result.documents : []).map(normalizeDocumentInfo).filter(function (document) {
|
|
2891
|
+
return document && document.documentId;
|
|
2892
|
+
});
|
|
2893
|
+
interactionDocuments = serverDocuments.length > 0 ? serverDocuments : interactionDocuments.filter(function (document) {
|
|
2894
|
+
return document.documentId !== documentId;
|
|
2895
|
+
});
|
|
2896
|
+
renderDocuments();
|
|
2897
|
+
showUploadStatus('Document removed.', 'text-success');
|
|
2898
|
+
_context7.n = 7;
|
|
2899
|
+
break;
|
|
2900
|
+
case 6:
|
|
2901
|
+
_context7.p = 6;
|
|
2902
|
+
_t5 = _context7.v;
|
|
2903
|
+
console.error('Remove failed:', _t5);
|
|
2904
|
+
showUploadStatus('Failed to remove document.', 'text-danger');
|
|
2905
|
+
case 7:
|
|
2906
|
+
return _context7.a(2);
|
|
2907
|
+
}
|
|
2908
|
+
}, _callee7, null, [[1, 6]]);
|
|
2909
|
+
}));
|
|
2910
|
+
return _removeDocument.apply(this, arguments);
|
|
2911
|
+
}
|
|
2912
|
+
var onFileInputChange = function onFileInputChange(event) {
|
|
2913
|
+
var selectedFiles = event.target.files ? Array.from(event.target.files) : [];
|
|
2914
|
+
uploadDocuments(selectedFiles);
|
|
2915
|
+
};
|
|
2916
|
+
fileInput.addEventListener('change', onFileInputChange);
|
|
2917
|
+
fileInput[managerStateKey] = {
|
|
2918
|
+
dispose: function dispose() {
|
|
2919
|
+
fileInput.removeEventListener('change', onFileInputChange);
|
|
2920
|
+
}
|
|
2921
|
+
};
|
|
2922
|
+
renderDocuments();
|
|
2923
|
+
renderUploadQueue();
|
|
2924
|
+
showUploadStatus(null);
|
|
2925
|
+
showUploadProgress(null);
|
|
2926
|
+
return fileInput[managerStateKey];
|
|
2927
|
+
}
|
|
2928
|
+
function parseJsonAttribute(element, attributeName, description) {
|
|
2929
|
+
var rawValue = element.getAttribute(attributeName);
|
|
2930
|
+
if (!rawValue) {
|
|
2931
|
+
return null;
|
|
2932
|
+
}
|
|
2933
|
+
try {
|
|
2934
|
+
return JSON.parse(rawValue);
|
|
2935
|
+
} catch (error) {
|
|
2936
|
+
console.error('Failed to parse ' + description + ' JSON.', error);
|
|
2937
|
+
return null;
|
|
2938
|
+
}
|
|
2939
|
+
}
|
|
2940
|
+
function initializeFromElement(element) {
|
|
2941
|
+
if (!element || element.dataset.chatInteractionDocumentManagerInitialized === 'true') {
|
|
2942
|
+
return element ? element[managerStateKey] || null : null;
|
|
2943
|
+
}
|
|
2944
|
+
var config = parseJsonAttribute(element, 'data-chat-interaction-document-manager-config', 'chat interaction document manager config');
|
|
2945
|
+
if (!config) {
|
|
2946
|
+
return null;
|
|
2947
|
+
}
|
|
2948
|
+
var state = initialize(config);
|
|
2949
|
+
if (!state) {
|
|
2950
|
+
return null;
|
|
2951
|
+
}
|
|
2952
|
+
element.dataset.chatInteractionDocumentManagerInitialized = 'true';
|
|
2953
|
+
return state;
|
|
2954
|
+
}
|
|
2955
|
+
function scanForAutoInitialization(root) {
|
|
2956
|
+
if (!root || typeof root.querySelectorAll !== 'function') {
|
|
2957
|
+
return;
|
|
2958
|
+
}
|
|
2959
|
+
if (typeof root.matches === 'function' && root.matches('[data-chat-interaction-document-manager-config]')) {
|
|
2960
|
+
initializeFromElement(root);
|
|
2961
|
+
}
|
|
2962
|
+
root.querySelectorAll('[data-chat-interaction-document-manager-config]').forEach(initializeFromElement);
|
|
2963
|
+
}
|
|
2964
|
+
function startAutoInitialization() {
|
|
2965
|
+
scanForAutoInitialization(document);
|
|
2966
|
+
if (typeof MutationObserver === 'undefined') {
|
|
2967
|
+
return;
|
|
2968
|
+
}
|
|
2969
|
+
var observer = new MutationObserver(function (mutations) {
|
|
2970
|
+
mutations.forEach(function (mutation) {
|
|
2971
|
+
mutation.addedNodes.forEach(function (node) {
|
|
2972
|
+
if (node && node.nodeType === 1) {
|
|
2973
|
+
scanForAutoInitialization(node);
|
|
2974
|
+
}
|
|
2975
|
+
});
|
|
2976
|
+
});
|
|
2977
|
+
});
|
|
2978
|
+
observer.observe(document.body, {
|
|
2979
|
+
childList: true,
|
|
2980
|
+
subtree: true
|
|
2981
|
+
});
|
|
2982
|
+
}
|
|
2983
|
+
if (document.readyState === 'loading') {
|
|
2984
|
+
document.addEventListener('DOMContentLoaded', startAutoInitialization, {
|
|
2985
|
+
once: true
|
|
2986
|
+
});
|
|
2987
|
+
} else {
|
|
2988
|
+
startAutoInitialization();
|
|
2989
|
+
}
|
|
2131
2990
|
return {
|
|
2132
|
-
initialize: initialize
|
|
2991
|
+
initialize: initialize,
|
|
2992
|
+
initializeFromElement: initializeFromElement
|
|
2133
2993
|
};
|
|
2134
2994
|
}();
|
|
2135
2995
|
|