@crestapps/ai-chat-ui 1.0.0-preview.9 → 1.0.0-preview.95
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai-chat-widget.js +962 -0
- package/dist/ai-chat-widget.js.map +1 -0
- package/dist/ai-chat-widget.min.js +2 -0
- package/dist/ai-chat-widget.min.js.map +1 -0
- package/dist/ai-chat.css +45 -14
- package/dist/ai-chat.css.map +1 -1
- package/dist/ai-chat.js +1076 -1019
- package/dist/ai-chat.js.map +1 -1
- package/dist/ai-chat.min.css +1 -1
- package/dist/ai-chat.min.js +1 -1
- package/dist/ai-chat.min.js.map +1 -1
- package/dist/chat-interaction-settings.js +297 -0
- package/dist/chat-interaction-settings.js.map +1 -0
- package/dist/chat-interaction-settings.min.js +2 -0
- package/dist/chat-interaction-settings.min.js.map +1 -0
- package/dist/chat-interaction.js +1224 -325
- package/dist/chat-interaction.js.map +1 -1
- package/dist/chat-interaction.min.js +1 -1
- package/dist/chat-interaction.min.js.map +1 -1
- package/dist/chat-widget.css +48 -26
- package/dist/chat-widget.css.map +1 -1
- package/dist/chat-widget.min.css +1 -1
- package/dist/document-drop-zone.css +10 -10
- package/dist/document-drop-zone.css.map +1 -1
- package/dist/document-drop-zone.js +92 -14
- package/dist/document-drop-zone.js.map +1 -1
- package/dist/document-drop-zone.min.css +1 -1
- package/dist/document-drop-zone.min.js +1 -1
- package/dist/document-drop-zone.min.js.map +1 -1
- package/dist/technical-name-generator.js +36 -8
- package/dist/technical-name-generator.js.map +1 -1
- package/dist/technical-name-generator.min.js +1 -1
- package/dist/technical-name-generator.min.js.map +1 -1
- package/package.json +9 -1
- package/README.md +0 -145
package/dist/ai-chat.js
CHANGED
|
@@ -3,15 +3,18 @@
|
|
|
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
|
+
var _excluded = ["placeholder"];
|
|
6
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 }; })(); }
|
|
7
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); }
|
|
8
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); }
|
|
9
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); }); }; }
|
|
10
|
-
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; } } }; }
|
|
11
11
|
function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
|
|
12
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."); }
|
|
13
13
|
function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
|
|
14
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; } } }; }
|
|
15
18
|
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
|
|
16
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."); }
|
|
17
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; } }
|
|
@@ -19,7 +22,7 @@ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length)
|
|
|
19
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; } }
|
|
20
23
|
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
|
|
21
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
|
-
window.
|
|
25
|
+
window.coreAIChatManager = function () {
|
|
23
26
|
// Defaults (can be overridden by instanceConfig)
|
|
24
27
|
var defaultConfig = {
|
|
25
28
|
// UI defaults for generated media
|
|
@@ -33,7 +36,9 @@ window.openAIChatManager = function () {
|
|
|
33
36
|
thumbsUpTitle: 'Thumbs up',
|
|
34
37
|
thumbsDownTitle: 'Thumbs down',
|
|
35
38
|
copyTitle: 'Click here to copy response to clipboard.',
|
|
39
|
+
copiedTitle: 'Response copied to clipboard.',
|
|
36
40
|
codeCopiedText: 'Copied!',
|
|
41
|
+
copyResetDelayMs: 2000,
|
|
37
42
|
widget: {
|
|
38
43
|
chatWidgetContainer: null,
|
|
39
44
|
chatWidgetStateName: null,
|
|
@@ -52,8 +57,8 @@ window.openAIChatManager = function () {
|
|
|
52
57
|
minWidth: 320,
|
|
53
58
|
minHeight: 420
|
|
54
59
|
},
|
|
55
|
-
messageTemplate: "\n <div class=\"ai-chat-messages\">\n <div v-for=\"(message, index) in messages\" :key=\"'msg-' + 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\">{{ userLabel }}</div>\n <div v-else-if=\"message.role !== 'indicator'\" :class=\"getAssistantRoleClasses(message)\">\n <span :class=\"getAssistantIconClasses(message, index)\"><
|
|
56
|
-
indicatorTemplate: "\n <div class=\"ai-chat-msg-role ai-chat-msg-role-assistant\">\n <span class=\"ai-streaming-icon\"><
|
|
60
|
+
messageTemplate: "\n <div class=\"ai-chat-messages\">\n <div v-for=\"(message, index) in messages\" :key=\"'msg-' + 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\">{{ userLabel }}</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 <template v-if=\"metricsEnabled && message.role === 'assistant'\">\n <span class=\"ai-chat-message-assistant-feedback\" :data-message-id=\"message.id\">\n <button type=\"button\" class=\"btn btn-sm btn-link text-success p-0 me-2 button-message-toolbox rate-up-btn\" @click=\"rateMessage(message, true, $event)\" :title=\"thumbsUpTitle\">\n <i class=\"fa-regular fa-thumbs-up\"></i>\n </button>\n <button type=\"button\" class=\"btn btn-sm btn-link text-danger p-0 me-2 button-message-toolbox rate-down-btn\" @click=\"rateMessage(message, false, $event)\" :title=\"thumbsDownTitle\">\n <i class=\"fa-regular fa-thumbs-down\"></i>\n </button>\n </span>\n </template>\n <button type=\"button\" v-if=\"textToSpeechEnabled && !isConversationMode && message.role === 'assistant' && !message.isStreaming\" class=\"btn btn-sm btn-link text-secondary p-0 me-1 button-message-toolbox\" :class=\"{ 'tts-playing': ttsPlayingMessageIndex === index }\" :data-tts-message-index=\"index\" @click=\"toggleMessageTts(message, index)\" :title=\"ttsPlayingMessageIndex === index ? 'Pause audio' : 'Read aloud'\">\n <span :class=\"ttsPlayingMessageIndex === index ? 'fa-solid fa-circle-pause' : 'fa-solid fa-circle-play'\"></span>\n </button>\n <button 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 type=\"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 type=\"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 ",
|
|
61
|
+
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 "
|
|
57
62
|
};
|
|
58
63
|
|
|
59
64
|
// Sanitize URLs to prevent javascript: protocol injection.
|
|
@@ -72,6 +77,42 @@ window.openAIChatManager = function () {
|
|
|
72
77
|
span.textContent = text;
|
|
73
78
|
return span.innerHTML;
|
|
74
79
|
}
|
|
80
|
+
function containsFontAwesomePlaceholders(root) {
|
|
81
|
+
if (!root || root.nodeType !== 1) {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
var selector = 'i[class*="fa-"],i.fa,i.fas,i.far,i.fab';
|
|
85
|
+
if (typeof root.matches === 'function' && root.matches(selector)) {
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
return typeof root.querySelector === 'function' && !!root.querySelector(selector);
|
|
89
|
+
}
|
|
90
|
+
function refreshFontAwesomeIcons(root) {
|
|
91
|
+
var fontAwesome = window.FontAwesome;
|
|
92
|
+
if (!containsFontAwesomePlaceholders(root) || !fontAwesome || !fontAwesome.dom || typeof fontAwesome.dom.i2svg !== 'function') {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
fontAwesome.dom.i2svg({
|
|
96
|
+
node: root
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
function observeFontAwesomeIcons(root) {
|
|
100
|
+
if (!root || typeof MutationObserver === 'undefined') {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
var observer = new MutationObserver(function (mutations) {
|
|
104
|
+
mutations.forEach(function (mutation) {
|
|
105
|
+
mutation.addedNodes.forEach(function (node) {
|
|
106
|
+
refreshFontAwesomeIcons(node);
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
observer.observe(root, {
|
|
111
|
+
childList: true,
|
|
112
|
+
subtree: true
|
|
113
|
+
});
|
|
114
|
+
return observer;
|
|
115
|
+
}
|
|
75
116
|
function parsePixelValue(value) {
|
|
76
117
|
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
77
118
|
return value;
|
|
@@ -86,16 +127,31 @@ window.openAIChatManager = function () {
|
|
|
86
127
|
return Math.min(Math.max(value, min), max);
|
|
87
128
|
}
|
|
88
129
|
function normalizeReference(reference) {
|
|
89
|
-
var _ref, _normalized$index, _ref2, _normalized$text, _ref3, _normalized$link;
|
|
130
|
+
var _ref, _normalized$index, _ref2, _normalized$text, _ref3, _normalized$title, _ref4, _normalized$link, _ref5, _normalized$reference, _normalized$isGenerat;
|
|
90
131
|
if (!reference || _typeof(reference) !== 'object') {
|
|
91
132
|
return null;
|
|
92
133
|
}
|
|
93
134
|
var normalized = Object.assign({}, reference);
|
|
94
135
|
normalized.index = (_ref = (_normalized$index = normalized.index) !== null && _normalized$index !== void 0 ? _normalized$index : normalized.Index) !== null && _ref !== void 0 ? _ref : 0;
|
|
95
136
|
normalized.text = (_ref2 = (_normalized$text = normalized.text) !== null && _normalized$text !== void 0 ? _normalized$text : normalized.Text) !== null && _ref2 !== void 0 ? _ref2 : null;
|
|
96
|
-
normalized.
|
|
137
|
+
normalized.title = (_ref3 = (_normalized$title = normalized.title) !== null && _normalized$title !== void 0 ? _normalized$title : normalized.Title) !== null && _ref3 !== void 0 ? _ref3 : null;
|
|
138
|
+
normalized.link = sanitizeUrl((_ref4 = (_normalized$link = normalized.link) !== null && _normalized$link !== void 0 ? _normalized$link : normalized.Link) !== null && _ref4 !== void 0 ? _ref4 : null);
|
|
139
|
+
normalized.referenceType = (_ref5 = (_normalized$reference = normalized.referenceType) !== null && _normalized$reference !== void 0 ? _normalized$reference : normalized.ReferenceType) !== null && _ref5 !== void 0 ? _ref5 : null;
|
|
140
|
+
normalized.isGenerated = ((_normalized$isGenerat = normalized.isGenerated) !== null && _normalized$isGenerat !== void 0 ? _normalized$isGenerat : normalized.IsGenerated) === true;
|
|
97
141
|
return normalized;
|
|
98
142
|
}
|
|
143
|
+
function isDownloadCitationReference(reference) {
|
|
144
|
+
if (!reference || _typeof(reference) !== 'object') {
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
if (typeof reference.referenceType === 'string' && reference.referenceType.toLowerCase() === 'document') {
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
if (typeof reference.link === 'string' && /\/ai\/documents\/.+\/download(?:$|\?)/i.test(reference.link)) {
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
99
155
|
function normalizeReferences(references) {
|
|
100
156
|
if (!references || _typeof(references) !== 'object') {
|
|
101
157
|
return {};
|
|
@@ -110,6 +166,164 @@ window.openAIChatManager = function () {
|
|
|
110
166
|
}
|
|
111
167
|
return normalized;
|
|
112
168
|
}
|
|
169
|
+
function getCitationLabel(reference, key) {
|
|
170
|
+
return reference.title || reference.text || key;
|
|
171
|
+
}
|
|
172
|
+
function buildCitationDisplay(content, references) {
|
|
173
|
+
var processedContent = (content || '').trim();
|
|
174
|
+
var messageReferences = normalizeReferences(references);
|
|
175
|
+
var referenceEntries = Object.entries(messageReferences);
|
|
176
|
+
if (!referenceEntries.length) {
|
|
177
|
+
return {
|
|
178
|
+
content: processedContent,
|
|
179
|
+
citations: []
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
var citedRefs = referenceEntries.filter(function (_ref6) {
|
|
183
|
+
var _ref7 = _slicedToArray(_ref6, 1),
|
|
184
|
+
key = _ref7[0];
|
|
185
|
+
return processedContent.includes(key);
|
|
186
|
+
});
|
|
187
|
+
var generatedRefs = referenceEntries.filter(function (_ref8) {
|
|
188
|
+
var _ref9 = _slicedToArray(_ref8, 2),
|
|
189
|
+
key = _ref9[0],
|
|
190
|
+
value = _ref9[1];
|
|
191
|
+
return value.isGenerated && !processedContent.includes(key);
|
|
192
|
+
});
|
|
193
|
+
if (!citedRefs.length && !generatedRefs.length) {
|
|
194
|
+
return {
|
|
195
|
+
content: processedContent,
|
|
196
|
+
citations: []
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
citedRefs.sort(function (_ref0, _ref1) {
|
|
200
|
+
var _ref10 = _slicedToArray(_ref0, 2),
|
|
201
|
+
a = _ref10[1];
|
|
202
|
+
var _ref11 = _slicedToArray(_ref1, 2),
|
|
203
|
+
b = _ref11[1];
|
|
204
|
+
return a.index - b.index;
|
|
205
|
+
});
|
|
206
|
+
generatedRefs.sort(function (_ref12, _ref13) {
|
|
207
|
+
var _ref14 = _slicedToArray(_ref12, 2),
|
|
208
|
+
a = _ref14[1];
|
|
209
|
+
var _ref15 = _slicedToArray(_ref13, 2),
|
|
210
|
+
b = _ref15[1];
|
|
211
|
+
return a.index - b.index;
|
|
212
|
+
});
|
|
213
|
+
var citations = [];
|
|
214
|
+
var displayIndex = 1;
|
|
215
|
+
var _iterator = _createForOfIteratorHelper(citedRefs),
|
|
216
|
+
_step;
|
|
217
|
+
try {
|
|
218
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
219
|
+
var _step$value = _slicedToArray(_step.value, 2),
|
|
220
|
+
key = _step$value[0],
|
|
221
|
+
value = _step$value[1];
|
|
222
|
+
var placeholder = "__CITE_".concat(displayIndex, "_").concat(value.index || displayIndex, "__");
|
|
223
|
+
processedContent = processedContent.replaceAll(key, placeholder);
|
|
224
|
+
citations.push({
|
|
225
|
+
referenceKey: key,
|
|
226
|
+
displayIndex: displayIndex,
|
|
227
|
+
label: getCitationLabel(value, key),
|
|
228
|
+
link: value.link || null,
|
|
229
|
+
isDownload: isDownloadCitationReference(value),
|
|
230
|
+
placeholder: placeholder
|
|
231
|
+
});
|
|
232
|
+
displayIndex++;
|
|
233
|
+
}
|
|
234
|
+
} catch (err) {
|
|
235
|
+
_iterator.e(err);
|
|
236
|
+
} finally {
|
|
237
|
+
_iterator.f();
|
|
238
|
+
}
|
|
239
|
+
for (var _i2 = 0, _citations = citations; _i2 < _citations.length; _i2++) {
|
|
240
|
+
var citation = _citations[_i2];
|
|
241
|
+
processedContent = processedContent.replaceAll(citation.placeholder, "<sup>".concat(citation.displayIndex, "</sup>"));
|
|
242
|
+
}
|
|
243
|
+
processedContent = processedContent.replaceAll('</sup><sup>', '</sup><sup>,</sup><sup>');
|
|
244
|
+
|
|
245
|
+
// Generated files (such as exported tabular data) are always offered as a download even when
|
|
246
|
+
// the model does not cite them inline, so the user never loses access to the produced file.
|
|
247
|
+
var _iterator2 = _createForOfIteratorHelper(generatedRefs),
|
|
248
|
+
_step2;
|
|
249
|
+
try {
|
|
250
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
251
|
+
var _step2$value = _slicedToArray(_step2.value, 2),
|
|
252
|
+
_key = _step2$value[0],
|
|
253
|
+
_value = _step2$value[1];
|
|
254
|
+
citations.push({
|
|
255
|
+
referenceKey: _key,
|
|
256
|
+
displayIndex: displayIndex,
|
|
257
|
+
label: getCitationLabel(_value, _key),
|
|
258
|
+
link: _value.link || null,
|
|
259
|
+
isDownload: true,
|
|
260
|
+
placeholder: null
|
|
261
|
+
});
|
|
262
|
+
displayIndex++;
|
|
263
|
+
}
|
|
264
|
+
} catch (err) {
|
|
265
|
+
_iterator2.e(err);
|
|
266
|
+
} finally {
|
|
267
|
+
_iterator2.f();
|
|
268
|
+
}
|
|
269
|
+
return {
|
|
270
|
+
content: processedContent,
|
|
271
|
+
citations: citations.map(function (_ref16) {
|
|
272
|
+
var placeholder = _ref16.placeholder,
|
|
273
|
+
citation = _objectWithoutProperties(_ref16, _excluded);
|
|
274
|
+
return citation;
|
|
275
|
+
})
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
function buildCopyContent(content, citations) {
|
|
279
|
+
var copyContent = (content || '').trim();
|
|
280
|
+
if (!copyContent || !Array.isArray(citations) || citations.length === 0) {
|
|
281
|
+
return copyContent;
|
|
282
|
+
}
|
|
283
|
+
var _iterator3 = _createForOfIteratorHelper(citations),
|
|
284
|
+
_step3;
|
|
285
|
+
try {
|
|
286
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
287
|
+
var citation = _step3.value;
|
|
288
|
+
copyContent = copyContent.replaceAll(citation.referenceKey, "[".concat(citation.displayIndex, "]"));
|
|
289
|
+
}
|
|
290
|
+
} catch (err) {
|
|
291
|
+
_iterator3.e(err);
|
|
292
|
+
} finally {
|
|
293
|
+
_iterator3.f();
|
|
294
|
+
}
|
|
295
|
+
copyContent += '\n\nReferences:\n';
|
|
296
|
+
var _iterator4 = _createForOfIteratorHelper(citations),
|
|
297
|
+
_step4;
|
|
298
|
+
try {
|
|
299
|
+
for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
|
|
300
|
+
var _citation = _step4.value;
|
|
301
|
+
copyContent += "".concat(_citation.displayIndex, ". ").concat(_citation.label);
|
|
302
|
+
if (_citation.link) {
|
|
303
|
+
copyContent += " - ".concat(_citation.link);
|
|
304
|
+
}
|
|
305
|
+
copyContent += '\n';
|
|
306
|
+
}
|
|
307
|
+
} catch (err) {
|
|
308
|
+
_iterator4.e(err);
|
|
309
|
+
} finally {
|
|
310
|
+
_iterator4.f();
|
|
311
|
+
}
|
|
312
|
+
return copyContent.trimEnd();
|
|
313
|
+
}
|
|
314
|
+
function updateMessagePresentation(message, references) {
|
|
315
|
+
var messageReferences = normalizeReferences(references !== null && references !== void 0 ? references : message.references);
|
|
316
|
+
var rawContent = typeof message.rawContent === 'string' ? message.rawContent : typeof message.content === 'string' ? message.content : '';
|
|
317
|
+
var citationDisplay = buildCitationDisplay(rawContent, messageReferences);
|
|
318
|
+
message.rawContent = rawContent;
|
|
319
|
+
message.content = rawContent;
|
|
320
|
+
message.displayContent = citationDisplay.content;
|
|
321
|
+
message.references = messageReferences;
|
|
322
|
+
message.citationReferences = citationDisplay.citations;
|
|
323
|
+
message.copyContent = buildCopyContent(rawContent, citationDisplay.citations);
|
|
324
|
+
message.htmlContent = parseMarkdownContent(citationDisplay.content, message);
|
|
325
|
+
return message;
|
|
326
|
+
}
|
|
113
327
|
var renderer = new marked.Renderer();
|
|
114
328
|
|
|
115
329
|
// Modify the link rendering to open in a new tab
|
|
@@ -140,7 +354,7 @@ window.openAIChatManager = function () {
|
|
|
140
354
|
highlighted = escapeHtmlEntities(code);
|
|
141
355
|
}
|
|
142
356
|
var langDisplay = lang ? escapeHtmlEntities(lang) : 'code';
|
|
143
|
-
return "<div class=\"ai-code-block\"><div class=\"ai-code-header\"><span class=\"ai-code-lang\"><
|
|
357
|
+
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>");
|
|
144
358
|
};
|
|
145
359
|
|
|
146
360
|
// Custom image renderer for generated images with thumbnail styling and download button.
|
|
@@ -150,7 +364,7 @@ window.openAIChatManager = function () {
|
|
|
150
364
|
if (!src) return '';
|
|
151
365
|
var alt = data.text || defaultConfig.generatedImageAltText;
|
|
152
366
|
var maxWidth = defaultConfig.generatedImageMaxWidth;
|
|
153
|
-
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 <
|
|
367
|
+
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>");
|
|
154
368
|
};
|
|
155
369
|
|
|
156
370
|
// Chart counter for unique IDs
|
|
@@ -164,7 +378,7 @@ window.openAIChatManager = function () {
|
|
|
164
378
|
// its DOM update to render charts it didn't create itself.
|
|
165
379
|
window.__chartConfigs = window.__chartConfigs || {};
|
|
166
380
|
function createChartHtml(chartId) {
|
|
167
|
-
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, "\">") + "<
|
|
381
|
+
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>";
|
|
168
382
|
}
|
|
169
383
|
|
|
170
384
|
// Register [chart:{...json...}] as a native marked block extension so the
|
|
@@ -275,17 +489,17 @@ window.openAIChatManager = function () {
|
|
|
275
489
|
// Defer to requestAnimationFrame so the browser has fully laid out the
|
|
276
490
|
// canvas elements before Chart.js reads their dimensions.
|
|
277
491
|
requestAnimationFrame(function () {
|
|
278
|
-
var
|
|
279
|
-
|
|
492
|
+
var _iterator5 = _createForOfIteratorHelper(charts),
|
|
493
|
+
_step5;
|
|
280
494
|
try {
|
|
281
|
-
for (
|
|
282
|
-
var c =
|
|
495
|
+
for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
|
|
496
|
+
var c = _step5.value;
|
|
283
497
|
renderChartOnCanvas(c.chartId, c.config);
|
|
284
498
|
}
|
|
285
499
|
} catch (err) {
|
|
286
|
-
|
|
500
|
+
_iterator5.e(err);
|
|
287
501
|
} finally {
|
|
288
|
-
|
|
502
|
+
_iterator5.f();
|
|
289
503
|
}
|
|
290
504
|
});
|
|
291
505
|
}
|
|
@@ -338,8 +552,8 @@ window.openAIChatManager = function () {
|
|
|
338
552
|
return;
|
|
339
553
|
}
|
|
340
554
|
requestAnimationFrame(function () {
|
|
341
|
-
for (var
|
|
342
|
-
var chartId = _Object$keys[
|
|
555
|
+
for (var _i3 = 0, _Object$keys = Object.keys(configs); _i3 < _Object$keys.length; _i3++) {
|
|
556
|
+
var chartId = _Object$keys[_i3];
|
|
343
557
|
renderChartOnCanvas(chartId, configs[chartId]);
|
|
344
558
|
}
|
|
345
559
|
});
|
|
@@ -359,10 +573,23 @@ window.openAIChatManager = function () {
|
|
|
359
573
|
ADD_ATTR: ['target']
|
|
360
574
|
});
|
|
361
575
|
}
|
|
576
|
+
function compactObject(source) {
|
|
577
|
+
if (!source || _typeof(source) !== 'object') {
|
|
578
|
+
return {};
|
|
579
|
+
}
|
|
580
|
+
return Object.fromEntries(Object.entries(source).filter(function (_ref17) {
|
|
581
|
+
var _ref18 = _slicedToArray(_ref17, 2),
|
|
582
|
+
value = _ref18[1];
|
|
583
|
+
return value !== undefined;
|
|
584
|
+
}));
|
|
585
|
+
}
|
|
362
586
|
var initialize = function initialize(instanceConfig) {
|
|
363
|
-
var
|
|
364
|
-
|
|
365
|
-
var
|
|
587
|
+
var normalizedInstanceConfig = compactObject(instanceConfig);
|
|
588
|
+
var normalizedWidgetConfig = compactObject(normalizedInstanceConfig.widget);
|
|
589
|
+
var config = Object.assign({}, defaultConfig, normalizedInstanceConfig);
|
|
590
|
+
config.widget = Object.assign({}, defaultConfig.widget || {}, normalizedWidgetConfig);
|
|
591
|
+
var hasWidgetConfig = !!(normalizedWidgetConfig.chatWidgetContainer && normalizedWidgetConfig.chatWidgetStateName);
|
|
592
|
+
var widgetBehavior = window.coreAIChatWidgetBehavior || null;
|
|
366
593
|
// Keep defaultConfig in sync so renderers use overridden values
|
|
367
594
|
defaultConfig = config;
|
|
368
595
|
if (!config.signalRHubUrl) {
|
|
@@ -385,7 +612,7 @@ window.openAIChatManager = function () {
|
|
|
385
612
|
console.error('The sendButtonElementSelector is required.');
|
|
386
613
|
return;
|
|
387
614
|
}
|
|
388
|
-
var
|
|
615
|
+
var appDefinition = {
|
|
389
616
|
data: function data() {
|
|
390
617
|
return {
|
|
391
618
|
inputElement: null,
|
|
@@ -394,18 +621,6 @@ window.openAIChatManager = function () {
|
|
|
394
621
|
placeholder: null,
|
|
395
622
|
isSessionStarted: false,
|
|
396
623
|
isPlaceholderVisible: true,
|
|
397
|
-
chatWidgetStateName: null,
|
|
398
|
-
chatWidgetStateSession: null,
|
|
399
|
-
chatWidgetLayoutKey: null,
|
|
400
|
-
chatHistorySection: null,
|
|
401
|
-
widgetContainerElement: null,
|
|
402
|
-
widgetToggleButtonElement: null,
|
|
403
|
-
widgetResetSizeButtonElement: null,
|
|
404
|
-
widgetResizeObserver: null,
|
|
405
|
-
widgetViewportResizeHandler: null,
|
|
406
|
-
widgetDefaultWidth: null,
|
|
407
|
-
widgetDefaultHeight: null,
|
|
408
|
-
widgetIsInitialized: false,
|
|
409
624
|
isStreaming: false,
|
|
410
625
|
isNavigatingAway: false,
|
|
411
626
|
autoScroll: true,
|
|
@@ -415,6 +630,8 @@ window.openAIChatManager = function () {
|
|
|
415
630
|
prompt: '',
|
|
416
631
|
documents: config.existingDocuments || [],
|
|
417
632
|
isUploading: false,
|
|
633
|
+
isDocumentOperationPending: false,
|
|
634
|
+
documentOperationQueue: null,
|
|
418
635
|
uploadErrors: [],
|
|
419
636
|
isDragOver: false,
|
|
420
637
|
documentBar: null,
|
|
@@ -424,6 +641,7 @@ window.openAIChatManager = function () {
|
|
|
424
641
|
thumbsUpTitle: config.thumbsUpTitle,
|
|
425
642
|
thumbsDownTitle: config.thumbsDownTitle,
|
|
426
643
|
copyTitle: config.copyTitle,
|
|
644
|
+
copiedTitle: config.copiedTitle,
|
|
427
645
|
isRecording: false,
|
|
428
646
|
mediaRecorder: null,
|
|
429
647
|
preRecordingPrompt: '',
|
|
@@ -444,7 +662,14 @@ window.openAIChatManager = function () {
|
|
|
444
662
|
conversationModeEnabled: config.chatMode === 'Conversation',
|
|
445
663
|
conversationButton: null,
|
|
446
664
|
isConversationMode: false,
|
|
447
|
-
notificationDismissTimers: {}
|
|
665
|
+
notificationDismissTimers: {},
|
|
666
|
+
pendingSessionPromise: null,
|
|
667
|
+
pendingSessionResolver: null,
|
|
668
|
+
pendingSessionRejector: null,
|
|
669
|
+
pendingSessionTimeoutId: null,
|
|
670
|
+
copiedMessageIndex: -1,
|
|
671
|
+
copyResetTimeoutId: null,
|
|
672
|
+
activeCopyButton: null
|
|
448
673
|
};
|
|
449
674
|
},
|
|
450
675
|
computed: {
|
|
@@ -461,336 +686,6 @@ window.openAIChatManager = function () {
|
|
|
461
686
|
handleBeforeUnload: function handleBeforeUnload() {
|
|
462
687
|
this.isNavigatingAway = true;
|
|
463
688
|
},
|
|
464
|
-
getStoredWidgetLayout: function getStoredWidgetLayout() {
|
|
465
|
-
if (!this.chatWidgetLayoutKey || !config.widget.persistLayout) {
|
|
466
|
-
return {};
|
|
467
|
-
}
|
|
468
|
-
try {
|
|
469
|
-
var storedLayout = localStorage.getItem(this.chatWidgetLayoutKey);
|
|
470
|
-
return storedLayout ? JSON.parse(storedLayout) || {} : {};
|
|
471
|
-
} catch (error) {
|
|
472
|
-
console.warn('Failed to read widget layout state.', error);
|
|
473
|
-
return {};
|
|
474
|
-
}
|
|
475
|
-
},
|
|
476
|
-
saveStoredWidgetLayout: function saveStoredWidgetLayout(partialLayout) {
|
|
477
|
-
if (!this.chatWidgetLayoutKey || !config.widget.persistLayout) {
|
|
478
|
-
return;
|
|
479
|
-
}
|
|
480
|
-
var currentLayout = this.getStoredWidgetLayout();
|
|
481
|
-
var nextLayout = Object.assign({}, currentLayout);
|
|
482
|
-
if (partialLayout.panel !== undefined) {
|
|
483
|
-
nextLayout.panel = Object.assign({}, currentLayout.panel || {}, partialLayout.panel || {});
|
|
484
|
-
}
|
|
485
|
-
if (partialLayout.position !== undefined) {
|
|
486
|
-
nextLayout.position = Object.assign({}, currentLayout.position || {}, partialLayout.position || {});
|
|
487
|
-
}
|
|
488
|
-
localStorage.setItem(this.chatWidgetLayoutKey, JSON.stringify(nextLayout));
|
|
489
|
-
},
|
|
490
|
-
getElementSize: function getElementSize(element, fallbackWidth, fallbackHeight) {
|
|
491
|
-
if (!element) {
|
|
492
|
-
return {
|
|
493
|
-
width: fallbackWidth || 0,
|
|
494
|
-
height: fallbackHeight || 0
|
|
495
|
-
};
|
|
496
|
-
}
|
|
497
|
-
var rect = element.getBoundingClientRect();
|
|
498
|
-
var computed = window.getComputedStyle(element);
|
|
499
|
-
return {
|
|
500
|
-
width: Math.round(rect.width || parsePixelValue(computed.width) || fallbackWidth || 0),
|
|
501
|
-
height: Math.round(rect.height || parsePixelValue(computed.height) || fallbackHeight || 0)
|
|
502
|
-
};
|
|
503
|
-
},
|
|
504
|
-
getElementPosition: function getElementPosition(element) {
|
|
505
|
-
if (!element) {
|
|
506
|
-
return {
|
|
507
|
-
left: 0,
|
|
508
|
-
top: 0
|
|
509
|
-
};
|
|
510
|
-
}
|
|
511
|
-
var rect = element.getBoundingClientRect();
|
|
512
|
-
var computed = window.getComputedStyle(element);
|
|
513
|
-
var inlineLeft = parsePixelValue(element.style.left);
|
|
514
|
-
var inlineTop = parsePixelValue(element.style.top);
|
|
515
|
-
var computedLeft = parsePixelValue(computed.left);
|
|
516
|
-
var computedTop = parsePixelValue(computed.top);
|
|
517
|
-
var isHidden = computed.display === 'none';
|
|
518
|
-
return {
|
|
519
|
-
left: Math.round(isHidden && Number.isFinite(inlineLeft) ? inlineLeft : rect.left || inlineLeft || computedLeft || 0),
|
|
520
|
-
top: Math.round(isHidden && Number.isFinite(inlineTop) ? inlineTop : rect.top || inlineTop || computedTop || 0)
|
|
521
|
-
};
|
|
522
|
-
},
|
|
523
|
-
clampWidgetPosition: function clampWidgetPosition(left, top, width, height) {
|
|
524
|
-
var viewportPadding = 8;
|
|
525
|
-
var maxLeft = Math.max(viewportPadding, window.innerWidth - width - viewportPadding);
|
|
526
|
-
var maxTop = Math.max(viewportPadding, window.innerHeight - height - viewportPadding);
|
|
527
|
-
return {
|
|
528
|
-
left: Math.round(clamp(left, viewportPadding, maxLeft)),
|
|
529
|
-
top: Math.round(clamp(top, viewportPadding, maxTop))
|
|
530
|
-
};
|
|
531
|
-
},
|
|
532
|
-
applyAbsolutePosition: function applyAbsolutePosition(element, left, top) {
|
|
533
|
-
if (!element) {
|
|
534
|
-
return;
|
|
535
|
-
}
|
|
536
|
-
element.style.left = left + 'px';
|
|
537
|
-
element.style.top = top + 'px';
|
|
538
|
-
element.style.right = 'auto';
|
|
539
|
-
element.style.bottom = 'auto';
|
|
540
|
-
},
|
|
541
|
-
getWidgetDefaultSize: function getWidgetDefaultSize() {
|
|
542
|
-
return {
|
|
543
|
-
width: this.widgetDefaultWidth || parsePixelValue(config.widget.defaultWidth) || 380,
|
|
544
|
-
height: this.widgetDefaultHeight || parsePixelValue(config.widget.defaultHeight) || 520
|
|
545
|
-
};
|
|
546
|
-
},
|
|
547
|
-
getWidgetToggleGap: function getWidgetToggleGap() {
|
|
548
|
-
return 8;
|
|
549
|
-
},
|
|
550
|
-
isWidgetPanelVisible: function isWidgetPanelVisible() {
|
|
551
|
-
if (!this.widgetContainerElement) {
|
|
552
|
-
return false;
|
|
553
|
-
}
|
|
554
|
-
var computed = window.getComputedStyle(this.widgetContainerElement);
|
|
555
|
-
return this.widgetContainerElement.classList.contains('open') && computed.display !== 'none';
|
|
556
|
-
},
|
|
557
|
-
persistWidgetPanelPosition: function persistWidgetPanelPosition() {
|
|
558
|
-
if (!this.widgetContainerElement || !config.widget.persistLayout) {
|
|
559
|
-
return;
|
|
560
|
-
}
|
|
561
|
-
var panelDefaultSize = this.getWidgetDefaultSize();
|
|
562
|
-
var panelPosition = this.getElementPosition(this.widgetContainerElement);
|
|
563
|
-
var panelSize = this.getElementSize(this.widgetContainerElement, panelDefaultSize.width, panelDefaultSize.height);
|
|
564
|
-
var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);
|
|
565
|
-
var linkedPosition = this.clampWidgetPosition(panelPosition.left + panelSize.width - toggleSize.width, panelPosition.top + panelSize.height + this.getWidgetToggleGap(), toggleSize.width, toggleSize.height);
|
|
566
|
-
this.saveStoredWidgetLayout({
|
|
567
|
-
position: {
|
|
568
|
-
left: linkedPosition.left,
|
|
569
|
-
top: linkedPosition.top
|
|
570
|
-
}
|
|
571
|
-
});
|
|
572
|
-
},
|
|
573
|
-
persistWidgetTogglePosition: function persistWidgetTogglePosition() {
|
|
574
|
-
if (!this.widgetToggleButtonElement || !config.widget.persistLayout) {
|
|
575
|
-
return;
|
|
576
|
-
}
|
|
577
|
-
var toggleRect = this.widgetToggleButtonElement.getBoundingClientRect();
|
|
578
|
-
this.saveStoredWidgetLayout({
|
|
579
|
-
position: {
|
|
580
|
-
left: this.getElementPosition(this.widgetToggleButtonElement).left,
|
|
581
|
-
top: this.getElementPosition(this.widgetToggleButtonElement).top
|
|
582
|
-
}
|
|
583
|
-
});
|
|
584
|
-
},
|
|
585
|
-
persistWidgetPanelSize: function persistWidgetPanelSize() {
|
|
586
|
-
if (!this.widgetContainerElement || !config.widget.enableResizing || !config.widget.persistLayout) {
|
|
587
|
-
return;
|
|
588
|
-
}
|
|
589
|
-
var defaultSize = this.getWidgetDefaultSize();
|
|
590
|
-
var currentSize = this.getElementSize(this.widgetContainerElement, defaultSize.width, defaultSize.height);
|
|
591
|
-
this.saveStoredWidgetLayout({
|
|
592
|
-
panel: {
|
|
593
|
-
width: Math.abs(currentSize.width - defaultSize.width) <= 1 ? null : currentSize.width,
|
|
594
|
-
height: Math.abs(currentSize.height - defaultSize.height) <= 1 ? null : currentSize.height
|
|
595
|
-
}
|
|
596
|
-
});
|
|
597
|
-
},
|
|
598
|
-
syncTogglePositionToPanel: function syncTogglePositionToPanel() {
|
|
599
|
-
var persistLayout = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
|
|
600
|
-
if (!this.widgetContainerElement || !this.widgetToggleButtonElement) {
|
|
601
|
-
return;
|
|
602
|
-
}
|
|
603
|
-
var panelDefaultSize = this.getWidgetDefaultSize();
|
|
604
|
-
var panelSize = this.getElementSize(this.widgetContainerElement, panelDefaultSize.width, panelDefaultSize.height);
|
|
605
|
-
var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);
|
|
606
|
-
var panelPosition = this.getElementPosition(this.widgetContainerElement);
|
|
607
|
-
var linkedPosition = this.clampWidgetPosition(panelPosition.left + panelSize.width - toggleSize.width, panelPosition.top + panelSize.height + this.getWidgetToggleGap(), toggleSize.width, toggleSize.height);
|
|
608
|
-
this.applyAbsolutePosition(this.widgetToggleButtonElement, linkedPosition.left, linkedPosition.top);
|
|
609
|
-
if (persistLayout && config.widget.persistLayout) {
|
|
610
|
-
this.persistWidgetTogglePosition();
|
|
611
|
-
}
|
|
612
|
-
},
|
|
613
|
-
syncPanelPositionToToggle: function syncPanelPositionToToggle() {
|
|
614
|
-
var persistLayout = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
|
|
615
|
-
if (!this.widgetContainerElement || !this.widgetToggleButtonElement) {
|
|
616
|
-
return;
|
|
617
|
-
}
|
|
618
|
-
var panelDefaultSize = this.getWidgetDefaultSize();
|
|
619
|
-
var panelSize = this.getElementSize(this.widgetContainerElement, panelDefaultSize.width, panelDefaultSize.height);
|
|
620
|
-
var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);
|
|
621
|
-
var togglePosition = this.getElementPosition(this.widgetToggleButtonElement);
|
|
622
|
-
var linkedPosition = this.clampWidgetPosition(togglePosition.left + toggleSize.width - panelSize.width, togglePosition.top - panelSize.height - this.getWidgetToggleGap(), panelSize.width, panelSize.height);
|
|
623
|
-
this.applyAbsolutePosition(this.widgetContainerElement, linkedPosition.left, linkedPosition.top);
|
|
624
|
-
if (persistLayout && config.widget.persistLayout) {
|
|
625
|
-
this.persistWidgetPanelPosition();
|
|
626
|
-
}
|
|
627
|
-
},
|
|
628
|
-
updateWidgetResetSizeButtonVisibility: function updateWidgetResetSizeButtonVisibility() {
|
|
629
|
-
if (!this.widgetResetSizeButtonElement) {
|
|
630
|
-
return;
|
|
631
|
-
}
|
|
632
|
-
if (!config.widget.enableResizing || !this.widgetContainerElement) {
|
|
633
|
-
this.widgetResetSizeButtonElement.classList.add('d-none');
|
|
634
|
-
return;
|
|
635
|
-
}
|
|
636
|
-
var defaultSize = this.getWidgetDefaultSize();
|
|
637
|
-
var currentSize = this.getElementSize(this.widgetContainerElement, defaultSize.width, defaultSize.height);
|
|
638
|
-
var isResized = Math.abs(currentSize.width - defaultSize.width) > 1 || Math.abs(currentSize.height - defaultSize.height) > 1 || !!this.widgetContainerElement.style.width || !!this.widgetContainerElement.style.height;
|
|
639
|
-
this.widgetResetSizeButtonElement.classList.toggle('d-none', !isResized);
|
|
640
|
-
},
|
|
641
|
-
resetWidgetSize: function resetWidgetSize() {
|
|
642
|
-
if (!this.widgetContainerElement || !config.widget.enableResizing) {
|
|
643
|
-
return;
|
|
644
|
-
}
|
|
645
|
-
this.widgetContainerElement.style.removeProperty('width');
|
|
646
|
-
this.widgetContainerElement.style.removeProperty('height');
|
|
647
|
-
this.persistWidgetPanelSize();
|
|
648
|
-
this.constrainWidgetElementsToViewport();
|
|
649
|
-
this.updateWidgetResetSizeButtonVisibility();
|
|
650
|
-
},
|
|
651
|
-
restoreWidgetLayout: function restoreWidgetLayout() {
|
|
652
|
-
var storedLayout = this.getStoredWidgetLayout();
|
|
653
|
-
if (this.widgetContainerElement && config.widget.enableResizing) {
|
|
654
|
-
if (Number.isFinite(storedLayout.panel && storedLayout.panel.width)) {
|
|
655
|
-
this.widgetContainerElement.style.width = storedLayout.panel.width + 'px';
|
|
656
|
-
} else {
|
|
657
|
-
this.widgetContainerElement.style.removeProperty('width');
|
|
658
|
-
}
|
|
659
|
-
if (Number.isFinite(storedLayout.panel && storedLayout.panel.height)) {
|
|
660
|
-
this.widgetContainerElement.style.height = storedLayout.panel.height + 'px';
|
|
661
|
-
} else {
|
|
662
|
-
this.widgetContainerElement.style.removeProperty('height');
|
|
663
|
-
}
|
|
664
|
-
}
|
|
665
|
-
if (this.widgetToggleButtonElement && config.widget.enableDragging && Number.isFinite(storedLayout.position && storedLayout.position.left) && Number.isFinite(storedLayout.position && storedLayout.position.top)) {
|
|
666
|
-
this.applyAbsolutePosition(this.widgetToggleButtonElement, storedLayout.position.left, storedLayout.position.top);
|
|
667
|
-
this.syncPanelPositionToToggle(false);
|
|
668
|
-
} else if (this.widgetToggleButtonElement && config.widget.enableDragging && Number.isFinite(storedLayout.toggle && storedLayout.toggle.left) && Number.isFinite(storedLayout.toggle && storedLayout.toggle.top)) {
|
|
669
|
-
this.applyAbsolutePosition(this.widgetToggleButtonElement, storedLayout.toggle.left, storedLayout.toggle.top);
|
|
670
|
-
this.syncPanelPositionToToggle(false);
|
|
671
|
-
} else if (this.widgetContainerElement && config.widget.enableDragging && Number.isFinite(storedLayout.panel && storedLayout.panel.left) && Number.isFinite(storedLayout.panel && storedLayout.panel.top)) {
|
|
672
|
-
this.applyAbsolutePosition(this.widgetContainerElement, storedLayout.panel.left, storedLayout.panel.top);
|
|
673
|
-
this.syncTogglePositionToPanel(false);
|
|
674
|
-
}
|
|
675
|
-
this.constrainWidgetElementsToViewport();
|
|
676
|
-
this.updateWidgetResetSizeButtonVisibility();
|
|
677
|
-
},
|
|
678
|
-
attachDraggableWidgetElement: function attachDraggableWidgetElement(element, handle, layoutKey, suppressClickOnDrag) {
|
|
679
|
-
var _this = this;
|
|
680
|
-
if (!element || !handle || !config.widget.enableDragging) {
|
|
681
|
-
return;
|
|
682
|
-
}
|
|
683
|
-
var activePointerId = null;
|
|
684
|
-
var startX = 0;
|
|
685
|
-
var startY = 0;
|
|
686
|
-
var startLeft = 0;
|
|
687
|
-
var startTop = 0;
|
|
688
|
-
var dragged = false;
|
|
689
|
-
var dragThreshold = 4;
|
|
690
|
-
var interactiveSelector = 'button, a, input, textarea, select, option, label';
|
|
691
|
-
var _stopDragging = function stopDragging(event) {
|
|
692
|
-
if (activePointerId === null) {
|
|
693
|
-
return;
|
|
694
|
-
}
|
|
695
|
-
if (event && event.pointerId !== undefined && event.pointerId !== activePointerId) {
|
|
696
|
-
return;
|
|
697
|
-
}
|
|
698
|
-
document.removeEventListener('pointermove', onPointerMove);
|
|
699
|
-
document.removeEventListener('pointerup', _stopDragging);
|
|
700
|
-
document.removeEventListener('pointercancel', _stopDragging);
|
|
701
|
-
element.classList.remove('ai-chat-widget-dragging');
|
|
702
|
-
activePointerId = null;
|
|
703
|
-
if (!dragged) {
|
|
704
|
-
return;
|
|
705
|
-
}
|
|
706
|
-
if (layoutKey === 'panel') {
|
|
707
|
-
_this.syncTogglePositionToPanel(false);
|
|
708
|
-
_this.persistWidgetPanelPosition();
|
|
709
|
-
} else if (layoutKey === 'toggle') {
|
|
710
|
-
_this.syncPanelPositionToToggle(false);
|
|
711
|
-
_this.persistWidgetTogglePosition();
|
|
712
|
-
}
|
|
713
|
-
if (config.widget.persistLayout) {
|
|
714
|
-
_this.persistWidgetPanelPosition();
|
|
715
|
-
_this.persistWidgetTogglePosition();
|
|
716
|
-
}
|
|
717
|
-
if (suppressClickOnDrag) {
|
|
718
|
-
element.dataset.dragSuppressClick = 'true';
|
|
719
|
-
window.setTimeout(function () {
|
|
720
|
-
if (element.dataset.dragSuppressClick === 'true') {
|
|
721
|
-
element.dataset.dragSuppressClick = 'false';
|
|
722
|
-
}
|
|
723
|
-
}, 0);
|
|
724
|
-
}
|
|
725
|
-
};
|
|
726
|
-
var onPointerMove = function onPointerMove(event) {
|
|
727
|
-
if (activePointerId === null || event.pointerId !== activePointerId) {
|
|
728
|
-
return;
|
|
729
|
-
}
|
|
730
|
-
var deltaX = event.clientX - startX;
|
|
731
|
-
var deltaY = event.clientY - startY;
|
|
732
|
-
if (!dragged && Math.hypot(deltaX, deltaY) < dragThreshold) {
|
|
733
|
-
return;
|
|
734
|
-
}
|
|
735
|
-
dragged = true;
|
|
736
|
-
var defaultSize = _this.getWidgetDefaultSize();
|
|
737
|
-
var currentSize = _this.getElementSize(element, layoutKey === 'panel' ? defaultSize.width : 52, layoutKey === 'panel' ? defaultSize.height : 52);
|
|
738
|
-
var nextPosition = _this.clampWidgetPosition(startLeft + deltaX, startTop + deltaY, currentSize.width, currentSize.height);
|
|
739
|
-
_this.applyAbsolutePosition(element, nextPosition.left, nextPosition.top);
|
|
740
|
-
if (layoutKey === 'panel') {
|
|
741
|
-
_this.syncTogglePositionToPanel(false);
|
|
742
|
-
} else if (layoutKey === 'toggle') {
|
|
743
|
-
_this.syncPanelPositionToToggle(false);
|
|
744
|
-
}
|
|
745
|
-
};
|
|
746
|
-
handle.addEventListener('pointerdown', function (event) {
|
|
747
|
-
if (event.button !== 0) {
|
|
748
|
-
return;
|
|
749
|
-
}
|
|
750
|
-
if (layoutKey === 'panel' && event.target.closest(interactiveSelector)) {
|
|
751
|
-
return;
|
|
752
|
-
}
|
|
753
|
-
var rect = element.getBoundingClientRect();
|
|
754
|
-
startX = event.clientX;
|
|
755
|
-
startY = event.clientY;
|
|
756
|
-
startLeft = rect.left;
|
|
757
|
-
startTop = rect.top;
|
|
758
|
-
dragged = false;
|
|
759
|
-
activePointerId = event.pointerId;
|
|
760
|
-
element.classList.add('ai-chat-widget-dragging');
|
|
761
|
-
if (handle.setPointerCapture) {
|
|
762
|
-
handle.setPointerCapture(event.pointerId);
|
|
763
|
-
}
|
|
764
|
-
document.addEventListener('pointermove', onPointerMove);
|
|
765
|
-
document.addEventListener('pointerup', _stopDragging);
|
|
766
|
-
document.addEventListener('pointercancel', _stopDragging);
|
|
767
|
-
event.preventDefault();
|
|
768
|
-
});
|
|
769
|
-
},
|
|
770
|
-
constrainWidgetElementsToViewport: function constrainWidgetElementsToViewport() {
|
|
771
|
-
if (this.widgetContainerElement && this.widgetContainerElement.style.left && this.isWidgetPanelVisible()) {
|
|
772
|
-
var panelDefaultSize = this.getWidgetDefaultSize();
|
|
773
|
-
var panelSize = this.getElementSize(this.widgetContainerElement, panelDefaultSize.width, panelDefaultSize.height);
|
|
774
|
-
var panelPosition = this.getElementPosition(this.widgetContainerElement);
|
|
775
|
-
var clampedPanel = this.clampWidgetPosition(panelPosition.left, panelPosition.top, panelSize.width, panelSize.height);
|
|
776
|
-
this.applyAbsolutePosition(this.widgetContainerElement, clampedPanel.left, clampedPanel.top);
|
|
777
|
-
this.syncTogglePositionToPanel(false);
|
|
778
|
-
if (config.widget.persistLayout) {
|
|
779
|
-
this.persistWidgetPanelPosition();
|
|
780
|
-
this.persistWidgetTogglePosition();
|
|
781
|
-
}
|
|
782
|
-
} else if (this.widgetToggleButtonElement && this.widgetToggleButtonElement.style.left) {
|
|
783
|
-
var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);
|
|
784
|
-
var togglePosition = this.getElementPosition(this.widgetToggleButtonElement);
|
|
785
|
-
var clampedToggle = this.clampWidgetPosition(togglePosition.left, togglePosition.top, toggleSize.width, toggleSize.height);
|
|
786
|
-
this.applyAbsolutePosition(this.widgetToggleButtonElement, clampedToggle.left, clampedToggle.top);
|
|
787
|
-
this.syncPanelPositionToToggle(false);
|
|
788
|
-
if (config.widget.persistLayout) {
|
|
789
|
-
this.persistWidgetTogglePosition();
|
|
790
|
-
this.persistWidgetPanelPosition();
|
|
791
|
-
}
|
|
792
|
-
}
|
|
793
|
-
},
|
|
794
689
|
handleDragOver: function handleDragOver(e) {
|
|
795
690
|
if (!config.sessionDocumentsEnabled) return;
|
|
796
691
|
e.preventDefault();
|
|
@@ -815,180 +710,272 @@ window.openAIChatManager = function () {
|
|
|
815
710
|
var inputArea = this.inputElement ? this.inputElement.closest('.ai-admin-widget-input, .text-bg-light') : null;
|
|
816
711
|
if (inputArea) inputArea.classList.remove('ai-chat-drag-over');
|
|
817
712
|
if (e.dataTransfer && e.dataTransfer.files && e.dataTransfer.files.length > 0) {
|
|
818
|
-
this.uploadFiles(e.dataTransfer.files);
|
|
713
|
+
this.uploadFiles(Array.from(e.dataTransfer.files));
|
|
819
714
|
}
|
|
820
715
|
},
|
|
821
716
|
triggerFileInput: function triggerFileInput() {
|
|
822
|
-
if (!config.sessionDocumentsEnabled) return;
|
|
717
|
+
if (!config.sessionDocumentsEnabled || this.isDocumentOperationPending) return;
|
|
823
718
|
var fileInput = document.getElementById('ai-chat-doc-input');
|
|
824
719
|
if (fileInput) fileInput.click();
|
|
825
720
|
},
|
|
826
721
|
handleFileInputChange: function handleFileInputChange(e) {
|
|
827
|
-
var files = e.target.files;
|
|
722
|
+
var files = e.target.files ? Array.from(e.target.files) : [];
|
|
828
723
|
if (files && files.length > 0) {
|
|
829
724
|
this.uploadFiles(files);
|
|
830
725
|
}
|
|
831
726
|
e.target.value = '';
|
|
832
727
|
},
|
|
833
|
-
|
|
834
|
-
var
|
|
835
|
-
|
|
836
|
-
|
|
728
|
+
queueDocumentOperation: function queueDocumentOperation(operation) {
|
|
729
|
+
var self = this;
|
|
730
|
+
var previousOperation = this.documentOperationQueue || Promise.resolve();
|
|
731
|
+
var nextOperation = previousOperation["catch"](function () {}).then(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee() {
|
|
837
732
|
return _regenerator().w(function (_context) {
|
|
838
733
|
while (1) switch (_context.p = _context.n) {
|
|
734
|
+
case 0:
|
|
735
|
+
self.isDocumentOperationPending = true;
|
|
736
|
+
_context.p = 1;
|
|
737
|
+
_context.n = 2;
|
|
738
|
+
return operation();
|
|
739
|
+
case 2:
|
|
740
|
+
return _context.a(2, _context.v);
|
|
741
|
+
case 3:
|
|
742
|
+
_context.p = 3;
|
|
743
|
+
self.isDocumentOperationPending = false;
|
|
744
|
+
return _context.f(3);
|
|
745
|
+
case 4:
|
|
746
|
+
return _context.a(2);
|
|
747
|
+
}
|
|
748
|
+
}, _callee, null, [[1,, 3, 4]]);
|
|
749
|
+
})));
|
|
750
|
+
this.documentOperationQueue = nextOperation["finally"](function () {
|
|
751
|
+
if (self.documentOperationQueue === nextOperation) {
|
|
752
|
+
self.documentOperationQueue = null;
|
|
753
|
+
}
|
|
754
|
+
});
|
|
755
|
+
return this.documentOperationQueue;
|
|
756
|
+
},
|
|
757
|
+
uploadFiles: function uploadFiles(files) {
|
|
758
|
+
var _this = this;
|
|
759
|
+
return _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3() {
|
|
760
|
+
var filesToUpload;
|
|
761
|
+
return _regenerator().w(function (_context3) {
|
|
762
|
+
while (1) switch (_context3.n) {
|
|
839
763
|
case 0:
|
|
840
764
|
if (config.uploadDocumentUrl) {
|
|
841
|
-
|
|
765
|
+
_context3.n = 1;
|
|
842
766
|
break;
|
|
843
767
|
}
|
|
844
|
-
return
|
|
768
|
+
return _context3.a(2);
|
|
845
769
|
case 1:
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
_context.n = 2;
|
|
770
|
+
filesToUpload = Array.isArray(files) ? files.slice() : Array.from(files || []);
|
|
771
|
+
if (!(filesToUpload.length === 0)) {
|
|
772
|
+
_context3.n = 2;
|
|
850
773
|
break;
|
|
851
774
|
}
|
|
852
|
-
|
|
853
|
-
return _context.a(2);
|
|
775
|
+
return _context3.a(2);
|
|
854
776
|
case 2:
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
777
|
+
return _context3.a(2, _this.queueDocumentOperation(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2() {
|
|
778
|
+
var sessionId, profileId, formData, i, response, errorText, uploadError, result, _t, _t2;
|
|
779
|
+
return _regenerator().w(function (_context2) {
|
|
780
|
+
while (1) switch (_context2.p = _context2.n) {
|
|
781
|
+
case 0:
|
|
782
|
+
sessionId = _this.getSessionId();
|
|
783
|
+
profileId = _this.getProfileId();
|
|
784
|
+
if (sessionId) {
|
|
785
|
+
_context2.n = 4;
|
|
786
|
+
break;
|
|
787
|
+
}
|
|
788
|
+
_context2.p = 1;
|
|
789
|
+
_context2.n = 2;
|
|
790
|
+
return _this.ensureSessionForDocuments(profileId);
|
|
791
|
+
case 2:
|
|
792
|
+
sessionId = _context2.v;
|
|
793
|
+
_context2.n = 4;
|
|
794
|
+
break;
|
|
795
|
+
case 3:
|
|
796
|
+
_context2.p = 3;
|
|
797
|
+
_t = _context2.v;
|
|
798
|
+
console.error('Failed to create a chat session for document upload:', _t);
|
|
799
|
+
_this.uploadErrors = [{
|
|
800
|
+
fileName: '',
|
|
801
|
+
error: 'Could not create a chat session for the upload.'
|
|
802
|
+
}];
|
|
803
|
+
_this.renderDocumentBar();
|
|
804
|
+
return _context2.a(2);
|
|
805
|
+
case 4:
|
|
806
|
+
if (sessionId) {
|
|
807
|
+
_context2.n = 5;
|
|
808
|
+
break;
|
|
809
|
+
}
|
|
810
|
+
console.warn('Cannot upload documents without a session or profile.');
|
|
811
|
+
_this.uploadErrors = [{
|
|
812
|
+
fileName: '',
|
|
813
|
+
error: 'Could not create a chat session for the upload.'
|
|
814
|
+
}];
|
|
815
|
+
_this.renderDocumentBar();
|
|
816
|
+
return _context2.a(2);
|
|
817
|
+
case 5:
|
|
818
|
+
_this.isUploading = true;
|
|
819
|
+
_this.uploadErrors = [];
|
|
820
|
+
_this.renderDocumentBar();
|
|
821
|
+
_context2.p = 6;
|
|
822
|
+
formData = new FormData();
|
|
823
|
+
formData.append('sessionId', sessionId);
|
|
824
|
+
for (i = 0; i < filesToUpload.length; i++) {
|
|
825
|
+
formData.append('files', filesToUpload[i]);
|
|
826
|
+
}
|
|
827
|
+
_context2.n = 7;
|
|
828
|
+
return fetch(config.uploadDocumentUrl, {
|
|
829
|
+
method: 'POST',
|
|
830
|
+
body: formData
|
|
831
|
+
});
|
|
832
|
+
case 7:
|
|
833
|
+
response = _context2.v;
|
|
834
|
+
if (response.ok) {
|
|
835
|
+
_context2.n = 9;
|
|
836
|
+
break;
|
|
837
|
+
}
|
|
838
|
+
_context2.n = 8;
|
|
839
|
+
return response.text();
|
|
840
|
+
case 8:
|
|
841
|
+
errorText = _context2.v;
|
|
842
|
+
uploadError = _this.extractReadableErrorMessage(errorText, 'Upload failed. Please try again.');
|
|
843
|
+
console.error('Upload failed:', errorText);
|
|
844
|
+
_this.uploadErrors = [{
|
|
845
|
+
fileName: '',
|
|
846
|
+
error: uploadError
|
|
847
|
+
}];
|
|
848
|
+
return _context2.a(2);
|
|
849
|
+
case 9:
|
|
850
|
+
_context2.n = 10;
|
|
851
|
+
return response.json();
|
|
852
|
+
case 10:
|
|
853
|
+
result = _context2.v;
|
|
854
|
+
if (result.sessionId && result.sessionId !== _this.getSessionId()) {
|
|
855
|
+
_this.initializeSession(result.sessionId);
|
|
856
|
+
}
|
|
857
|
+
if (Array.isArray(result.documents)) {
|
|
858
|
+
_this.documents = result.documents;
|
|
859
|
+
} else if (result.uploaded && result.uploaded.length > 0) {
|
|
860
|
+
_this.documents = _this.documents.concat(result.uploaded);
|
|
861
|
+
}
|
|
862
|
+
if (result.failed && result.failed.length > 0) {
|
|
863
|
+
_this.uploadErrors = result.failed;
|
|
864
|
+
}
|
|
865
|
+
_context2.n = 12;
|
|
866
|
+
break;
|
|
867
|
+
case 11:
|
|
868
|
+
_context2.p = 11;
|
|
869
|
+
_t2 = _context2.v;
|
|
870
|
+
console.error('Upload error:', _t2);
|
|
871
|
+
_this.uploadErrors = [{
|
|
872
|
+
fileName: '',
|
|
873
|
+
error: 'Upload failed. Please try again.'
|
|
874
|
+
}];
|
|
875
|
+
if (_this.getSessionId()) {
|
|
876
|
+
_this.reloadCurrentSession();
|
|
877
|
+
}
|
|
878
|
+
case 12:
|
|
879
|
+
_context2.p = 12;
|
|
880
|
+
_this.isUploading = false;
|
|
881
|
+
_this.renderDocumentBar();
|
|
882
|
+
return _context2.f(12);
|
|
883
|
+
case 13:
|
|
884
|
+
return _context2.a(2);
|
|
885
|
+
}
|
|
886
|
+
}, _callee2, null, [[6, 11, 12, 13], [1, 3]]);
|
|
887
|
+
}))));
|
|
924
888
|
}
|
|
925
|
-
},
|
|
889
|
+
}, _callee3);
|
|
926
890
|
}))();
|
|
927
891
|
},
|
|
928
892
|
removeDocument: function removeDocument(doc) {
|
|
929
|
-
var
|
|
930
|
-
return _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
while (1) switch (_context2.p = _context2.n) {
|
|
893
|
+
var _this2 = this;
|
|
894
|
+
return _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee5() {
|
|
895
|
+
return _regenerator().w(function (_context5) {
|
|
896
|
+
while (1) switch (_context5.n) {
|
|
934
897
|
case 0:
|
|
935
898
|
if (config.removeDocumentUrl) {
|
|
936
|
-
|
|
899
|
+
_context5.n = 1;
|
|
937
900
|
break;
|
|
938
901
|
}
|
|
939
|
-
return
|
|
902
|
+
return _context5.a(2);
|
|
940
903
|
case 1:
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
904
|
+
return _context5.a(2, _this2.queueDocumentOperation(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4() {
|
|
905
|
+
var sessionId, response, result, idx, errorText, removeError, _t3;
|
|
906
|
+
return _regenerator().w(function (_context4) {
|
|
907
|
+
while (1) switch (_context4.p = _context4.n) {
|
|
908
|
+
case 0:
|
|
909
|
+
_context4.p = 0;
|
|
910
|
+
sessionId = _this2.getSessionId();
|
|
911
|
+
_context4.n = 1;
|
|
912
|
+
return fetch(config.removeDocumentUrl, {
|
|
913
|
+
method: 'POST',
|
|
914
|
+
headers: {
|
|
915
|
+
'Content-Type': 'application/json'
|
|
916
|
+
},
|
|
917
|
+
body: JSON.stringify({
|
|
918
|
+
itemId: sessionId,
|
|
919
|
+
documentId: doc.documentId
|
|
920
|
+
})
|
|
921
|
+
});
|
|
922
|
+
case 1:
|
|
923
|
+
response = _context4.v;
|
|
924
|
+
if (!response.ok) {
|
|
925
|
+
_context4.n = 3;
|
|
926
|
+
break;
|
|
927
|
+
}
|
|
928
|
+
_context4.n = 2;
|
|
929
|
+
return response.json();
|
|
930
|
+
case 2:
|
|
931
|
+
result = _context4.v;
|
|
932
|
+
if (Array.isArray(result.documents)) {
|
|
933
|
+
_this2.documents = result.documents;
|
|
934
|
+
} else {
|
|
935
|
+
idx = _this2.documents.indexOf(doc);
|
|
936
|
+
if (idx > -1) {
|
|
937
|
+
_this2.documents.splice(idx, 1);
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
_context4.n = 5;
|
|
941
|
+
break;
|
|
942
|
+
case 3:
|
|
943
|
+
_context4.n = 4;
|
|
944
|
+
return response.text();
|
|
945
|
+
case 4:
|
|
946
|
+
errorText = _context4.v;
|
|
947
|
+
removeError = _this2.extractReadableErrorMessage(errorText, 'Failed to remove document. Please try again.');
|
|
948
|
+
console.error('Failed to remove document:', response.status, errorText);
|
|
949
|
+
_this2.uploadErrors = [{
|
|
950
|
+
fileName: doc.fileName || '',
|
|
951
|
+
error: removeError
|
|
952
|
+
}];
|
|
953
|
+
if (sessionId) {
|
|
954
|
+
_this2.reloadCurrentSession();
|
|
955
|
+
}
|
|
956
|
+
_this2.renderDocumentBar();
|
|
957
|
+
case 5:
|
|
958
|
+
_context4.n = 7;
|
|
959
|
+
break;
|
|
960
|
+
case 6:
|
|
961
|
+
_context4.p = 6;
|
|
962
|
+
_t3 = _context4.v;
|
|
963
|
+
console.error('Remove document error:', _t3);
|
|
964
|
+
_this2.uploadErrors = [{
|
|
965
|
+
fileName: doc.fileName || '',
|
|
966
|
+
error: 'Failed to remove document. Please try again.'
|
|
967
|
+
}];
|
|
968
|
+
if (_this2.getSessionId()) {
|
|
969
|
+
_this2.reloadCurrentSession();
|
|
970
|
+
}
|
|
971
|
+
_this2.renderDocumentBar();
|
|
972
|
+
case 7:
|
|
973
|
+
return _context4.a(2);
|
|
974
|
+
}
|
|
975
|
+
}, _callee4, null, [[0, 6]]);
|
|
976
|
+
}))));
|
|
990
977
|
}
|
|
991
|
-
},
|
|
978
|
+
}, _callee5);
|
|
992
979
|
}))();
|
|
993
980
|
},
|
|
994
981
|
formatFileSize: function formatFileSize(bytes) {
|
|
@@ -1010,9 +997,9 @@ window.openAIChatManager = function () {
|
|
|
1010
997
|
var name = doc.fileName || 'Document';
|
|
1011
998
|
if (name.length > 20) name = name.substring(0, 17) + '...';
|
|
1012
999
|
html += '<span class="badge bg-secondary bg-opacity-25 text-dark d-inline-flex align-items-center gap-1 px-2 py-1" style="font-size: 0.8rem;" title="' + this.escapeHtml(doc.fileName || '') + '">';
|
|
1013
|
-
html += '<
|
|
1000
|
+
html += '<i class="fa-solid fa-file-lines" style="font-size: 0.7rem;"></i> ';
|
|
1014
1001
|
html += this.escapeHtml(name);
|
|
1015
|
-
html += ' <button type="button" class="btn-close btn-close-sm ms-1" style="font-size: 0.5rem;" data-doc-index="' + i + '" aria-label="Remove"></button>';
|
|
1002
|
+
html += ' <button type="button" class="btn-close btn-close-sm ms-1" style="font-size: 0.5rem;" data-doc-index="' + i + '" aria-label="Remove"' + (this.isDocumentOperationPending ? ' disabled' : '') + '></button>';
|
|
1016
1003
|
html += '</span>';
|
|
1017
1004
|
}
|
|
1018
1005
|
for (var m = 0; m < this.uploadErrors.length; m++) {
|
|
@@ -1021,7 +1008,7 @@ window.openAIChatManager = function () {
|
|
|
1021
1008
|
var errorMsg = failedItem.error || 'Upload failed';
|
|
1022
1009
|
if (failedName.length > 15) failedName = failedName.substring(0, 12) + '...';
|
|
1023
1010
|
html += '<span class="badge bg-danger bg-opacity-25 text-danger d-inline-flex align-items-center gap-1 px-2 py-1" style="font-size: 0.8rem;" title="' + this.escapeHtml((failedItem.fileName || '') + ': ' + errorMsg) + '">';
|
|
1024
|
-
html += '<
|
|
1011
|
+
html += '<i class="fa-solid fa-circle-exclamation" style="font-size: 0.7rem;"></i> ';
|
|
1025
1012
|
html += this.escapeHtml(failedName);
|
|
1026
1013
|
html += ' <button type="button" class="btn-close btn-close-sm ms-1" style="font-size: 0.5rem;" data-error-index="' + m + '" aria-label="Dismiss"></button>';
|
|
1027
1014
|
html += '</span>';
|
|
@@ -1031,8 +1018,8 @@ window.openAIChatManager = function () {
|
|
|
1031
1018
|
html += '<span class="spinner-border spinner-border-sm" style="width: 0.7rem; height: 0.7rem;"></span> Uploading...';
|
|
1032
1019
|
html += '</span>';
|
|
1033
1020
|
}
|
|
1034
|
-
html += '<button type="button" class="btn btn-sm btn-outline-secondary rounded-pill ai-chat-doc-add-btn d-inline-flex align-items-center gap-1" style="font-size: 0.75rem; padding: 0.15rem 0.5rem;" title="Attach documents">';
|
|
1035
|
-
html += '<
|
|
1021
|
+
html += '<button type="button" class="btn btn-sm btn-outline-secondary rounded-pill ai-chat-doc-add-btn d-inline-flex align-items-center gap-1" style="font-size: 0.75rem; padding: 0.15rem 0.5rem;" title="Attach documents"' + (this.isDocumentOperationPending ? ' disabled' : '') + '>';
|
|
1022
|
+
html += '<i class="fa-solid fa-paperclip"></i>';
|
|
1036
1023
|
if (this.documents.length === 0 && !this.isUploading) {
|
|
1037
1024
|
html += ' <span>Attach files</span>';
|
|
1038
1025
|
}
|
|
@@ -1054,6 +1041,9 @@ window.openAIChatManager = function () {
|
|
|
1054
1041
|
return function (e) {
|
|
1055
1042
|
e.preventDefault();
|
|
1056
1043
|
e.stopPropagation();
|
|
1044
|
+
if (self.isDocumentOperationPending) {
|
|
1045
|
+
return;
|
|
1046
|
+
}
|
|
1057
1047
|
var docToRemove = self.documents[idx];
|
|
1058
1048
|
if (docToRemove) self.removeDocument(docToRemove);
|
|
1059
1049
|
};
|
|
@@ -1078,6 +1068,9 @@ window.openAIChatManager = function () {
|
|
|
1078
1068
|
if (addBtn) {
|
|
1079
1069
|
addBtn.addEventListener('click', function (e) {
|
|
1080
1070
|
e.preventDefault();
|
|
1071
|
+
if (self.isDocumentOperationPending) {
|
|
1072
|
+
return;
|
|
1073
|
+
}
|
|
1081
1074
|
self.triggerFileInput();
|
|
1082
1075
|
});
|
|
1083
1076
|
}
|
|
@@ -1154,139 +1147,135 @@ window.openAIChatManager = function () {
|
|
|
1154
1147
|
return !!message && message.isStreaming && index === this.lastAssistantIndex && !(appearance && appearance.disableStreamingAnimation);
|
|
1155
1148
|
},
|
|
1156
1149
|
startConnection: function startConnection() {
|
|
1157
|
-
var
|
|
1158
|
-
return _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
1159
|
-
var
|
|
1160
|
-
return _regenerator().w(function (
|
|
1161
|
-
while (1) switch (
|
|
1150
|
+
var _this3 = this;
|
|
1151
|
+
return _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee6() {
|
|
1152
|
+
var _t4;
|
|
1153
|
+
return _regenerator().w(function (_context6) {
|
|
1154
|
+
while (1) switch (_context6.p = _context6.n) {
|
|
1162
1155
|
case 0:
|
|
1163
|
-
|
|
1156
|
+
_this3.connection = new signalR.HubConnectionBuilder().withUrl(config.signalRHubUrl).withAutomaticReconnect().build();
|
|
1164
1157
|
|
|
1165
1158
|
// Allow long-running operations (e.g., multi-step MCP tool calls)
|
|
1166
1159
|
// without the client disconnecting prematurely.
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1160
|
+
_this3.connection.serverTimeoutInMilliseconds = 600000;
|
|
1161
|
+
_this3.connection.keepAliveIntervalInMilliseconds = 15000;
|
|
1162
|
+
_this3.connection.on("LoadSession", function (data) {
|
|
1170
1163
|
var _data$messages;
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1164
|
+
_this3.initializeSession(data.sessionId, true);
|
|
1165
|
+
_this3.messages = [];
|
|
1166
|
+
_this3.documents = data.documents || [];
|
|
1167
|
+
_this3.uploadErrors = [];
|
|
1174
1168
|
((_data$messages = data.messages) !== null && _data$messages !== void 0 ? _data$messages : []).forEach(function (msg) {
|
|
1175
|
-
|
|
1176
|
-
|
|
1169
|
+
_this3.addMessage(msg);
|
|
1170
|
+
_this3.$nextTick(function () {
|
|
1177
1171
|
renderChartsInMessage(msg);
|
|
1178
1172
|
});
|
|
1179
1173
|
});
|
|
1180
1174
|
|
|
1181
1175
|
// Update feedback icons in the DOM after all messages have rendered.
|
|
1182
|
-
|
|
1183
|
-
|
|
1176
|
+
_this3.$nextTick(function () {
|
|
1177
|
+
_this3.refreshAllFeedbackIcons();
|
|
1184
1178
|
});
|
|
1185
1179
|
|
|
1186
1180
|
// When the session is new (no messages) and an initial prompt is configured,
|
|
1187
1181
|
// automatically send it as the first user message to trigger an AI response.
|
|
1188
|
-
if (
|
|
1189
|
-
|
|
1190
|
-
|
|
1182
|
+
if (_this3.messages.length === 0 && config.initialPrompt) {
|
|
1183
|
+
_this3.prompt = config.initialPrompt;
|
|
1184
|
+
_this3.sendMessage();
|
|
1191
1185
|
}
|
|
1192
1186
|
});
|
|
1193
|
-
|
|
1187
|
+
_this3.connection.on("ReceiveError", function (error) {
|
|
1194
1188
|
console.error("SignalR Error: ", error);
|
|
1195
|
-
if (
|
|
1196
|
-
|
|
1189
|
+
if (_this3.isRecording) {
|
|
1190
|
+
_this3.stopRecording();
|
|
1197
1191
|
}
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
// clear the cached session and start fresh with the current profile.
|
|
1201
|
-
if (_this4.widgetIsInitialized && !_this4.isSessionStarted && !_this4._attemptedSessionRecovery) {
|
|
1202
|
-
_this4._attemptedSessionRecovery = true;
|
|
1203
|
-
localStorage.removeItem(_this4.chatWidgetStateSession);
|
|
1204
|
-
_this4.startNewSession();
|
|
1192
|
+
if (widgetBehavior && typeof widgetBehavior.handleReceiveError === 'function') {
|
|
1193
|
+
widgetBehavior.handleReceiveError(_this3, error, config);
|
|
1205
1194
|
}
|
|
1206
1195
|
});
|
|
1207
|
-
|
|
1208
|
-
var msg =
|
|
1196
|
+
_this3.connection.on("MessageRated", function (messageId, userRating) {
|
|
1197
|
+
var msg = _this3.messages.find(function (m) {
|
|
1209
1198
|
return m.id === messageId;
|
|
1210
1199
|
});
|
|
1211
1200
|
if (msg) {
|
|
1212
1201
|
msg.userRating = userRating;
|
|
1213
1202
|
}
|
|
1214
1203
|
});
|
|
1215
|
-
|
|
1216
|
-
if (
|
|
1204
|
+
_this3.connection.on("ReceiveTranscript", function (sessionId, text, isFinal) {
|
|
1205
|
+
if (_this3.isConversationMode) {
|
|
1217
1206
|
if (!isFinal && text) {
|
|
1218
|
-
|
|
1207
|
+
_this3._conversationPartialTranscript = text;
|
|
1219
1208
|
var escaped = text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
1220
1209
|
var html = '<p class="ai-partial-transcript">' + escaped + '</p>';
|
|
1221
1210
|
|
|
1222
1211
|
// Show partial transcript as a live user message.
|
|
1223
|
-
if (!
|
|
1224
|
-
|
|
1225
|
-
|
|
1212
|
+
if (!_this3._conversationPartialMessage) {
|
|
1213
|
+
_this3.hidePlaceholder();
|
|
1214
|
+
_this3._conversationPartialMessage = {
|
|
1226
1215
|
role: 'user',
|
|
1227
1216
|
content: text,
|
|
1228
1217
|
htmlContent: html,
|
|
1229
1218
|
isPartial: true
|
|
1230
1219
|
};
|
|
1231
|
-
|
|
1220
|
+
_this3.messages.push(_this3._conversationPartialMessage);
|
|
1232
1221
|
} else {
|
|
1233
|
-
|
|
1234
|
-
|
|
1222
|
+
_this3._conversationPartialMessage.content = text;
|
|
1223
|
+
_this3._conversationPartialMessage.htmlContent = html;
|
|
1235
1224
|
}
|
|
1236
|
-
|
|
1225
|
+
_this3.scrollToBottom();
|
|
1237
1226
|
}
|
|
1238
1227
|
return;
|
|
1239
1228
|
}
|
|
1240
|
-
if (text && !
|
|
1241
|
-
|
|
1242
|
-
if (
|
|
1243
|
-
|
|
1244
|
-
|
|
1229
|
+
if (text && !_this3._audioInputSent) {
|
|
1230
|
+
_this3.prompt = _this3.preRecordingPrompt + text;
|
|
1231
|
+
if (_this3.inputElement) {
|
|
1232
|
+
_this3.inputElement.value = _this3.prompt;
|
|
1233
|
+
_this3.inputElement.dispatchEvent(new Event('input'));
|
|
1245
1234
|
}
|
|
1246
1235
|
}
|
|
1247
1236
|
});
|
|
1248
|
-
|
|
1237
|
+
_this3.connection.on("ReceiveConversationUserMessage", function (sessionId, text) {
|
|
1249
1238
|
if (text) {
|
|
1250
|
-
|
|
1239
|
+
_this3.stopAudio();
|
|
1251
1240
|
|
|
1252
1241
|
// If there's an interrupted assistant message still streaming,
|
|
1253
1242
|
// mark it as done to stop the spinner animation.
|
|
1254
|
-
if (
|
|
1255
|
-
var oldMsg =
|
|
1243
|
+
if (_this3._conversationAssistantMessage) {
|
|
1244
|
+
var oldMsg = _this3.messages[_this3._conversationAssistantMessage.index];
|
|
1256
1245
|
if (oldMsg) {
|
|
1257
1246
|
oldMsg.isStreaming = false;
|
|
1258
1247
|
}
|
|
1259
|
-
|
|
1248
|
+
_this3._conversationAssistantMessage = null;
|
|
1260
1249
|
}
|
|
1261
1250
|
|
|
1262
1251
|
// Replace the partial transcript message with the final one.
|
|
1263
|
-
if (
|
|
1252
|
+
if (_this3._conversationPartialMessage) {
|
|
1264
1253
|
var escaped = text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1254
|
+
_this3._conversationPartialMessage.content = text;
|
|
1255
|
+
_this3._conversationPartialMessage.htmlContent = '<p>' + escaped + '</p>';
|
|
1256
|
+
_this3._conversationPartialMessage.isPartial = false;
|
|
1257
|
+
_this3._conversationPartialMessage = null;
|
|
1269
1258
|
} else {
|
|
1270
|
-
|
|
1259
|
+
_this3.addMessage({
|
|
1271
1260
|
role: 'user',
|
|
1272
1261
|
content: text
|
|
1273
1262
|
});
|
|
1274
1263
|
}
|
|
1275
|
-
|
|
1264
|
+
_this3.scrollToBottom();
|
|
1276
1265
|
}
|
|
1277
1266
|
});
|
|
1278
|
-
|
|
1279
|
-
if (!
|
|
1280
|
-
|
|
1281
|
-
|
|
1267
|
+
_this3.connection.on("ReceiveConversationAssistantToken", function (sessionId, messageId, token, responseId, references, appearance) {
|
|
1268
|
+
if (!_this3._conversationAssistantMessage) {
|
|
1269
|
+
_this3.stopAudio();
|
|
1270
|
+
_this3.hideTypingIndicator();
|
|
1282
1271
|
|
|
1283
1272
|
// Ensure no stale streaming indicators remain from prior messages.
|
|
1284
|
-
for (var j = 0; j <
|
|
1285
|
-
if (
|
|
1286
|
-
|
|
1273
|
+
for (var j = 0; j < _this3.messages.length; j++) {
|
|
1274
|
+
if (_this3.messages[j].isStreaming) {
|
|
1275
|
+
_this3.messages[j].isStreaming = false;
|
|
1287
1276
|
}
|
|
1288
1277
|
}
|
|
1289
|
-
var msgIndex =
|
|
1278
|
+
var msgIndex = _this3.messages.length;
|
|
1290
1279
|
var newMessage = {
|
|
1291
1280
|
id: messageId,
|
|
1292
1281
|
role: "assistant",
|
|
@@ -1294,110 +1283,114 @@ window.openAIChatManager = function () {
|
|
|
1294
1283
|
htmlContent: "",
|
|
1295
1284
|
isStreaming: true,
|
|
1296
1285
|
userRating: null,
|
|
1297
|
-
appearance:
|
|
1286
|
+
appearance: _this3.normalizeAssistantAppearance(appearance),
|
|
1287
|
+
references: {}
|
|
1298
1288
|
};
|
|
1299
|
-
|
|
1300
|
-
|
|
1289
|
+
_this3.messages.push(newMessage);
|
|
1290
|
+
_this3._conversationAssistantMessage = {
|
|
1301
1291
|
index: msgIndex,
|
|
1302
1292
|
content: ''
|
|
1303
1293
|
};
|
|
1304
1294
|
}
|
|
1305
|
-
|
|
1306
|
-
var msg =
|
|
1295
|
+
_this3._conversationAssistantMessage.content += token;
|
|
1296
|
+
var msg = _this3.messages[_this3._conversationAssistantMessage.index];
|
|
1307
1297
|
if (msg) {
|
|
1308
1298
|
if (!msg.appearance) {
|
|
1309
|
-
msg.appearance =
|
|
1299
|
+
msg.appearance = _this3.normalizeAssistantAppearance(appearance);
|
|
1310
1300
|
}
|
|
1311
|
-
msg.
|
|
1312
|
-
msg.
|
|
1313
|
-
|
|
1301
|
+
msg.rawContent = _this3._conversationAssistantMessage.content;
|
|
1302
|
+
msg.references = normalizeReferences(Object.assign({}, msg.references || {}, references || {}));
|
|
1303
|
+
updateMessagePresentation(msg, msg.references);
|
|
1304
|
+
_this3.$nextTick(function () {
|
|
1314
1305
|
renderChartsInMessage(msg);
|
|
1315
|
-
|
|
1306
|
+
_this3.scrollToBottom();
|
|
1316
1307
|
});
|
|
1317
1308
|
}
|
|
1318
1309
|
});
|
|
1319
|
-
|
|
1320
|
-
if (
|
|
1321
|
-
var msg =
|
|
1310
|
+
_this3.connection.on("ReceiveConversationAssistantComplete", function (sessionId, messageId, references) {
|
|
1311
|
+
if (_this3._conversationAssistantMessage) {
|
|
1312
|
+
var msg = _this3.messages[_this3._conversationAssistantMessage.index];
|
|
1322
1313
|
if (msg) {
|
|
1323
1314
|
msg.isStreaming = false;
|
|
1315
|
+
msg.references = normalizeReferences(Object.assign({}, msg.references || {}, references || {}));
|
|
1316
|
+
updateMessagePresentation(msg, msg.references);
|
|
1324
1317
|
}
|
|
1325
|
-
|
|
1318
|
+
_this3._conversationAssistantMessage = null;
|
|
1326
1319
|
}
|
|
1327
1320
|
});
|
|
1328
|
-
|
|
1321
|
+
_this3.connection.on("ReceiveAudioChunk", function (sessionId, base64Audio, contentType) {
|
|
1329
1322
|
if (base64Audio) {
|
|
1330
1323
|
var binaryString = atob(base64Audio);
|
|
1331
1324
|
var bytes = new Uint8Array(binaryString.length);
|
|
1332
1325
|
for (var i = 0; i < binaryString.length; i++) {
|
|
1333
1326
|
bytes[i] = binaryString.charCodeAt(i);
|
|
1334
1327
|
}
|
|
1335
|
-
|
|
1328
|
+
_this3.audioChunks.push(bytes);
|
|
1336
1329
|
}
|
|
1337
1330
|
});
|
|
1338
|
-
|
|
1339
|
-
|
|
1331
|
+
_this3.connection.on("ReceiveAudioComplete", function (sessionId) {
|
|
1332
|
+
_this3.playCollectedAudio();
|
|
1340
1333
|
});
|
|
1341
|
-
|
|
1342
|
-
|
|
1334
|
+
_this3.connection.on("ReceiveNotification", function (notification) {
|
|
1335
|
+
_this3.receiveNotification(notification);
|
|
1343
1336
|
});
|
|
1344
|
-
|
|
1345
|
-
|
|
1337
|
+
_this3.connection.on("UpdateNotification", function (notification) {
|
|
1338
|
+
_this3.updateNotification(notification);
|
|
1346
1339
|
});
|
|
1347
|
-
|
|
1348
|
-
|
|
1340
|
+
_this3.connection.on("RemoveNotification", function (notificationType) {
|
|
1341
|
+
_this3.removeNotification(notificationType);
|
|
1349
1342
|
});
|
|
1350
|
-
|
|
1343
|
+
_this3.connection.onreconnecting(function () {
|
|
1351
1344
|
console.warn("SignalR: reconnecting...");
|
|
1352
1345
|
});
|
|
1353
|
-
|
|
1346
|
+
_this3.connection.onreconnected(function () {
|
|
1354
1347
|
console.info("SignalR: reconnected.");
|
|
1355
|
-
if (
|
|
1356
|
-
|
|
1348
|
+
if (_this3.isSessionStarted) {
|
|
1349
|
+
_this3.reloadCurrentSession();
|
|
1357
1350
|
} else if (config.autoCreateSession) {
|
|
1358
|
-
|
|
1351
|
+
_this3.startNewSession();
|
|
1359
1352
|
}
|
|
1360
1353
|
});
|
|
1361
|
-
|
|
1362
|
-
if (
|
|
1354
|
+
_this3.connection.onclose(function (error) {
|
|
1355
|
+
if (_this3.isNavigatingAway) {
|
|
1363
1356
|
return;
|
|
1364
1357
|
}
|
|
1365
1358
|
if (error) {
|
|
1366
1359
|
console.warn("SignalR connection closed with error:", error.message || error);
|
|
1367
1360
|
}
|
|
1368
1361
|
});
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
return
|
|
1362
|
+
_context6.p = 1;
|
|
1363
|
+
_context6.n = 2;
|
|
1364
|
+
return _this3.connection.start();
|
|
1372
1365
|
case 2:
|
|
1373
|
-
|
|
1366
|
+
_context6.n = 4;
|
|
1374
1367
|
break;
|
|
1375
1368
|
case 3:
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
console.error("SignalR Connection Error: ",
|
|
1369
|
+
_context6.p = 3;
|
|
1370
|
+
_t4 = _context6.v;
|
|
1371
|
+
console.error("SignalR Connection Error: ", _t4);
|
|
1379
1372
|
case 4:
|
|
1380
|
-
return
|
|
1373
|
+
return _context6.a(2);
|
|
1381
1374
|
}
|
|
1382
|
-
},
|
|
1375
|
+
}, _callee6, null, [[1, 3]]);
|
|
1383
1376
|
}))();
|
|
1384
1377
|
},
|
|
1385
1378
|
addMessageInternal: function addMessageInternal(message) {
|
|
1386
|
-
var
|
|
1379
|
+
var _this4 = this;
|
|
1387
1380
|
if (message.role === 'assistant') {
|
|
1388
1381
|
message.appearance = this.normalizeAssistantAppearance(message.appearance);
|
|
1389
1382
|
}
|
|
1390
1383
|
if (message.content && !message.htmlContent) {
|
|
1391
1384
|
message.htmlContent = parseMarkdownContent(message.content, message);
|
|
1392
1385
|
}
|
|
1393
|
-
this.fireEvent(new CustomEvent("
|
|
1386
|
+
this.fireEvent(new CustomEvent("addingCoreAIPromotMessage", {
|
|
1394
1387
|
detail: {
|
|
1395
1388
|
message: message
|
|
1396
1389
|
}
|
|
1397
1390
|
}));
|
|
1398
1391
|
this.messages.push(message);
|
|
1399
1392
|
this.$nextTick(function () {
|
|
1400
|
-
|
|
1393
|
+
_this4.fireEvent(new CustomEvent("addedCoreAIPromotMessage", {
|
|
1401
1394
|
detail: {
|
|
1402
1395
|
message: message
|
|
1403
1396
|
}
|
|
@@ -1405,105 +1398,32 @@ window.openAIChatManager = function () {
|
|
|
1405
1398
|
});
|
|
1406
1399
|
},
|
|
1407
1400
|
addMessage: function addMessage(message) {
|
|
1408
|
-
var
|
|
1401
|
+
var _this5 = this;
|
|
1409
1402
|
// Ensure userRating is always defined for Vue reactivity.
|
|
1410
1403
|
if (message.userRating === undefined) {
|
|
1411
1404
|
message.userRating = null;
|
|
1412
1405
|
}
|
|
1413
1406
|
if (message.content) {
|
|
1414
|
-
var
|
|
1415
|
-
message.
|
|
1416
|
-
|
|
1417
|
-
// Only include references that were actually cited in the response.
|
|
1418
|
-
var citedRefs = Object.entries(message.references).filter(function (_ref4) {
|
|
1419
|
-
var _ref5 = _slicedToArray(_ref4, 1),
|
|
1420
|
-
key = _ref5[0];
|
|
1421
|
-
return processedContent.includes(key);
|
|
1422
|
-
});
|
|
1423
|
-
if (citedRefs.length) {
|
|
1424
|
-
// Sort by original index so display indices follow a natural order.
|
|
1425
|
-
citedRefs.sort(function (_ref6, _ref7) {
|
|
1426
|
-
var _ref8 = _slicedToArray(_ref6, 2),
|
|
1427
|
-
a = _ref8[1];
|
|
1428
|
-
var _ref9 = _slicedToArray(_ref7, 2),
|
|
1429
|
-
b = _ref9[1];
|
|
1430
|
-
return a.index - b.index;
|
|
1431
|
-
});
|
|
1432
|
-
|
|
1433
|
-
// Phase 1: Replace all markers with unique placeholders.
|
|
1434
|
-
var displayIndex = 1;
|
|
1435
|
-
var _iterator2 = _createForOfIteratorHelper(citedRefs),
|
|
1436
|
-
_step2;
|
|
1437
|
-
try {
|
|
1438
|
-
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
1439
|
-
var _step2$value = _slicedToArray(_step2.value, 2),
|
|
1440
|
-
key = _step2$value[0],
|
|
1441
|
-
value = _step2$value[1];
|
|
1442
|
-
var placeholder = "__CITE_".concat(value.index, "__");
|
|
1443
|
-
processedContent = processedContent.replaceAll(key, placeholder);
|
|
1444
|
-
value._displayIndex = displayIndex++;
|
|
1445
|
-
value._placeholder = placeholder;
|
|
1446
|
-
}
|
|
1447
|
-
|
|
1448
|
-
// Phase 2: Replace placeholders with sequential display indices.
|
|
1449
|
-
} catch (err) {
|
|
1450
|
-
_iterator2.e(err);
|
|
1451
|
-
} finally {
|
|
1452
|
-
_iterator2.f();
|
|
1453
|
-
}
|
|
1454
|
-
var _iterator3 = _createForOfIteratorHelper(citedRefs),
|
|
1455
|
-
_step3;
|
|
1456
|
-
try {
|
|
1457
|
-
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
1458
|
-
var _step3$value = _slicedToArray(_step3.value, 2),
|
|
1459
|
-
_value = _step3$value[1];
|
|
1460
|
-
processedContent = processedContent.replaceAll(_value._placeholder, "<sup><strong>".concat(_value._displayIndex, "</strong></sup>"));
|
|
1461
|
-
}
|
|
1462
|
-
|
|
1463
|
-
// if we have multiple references, add a comma to ensure we don't concatenate numbers.
|
|
1464
|
-
} catch (err) {
|
|
1465
|
-
_iterator3.e(err);
|
|
1466
|
-
} finally {
|
|
1467
|
-
_iterator3.f();
|
|
1468
|
-
}
|
|
1469
|
-
processedContent = processedContent.replaceAll('</strong></sup><sup>', '</strong></sup><sup>,</sup><sup>');
|
|
1470
|
-
processedContent += '<br><br>';
|
|
1471
|
-
var _iterator4 = _createForOfIteratorHelper(citedRefs),
|
|
1472
|
-
_step4;
|
|
1473
|
-
try {
|
|
1474
|
-
for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
|
|
1475
|
-
var _step4$value = _slicedToArray(_step4.value, 2),
|
|
1476
|
-
_key = _step4$value[0],
|
|
1477
|
-
_value2 = _step4$value[1];
|
|
1478
|
-
var label = _value2.text || _key;
|
|
1479
|
-
processedContent += _value2.link ? "**".concat(_value2._displayIndex, "**. [").concat(label, "](").concat(_value2.link, ")<br>") : "**".concat(_value2._displayIndex, "**. ").concat(label, "<br>");
|
|
1480
|
-
}
|
|
1481
|
-
} catch (err) {
|
|
1482
|
-
_iterator4.e(err);
|
|
1483
|
-
} finally {
|
|
1484
|
-
_iterator4.f();
|
|
1485
|
-
}
|
|
1486
|
-
}
|
|
1487
|
-
}
|
|
1488
|
-
message.content = processedContent;
|
|
1489
|
-
message.htmlContent = parseMarkdownContent(processedContent, message);
|
|
1407
|
+
var _message$rawContent;
|
|
1408
|
+
message.rawContent = (_message$rawContent = message.rawContent) !== null && _message$rawContent !== void 0 ? _message$rawContent : message.content;
|
|
1409
|
+
updateMessagePresentation(message, message.references);
|
|
1490
1410
|
}
|
|
1491
1411
|
this.addMessageInternal(message);
|
|
1492
1412
|
this.hidePlaceholder();
|
|
1493
1413
|
this.$nextTick(function () {
|
|
1494
1414
|
// Render any pending charts once the DOM is updated
|
|
1495
1415
|
renderChartsInMessage(message);
|
|
1496
|
-
|
|
1416
|
+
_this5.scrollToBottom();
|
|
1497
1417
|
});
|
|
1498
1418
|
},
|
|
1499
1419
|
addMessages: function addMessages(messages) {
|
|
1500
|
-
var
|
|
1420
|
+
var _this6 = this;
|
|
1501
1421
|
for (var i = 0; i < messages.length; i++) {
|
|
1502
1422
|
this.addMessageInternal(messages[i]);
|
|
1503
1423
|
}
|
|
1504
1424
|
this.hidePlaceholder();
|
|
1505
1425
|
this.$nextTick(function () {
|
|
1506
|
-
|
|
1426
|
+
_this6.scrollToBottom();
|
|
1507
1427
|
});
|
|
1508
1428
|
},
|
|
1509
1429
|
hidePlaceholder: function hidePlaceholder() {
|
|
@@ -1580,7 +1500,7 @@ window.openAIChatManager = function () {
|
|
|
1580
1500
|
this.prompt = '';
|
|
1581
1501
|
},
|
|
1582
1502
|
startRecording: function startRecording() {
|
|
1583
|
-
var
|
|
1503
|
+
var _this7 = this;
|
|
1584
1504
|
if (this.isRecording || !this.connection) {
|
|
1585
1505
|
return;
|
|
1586
1506
|
}
|
|
@@ -1592,27 +1512,27 @@ window.openAIChatManager = function () {
|
|
|
1592
1512
|
}
|
|
1593
1513
|
}).then(function (stream) {
|
|
1594
1514
|
var mimeType = MediaRecorder.isTypeSupported('audio/ogg;codecs=opus') ? 'audio/ogg;codecs=opus' : MediaRecorder.isTypeSupported('audio/webm;codecs=opus') ? 'audio/webm;codecs=opus' : 'audio/webm';
|
|
1595
|
-
|
|
1515
|
+
_this7.mediaRecorder = new MediaRecorder(stream, {
|
|
1596
1516
|
mimeType: mimeType,
|
|
1597
1517
|
audioBitsPerSecond: 128000
|
|
1598
1518
|
});
|
|
1599
|
-
|
|
1600
|
-
|
|
1519
|
+
_this7.preRecordingPrompt = _this7.prompt;
|
|
1520
|
+
_this7._audioInputSent = false;
|
|
1601
1521
|
var subject = new signalR.Subject();
|
|
1602
|
-
var profileId =
|
|
1603
|
-
var sessionId =
|
|
1522
|
+
var profileId = _this7.getProfileId();
|
|
1523
|
+
var sessionId = _this7.getSessionId() || '';
|
|
1604
1524
|
var pendingChunk = Promise.resolve();
|
|
1605
|
-
|
|
1525
|
+
_this7.mediaRecorder.addEventListener('dataavailable', function (e) {
|
|
1606
1526
|
if (e.data && e.data.size > 0) {
|
|
1607
|
-
pendingChunk = pendingChunk.then(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
1527
|
+
pendingChunk = pendingChunk.then(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee7() {
|
|
1608
1528
|
var data, uint8Array, binaryString, base64;
|
|
1609
|
-
return _regenerator().w(function (
|
|
1610
|
-
while (1) switch (
|
|
1529
|
+
return _regenerator().w(function (_context7) {
|
|
1530
|
+
while (1) switch (_context7.n) {
|
|
1611
1531
|
case 0:
|
|
1612
|
-
|
|
1532
|
+
_context7.n = 1;
|
|
1613
1533
|
return e.data.arrayBuffer();
|
|
1614
1534
|
case 1:
|
|
1615
|
-
data =
|
|
1535
|
+
data = _context7.v;
|
|
1616
1536
|
uint8Array = new Uint8Array(data);
|
|
1617
1537
|
binaryString = uint8Array.reduce(function (str, _byte) {
|
|
1618
1538
|
return str + String.fromCharCode(_byte);
|
|
@@ -1620,13 +1540,13 @@ window.openAIChatManager = function () {
|
|
|
1620
1540
|
base64 = btoa(binaryString);
|
|
1621
1541
|
subject.next(base64);
|
|
1622
1542
|
case 2:
|
|
1623
|
-
return
|
|
1543
|
+
return _context7.a(2);
|
|
1624
1544
|
}
|
|
1625
|
-
},
|
|
1545
|
+
}, _callee7);
|
|
1626
1546
|
})));
|
|
1627
1547
|
}
|
|
1628
1548
|
});
|
|
1629
|
-
|
|
1549
|
+
_this7.mediaRecorder.addEventListener('stop', function () {
|
|
1630
1550
|
stream.getTracks().forEach(function (track) {
|
|
1631
1551
|
return track.stop();
|
|
1632
1552
|
});
|
|
@@ -1635,10 +1555,10 @@ window.openAIChatManager = function () {
|
|
|
1635
1555
|
});
|
|
1636
1556
|
});
|
|
1637
1557
|
var language = navigator.language || document.documentElement.lang || 'en-US';
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1558
|
+
_this7.connection.send("SendAudioStream", profileId, sessionId, subject, mimeType, language);
|
|
1559
|
+
_this7.mediaRecorder.start(250);
|
|
1560
|
+
_this7.isRecording = true;
|
|
1561
|
+
_this7.updateMicButton();
|
|
1642
1562
|
})["catch"](function (err) {
|
|
1643
1563
|
console.error('Microphone access denied:', err);
|
|
1644
1564
|
});
|
|
@@ -1664,14 +1584,14 @@ window.openAIChatManager = function () {
|
|
|
1664
1584
|
}
|
|
1665
1585
|
if (this.isRecording) {
|
|
1666
1586
|
this.micButton.classList.add('stt-recording');
|
|
1667
|
-
this.micButton.innerHTML = '<
|
|
1587
|
+
this.micButton.innerHTML = '<i class="fa-solid fa-stop"></i>';
|
|
1668
1588
|
} else {
|
|
1669
1589
|
this.micButton.classList.remove('stt-recording');
|
|
1670
|
-
this.micButton.innerHTML = '<
|
|
1590
|
+
this.micButton.innerHTML = '<i class="fa-solid fa-microphone"></i>';
|
|
1671
1591
|
}
|
|
1672
1592
|
},
|
|
1673
1593
|
streamMessage: function streamMessage(profileId, trimmedPrompt, sessionProfileId) {
|
|
1674
|
-
var
|
|
1594
|
+
var _this8 = this;
|
|
1675
1595
|
if (this.stream) {
|
|
1676
1596
|
this.stream.dispose();
|
|
1677
1597
|
this.stream = null;
|
|
@@ -1688,14 +1608,14 @@ window.openAIChatManager = function () {
|
|
|
1688
1608
|
var currentSessionId = this.getSessionId();
|
|
1689
1609
|
this.stream = this.connection.stream("SendMessage", profileId, trimmedPrompt, currentSessionId, sessionProfileId).subscribe({
|
|
1690
1610
|
next: function next(chunk) {
|
|
1691
|
-
var message =
|
|
1611
|
+
var message = _this8.messages[messageIndex];
|
|
1692
1612
|
if (!message) {
|
|
1693
1613
|
if (chunk.sessionId && !currentSessionId) {
|
|
1694
|
-
|
|
1614
|
+
_this8.initializeSession(chunk.sessionId);
|
|
1695
1615
|
}
|
|
1696
|
-
|
|
1616
|
+
_this8.hideTypingIndicator();
|
|
1697
1617
|
// Re-assign the index after hiding the typing indicator.
|
|
1698
|
-
messageIndex =
|
|
1618
|
+
messageIndex = _this8.messages.length;
|
|
1699
1619
|
var newMessage = {
|
|
1700
1620
|
id: chunk.messageId,
|
|
1701
1621
|
role: "assistant",
|
|
@@ -1705,16 +1625,16 @@ window.openAIChatManager = function () {
|
|
|
1705
1625
|
isStreaming: true,
|
|
1706
1626
|
userRating: null
|
|
1707
1627
|
};
|
|
1708
|
-
|
|
1628
|
+
_this8.messages.push(newMessage);
|
|
1709
1629
|
message = newMessage;
|
|
1710
1630
|
}
|
|
1711
1631
|
if (chunk.title && (!message.title || message.title !== chunk.title)) {
|
|
1712
1632
|
message.title = chunk.title;
|
|
1713
1633
|
}
|
|
1714
1634
|
if (chunk.references && _typeof(chunk.references) === "object" && Object.keys(chunk.references).length) {
|
|
1715
|
-
for (var
|
|
1635
|
+
for (var _i4 = 0, _Object$entries2 = Object.entries(chunk.references); _i4 < _Object$entries2.length; _i4++) {
|
|
1716
1636
|
var _normalizeReference2;
|
|
1717
|
-
var _Object$entries2$_i = _slicedToArray(_Object$entries2[
|
|
1637
|
+
var _Object$entries2$_i = _slicedToArray(_Object$entries2[_i4], 2),
|
|
1718
1638
|
key = _Object$entries2$_i[0],
|
|
1719
1639
|
value = _Object$entries2$_i[1];
|
|
1720
1640
|
references[key] = (_normalizeReference2 = normalizeReference(value)) !== null && _normalizeReference2 !== void 0 ? _normalizeReference2 : {};
|
|
@@ -1729,62 +1649,52 @@ window.openAIChatManager = function () {
|
|
|
1729
1649
|
if (chunk.responseId) {
|
|
1730
1650
|
lastResponseId = chunk.responseId;
|
|
1731
1651
|
}
|
|
1732
|
-
|
|
1733
|
-
for (var _i4 = 0, _Object$entries3 = Object.entries(references); _i4 < _Object$entries3.length; _i4++) {
|
|
1734
|
-
var _Object$entries3$_i = _slicedToArray(_Object$entries3[_i4], 2),
|
|
1735
|
-
_key2 = _Object$entries3$_i[0],
|
|
1736
|
-
_value3 = _Object$entries3$_i[1];
|
|
1737
|
-
processedContent = processedContent.replaceAll(_key2, "<sup><strong>".concat(_value3.index, "</strong></sup>"));
|
|
1738
|
-
}
|
|
1739
|
-
|
|
1740
|
-
// Append processed content to the message.
|
|
1741
|
-
// if we have multiple references, add a comma to ensure we don't concatenate numbers.
|
|
1742
|
-
content += processedContent.replaceAll('</strong></sup><sup>', '</strong></sup><sup>,</sup><sup>');
|
|
1652
|
+
content += chunk.content;
|
|
1743
1653
|
}
|
|
1744
1654
|
|
|
1745
1655
|
// Update the existing message
|
|
1746
|
-
message.
|
|
1747
|
-
message
|
|
1748
|
-
|
|
1749
|
-
|
|
1656
|
+
message.rawContent = content;
|
|
1657
|
+
updateMessagePresentation(message, references);
|
|
1658
|
+
_this8.messages[messageIndex] = message;
|
|
1659
|
+
_this8.$nextTick(function () {
|
|
1750
1660
|
renderChartsInMessage(message);
|
|
1751
|
-
|
|
1661
|
+
_this8.scrollToBottom();
|
|
1752
1662
|
});
|
|
1753
1663
|
},
|
|
1754
1664
|
complete: function complete() {
|
|
1755
|
-
var
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
var msg =
|
|
1665
|
+
var _this8$stream;
|
|
1666
|
+
_this8.processReferences(references, messageIndex);
|
|
1667
|
+
_this8.streamingFinished();
|
|
1668
|
+
var msg = _this8.messages[messageIndex];
|
|
1759
1669
|
if (msg) {
|
|
1760
1670
|
msg.isStreaming = false;
|
|
1761
1671
|
}
|
|
1762
1672
|
if (!msg || !msg.content) {
|
|
1763
1673
|
// No content received at all.
|
|
1764
|
-
|
|
1674
|
+
_this8.hideTypingIndicator();
|
|
1765
1675
|
}
|
|
1766
1676
|
|
|
1767
1677
|
// Trigger text-to-speech only in conversation mode.
|
|
1768
|
-
if (
|
|
1769
|
-
|
|
1678
|
+
if (_this8.isConversationMode && _this8.textToSpeechEnabled && msg && msg.content) {
|
|
1679
|
+
_this8.synthesizeSpeech(msg.content);
|
|
1770
1680
|
}
|
|
1771
|
-
(
|
|
1772
|
-
|
|
1681
|
+
(_this8$stream = _this8.stream) === null || _this8$stream === void 0 || _this8$stream.dispose();
|
|
1682
|
+
_this8.stream = null;
|
|
1773
1683
|
},
|
|
1774
1684
|
error: function error(err) {
|
|
1775
|
-
var
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
var msg =
|
|
1685
|
+
var _this8$stream2;
|
|
1686
|
+
_this8.processReferences(references, messageIndex);
|
|
1687
|
+
_this8.streamingFinished();
|
|
1688
|
+
var msg = _this8.messages[messageIndex];
|
|
1779
1689
|
if (msg) {
|
|
1780
1690
|
msg.isStreaming = false;
|
|
1781
1691
|
}
|
|
1782
|
-
|
|
1783
|
-
if (!
|
|
1784
|
-
|
|
1692
|
+
_this8.hideTypingIndicator();
|
|
1693
|
+
if (!_this8.isNavigatingAway) {
|
|
1694
|
+
_this8.addMessage(_this8.getServiceDownMessage());
|
|
1785
1695
|
}
|
|
1786
|
-
(
|
|
1787
|
-
|
|
1696
|
+
(_this8$stream2 = _this8.stream) === null || _this8$stream2 === void 0 || _this8$stream2.dispose();
|
|
1697
|
+
_this8.stream = null;
|
|
1788
1698
|
console.error("Stream error:", err);
|
|
1789
1699
|
}
|
|
1790
1700
|
});
|
|
@@ -1798,92 +1708,17 @@ window.openAIChatManager = function () {
|
|
|
1798
1708
|
return newMessage;
|
|
1799
1709
|
},
|
|
1800
1710
|
processReferences: function processReferences(references, messageIndex) {
|
|
1801
|
-
var
|
|
1711
|
+
var _this9 = this;
|
|
1802
1712
|
references = normalizeReferences(references);
|
|
1803
1713
|
if (Object.keys(references).length) {
|
|
1714
|
+
var _ref23, _message$rawContent2;
|
|
1804
1715
|
var message = this.messages[messageIndex];
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
// Only include references that were actually cited in the response.
|
|
1808
|
-
// Check both raw [doc:N] markers and already-rendered <sup> tags from streaming.
|
|
1809
|
-
var citedRefs = Object.entries(references).filter(function (_ref1) {
|
|
1810
|
-
var _ref10 = _slicedToArray(_ref1, 2),
|
|
1811
|
-
key = _ref10[0],
|
|
1812
|
-
value = _ref10[1];
|
|
1813
|
-
return content.includes(key) || content.includes("<sup><strong>".concat(value.index, "</strong></sup>"));
|
|
1814
|
-
});
|
|
1815
|
-
if (!citedRefs.length) {
|
|
1816
|
-
return;
|
|
1817
|
-
}
|
|
1818
|
-
|
|
1819
|
-
// Sort by original index so display indices follow a natural order.
|
|
1820
|
-
citedRefs.sort(function (_ref11, _ref12) {
|
|
1821
|
-
var _ref13 = _slicedToArray(_ref11, 2),
|
|
1822
|
-
a = _ref13[1];
|
|
1823
|
-
var _ref14 = _slicedToArray(_ref12, 2),
|
|
1824
|
-
b = _ref14[1];
|
|
1825
|
-
return a.index - b.index;
|
|
1826
|
-
});
|
|
1827
|
-
|
|
1828
|
-
// Phase 1: Replace all markers with unique placeholders to avoid collisions during remapping.
|
|
1829
|
-
var processed = content.trim();
|
|
1830
|
-
var displayIndex = 1;
|
|
1831
|
-
var _iterator5 = _createForOfIteratorHelper(citedRefs),
|
|
1832
|
-
_step5;
|
|
1833
|
-
try {
|
|
1834
|
-
for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
|
|
1835
|
-
var _step5$value = _slicedToArray(_step5.value, 2),
|
|
1836
|
-
key = _step5$value[0],
|
|
1837
|
-
value = _step5$value[1];
|
|
1838
|
-
var placeholder = "__CITE_".concat(value.index, "__");
|
|
1839
|
-
processed = processed.replaceAll(key, placeholder);
|
|
1840
|
-
processed = processed.replaceAll("<sup><strong>".concat(value.index, "</strong></sup>"), placeholder);
|
|
1841
|
-
value._displayIndex = displayIndex++;
|
|
1842
|
-
value._placeholder = placeholder;
|
|
1843
|
-
}
|
|
1844
|
-
|
|
1845
|
-
// Phase 2: Replace placeholders with sequential display indices.
|
|
1846
|
-
} catch (err) {
|
|
1847
|
-
_iterator5.e(err);
|
|
1848
|
-
} finally {
|
|
1849
|
-
_iterator5.f();
|
|
1850
|
-
}
|
|
1851
|
-
var _iterator6 = _createForOfIteratorHelper(citedRefs),
|
|
1852
|
-
_step6;
|
|
1853
|
-
try {
|
|
1854
|
-
for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
|
|
1855
|
-
var _step6$value = _slicedToArray(_step6.value, 2),
|
|
1856
|
-
_value4 = _step6$value[1];
|
|
1857
|
-
processed = processed.replaceAll(_value4._placeholder, "<sup><strong>".concat(_value4._displayIndex, "</strong></sup>"));
|
|
1858
|
-
}
|
|
1859
|
-
} catch (err) {
|
|
1860
|
-
_iterator6.e(err);
|
|
1861
|
-
} finally {
|
|
1862
|
-
_iterator6.f();
|
|
1863
|
-
}
|
|
1864
|
-
processed = processed.replaceAll('</strong></sup><sup>', '</strong></sup><sup>,</sup><sup>');
|
|
1865
|
-
processed += '<br><br>';
|
|
1866
|
-
var _iterator7 = _createForOfIteratorHelper(citedRefs),
|
|
1867
|
-
_step7;
|
|
1868
|
-
try {
|
|
1869
|
-
for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
|
|
1870
|
-
var _step7$value = _slicedToArray(_step7.value, 2),
|
|
1871
|
-
_key3 = _step7$value[0],
|
|
1872
|
-
_value5 = _step7$value[1];
|
|
1873
|
-
var label = _value5.text || _key3;
|
|
1874
|
-
processed += _value5.link ? "**".concat(_value5._displayIndex, "**. [").concat(label, "](").concat(_value5.link, ")<br>") : "**".concat(_value5._displayIndex, "**. ").concat(label, "<br>");
|
|
1875
|
-
}
|
|
1876
|
-
} catch (err) {
|
|
1877
|
-
_iterator7.e(err);
|
|
1878
|
-
} finally {
|
|
1879
|
-
_iterator7.f();
|
|
1880
|
-
}
|
|
1881
|
-
message.content = processed;
|
|
1882
|
-
message.htmlContent = parseMarkdownContent(processed, message);
|
|
1716
|
+
message.rawContent = (_ref23 = (_message$rawContent2 = message.rawContent) !== null && _message$rawContent2 !== void 0 ? _message$rawContent2 : message.content) !== null && _ref23 !== void 0 ? _ref23 : '';
|
|
1717
|
+
updateMessagePresentation(message, references);
|
|
1883
1718
|
this.messages[messageIndex] = message;
|
|
1884
1719
|
this.$nextTick(function () {
|
|
1885
1720
|
renderChartsInMessage(message);
|
|
1886
|
-
|
|
1721
|
+
_this9.scrollToBottom();
|
|
1887
1722
|
});
|
|
1888
1723
|
}
|
|
1889
1724
|
},
|
|
@@ -1934,22 +1769,48 @@ window.openAIChatManager = function () {
|
|
|
1934
1769
|
this.stopAudio(false);
|
|
1935
1770
|
},
|
|
1936
1771
|
updateTtsPlaybackButtons: function updateTtsPlaybackButtons() {
|
|
1937
|
-
var
|
|
1772
|
+
var _this0 = this;
|
|
1938
1773
|
if (!this.chatContainer) {
|
|
1939
1774
|
return;
|
|
1940
1775
|
}
|
|
1941
1776
|
var buttons = this.chatContainer.querySelectorAll('[data-tts-message-index]');
|
|
1942
1777
|
buttons.forEach(function (button) {
|
|
1943
1778
|
var buttonIndex = Number(button.getAttribute('data-tts-message-index'));
|
|
1944
|
-
var isPlaying = buttonIndex ===
|
|
1945
|
-
var iconHtml = isPlaying ? '<span class="fa-solid fa-circle-pause"></span>' : '<span class="fa-solid fa-circle-play"></span>';
|
|
1779
|
+
var isPlaying = buttonIndex === _this0.ttsPlayingMessageIndex;
|
|
1946
1780
|
button.classList.toggle('tts-playing', isPlaying);
|
|
1947
1781
|
button.setAttribute('title', isPlaying ? 'Pause audio' : 'Read aloud');
|
|
1782
|
+
});
|
|
1783
|
+
},
|
|
1784
|
+
updateCopyButtons: function updateCopyButtons() {
|
|
1785
|
+
var _this1 = this;
|
|
1786
|
+
if (!this.chatContainer) {
|
|
1787
|
+
return;
|
|
1788
|
+
}
|
|
1789
|
+
var buttons = this.chatContainer.querySelectorAll('[data-copy-message-index]');
|
|
1790
|
+
buttons.forEach(function (button) {
|
|
1791
|
+
var buttonIndex = Number(button.getAttribute('data-copy-message-index'));
|
|
1792
|
+
var isCopied = buttonIndex === _this1.copiedMessageIndex;
|
|
1793
|
+
var iconHtml = isCopied ? '<i class="fa-solid fa-check"></i>' : '<i class="fa-solid fa-copy"></i>';
|
|
1794
|
+
button.classList.toggle('text-success', isCopied);
|
|
1795
|
+
button.classList.toggle('text-secondary', !isCopied);
|
|
1796
|
+
button.setAttribute('title', isCopied ? _this1.copiedTitle : _this1.copyTitle);
|
|
1948
1797
|
button.replaceChildren(DOMPurify.sanitize(iconHtml, {
|
|
1949
1798
|
RETURN_DOM_FRAGMENT: true
|
|
1950
1799
|
}));
|
|
1951
1800
|
});
|
|
1952
1801
|
},
|
|
1802
|
+
setCopyButtonState: function setCopyButtonState(button, isCopied) {
|
|
1803
|
+
if (!button) {
|
|
1804
|
+
return;
|
|
1805
|
+
}
|
|
1806
|
+
var iconHtml = isCopied ? '<i class="fa-solid fa-check"></i>' : '<i class="fa-solid fa-copy"></i>';
|
|
1807
|
+
button.classList.toggle('text-success', isCopied);
|
|
1808
|
+
button.classList.toggle('text-secondary', !isCopied);
|
|
1809
|
+
button.setAttribute('title', isCopied ? this.copiedTitle : this.copyTitle);
|
|
1810
|
+
button.replaceChildren(DOMPurify.sanitize(iconHtml, {
|
|
1811
|
+
RETURN_DOM_FRAGMENT: true
|
|
1812
|
+
}));
|
|
1813
|
+
},
|
|
1953
1814
|
synthesizeSpeech: function synthesizeSpeech(text, cacheIndex) {
|
|
1954
1815
|
var _this10 = this;
|
|
1955
1816
|
if (!this.textToSpeechEnabled || !text || !this.connection) {
|
|
@@ -2007,18 +1868,18 @@ window.openAIChatManager = function () {
|
|
|
2007
1868
|
}, 0);
|
|
2008
1869
|
var combined = new Uint8Array(totalLength);
|
|
2009
1870
|
var offset = 0;
|
|
2010
|
-
var
|
|
2011
|
-
|
|
1871
|
+
var _iterator6 = _createForOfIteratorHelper(this.audioChunks),
|
|
1872
|
+
_step6;
|
|
2012
1873
|
try {
|
|
2013
|
-
for (
|
|
2014
|
-
var chunk =
|
|
1874
|
+
for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
|
|
1875
|
+
var chunk = _step6.value;
|
|
2015
1876
|
combined.set(chunk, offset);
|
|
2016
1877
|
offset += chunk.length;
|
|
2017
1878
|
}
|
|
2018
1879
|
} catch (err) {
|
|
2019
|
-
|
|
1880
|
+
_iterator6.e(err);
|
|
2020
1881
|
} finally {
|
|
2021
|
-
|
|
1882
|
+
_iterator6.f();
|
|
2022
1883
|
}
|
|
2023
1884
|
this.audioChunks = [];
|
|
2024
1885
|
var blob = new Blob([combined], {
|
|
@@ -2173,15 +2034,15 @@ window.openAIChatManager = function () {
|
|
|
2173
2034
|
// Always send audio to STT — browser echo cancellation
|
|
2174
2035
|
// handles speaker echo; continuous audio avoids gaps
|
|
2175
2036
|
// that increase recognition latency.
|
|
2176
|
-
pendingChunk = pendingChunk.then(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
2037
|
+
pendingChunk = pendingChunk.then(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee8() {
|
|
2177
2038
|
var data, uint8Array, binaryString, base64;
|
|
2178
|
-
return _regenerator().w(function (
|
|
2179
|
-
while (1) switch (
|
|
2039
|
+
return _regenerator().w(function (_context8) {
|
|
2040
|
+
while (1) switch (_context8.n) {
|
|
2180
2041
|
case 0:
|
|
2181
|
-
|
|
2042
|
+
_context8.n = 1;
|
|
2182
2043
|
return e.data.arrayBuffer();
|
|
2183
2044
|
case 1:
|
|
2184
|
-
data =
|
|
2045
|
+
data = _context8.v;
|
|
2185
2046
|
uint8Array = new Uint8Array(data);
|
|
2186
2047
|
binaryString = uint8Array.reduce(function (str, _byte2) {
|
|
2187
2048
|
return str + String.fromCharCode(_byte2);
|
|
@@ -2193,9 +2054,9 @@ window.openAIChatManager = function () {
|
|
|
2193
2054
|
// Subject may have been completed already.
|
|
2194
2055
|
}
|
|
2195
2056
|
case 2:
|
|
2196
|
-
return
|
|
2057
|
+
return _context8.a(2);
|
|
2197
2058
|
}
|
|
2198
|
-
},
|
|
2059
|
+
}, _callee8);
|
|
2199
2060
|
})));
|
|
2200
2061
|
}
|
|
2201
2062
|
});
|
|
@@ -2426,19 +2287,20 @@ window.openAIChatManager = function () {
|
|
|
2426
2287
|
this.prompt = event.target.value;
|
|
2427
2288
|
},
|
|
2428
2289
|
getProfileId: function getProfileId() {
|
|
2429
|
-
return this.inputElement.getAttribute('data-profile-id');
|
|
2290
|
+
return this.inputElement ? this.inputElement.getAttribute('data-profile-id') : null;
|
|
2430
2291
|
},
|
|
2431
2292
|
setSessionId: function setSessionId(sessionId) {
|
|
2293
|
+
if (!this.inputElement) {
|
|
2294
|
+
return;
|
|
2295
|
+
}
|
|
2432
2296
|
this.inputElement.setAttribute('data-session-id', sessionId || '');
|
|
2433
2297
|
},
|
|
2434
2298
|
resetSession: function resetSession() {
|
|
2435
2299
|
this.stopRecording();
|
|
2300
|
+
this.rejectPendingSessionRequest('Session was reset.');
|
|
2436
2301
|
this.setSessionId('');
|
|
2437
2302
|
this.isSessionStarted = false;
|
|
2438
2303
|
this.sessionRating = null;
|
|
2439
|
-
if (this.widgetIsInitialized) {
|
|
2440
|
-
localStorage.removeItem(this.chatWidgetStateSession);
|
|
2441
|
-
}
|
|
2442
2304
|
this.messages = [];
|
|
2443
2305
|
this.documents = [];
|
|
2444
2306
|
if (!config.autoCreateSession) {
|
|
@@ -2447,6 +2309,9 @@ window.openAIChatManager = function () {
|
|
|
2447
2309
|
if (config.autoCreateSession) {
|
|
2448
2310
|
this.startNewSession();
|
|
2449
2311
|
}
|
|
2312
|
+
if (widgetBehavior && typeof widgetBehavior.onSessionReset === 'function') {
|
|
2313
|
+
widgetBehavior.onSessionReset(this, config);
|
|
2314
|
+
}
|
|
2450
2315
|
},
|
|
2451
2316
|
startNewSession: function startNewSession() {
|
|
2452
2317
|
if (!this.applyOrchestratorAvailability()) {
|
|
@@ -2456,16 +2321,94 @@ window.openAIChatManager = function () {
|
|
|
2456
2321
|
if (!profileId || !this.connection) {
|
|
2457
2322
|
return;
|
|
2458
2323
|
}
|
|
2459
|
-
this.
|
|
2324
|
+
this.requestNewSession(profileId)["catch"](function (err) {
|
|
2460
2325
|
return console.error(err);
|
|
2461
2326
|
});
|
|
2462
2327
|
},
|
|
2463
|
-
|
|
2328
|
+
ensureSessionForDocuments: function ensureSessionForDocuments(profileId) {
|
|
2464
2329
|
var _this20 = this;
|
|
2330
|
+
return _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee9() {
|
|
2331
|
+
var sessionId;
|
|
2332
|
+
return _regenerator().w(function (_context9) {
|
|
2333
|
+
while (1) switch (_context9.n) {
|
|
2334
|
+
case 0:
|
|
2335
|
+
sessionId = _this20.getSessionId();
|
|
2336
|
+
if (!sessionId) {
|
|
2337
|
+
_context9.n = 1;
|
|
2338
|
+
break;
|
|
2339
|
+
}
|
|
2340
|
+
return _context9.a(2, sessionId);
|
|
2341
|
+
case 1:
|
|
2342
|
+
if (!(!profileId || !_this20.connection)) {
|
|
2343
|
+
_context9.n = 2;
|
|
2344
|
+
break;
|
|
2345
|
+
}
|
|
2346
|
+
return _context9.a(2, null);
|
|
2347
|
+
case 2:
|
|
2348
|
+
_context9.n = 3;
|
|
2349
|
+
return _this20.requestNewSession(profileId);
|
|
2350
|
+
case 3:
|
|
2351
|
+
return _context9.a(2, _context9.v);
|
|
2352
|
+
}
|
|
2353
|
+
}, _callee9);
|
|
2354
|
+
}))();
|
|
2355
|
+
},
|
|
2356
|
+
requestNewSession: function requestNewSession(profileId) {
|
|
2357
|
+
var _this21 = this;
|
|
2358
|
+
if (this.pendingSessionPromise) {
|
|
2359
|
+
return this.pendingSessionPromise;
|
|
2360
|
+
}
|
|
2361
|
+
if (!profileId || !this.connection) {
|
|
2362
|
+
return Promise.resolve(null);
|
|
2363
|
+
}
|
|
2364
|
+
this.pendingSessionPromise = new Promise(function (resolve, reject) {
|
|
2365
|
+
_this21.pendingSessionResolver = resolve;
|
|
2366
|
+
_this21.pendingSessionRejector = reject;
|
|
2367
|
+
_this21.pendingSessionTimeoutId = window.setTimeout(function () {
|
|
2368
|
+
_this21.rejectPendingSessionRequest('Timed out while creating a chat session.');
|
|
2369
|
+
}, 15000);
|
|
2370
|
+
});
|
|
2371
|
+
this.connection.invoke("StartSession", profileId, null)["catch"](function (err) {
|
|
2372
|
+
_this21.rejectPendingSessionRequest(err);
|
|
2373
|
+
});
|
|
2374
|
+
return this.pendingSessionPromise;
|
|
2375
|
+
},
|
|
2376
|
+
resolvePendingSessionRequest: function resolvePendingSessionRequest(sessionId) {
|
|
2377
|
+
if (this.pendingSessionResolver) {
|
|
2378
|
+
this.pendingSessionResolver(sessionId);
|
|
2379
|
+
}
|
|
2380
|
+
this.clearPendingSessionRequest();
|
|
2381
|
+
},
|
|
2382
|
+
rejectPendingSessionRequest: function rejectPendingSessionRequest(error) {
|
|
2383
|
+
if (this.pendingSessionRejector) {
|
|
2384
|
+
this.pendingSessionRejector(error);
|
|
2385
|
+
}
|
|
2386
|
+
this.clearPendingSessionRequest();
|
|
2387
|
+
},
|
|
2388
|
+
clearPendingSessionRequest: function clearPendingSessionRequest() {
|
|
2389
|
+
if (this.pendingSessionTimeoutId) {
|
|
2390
|
+
window.clearTimeout(this.pendingSessionTimeoutId);
|
|
2391
|
+
}
|
|
2392
|
+
this.pendingSessionPromise = null;
|
|
2393
|
+
this.pendingSessionResolver = null;
|
|
2394
|
+
this.pendingSessionRejector = null;
|
|
2395
|
+
this.pendingSessionTimeoutId = null;
|
|
2396
|
+
},
|
|
2397
|
+
initializeApp: function initializeApp() {
|
|
2398
|
+
var _this22 = this;
|
|
2465
2399
|
this.inputElement = document.querySelector(config.inputElementSelector);
|
|
2466
2400
|
this.buttonElement = document.querySelector(config.sendButtonElementSelector);
|
|
2467
2401
|
this.chatContainer = document.querySelector(config.chatContainerElementSelector);
|
|
2468
2402
|
this.placeholder = document.querySelector(config.placeholderElementSelector);
|
|
2403
|
+
if (!this.inputElement || !this.buttonElement || !this.chatContainer || !this.placeholder) {
|
|
2404
|
+
console.error('AI chat app could not initialize because one or more required elements were not found.', {
|
|
2405
|
+
inputElementSelector: config.inputElementSelector,
|
|
2406
|
+
sendButtonElementSelector: config.sendButtonElementSelector,
|
|
2407
|
+
chatContainerElementSelector: config.chatContainerElementSelector,
|
|
2408
|
+
placeholderElementSelector: config.placeholderElementSelector
|
|
2409
|
+
});
|
|
2410
|
+
return false;
|
|
2411
|
+
}
|
|
2469
2412
|
this.applyOrchestratorAvailability();
|
|
2470
2413
|
var sessionId = this.getSessionId();
|
|
2471
2414
|
if (!hasWidgetConfig && sessionId) {
|
|
@@ -2490,7 +2433,7 @@ window.openAIChatManager = function () {
|
|
|
2490
2433
|
fileInput.accept = config.allowedExtensions;
|
|
2491
2434
|
}
|
|
2492
2435
|
fileInput.addEventListener('change', function (e) {
|
|
2493
|
-
return
|
|
2436
|
+
return _this22.handleFileInputChange(e);
|
|
2494
2437
|
});
|
|
2495
2438
|
this.documentBar.parentElement.appendChild(fileInput);
|
|
2496
2439
|
|
|
@@ -2498,13 +2441,13 @@ window.openAIChatManager = function () {
|
|
|
2498
2441
|
var inputArea = this.inputElement ? this.inputElement.closest('.ai-admin-widget-input, .text-bg-light') : null;
|
|
2499
2442
|
if (inputArea) {
|
|
2500
2443
|
inputArea.addEventListener('dragover', function (e) {
|
|
2501
|
-
return
|
|
2444
|
+
return _this22.handleDragOver(e);
|
|
2502
2445
|
});
|
|
2503
2446
|
inputArea.addEventListener('dragleave', function (e) {
|
|
2504
|
-
return
|
|
2447
|
+
return _this22.handleDragLeave(e);
|
|
2505
2448
|
});
|
|
2506
2449
|
inputArea.addEventListener('drop', function (e) {
|
|
2507
|
-
return
|
|
2450
|
+
return _this22.handleDrop(e);
|
|
2508
2451
|
});
|
|
2509
2452
|
}
|
|
2510
2453
|
}
|
|
@@ -2512,55 +2455,55 @@ window.openAIChatManager = function () {
|
|
|
2512
2455
|
|
|
2513
2456
|
// Pause auto-scroll when the user manually scrolls up during streaming.
|
|
2514
2457
|
this.chatContainer.addEventListener('scroll', function () {
|
|
2515
|
-
if (!
|
|
2458
|
+
if (!_this22.stream) {
|
|
2516
2459
|
return;
|
|
2517
2460
|
}
|
|
2518
2461
|
var threshold = 30;
|
|
2519
|
-
var atBottom =
|
|
2520
|
-
|
|
2462
|
+
var atBottom = _this22.chatContainer.scrollHeight - _this22.chatContainer.clientHeight - _this22.chatContainer.scrollTop <= threshold;
|
|
2463
|
+
_this22.autoScroll = atBottom;
|
|
2521
2464
|
});
|
|
2522
2465
|
this.inputElement.addEventListener('keydown', function (event) {
|
|
2523
|
-
if (
|
|
2466
|
+
if (_this22.stream != null) {
|
|
2524
2467
|
return;
|
|
2525
2468
|
}
|
|
2526
2469
|
if (event.key === "Enter" && !event.shiftKey) {
|
|
2527
2470
|
event.preventDefault();
|
|
2528
|
-
|
|
2471
|
+
_this22.buttonElement.click();
|
|
2529
2472
|
}
|
|
2530
2473
|
});
|
|
2531
2474
|
this.inputElement.addEventListener('input', function (e) {
|
|
2532
|
-
|
|
2475
|
+
_this22.handleUserInput(e);
|
|
2533
2476
|
if (e.target.value.trim()) {
|
|
2534
|
-
|
|
2477
|
+
_this22.buttonElement.removeAttribute('disabled');
|
|
2535
2478
|
} else {
|
|
2536
|
-
|
|
2479
|
+
_this22.buttonElement.setAttribute('disabled', true);
|
|
2537
2480
|
}
|
|
2538
2481
|
});
|
|
2539
2482
|
this.buttonElement.addEventListener('click', function () {
|
|
2540
|
-
if (
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2483
|
+
if (_this22.stream != null) {
|
|
2484
|
+
_this22.stream.dispose();
|
|
2485
|
+
_this22.stream = null;
|
|
2486
|
+
_this22.streamingFinished();
|
|
2487
|
+
_this22.hideTypingIndicator();
|
|
2545
2488
|
|
|
2546
2489
|
// Clean up: remove empty assistant message or stop streaming animation.
|
|
2547
|
-
if (
|
|
2548
|
-
var lastMsg =
|
|
2490
|
+
if (_this22.messages.length > 0) {
|
|
2491
|
+
var lastMsg = _this22.messages[_this22.messages.length - 1];
|
|
2549
2492
|
if (lastMsg.role === 'assistant' && !lastMsg.content) {
|
|
2550
|
-
|
|
2493
|
+
_this22.messages.pop();
|
|
2551
2494
|
} else if (lastMsg.isStreaming) {
|
|
2552
2495
|
lastMsg.isStreaming = false;
|
|
2553
2496
|
}
|
|
2554
2497
|
}
|
|
2555
2498
|
return;
|
|
2556
2499
|
}
|
|
2557
|
-
|
|
2500
|
+
_this22.sendMessage();
|
|
2558
2501
|
});
|
|
2559
2502
|
var promptGenerators = document.getElementsByClassName('profile-generated-prompt');
|
|
2560
2503
|
for (var i = 0; i < promptGenerators.length; i++) {
|
|
2561
2504
|
promptGenerators[i].addEventListener('click', function (e) {
|
|
2562
2505
|
e.preventDefault();
|
|
2563
|
-
|
|
2506
|
+
_this22.generatePrompt(e.target);
|
|
2564
2507
|
});
|
|
2565
2508
|
}
|
|
2566
2509
|
var chatSessions = document.getElementsByClassName('chat-session-history-item');
|
|
@@ -2572,17 +2515,18 @@ window.openAIChatManager = function () {
|
|
|
2572
2515
|
console.error('an element with the class chat-session-history-item with no data-session-id set.');
|
|
2573
2516
|
return;
|
|
2574
2517
|
}
|
|
2575
|
-
|
|
2576
|
-
|
|
2518
|
+
_this22.loadSession(sessionId);
|
|
2519
|
+
_this22.showChatScreen();
|
|
2577
2520
|
});
|
|
2578
2521
|
}
|
|
2579
|
-
|
|
2580
|
-
|
|
2522
|
+
var initialMessages = Array.isArray(config.messages) ? config.messages : [];
|
|
2523
|
+
for (var _i5 = 0; _i5 < initialMessages.length; _i5++) {
|
|
2524
|
+
this.addMessage(initialMessages[_i5]);
|
|
2581
2525
|
}
|
|
2582
2526
|
|
|
2583
2527
|
// Update feedback icons in the DOM after initial messages have rendered.
|
|
2584
2528
|
this.$nextTick(function () {
|
|
2585
|
-
|
|
2529
|
+
_this22.refreshAllFeedbackIcons();
|
|
2586
2530
|
});
|
|
2587
2531
|
|
|
2588
2532
|
// Delegate click for code block copy buttons.
|
|
@@ -2600,9 +2544,9 @@ window.openAIChatManager = function () {
|
|
|
2600
2544
|
if (codeEl) {
|
|
2601
2545
|
navigator.clipboard.writeText(codeEl.textContent);
|
|
2602
2546
|
var copiedText = config.codeCopiedText || 'Copied!';
|
|
2603
|
-
btn.innerHTML = '<
|
|
2547
|
+
btn.innerHTML = '<i class="fa-solid fa-check"></i> ' + copiedText;
|
|
2604
2548
|
setTimeout(function () {
|
|
2605
|
-
btn.innerHTML = '<
|
|
2549
|
+
btn.innerHTML = '<i class="fa-regular fa-copy"></i>';
|
|
2606
2550
|
}, 2000);
|
|
2607
2551
|
}
|
|
2608
2552
|
});
|
|
@@ -2614,7 +2558,7 @@ window.openAIChatManager = function () {
|
|
|
2614
2558
|
if (this.micButton) {
|
|
2615
2559
|
this.micButton.style.display = '';
|
|
2616
2560
|
this.micButton.addEventListener('click', function () {
|
|
2617
|
-
|
|
2561
|
+
_this22.toggleRecording();
|
|
2618
2562
|
});
|
|
2619
2563
|
}
|
|
2620
2564
|
}
|
|
@@ -2624,10 +2568,11 @@ window.openAIChatManager = function () {
|
|
|
2624
2568
|
this.conversationButton = document.querySelector(config.conversationButtonElementSelector);
|
|
2625
2569
|
if (this.conversationButton) {
|
|
2626
2570
|
this.conversationButton.addEventListener('click', function () {
|
|
2627
|
-
|
|
2571
|
+
_this22.toggleConversationMode();
|
|
2628
2572
|
});
|
|
2629
2573
|
}
|
|
2630
2574
|
}
|
|
2575
|
+
return true;
|
|
2631
2576
|
},
|
|
2632
2577
|
loadSession: function loadSession(sessionId) {
|
|
2633
2578
|
this.connection.invoke("LoadSession", sessionId)["catch"](function (err) {
|
|
@@ -2642,130 +2587,69 @@ window.openAIChatManager = function () {
|
|
|
2642
2587
|
},
|
|
2643
2588
|
initializeSession: function initializeSession(sessionId, force) {
|
|
2644
2589
|
if (this.isSessionStarted && !force) {
|
|
2590
|
+
if (sessionId && this.getSessionId() === sessionId) {
|
|
2591
|
+
this.resolvePendingSessionRequest(sessionId);
|
|
2592
|
+
}
|
|
2645
2593
|
return;
|
|
2646
2594
|
}
|
|
2647
|
-
this.fireEvent(new CustomEvent("
|
|
2595
|
+
this.fireEvent(new CustomEvent("initializingSessionCoreAIChat", {
|
|
2648
2596
|
detail: {
|
|
2649
2597
|
sessionId: sessionId
|
|
2650
2598
|
}
|
|
2651
2599
|
}));
|
|
2652
2600
|
this.setSessionId(sessionId);
|
|
2653
2601
|
this.isSessionStarted = true;
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
},
|
|
2658
|
-
initializeWidget: function initializeWidget() {
|
|
2659
|
-
var _this21 = this;
|
|
2660
|
-
if (!config.widget.chatWidgetContainer) {
|
|
2661
|
-
console.error('The widget chatWidgetContainer is required.');
|
|
2662
|
-
return;
|
|
2663
|
-
}
|
|
2664
|
-
if (!config.widget.chatWidgetStateName) {
|
|
2665
|
-
console.error('The widget chatWidgetStateName is required.');
|
|
2666
|
-
return;
|
|
2667
|
-
}
|
|
2668
|
-
var chatWidgetContainer = document.querySelector(config.widget.chatWidgetContainer);
|
|
2669
|
-
if (!chatWidgetContainer) {
|
|
2670
|
-
return;
|
|
2671
|
-
}
|
|
2672
|
-
if (config.widget.chatHistorySection) {
|
|
2673
|
-
this.chatHistorySection = document.querySelector(config.widget.chatHistorySection);
|
|
2674
|
-
}
|
|
2675
|
-
this.chatWidgetStateName = config.widget.chatWidgetStateName;
|
|
2676
|
-
this.chatWidgetStateSession = config.widget.chatWidgetStateName + 'Session';
|
|
2677
|
-
this.chatWidgetLayoutKey = config.widget.chatWidgetStateName + 'Layout';
|
|
2678
|
-
this.widgetContainerElement = chatWidgetContainer;
|
|
2679
|
-
this.widgetToggleButtonElement = config.widget.toggleButtonSelector ? document.querySelector(config.widget.toggleButtonSelector) : null;
|
|
2680
|
-
this.widgetResetSizeButtonElement = config.widget.resetSizeButtonSelector ? document.querySelector(config.widget.resetSizeButtonSelector) : null;
|
|
2681
|
-
this.widgetDefaultWidth = parsePixelValue(config.widget.defaultWidth) || parsePixelValue(window.getComputedStyle(chatWidgetContainer).width) || 380;
|
|
2682
|
-
this.widgetDefaultHeight = parsePixelValue(config.widget.defaultHeight) || parsePixelValue(window.getComputedStyle(chatWidgetContainer).height) || 520;
|
|
2683
|
-
this.widgetIsInitialized = true;
|
|
2684
|
-
if (config.widget.enableResizing) {
|
|
2685
|
-
chatWidgetContainer.classList.add('ai-chat-widget-resizable');
|
|
2686
|
-
chatWidgetContainer.style.minWidth = (parsePixelValue(config.widget.minWidth) || 320) + 'px';
|
|
2687
|
-
chatWidgetContainer.style.minHeight = (parsePixelValue(config.widget.minHeight) || 420) + 'px';
|
|
2688
|
-
if (typeof ResizeObserver !== 'undefined') {
|
|
2689
|
-
this.widgetResizeObserver = new ResizeObserver(function () {
|
|
2690
|
-
_this21.persistWidgetPanelSize();
|
|
2691
|
-
_this21.constrainWidgetElementsToViewport();
|
|
2692
|
-
_this21.updateWidgetResetSizeButtonVisibility();
|
|
2693
|
-
});
|
|
2694
|
-
this.widgetResizeObserver.observe(chatWidgetContainer);
|
|
2695
|
-
}
|
|
2696
|
-
}
|
|
2697
|
-
var dragHandleSelector = config.widget.dragHandleSelector || '.ai-chat-widget-header';
|
|
2698
|
-
var dragHandle = chatWidgetContainer.querySelector(dragHandleSelector);
|
|
2699
|
-
if (config.widget.enableDragging && dragHandle) {
|
|
2700
|
-
dragHandle.classList.add('ai-chat-widget-drag-handle');
|
|
2701
|
-
chatWidgetContainer.classList.add('ai-chat-widget-draggable');
|
|
2702
|
-
this.attachDraggableWidgetElement(chatWidgetContainer, dragHandle, 'panel', false);
|
|
2703
|
-
}
|
|
2704
|
-
if (config.widget.enableDragging && this.widgetToggleButtonElement) {
|
|
2705
|
-
this.widgetToggleButtonElement.classList.add('ai-chat-widget-draggable');
|
|
2706
|
-
this.attachDraggableWidgetElement(this.widgetToggleButtonElement, this.widgetToggleButtonElement, 'toggle', true);
|
|
2707
|
-
}
|
|
2708
|
-
if (this.widgetResetSizeButtonElement) {
|
|
2709
|
-
this.widgetResetSizeButtonElement.addEventListener('click', function (event) {
|
|
2710
|
-
event.preventDefault();
|
|
2711
|
-
_this21.resetWidgetSize();
|
|
2712
|
-
});
|
|
2713
|
-
}
|
|
2714
|
-
this.restoreWidgetLayout();
|
|
2715
|
-
if (!this.widgetViewportResizeHandler) {
|
|
2716
|
-
this.widgetViewportResizeHandler = function () {
|
|
2717
|
-
_this21.constrainWidgetElementsToViewport();
|
|
2718
|
-
_this21.updateWidgetResetSizeButtonVisibility();
|
|
2719
|
-
};
|
|
2720
|
-
window.addEventListener('resize', this.widgetViewportResizeHandler);
|
|
2721
|
-
}
|
|
2722
|
-
|
|
2723
|
-
// Auto-load the last session so the user always sees previous chat history.
|
|
2724
|
-
this.reloadCurrentSession();
|
|
2725
|
-
if (config.autoCreateSession && !this.getSessionId()) {
|
|
2726
|
-
this.startNewSession();
|
|
2727
|
-
}
|
|
2728
|
-
if (config.widget.showHistoryButton && this.chatHistorySection) {
|
|
2729
|
-
var showHistoryButton = document.querySelector(config.widget.showHistoryButton);
|
|
2730
|
-
if (showHistoryButton) {
|
|
2731
|
-
showHistoryButton.addEventListener('click', function () {
|
|
2732
|
-
_this21.chatHistorySection.classList.toggle('show');
|
|
2733
|
-
});
|
|
2734
|
-
}
|
|
2735
|
-
if (config.widget.closeHistoryButton) {
|
|
2736
|
-
var closeHistoryButton = document.querySelector(config.widget.closeHistoryButton);
|
|
2737
|
-
if (closeHistoryButton) {
|
|
2738
|
-
closeHistoryButton.addEventListener('click', function () {
|
|
2739
|
-
_this21.showChatScreen();
|
|
2740
|
-
});
|
|
2741
|
-
}
|
|
2742
|
-
}
|
|
2743
|
-
}
|
|
2744
|
-
if (config.widget.newChatButton) {
|
|
2745
|
-
var newChatButton = document.querySelector(config.widget.newChatButton);
|
|
2746
|
-
if (newChatButton) {
|
|
2747
|
-
newChatButton.addEventListener('click', function () {
|
|
2748
|
-
_this21.resetSession();
|
|
2749
|
-
_this21.showChatScreen();
|
|
2750
|
-
});
|
|
2751
|
-
}
|
|
2752
|
-
}
|
|
2753
|
-
},
|
|
2754
|
-
showChatScreen: function showChatScreen() {
|
|
2755
|
-
if (!this.chatHistorySection) {
|
|
2756
|
-
return;
|
|
2602
|
+
this.resolvePendingSessionRequest(sessionId);
|
|
2603
|
+
if (widgetBehavior && typeof widgetBehavior.onSessionInitialized === 'function') {
|
|
2604
|
+
widgetBehavior.onSessionInitialized(this, sessionId, config);
|
|
2757
2605
|
}
|
|
2758
|
-
this.chatHistorySection.classList.remove('show');
|
|
2759
2606
|
},
|
|
2760
2607
|
getSessionId: function getSessionId() {
|
|
2761
|
-
var sessionId = this.inputElement.getAttribute('data-session-id');
|
|
2762
|
-
if (!sessionId &&
|
|
2763
|
-
sessionId =
|
|
2608
|
+
var sessionId = this.inputElement ? this.inputElement.getAttribute('data-session-id') : null;
|
|
2609
|
+
if (!sessionId && widgetBehavior && typeof widgetBehavior.resolveSessionId === 'function') {
|
|
2610
|
+
sessionId = widgetBehavior.resolveSessionId(this, config);
|
|
2764
2611
|
}
|
|
2765
2612
|
return sessionId;
|
|
2766
2613
|
},
|
|
2767
|
-
|
|
2768
|
-
|
|
2614
|
+
clearCopiedMessageState: function clearCopiedMessageState() {
|
|
2615
|
+
if (this.copyResetTimeoutId) {
|
|
2616
|
+
window.clearTimeout(this.copyResetTimeoutId);
|
|
2617
|
+
this.copyResetTimeoutId = null;
|
|
2618
|
+
}
|
|
2619
|
+
if (this.activeCopyButton) {
|
|
2620
|
+
this.setCopyButtonState(this.activeCopyButton, false);
|
|
2621
|
+
this.activeCopyButton = null;
|
|
2622
|
+
}
|
|
2623
|
+
this.copiedMessageIndex = -1;
|
|
2624
|
+
},
|
|
2625
|
+
copyResponse: function copyResponse(message, index, event) {
|
|
2626
|
+
var _ref25,
|
|
2627
|
+
_message$copyContent,
|
|
2628
|
+
_event$target,
|
|
2629
|
+
_event$target$closest,
|
|
2630
|
+
_this23 = this;
|
|
2631
|
+
var text = message && _typeof(message) === 'object' ? (_ref25 = (_message$copyContent = message.copyContent) !== null && _message$copyContent !== void 0 ? _message$copyContent : message.content) !== null && _ref25 !== void 0 ? _ref25 : '' : message !== null && message !== void 0 ? message : '';
|
|
2632
|
+
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;
|
|
2633
|
+
navigator.clipboard.writeText(text).then(function () {
|
|
2634
|
+
_this23.clearCopiedMessageState();
|
|
2635
|
+
_this23.copiedMessageIndex = typeof index === 'number' ? index : -1;
|
|
2636
|
+
_this23.activeCopyButton = button;
|
|
2637
|
+
if (button) {
|
|
2638
|
+
_this23.setCopyButtonState(button, true);
|
|
2639
|
+
} else {
|
|
2640
|
+
_this23.$nextTick(function () {
|
|
2641
|
+
return _this23.updateCopyButtons();
|
|
2642
|
+
});
|
|
2643
|
+
}
|
|
2644
|
+
_this23.copyResetTimeoutId = window.setTimeout(function () {
|
|
2645
|
+
_this23.clearCopiedMessageState();
|
|
2646
|
+
_this23.$nextTick(function () {
|
|
2647
|
+
return _this23.updateCopyButtons();
|
|
2648
|
+
});
|
|
2649
|
+
}, Number(config.copyResetDelayMs) || 2000);
|
|
2650
|
+
})["catch"](function (err) {
|
|
2651
|
+
return console.error('Failed to copy response:', err);
|
|
2652
|
+
});
|
|
2769
2653
|
},
|
|
2770
2654
|
updateFeedbackIcons: function updateFeedbackIcons(container, userRating) {
|
|
2771
2655
|
if (!container) {
|
|
@@ -2844,16 +2728,28 @@ window.openAIChatManager = function () {
|
|
|
2844
2728
|
documents: {
|
|
2845
2729
|
handler: function handler() {
|
|
2846
2730
|
this.renderDocumentBar();
|
|
2731
|
+
if (widgetBehavior && typeof widgetBehavior.onDocumentsChanged === 'function') {
|
|
2732
|
+
widgetBehavior.onDocumentsChanged(this, this.documents, config);
|
|
2733
|
+
}
|
|
2847
2734
|
},
|
|
2848
2735
|
deep: true
|
|
2849
2736
|
},
|
|
2850
2737
|
isUploading: function isUploading() {
|
|
2851
2738
|
this.renderDocumentBar();
|
|
2852
2739
|
},
|
|
2740
|
+
isDocumentOperationPending: function isDocumentOperationPending() {
|
|
2741
|
+
this.renderDocumentBar();
|
|
2742
|
+
},
|
|
2853
2743
|
isPlayingAudio: function isPlayingAudio() {
|
|
2854
2744
|
// Reserved for future use — volume-based interrupt detection
|
|
2855
2745
|
// no longer mutes tracks; browser echo cancellation handles echo.
|
|
2856
2746
|
},
|
|
2747
|
+
copiedMessageIndex: function copiedMessageIndex() {
|
|
2748
|
+
var _this24 = this;
|
|
2749
|
+
this.$nextTick(function () {
|
|
2750
|
+
return _this24.updateCopyButtons();
|
|
2751
|
+
});
|
|
2752
|
+
},
|
|
2857
2753
|
isConversationMode: function isConversationMode(active) {
|
|
2858
2754
|
// Hide/show mic button.
|
|
2859
2755
|
if (this.micButton) {
|
|
@@ -2875,22 +2771,28 @@ window.openAIChatManager = function () {
|
|
|
2875
2771
|
}
|
|
2876
2772
|
},
|
|
2877
2773
|
mounted: function mounted() {
|
|
2878
|
-
var
|
|
2879
|
-
_asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
2880
|
-
|
|
2881
|
-
|
|
2774
|
+
var _this25 = this;
|
|
2775
|
+
_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee0() {
|
|
2776
|
+
var isInitialized;
|
|
2777
|
+
return _regenerator().w(function (_context0) {
|
|
2778
|
+
while (1) switch (_context0.n) {
|
|
2882
2779
|
case 0:
|
|
2883
|
-
|
|
2884
|
-
return
|
|
2780
|
+
_context0.n = 1;
|
|
2781
|
+
return _this25.startConnection();
|
|
2885
2782
|
case 1:
|
|
2886
|
-
|
|
2887
|
-
if (hasWidgetConfig) {
|
|
2888
|
-
|
|
2783
|
+
isInitialized = _this25.initializeApp();
|
|
2784
|
+
if (isInitialized && hasWidgetConfig && widgetBehavior && typeof widgetBehavior.onMounted === 'function') {
|
|
2785
|
+
widgetBehavior.onMounted(_this25, config);
|
|
2889
2786
|
}
|
|
2787
|
+
_this25.$nextTick(function () {
|
|
2788
|
+
_this25.updateCopyButtons();
|
|
2789
|
+
refreshFontAwesomeIcons(_this25.$el);
|
|
2790
|
+
_this25.fontAwesomeObserver = observeFontAwesomeIcons(_this25.$el);
|
|
2791
|
+
});
|
|
2890
2792
|
case 2:
|
|
2891
|
-
return
|
|
2793
|
+
return _context0.a(2);
|
|
2892
2794
|
}
|
|
2893
|
-
},
|
|
2795
|
+
}, _callee0);
|
|
2894
2796
|
}))();
|
|
2895
2797
|
window.addEventListener('beforeunload', this.handleBeforeUnload);
|
|
2896
2798
|
window.addEventListener('crestapps-ai-chat-stop-tts', this.handleExternalTtsStop);
|
|
@@ -2898,6 +2800,11 @@ window.openAIChatManager = function () {
|
|
|
2898
2800
|
beforeUnmount: function beforeUnmount() {
|
|
2899
2801
|
window.removeEventListener('beforeunload', this.handleBeforeUnload);
|
|
2900
2802
|
window.removeEventListener('crestapps-ai-chat-stop-tts', this.handleExternalTtsStop);
|
|
2803
|
+
if (this.fontAwesomeObserver) {
|
|
2804
|
+
this.fontAwesomeObserver.disconnect();
|
|
2805
|
+
this.fontAwesomeObserver = null;
|
|
2806
|
+
}
|
|
2807
|
+
this.clearCopiedMessageState();
|
|
2901
2808
|
this.stopAudio(false);
|
|
2902
2809
|
if (this.stream) {
|
|
2903
2810
|
this.stream.dispose();
|
|
@@ -2906,13 +2813,163 @@ window.openAIChatManager = function () {
|
|
|
2906
2813
|
if (this.connection) {
|
|
2907
2814
|
this.connection.stop();
|
|
2908
2815
|
}
|
|
2816
|
+
if (widgetBehavior && typeof widgetBehavior.onBeforeUnmount === 'function') {
|
|
2817
|
+
widgetBehavior.onBeforeUnmount(this, config);
|
|
2818
|
+
}
|
|
2909
2819
|
},
|
|
2910
2820
|
template: config.messageTemplate
|
|
2911
|
-
}
|
|
2821
|
+
};
|
|
2822
|
+
var app = Vue.createApp(appDefinition).mount(config.appElementSelector);
|
|
2823
|
+
if (widgetBehavior && typeof widgetBehavior.attach === 'function') {
|
|
2824
|
+
widgetBehavior.attach(app, config);
|
|
2825
|
+
}
|
|
2912
2826
|
return app;
|
|
2913
2827
|
};
|
|
2828
|
+
var autoInitializeSelector = '[data-coreai-chat-config],[data-coreai-chat-app-element-selector]';
|
|
2829
|
+
function getAttributeValue(element, attributeName) {
|
|
2830
|
+
var value = element.getAttribute(attributeName);
|
|
2831
|
+
return value === null || value === '' ? null : value;
|
|
2832
|
+
}
|
|
2833
|
+
function parseBooleanAttributeValue(value) {
|
|
2834
|
+
if (value === null || value === undefined) {
|
|
2835
|
+
return null;
|
|
2836
|
+
}
|
|
2837
|
+
if (typeof value === 'boolean') {
|
|
2838
|
+
return value;
|
|
2839
|
+
}
|
|
2840
|
+
var normalized = String(value).trim().toLowerCase();
|
|
2841
|
+
if (normalized === 'true') {
|
|
2842
|
+
return true;
|
|
2843
|
+
}
|
|
2844
|
+
if (normalized === 'false') {
|
|
2845
|
+
return false;
|
|
2846
|
+
}
|
|
2847
|
+
return null;
|
|
2848
|
+
}
|
|
2849
|
+
function parseJsonAttribute(element, attributeName, description) {
|
|
2850
|
+
var rawValue = getAttributeValue(element, attributeName);
|
|
2851
|
+
if (!rawValue) {
|
|
2852
|
+
return null;
|
|
2853
|
+
}
|
|
2854
|
+
try {
|
|
2855
|
+
return JSON.parse(rawValue);
|
|
2856
|
+
} catch (error) {
|
|
2857
|
+
console.error('Failed to parse ' + description + ' JSON.', error);
|
|
2858
|
+
return null;
|
|
2859
|
+
}
|
|
2860
|
+
}
|
|
2861
|
+
function buildConfigFromDataAttributes(element, options) {
|
|
2862
|
+
var _parseJsonAttribute, _parseJsonAttribute2;
|
|
2863
|
+
var settings = options || {};
|
|
2864
|
+
if (element.hasAttribute('data-coreai-chat-widget-container-selector') && settings.allowWidgetHost !== true) {
|
|
2865
|
+
return null;
|
|
2866
|
+
}
|
|
2867
|
+
var appElementSelector = getAttributeValue(element, 'data-coreai-chat-app-element-selector');
|
|
2868
|
+
if (!appElementSelector) {
|
|
2869
|
+
return null;
|
|
2870
|
+
}
|
|
2871
|
+
var config = {
|
|
2872
|
+
signalRHubUrl: getAttributeValue(element, 'data-coreai-chat-signalr-hub-url'),
|
|
2873
|
+
appElementSelector: appElementSelector,
|
|
2874
|
+
chatContainerElementSelector: getAttributeValue(element, 'data-coreai-chat-container-element-selector'),
|
|
2875
|
+
inputElementSelector: getAttributeValue(element, 'data-coreai-chat-input-element-selector'),
|
|
2876
|
+
sendButtonElementSelector: getAttributeValue(element, 'data-coreai-chat-send-button-element-selector'),
|
|
2877
|
+
placeholderElementSelector: getAttributeValue(element, 'data-coreai-chat-placeholder-element-selector'),
|
|
2878
|
+
messages: (_parseJsonAttribute = parseJsonAttribute(element, 'data-coreai-chat-messages', 'CoreAI chat messages')) !== null && _parseJsonAttribute !== void 0 ? _parseJsonAttribute : undefined,
|
|
2879
|
+
chatMode: getAttributeValue(element, 'data-coreai-chat-mode'),
|
|
2880
|
+
micButtonElementSelector: getAttributeValue(element, 'data-coreai-chat-mic-button-element-selector'),
|
|
2881
|
+
conversationButtonElementSelector: getAttributeValue(element, 'data-coreai-chat-conversation-button-element-selector'),
|
|
2882
|
+
ttsVoiceName: getAttributeValue(element, 'data-coreai-chat-tts-voice-name'),
|
|
2883
|
+
documentBarSelector: getAttributeValue(element, 'data-coreai-chat-document-bar-selector'),
|
|
2884
|
+
uploadDocumentUrl: getAttributeValue(element, 'data-coreai-chat-upload-document-url'),
|
|
2885
|
+
removeDocumentUrl: getAttributeValue(element, 'data-coreai-chat-remove-document-url'),
|
|
2886
|
+
allowedExtensions: getAttributeValue(element, 'data-coreai-chat-allowed-extensions'),
|
|
2887
|
+
supportedExtensionsText: getAttributeValue(element, 'data-coreai-chat-supported-extensions-text'),
|
|
2888
|
+
existingDocuments: (_parseJsonAttribute2 = parseJsonAttribute(element, 'data-coreai-chat-existing-documents', 'CoreAI chat existing documents')) !== null && _parseJsonAttribute2 !== void 0 ? _parseJsonAttribute2 : undefined,
|
|
2889
|
+
initialPrompt: getAttributeValue(element, 'data-coreai-chat-initial-prompt'),
|
|
2890
|
+
userLabel: getAttributeValue(element, 'data-coreai-chat-user-label'),
|
|
2891
|
+
assistantLabel: getAttributeValue(element, 'data-coreai-chat-assistant-label'),
|
|
2892
|
+
copyTitle: getAttributeValue(element, 'data-coreai-chat-copy-title'),
|
|
2893
|
+
copiedTitle: getAttributeValue(element, 'data-coreai-chat-copied-title')
|
|
2894
|
+
};
|
|
2895
|
+
var booleanAttributes = {
|
|
2896
|
+
metricsEnabled: 'data-coreai-chat-metrics-enabled',
|
|
2897
|
+
textToSpeechEnabled: 'data-coreai-chat-text-to-speech-enabled',
|
|
2898
|
+
sessionDocumentsEnabled: 'data-coreai-chat-session-documents-enabled',
|
|
2899
|
+
autoCreateSession: 'data-coreai-chat-auto-create-session',
|
|
2900
|
+
singleResponseMode: 'data-coreai-chat-single-response-mode'
|
|
2901
|
+
};
|
|
2902
|
+
Object.keys(booleanAttributes).forEach(function (key) {
|
|
2903
|
+
var parsed = parseBooleanAttributeValue(getAttributeValue(element, booleanAttributes[key]));
|
|
2904
|
+
if (parsed !== null) {
|
|
2905
|
+
config[key] = parsed;
|
|
2906
|
+
}
|
|
2907
|
+
});
|
|
2908
|
+
return compactObject(config);
|
|
2909
|
+
}
|
|
2910
|
+
function buildConfigFromElement(element, options) {
|
|
2911
|
+
var jsonConfig = parseJsonAttribute(element, 'data-coreai-chat-config', 'CoreAI chat config');
|
|
2912
|
+
var attributeConfig = buildConfigFromDataAttributes(element, options);
|
|
2913
|
+
if (!jsonConfig && !attributeConfig) {
|
|
2914
|
+
return null;
|
|
2915
|
+
}
|
|
2916
|
+
return Object.assign({}, jsonConfig || {}, attributeConfig || {});
|
|
2917
|
+
}
|
|
2918
|
+
function initializeFromElement(element) {
|
|
2919
|
+
if (!element || element.dataset.coreAiChatInitialized === 'true') {
|
|
2920
|
+
return element ? element.__coreAIChatApp || null : null;
|
|
2921
|
+
}
|
|
2922
|
+
var config = buildConfigFromElement(element);
|
|
2923
|
+
if (!config) {
|
|
2924
|
+
return null;
|
|
2925
|
+
}
|
|
2926
|
+
var app = initialize(config);
|
|
2927
|
+
if (!app) {
|
|
2928
|
+
return null;
|
|
2929
|
+
}
|
|
2930
|
+
element.dataset.coreAiChatInitialized = 'true';
|
|
2931
|
+
element.__coreAIChatApp = app;
|
|
2932
|
+
return app;
|
|
2933
|
+
}
|
|
2934
|
+
function scanForAutoInitialization(root) {
|
|
2935
|
+
if (!root || typeof root.querySelectorAll !== 'function') {
|
|
2936
|
+
return;
|
|
2937
|
+
}
|
|
2938
|
+
if (typeof root.matches === 'function' && root.matches(autoInitializeSelector)) {
|
|
2939
|
+
initializeFromElement(root);
|
|
2940
|
+
}
|
|
2941
|
+
root.querySelectorAll(autoInitializeSelector).forEach(initializeFromElement);
|
|
2942
|
+
}
|
|
2943
|
+
function startAutoInitialization() {
|
|
2944
|
+
scanForAutoInitialization(document);
|
|
2945
|
+
if (typeof MutationObserver === 'undefined') {
|
|
2946
|
+
return;
|
|
2947
|
+
}
|
|
2948
|
+
var observer = new MutationObserver(function (mutations) {
|
|
2949
|
+
mutations.forEach(function (mutation) {
|
|
2950
|
+
mutation.addedNodes.forEach(function (node) {
|
|
2951
|
+
if (node && node.nodeType === 1) {
|
|
2952
|
+
scanForAutoInitialization(node);
|
|
2953
|
+
}
|
|
2954
|
+
});
|
|
2955
|
+
});
|
|
2956
|
+
});
|
|
2957
|
+
observer.observe(document.body, {
|
|
2958
|
+
childList: true,
|
|
2959
|
+
subtree: true
|
|
2960
|
+
});
|
|
2961
|
+
}
|
|
2962
|
+
if (document.readyState === 'loading') {
|
|
2963
|
+
document.addEventListener('DOMContentLoaded', startAutoInitialization, {
|
|
2964
|
+
once: true
|
|
2965
|
+
});
|
|
2966
|
+
} else {
|
|
2967
|
+
startAutoInitialization();
|
|
2968
|
+
}
|
|
2914
2969
|
return {
|
|
2915
|
-
initialize: initialize
|
|
2970
|
+
initialize: initialize,
|
|
2971
|
+
initializeFromElement: initializeFromElement,
|
|
2972
|
+
buildConfigFromElement: buildConfigFromElement
|
|
2916
2973
|
};
|
|
2917
2974
|
}();
|
|
2918
2975
|
|