@crestapps/ai-chat-ui 1.0.0-preview.10 → 1.0.0-preview.108
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 +961 -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 +67 -17
- package/dist/ai-chat.css.map +1 -1
- package/dist/ai-chat.js +1082 -1027
- package/dist/ai-chat.js.map +1 -1
- package/dist/ai-chat.min.css +1 -1
- package/dist/ai-chat.min.js +1 -1
- package/dist/ai-chat.min.js.map +1 -1
- package/dist/chat-interaction-settings.js +297 -0
- package/dist/chat-interaction-settings.js.map +1 -0
- package/dist/chat-interaction-settings.min.js +2 -0
- package/dist/chat-interaction-settings.min.js.map +1 -0
- package/dist/chat-interaction.js +1198 -338
- package/dist/chat-interaction.js.map +1 -1
- package/dist/chat-interaction.min.js +1 -1
- package/dist/chat-interaction.min.js.map +1 -1
- package/dist/chat-widget.css +88 -35
- package/dist/chat-widget.css.map +1 -1
- package/dist/chat-widget.min.css +1 -1
- package/dist/document-drop-zone.css +10 -10
- package/dist/document-drop-zone.css.map +1 -1
- package/dist/document-drop-zone.js +92 -14
- package/dist/document-drop-zone.js.map +1 -1
- package/dist/document-drop-zone.min.css +1 -1
- package/dist/document-drop-zone.min.js +1 -1
- package/dist/document-drop-zone.min.js.map +1 -1
- package/dist/technical-name-generator.js +36 -8
- package/dist/technical-name-generator.js.map +1 -1
- package/dist/technical-name-generator.min.js +1 -1
- package/dist/technical-name-generator.min.js.map +1 -1
- package/package.json +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
|
|
56
|
-
indicatorTemplate: "\n <div class=\"ai-chat-msg-role ai-chat-msg-role-assistant\">\n
|
|
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-message-heading ai-chat-message-heading-user\">\n <span class=\"ai-chat-msg-role ai-chat-msg-role-user\">{{ userLabel }}</span>\n </div>\n <div v-else-if=\"message.role !== 'indicator'\" class=\"ai-chat-message-heading ai-chat-message-heading-assistant\">\n <div :class=\"getAssistantRoleClasses(message)\">\n <span :class=\"getAssistantIconClasses(message, index)\"><i :class=\"getAssistantIcon(message)\"></i></span>\n <span class=\"ai-chat-message-role-label\">{{ getAssistantLabel(message) }}</span>\n </div>\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-message-heading ai-chat-message-heading-assistant\">\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 <span class=\"ai-chat-message-role-label\">Assistant</span>\n </div>\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,31 @@ 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
|
+
}
|
|
586
|
+
function resolveIndicatorTemplate(template, assistantLabel) {
|
|
587
|
+
if (!template) {
|
|
588
|
+
return template;
|
|
589
|
+
}
|
|
590
|
+
var encodedAssistantLabel = escapeHtmlEntities(assistantLabel || 'Assistant');
|
|
591
|
+
return template.replace(/\{\{\s*assistantLabel\s*\}\}/g, encodedAssistantLabel);
|
|
592
|
+
}
|
|
362
593
|
var initialize = function initialize(instanceConfig) {
|
|
363
|
-
var
|
|
364
|
-
|
|
365
|
-
var
|
|
594
|
+
var normalizedInstanceConfig = compactObject(instanceConfig);
|
|
595
|
+
var normalizedWidgetConfig = compactObject(normalizedInstanceConfig.widget);
|
|
596
|
+
var config = Object.assign({}, defaultConfig, normalizedInstanceConfig);
|
|
597
|
+
config.widget = Object.assign({}, defaultConfig.widget || {}, normalizedWidgetConfig);
|
|
598
|
+
config.indicatorTemplate = resolveIndicatorTemplate(config.indicatorTemplate, config.assistantLabel);
|
|
599
|
+
var hasWidgetConfig = !!(normalizedWidgetConfig.chatWidgetContainer && normalizedWidgetConfig.chatWidgetStateName);
|
|
600
|
+
var widgetBehavior = window.coreAIChatWidgetBehavior || null;
|
|
366
601
|
// Keep defaultConfig in sync so renderers use overridden values
|
|
367
602
|
defaultConfig = config;
|
|
368
603
|
if (!config.signalRHubUrl) {
|
|
@@ -385,7 +620,7 @@ window.openAIChatManager = function () {
|
|
|
385
620
|
console.error('The sendButtonElementSelector is required.');
|
|
386
621
|
return;
|
|
387
622
|
}
|
|
388
|
-
var
|
|
623
|
+
var appDefinition = {
|
|
389
624
|
data: function data() {
|
|
390
625
|
return {
|
|
391
626
|
inputElement: null,
|
|
@@ -394,18 +629,6 @@ window.openAIChatManager = function () {
|
|
|
394
629
|
placeholder: null,
|
|
395
630
|
isSessionStarted: false,
|
|
396
631
|
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
632
|
isStreaming: false,
|
|
410
633
|
isNavigatingAway: false,
|
|
411
634
|
autoScroll: true,
|
|
@@ -415,6 +638,8 @@ window.openAIChatManager = function () {
|
|
|
415
638
|
prompt: '',
|
|
416
639
|
documents: config.existingDocuments || [],
|
|
417
640
|
isUploading: false,
|
|
641
|
+
isDocumentOperationPending: false,
|
|
642
|
+
documentOperationQueue: null,
|
|
418
643
|
uploadErrors: [],
|
|
419
644
|
isDragOver: false,
|
|
420
645
|
documentBar: null,
|
|
@@ -424,6 +649,7 @@ window.openAIChatManager = function () {
|
|
|
424
649
|
thumbsUpTitle: config.thumbsUpTitle,
|
|
425
650
|
thumbsDownTitle: config.thumbsDownTitle,
|
|
426
651
|
copyTitle: config.copyTitle,
|
|
652
|
+
copiedTitle: config.copiedTitle,
|
|
427
653
|
isRecording: false,
|
|
428
654
|
mediaRecorder: null,
|
|
429
655
|
preRecordingPrompt: '',
|
|
@@ -444,7 +670,14 @@ window.openAIChatManager = function () {
|
|
|
444
670
|
conversationModeEnabled: config.chatMode === 'Conversation',
|
|
445
671
|
conversationButton: null,
|
|
446
672
|
isConversationMode: false,
|
|
447
|
-
notificationDismissTimers: {}
|
|
673
|
+
notificationDismissTimers: {},
|
|
674
|
+
pendingSessionPromise: null,
|
|
675
|
+
pendingSessionResolver: null,
|
|
676
|
+
pendingSessionRejector: null,
|
|
677
|
+
pendingSessionTimeoutId: null,
|
|
678
|
+
copiedMessageIndex: -1,
|
|
679
|
+
copyResetTimeoutId: null,
|
|
680
|
+
activeCopyButton: null
|
|
448
681
|
};
|
|
449
682
|
},
|
|
450
683
|
computed: {
|
|
@@ -461,336 +694,6 @@ window.openAIChatManager = function () {
|
|
|
461
694
|
handleBeforeUnload: function handleBeforeUnload() {
|
|
462
695
|
this.isNavigatingAway = true;
|
|
463
696
|
},
|
|
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
697
|
handleDragOver: function handleDragOver(e) {
|
|
795
698
|
if (!config.sessionDocumentsEnabled) return;
|
|
796
699
|
e.preventDefault();
|
|
@@ -815,180 +718,272 @@ window.openAIChatManager = function () {
|
|
|
815
718
|
var inputArea = this.inputElement ? this.inputElement.closest('.ai-admin-widget-input, .text-bg-light') : null;
|
|
816
719
|
if (inputArea) inputArea.classList.remove('ai-chat-drag-over');
|
|
817
720
|
if (e.dataTransfer && e.dataTransfer.files && e.dataTransfer.files.length > 0) {
|
|
818
|
-
this.uploadFiles(e.dataTransfer.files);
|
|
721
|
+
this.uploadFiles(Array.from(e.dataTransfer.files));
|
|
819
722
|
}
|
|
820
723
|
},
|
|
821
724
|
triggerFileInput: function triggerFileInput() {
|
|
822
|
-
if (!config.sessionDocumentsEnabled) return;
|
|
725
|
+
if (!config.sessionDocumentsEnabled || this.isDocumentOperationPending) return;
|
|
823
726
|
var fileInput = document.getElementById('ai-chat-doc-input');
|
|
824
727
|
if (fileInput) fileInput.click();
|
|
825
728
|
},
|
|
826
729
|
handleFileInputChange: function handleFileInputChange(e) {
|
|
827
|
-
var files = e.target.files;
|
|
730
|
+
var files = e.target.files ? Array.from(e.target.files) : [];
|
|
828
731
|
if (files && files.length > 0) {
|
|
829
732
|
this.uploadFiles(files);
|
|
830
733
|
}
|
|
831
734
|
e.target.value = '';
|
|
832
735
|
},
|
|
833
|
-
|
|
834
|
-
var
|
|
835
|
-
|
|
836
|
-
|
|
736
|
+
queueDocumentOperation: function queueDocumentOperation(operation) {
|
|
737
|
+
var self = this;
|
|
738
|
+
var previousOperation = this.documentOperationQueue || Promise.resolve();
|
|
739
|
+
var nextOperation = previousOperation["catch"](function () {}).then(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee() {
|
|
837
740
|
return _regenerator().w(function (_context) {
|
|
838
741
|
while (1) switch (_context.p = _context.n) {
|
|
742
|
+
case 0:
|
|
743
|
+
self.isDocumentOperationPending = true;
|
|
744
|
+
_context.p = 1;
|
|
745
|
+
_context.n = 2;
|
|
746
|
+
return operation();
|
|
747
|
+
case 2:
|
|
748
|
+
return _context.a(2, _context.v);
|
|
749
|
+
case 3:
|
|
750
|
+
_context.p = 3;
|
|
751
|
+
self.isDocumentOperationPending = false;
|
|
752
|
+
return _context.f(3);
|
|
753
|
+
case 4:
|
|
754
|
+
return _context.a(2);
|
|
755
|
+
}
|
|
756
|
+
}, _callee, null, [[1,, 3, 4]]);
|
|
757
|
+
})));
|
|
758
|
+
this.documentOperationQueue = nextOperation["finally"](function () {
|
|
759
|
+
if (self.documentOperationQueue === nextOperation) {
|
|
760
|
+
self.documentOperationQueue = null;
|
|
761
|
+
}
|
|
762
|
+
});
|
|
763
|
+
return this.documentOperationQueue;
|
|
764
|
+
},
|
|
765
|
+
uploadFiles: function uploadFiles(files) {
|
|
766
|
+
var _this = this;
|
|
767
|
+
return _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3() {
|
|
768
|
+
var filesToUpload;
|
|
769
|
+
return _regenerator().w(function (_context3) {
|
|
770
|
+
while (1) switch (_context3.n) {
|
|
839
771
|
case 0:
|
|
840
772
|
if (config.uploadDocumentUrl) {
|
|
841
|
-
|
|
773
|
+
_context3.n = 1;
|
|
842
774
|
break;
|
|
843
775
|
}
|
|
844
|
-
return
|
|
776
|
+
return _context3.a(2);
|
|
845
777
|
case 1:
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
_context.n = 2;
|
|
778
|
+
filesToUpload = Array.isArray(files) ? files.slice() : Array.from(files || []);
|
|
779
|
+
if (!(filesToUpload.length === 0)) {
|
|
780
|
+
_context3.n = 2;
|
|
850
781
|
break;
|
|
851
782
|
}
|
|
852
|
-
|
|
853
|
-
return _context.a(2);
|
|
783
|
+
return _context3.a(2);
|
|
854
784
|
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
|
-
|
|
785
|
+
return _context3.a(2, _this.queueDocumentOperation(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2() {
|
|
786
|
+
var sessionId, profileId, formData, i, response, errorText, uploadError, result, _t, _t2;
|
|
787
|
+
return _regenerator().w(function (_context2) {
|
|
788
|
+
while (1) switch (_context2.p = _context2.n) {
|
|
789
|
+
case 0:
|
|
790
|
+
sessionId = _this.getSessionId();
|
|
791
|
+
profileId = _this.getProfileId();
|
|
792
|
+
if (sessionId) {
|
|
793
|
+
_context2.n = 4;
|
|
794
|
+
break;
|
|
795
|
+
}
|
|
796
|
+
_context2.p = 1;
|
|
797
|
+
_context2.n = 2;
|
|
798
|
+
return _this.ensureSessionForDocuments(profileId);
|
|
799
|
+
case 2:
|
|
800
|
+
sessionId = _context2.v;
|
|
801
|
+
_context2.n = 4;
|
|
802
|
+
break;
|
|
803
|
+
case 3:
|
|
804
|
+
_context2.p = 3;
|
|
805
|
+
_t = _context2.v;
|
|
806
|
+
console.error('Failed to create a chat session for document upload:', _t);
|
|
807
|
+
_this.uploadErrors = [{
|
|
808
|
+
fileName: '',
|
|
809
|
+
error: 'Could not create a chat session for the upload.'
|
|
810
|
+
}];
|
|
811
|
+
_this.renderDocumentBar();
|
|
812
|
+
return _context2.a(2);
|
|
813
|
+
case 4:
|
|
814
|
+
if (sessionId) {
|
|
815
|
+
_context2.n = 5;
|
|
816
|
+
break;
|
|
817
|
+
}
|
|
818
|
+
console.warn('Cannot upload documents without a session or profile.');
|
|
819
|
+
_this.uploadErrors = [{
|
|
820
|
+
fileName: '',
|
|
821
|
+
error: 'Could not create a chat session for the upload.'
|
|
822
|
+
}];
|
|
823
|
+
_this.renderDocumentBar();
|
|
824
|
+
return _context2.a(2);
|
|
825
|
+
case 5:
|
|
826
|
+
_this.isUploading = true;
|
|
827
|
+
_this.uploadErrors = [];
|
|
828
|
+
_this.renderDocumentBar();
|
|
829
|
+
_context2.p = 6;
|
|
830
|
+
formData = new FormData();
|
|
831
|
+
formData.append('sessionId', sessionId);
|
|
832
|
+
for (i = 0; i < filesToUpload.length; i++) {
|
|
833
|
+
formData.append('files', filesToUpload[i]);
|
|
834
|
+
}
|
|
835
|
+
_context2.n = 7;
|
|
836
|
+
return fetch(config.uploadDocumentUrl, {
|
|
837
|
+
method: 'POST',
|
|
838
|
+
body: formData
|
|
839
|
+
});
|
|
840
|
+
case 7:
|
|
841
|
+
response = _context2.v;
|
|
842
|
+
if (response.ok) {
|
|
843
|
+
_context2.n = 9;
|
|
844
|
+
break;
|
|
845
|
+
}
|
|
846
|
+
_context2.n = 8;
|
|
847
|
+
return response.text();
|
|
848
|
+
case 8:
|
|
849
|
+
errorText = _context2.v;
|
|
850
|
+
uploadError = _this.extractReadableErrorMessage(errorText, 'Upload failed. Please try again.');
|
|
851
|
+
console.error('Upload failed:', errorText);
|
|
852
|
+
_this.uploadErrors = [{
|
|
853
|
+
fileName: '',
|
|
854
|
+
error: uploadError
|
|
855
|
+
}];
|
|
856
|
+
return _context2.a(2);
|
|
857
|
+
case 9:
|
|
858
|
+
_context2.n = 10;
|
|
859
|
+
return response.json();
|
|
860
|
+
case 10:
|
|
861
|
+
result = _context2.v;
|
|
862
|
+
if (result.sessionId && result.sessionId !== _this.getSessionId()) {
|
|
863
|
+
_this.initializeSession(result.sessionId);
|
|
864
|
+
}
|
|
865
|
+
if (Array.isArray(result.documents)) {
|
|
866
|
+
_this.documents = result.documents;
|
|
867
|
+
} else if (result.uploaded && result.uploaded.length > 0) {
|
|
868
|
+
_this.documents = _this.documents.concat(result.uploaded);
|
|
869
|
+
}
|
|
870
|
+
if (result.failed && result.failed.length > 0) {
|
|
871
|
+
_this.uploadErrors = result.failed;
|
|
872
|
+
}
|
|
873
|
+
_context2.n = 12;
|
|
874
|
+
break;
|
|
875
|
+
case 11:
|
|
876
|
+
_context2.p = 11;
|
|
877
|
+
_t2 = _context2.v;
|
|
878
|
+
console.error('Upload error:', _t2);
|
|
879
|
+
_this.uploadErrors = [{
|
|
880
|
+
fileName: '',
|
|
881
|
+
error: 'Upload failed. Please try again.'
|
|
882
|
+
}];
|
|
883
|
+
if (_this.getSessionId()) {
|
|
884
|
+
_this.reloadCurrentSession();
|
|
885
|
+
}
|
|
886
|
+
case 12:
|
|
887
|
+
_context2.p = 12;
|
|
888
|
+
_this.isUploading = false;
|
|
889
|
+
_this.renderDocumentBar();
|
|
890
|
+
return _context2.f(12);
|
|
891
|
+
case 13:
|
|
892
|
+
return _context2.a(2);
|
|
893
|
+
}
|
|
894
|
+
}, _callee2, null, [[6, 11, 12, 13], [1, 3]]);
|
|
895
|
+
}))));
|
|
924
896
|
}
|
|
925
|
-
},
|
|
897
|
+
}, _callee3);
|
|
926
898
|
}))();
|
|
927
899
|
},
|
|
928
900
|
removeDocument: function removeDocument(doc) {
|
|
929
|
-
var
|
|
930
|
-
return _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
while (1) switch (_context2.p = _context2.n) {
|
|
901
|
+
var _this2 = this;
|
|
902
|
+
return _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee5() {
|
|
903
|
+
return _regenerator().w(function (_context5) {
|
|
904
|
+
while (1) switch (_context5.n) {
|
|
934
905
|
case 0:
|
|
935
906
|
if (config.removeDocumentUrl) {
|
|
936
|
-
|
|
907
|
+
_context5.n = 1;
|
|
937
908
|
break;
|
|
938
909
|
}
|
|
939
|
-
return
|
|
910
|
+
return _context5.a(2);
|
|
940
911
|
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
|
-
|
|
912
|
+
return _context5.a(2, _this2.queueDocumentOperation(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4() {
|
|
913
|
+
var sessionId, response, result, idx, errorText, removeError, _t3;
|
|
914
|
+
return _regenerator().w(function (_context4) {
|
|
915
|
+
while (1) switch (_context4.p = _context4.n) {
|
|
916
|
+
case 0:
|
|
917
|
+
_context4.p = 0;
|
|
918
|
+
sessionId = _this2.getSessionId();
|
|
919
|
+
_context4.n = 1;
|
|
920
|
+
return fetch(config.removeDocumentUrl, {
|
|
921
|
+
method: 'POST',
|
|
922
|
+
headers: {
|
|
923
|
+
'Content-Type': 'application/json'
|
|
924
|
+
},
|
|
925
|
+
body: JSON.stringify({
|
|
926
|
+
itemId: sessionId,
|
|
927
|
+
documentId: doc.documentId
|
|
928
|
+
})
|
|
929
|
+
});
|
|
930
|
+
case 1:
|
|
931
|
+
response = _context4.v;
|
|
932
|
+
if (!response.ok) {
|
|
933
|
+
_context4.n = 3;
|
|
934
|
+
break;
|
|
935
|
+
}
|
|
936
|
+
_context4.n = 2;
|
|
937
|
+
return response.json();
|
|
938
|
+
case 2:
|
|
939
|
+
result = _context4.v;
|
|
940
|
+
if (Array.isArray(result.documents)) {
|
|
941
|
+
_this2.documents = result.documents;
|
|
942
|
+
} else {
|
|
943
|
+
idx = _this2.documents.indexOf(doc);
|
|
944
|
+
if (idx > -1) {
|
|
945
|
+
_this2.documents.splice(idx, 1);
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
_context4.n = 5;
|
|
949
|
+
break;
|
|
950
|
+
case 3:
|
|
951
|
+
_context4.n = 4;
|
|
952
|
+
return response.text();
|
|
953
|
+
case 4:
|
|
954
|
+
errorText = _context4.v;
|
|
955
|
+
removeError = _this2.extractReadableErrorMessage(errorText, 'Failed to remove document. Please try again.');
|
|
956
|
+
console.error('Failed to remove document:', response.status, errorText);
|
|
957
|
+
_this2.uploadErrors = [{
|
|
958
|
+
fileName: doc.fileName || '',
|
|
959
|
+
error: removeError
|
|
960
|
+
}];
|
|
961
|
+
if (sessionId) {
|
|
962
|
+
_this2.reloadCurrentSession();
|
|
963
|
+
}
|
|
964
|
+
_this2.renderDocumentBar();
|
|
965
|
+
case 5:
|
|
966
|
+
_context4.n = 7;
|
|
967
|
+
break;
|
|
968
|
+
case 6:
|
|
969
|
+
_context4.p = 6;
|
|
970
|
+
_t3 = _context4.v;
|
|
971
|
+
console.error('Remove document error:', _t3);
|
|
972
|
+
_this2.uploadErrors = [{
|
|
973
|
+
fileName: doc.fileName || '',
|
|
974
|
+
error: 'Failed to remove document. Please try again.'
|
|
975
|
+
}];
|
|
976
|
+
if (_this2.getSessionId()) {
|
|
977
|
+
_this2.reloadCurrentSession();
|
|
978
|
+
}
|
|
979
|
+
_this2.renderDocumentBar();
|
|
980
|
+
case 7:
|
|
981
|
+
return _context4.a(2);
|
|
982
|
+
}
|
|
983
|
+
}, _callee4, null, [[0, 6]]);
|
|
984
|
+
}))));
|
|
990
985
|
}
|
|
991
|
-
},
|
|
986
|
+
}, _callee5);
|
|
992
987
|
}))();
|
|
993
988
|
},
|
|
994
989
|
formatFileSize: function formatFileSize(bytes) {
|
|
@@ -1010,9 +1005,9 @@ window.openAIChatManager = function () {
|
|
|
1010
1005
|
var name = doc.fileName || 'Document';
|
|
1011
1006
|
if (name.length > 20) name = name.substring(0, 17) + '...';
|
|
1012
1007
|
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 += '<
|
|
1008
|
+
html += '<i class="fa-solid fa-file-lines" style="font-size: 0.7rem;"></i> ';
|
|
1014
1009
|
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>';
|
|
1010
|
+
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
1011
|
html += '</span>';
|
|
1017
1012
|
}
|
|
1018
1013
|
for (var m = 0; m < this.uploadErrors.length; m++) {
|
|
@@ -1021,7 +1016,7 @@ window.openAIChatManager = function () {
|
|
|
1021
1016
|
var errorMsg = failedItem.error || 'Upload failed';
|
|
1022
1017
|
if (failedName.length > 15) failedName = failedName.substring(0, 12) + '...';
|
|
1023
1018
|
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 += '<
|
|
1019
|
+
html += '<i class="fa-solid fa-circle-exclamation" style="font-size: 0.7rem;"></i> ';
|
|
1025
1020
|
html += this.escapeHtml(failedName);
|
|
1026
1021
|
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
1022
|
html += '</span>';
|
|
@@ -1031,8 +1026,8 @@ window.openAIChatManager = function () {
|
|
|
1031
1026
|
html += '<span class="spinner-border spinner-border-sm" style="width: 0.7rem; height: 0.7rem;"></span> Uploading...';
|
|
1032
1027
|
html += '</span>';
|
|
1033
1028
|
}
|
|
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 += '<
|
|
1029
|
+
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' : '') + '>';
|
|
1030
|
+
html += '<i class="fa-solid fa-paperclip"></i>';
|
|
1036
1031
|
if (this.documents.length === 0 && !this.isUploading) {
|
|
1037
1032
|
html += ' <span>Attach files</span>';
|
|
1038
1033
|
}
|
|
@@ -1054,6 +1049,9 @@ window.openAIChatManager = function () {
|
|
|
1054
1049
|
return function (e) {
|
|
1055
1050
|
e.preventDefault();
|
|
1056
1051
|
e.stopPropagation();
|
|
1052
|
+
if (self.isDocumentOperationPending) {
|
|
1053
|
+
return;
|
|
1054
|
+
}
|
|
1057
1055
|
var docToRemove = self.documents[idx];
|
|
1058
1056
|
if (docToRemove) self.removeDocument(docToRemove);
|
|
1059
1057
|
};
|
|
@@ -1078,6 +1076,9 @@ window.openAIChatManager = function () {
|
|
|
1078
1076
|
if (addBtn) {
|
|
1079
1077
|
addBtn.addEventListener('click', function (e) {
|
|
1080
1078
|
e.preventDefault();
|
|
1079
|
+
if (self.isDocumentOperationPending) {
|
|
1080
|
+
return;
|
|
1081
|
+
}
|
|
1081
1082
|
self.triggerFileInput();
|
|
1082
1083
|
});
|
|
1083
1084
|
}
|
|
@@ -1154,139 +1155,135 @@ window.openAIChatManager = function () {
|
|
|
1154
1155
|
return !!message && message.isStreaming && index === this.lastAssistantIndex && !(appearance && appearance.disableStreamingAnimation);
|
|
1155
1156
|
},
|
|
1156
1157
|
startConnection: function startConnection() {
|
|
1157
|
-
var
|
|
1158
|
-
return _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
1159
|
-
var
|
|
1160
|
-
return _regenerator().w(function (
|
|
1161
|
-
while (1) switch (
|
|
1158
|
+
var _this3 = this;
|
|
1159
|
+
return _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee6() {
|
|
1160
|
+
var _t4;
|
|
1161
|
+
return _regenerator().w(function (_context6) {
|
|
1162
|
+
while (1) switch (_context6.p = _context6.n) {
|
|
1162
1163
|
case 0:
|
|
1163
|
-
|
|
1164
|
+
_this3.connection = new signalR.HubConnectionBuilder().withUrl(config.signalRHubUrl).withAutomaticReconnect().build();
|
|
1164
1165
|
|
|
1165
1166
|
// Allow long-running operations (e.g., multi-step MCP tool calls)
|
|
1166
1167
|
// without the client disconnecting prematurely.
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1168
|
+
_this3.connection.serverTimeoutInMilliseconds = 600000;
|
|
1169
|
+
_this3.connection.keepAliveIntervalInMilliseconds = 15000;
|
|
1170
|
+
_this3.connection.on("LoadSession", function (data) {
|
|
1170
1171
|
var _data$messages;
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1172
|
+
_this3.initializeSession(data.sessionId, true);
|
|
1173
|
+
_this3.messages = [];
|
|
1174
|
+
_this3.documents = data.documents || [];
|
|
1175
|
+
_this3.uploadErrors = [];
|
|
1174
1176
|
((_data$messages = data.messages) !== null && _data$messages !== void 0 ? _data$messages : []).forEach(function (msg) {
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
+
_this3.addMessage(msg);
|
|
1178
|
+
_this3.$nextTick(function () {
|
|
1177
1179
|
renderChartsInMessage(msg);
|
|
1178
1180
|
});
|
|
1179
1181
|
});
|
|
1180
1182
|
|
|
1181
1183
|
// Update feedback icons in the DOM after all messages have rendered.
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
+
_this3.$nextTick(function () {
|
|
1185
|
+
_this3.refreshAllFeedbackIcons();
|
|
1184
1186
|
});
|
|
1185
1187
|
|
|
1186
1188
|
// When the session is new (no messages) and an initial prompt is configured,
|
|
1187
1189
|
// automatically send it as the first user message to trigger an AI response.
|
|
1188
|
-
if (
|
|
1189
|
-
|
|
1190
|
-
|
|
1190
|
+
if (_this3.messages.length === 0 && config.initialPrompt) {
|
|
1191
|
+
_this3.prompt = config.initialPrompt;
|
|
1192
|
+
_this3.sendMessage();
|
|
1191
1193
|
}
|
|
1192
1194
|
});
|
|
1193
|
-
|
|
1195
|
+
_this3.connection.on("ReceiveError", function (error) {
|
|
1194
1196
|
console.error("SignalR Error: ", error);
|
|
1195
|
-
if (
|
|
1196
|
-
|
|
1197
|
+
if (_this3.isRecording) {
|
|
1198
|
+
_this3.stopRecording();
|
|
1197
1199
|
}
|
|
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();
|
|
1200
|
+
if (widgetBehavior && typeof widgetBehavior.handleReceiveError === 'function') {
|
|
1201
|
+
widgetBehavior.handleReceiveError(_this3, error, config);
|
|
1205
1202
|
}
|
|
1206
1203
|
});
|
|
1207
|
-
|
|
1208
|
-
var msg =
|
|
1204
|
+
_this3.connection.on("MessageRated", function (messageId, userRating) {
|
|
1205
|
+
var msg = _this3.messages.find(function (m) {
|
|
1209
1206
|
return m.id === messageId;
|
|
1210
1207
|
});
|
|
1211
1208
|
if (msg) {
|
|
1212
1209
|
msg.userRating = userRating;
|
|
1213
1210
|
}
|
|
1214
1211
|
});
|
|
1215
|
-
|
|
1216
|
-
if (
|
|
1212
|
+
_this3.connection.on("ReceiveTranscript", function (sessionId, text, isFinal) {
|
|
1213
|
+
if (_this3.isConversationMode) {
|
|
1217
1214
|
if (!isFinal && text) {
|
|
1218
|
-
|
|
1215
|
+
_this3._conversationPartialTranscript = text;
|
|
1219
1216
|
var escaped = text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
1220
1217
|
var html = '<p class="ai-partial-transcript">' + escaped + '</p>';
|
|
1221
1218
|
|
|
1222
1219
|
// Show partial transcript as a live user message.
|
|
1223
|
-
if (!
|
|
1224
|
-
|
|
1225
|
-
|
|
1220
|
+
if (!_this3._conversationPartialMessage) {
|
|
1221
|
+
_this3.hidePlaceholder();
|
|
1222
|
+
_this3._conversationPartialMessage = {
|
|
1226
1223
|
role: 'user',
|
|
1227
1224
|
content: text,
|
|
1228
1225
|
htmlContent: html,
|
|
1229
1226
|
isPartial: true
|
|
1230
1227
|
};
|
|
1231
|
-
|
|
1228
|
+
_this3.messages.push(_this3._conversationPartialMessage);
|
|
1232
1229
|
} else {
|
|
1233
|
-
|
|
1234
|
-
|
|
1230
|
+
_this3._conversationPartialMessage.content = text;
|
|
1231
|
+
_this3._conversationPartialMessage.htmlContent = html;
|
|
1235
1232
|
}
|
|
1236
|
-
|
|
1233
|
+
_this3.scrollToBottom();
|
|
1237
1234
|
}
|
|
1238
1235
|
return;
|
|
1239
1236
|
}
|
|
1240
|
-
if (text && !
|
|
1241
|
-
|
|
1242
|
-
if (
|
|
1243
|
-
|
|
1244
|
-
|
|
1237
|
+
if (text && !_this3._audioInputSent) {
|
|
1238
|
+
_this3.prompt = _this3.preRecordingPrompt + text;
|
|
1239
|
+
if (_this3.inputElement) {
|
|
1240
|
+
_this3.inputElement.value = _this3.prompt;
|
|
1241
|
+
_this3.inputElement.dispatchEvent(new Event('input'));
|
|
1245
1242
|
}
|
|
1246
1243
|
}
|
|
1247
1244
|
});
|
|
1248
|
-
|
|
1245
|
+
_this3.connection.on("ReceiveConversationUserMessage", function (sessionId, text) {
|
|
1249
1246
|
if (text) {
|
|
1250
|
-
|
|
1247
|
+
_this3.stopAudio();
|
|
1251
1248
|
|
|
1252
1249
|
// If there's an interrupted assistant message still streaming,
|
|
1253
1250
|
// mark it as done to stop the spinner animation.
|
|
1254
|
-
if (
|
|
1255
|
-
var oldMsg =
|
|
1251
|
+
if (_this3._conversationAssistantMessage) {
|
|
1252
|
+
var oldMsg = _this3.messages[_this3._conversationAssistantMessage.index];
|
|
1256
1253
|
if (oldMsg) {
|
|
1257
1254
|
oldMsg.isStreaming = false;
|
|
1258
1255
|
}
|
|
1259
|
-
|
|
1256
|
+
_this3._conversationAssistantMessage = null;
|
|
1260
1257
|
}
|
|
1261
1258
|
|
|
1262
1259
|
// Replace the partial transcript message with the final one.
|
|
1263
|
-
if (
|
|
1260
|
+
if (_this3._conversationPartialMessage) {
|
|
1264
1261
|
var escaped = text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1262
|
+
_this3._conversationPartialMessage.content = text;
|
|
1263
|
+
_this3._conversationPartialMessage.htmlContent = '<p>' + escaped + '</p>';
|
|
1264
|
+
_this3._conversationPartialMessage.isPartial = false;
|
|
1265
|
+
_this3._conversationPartialMessage = null;
|
|
1269
1266
|
} else {
|
|
1270
|
-
|
|
1267
|
+
_this3.addMessage({
|
|
1271
1268
|
role: 'user',
|
|
1272
1269
|
content: text
|
|
1273
1270
|
});
|
|
1274
1271
|
}
|
|
1275
|
-
|
|
1272
|
+
_this3.scrollToBottom();
|
|
1276
1273
|
}
|
|
1277
1274
|
});
|
|
1278
|
-
|
|
1279
|
-
if (!
|
|
1280
|
-
|
|
1281
|
-
|
|
1275
|
+
_this3.connection.on("ReceiveConversationAssistantToken", function (sessionId, messageId, token, responseId, references, appearance) {
|
|
1276
|
+
if (!_this3._conversationAssistantMessage) {
|
|
1277
|
+
_this3.stopAudio();
|
|
1278
|
+
_this3.hideTypingIndicator();
|
|
1282
1279
|
|
|
1283
1280
|
// Ensure no stale streaming indicators remain from prior messages.
|
|
1284
|
-
for (var j = 0; j <
|
|
1285
|
-
if (
|
|
1286
|
-
|
|
1281
|
+
for (var j = 0; j < _this3.messages.length; j++) {
|
|
1282
|
+
if (_this3.messages[j].isStreaming) {
|
|
1283
|
+
_this3.messages[j].isStreaming = false;
|
|
1287
1284
|
}
|
|
1288
1285
|
}
|
|
1289
|
-
var msgIndex =
|
|
1286
|
+
var msgIndex = _this3.messages.length;
|
|
1290
1287
|
var newMessage = {
|
|
1291
1288
|
id: messageId,
|
|
1292
1289
|
role: "assistant",
|
|
@@ -1294,110 +1291,112 @@ window.openAIChatManager = function () {
|
|
|
1294
1291
|
htmlContent: "",
|
|
1295
1292
|
isStreaming: true,
|
|
1296
1293
|
userRating: null,
|
|
1297
|
-
appearance:
|
|
1294
|
+
appearance: _this3.normalizeAssistantAppearance(appearance),
|
|
1295
|
+
references: {}
|
|
1298
1296
|
};
|
|
1299
|
-
|
|
1300
|
-
|
|
1297
|
+
_this3.messages.push(newMessage);
|
|
1298
|
+
_this3._conversationAssistantMessage = {
|
|
1301
1299
|
index: msgIndex,
|
|
1302
1300
|
content: ''
|
|
1303
1301
|
};
|
|
1304
1302
|
}
|
|
1305
|
-
|
|
1306
|
-
var msg =
|
|
1303
|
+
_this3._conversationAssistantMessage.content += token;
|
|
1304
|
+
var msg = _this3.messages[_this3._conversationAssistantMessage.index];
|
|
1307
1305
|
if (msg) {
|
|
1308
1306
|
if (!msg.appearance) {
|
|
1309
|
-
msg.appearance =
|
|
1307
|
+
msg.appearance = _this3.normalizeAssistantAppearance(appearance);
|
|
1310
1308
|
}
|
|
1311
|
-
msg.
|
|
1312
|
-
msg.
|
|
1313
|
-
|
|
1309
|
+
msg.rawContent = _this3._conversationAssistantMessage.content;
|
|
1310
|
+
msg.references = normalizeReferences(Object.assign({}, msg.references || {}, references || {}));
|
|
1311
|
+
updateMessagePresentation(msg, msg.references);
|
|
1312
|
+
_this3.$nextTick(function () {
|
|
1314
1313
|
renderChartsInMessage(msg);
|
|
1315
|
-
|
|
1314
|
+
_this3.scrollToBottom();
|
|
1316
1315
|
});
|
|
1317
1316
|
}
|
|
1318
1317
|
});
|
|
1319
|
-
|
|
1320
|
-
if (
|
|
1321
|
-
var msg =
|
|
1318
|
+
_this3.connection.on("ReceiveConversationAssistantComplete", function (sessionId, messageId, references) {
|
|
1319
|
+
if (_this3._conversationAssistantMessage) {
|
|
1320
|
+
var msg = _this3.messages[_this3._conversationAssistantMessage.index];
|
|
1322
1321
|
if (msg) {
|
|
1323
1322
|
msg.isStreaming = false;
|
|
1323
|
+
msg.references = normalizeReferences(Object.assign({}, msg.references || {}, references || {}));
|
|
1324
|
+
updateMessagePresentation(msg, msg.references);
|
|
1324
1325
|
}
|
|
1325
|
-
|
|
1326
|
+
_this3._conversationAssistantMessage = null;
|
|
1326
1327
|
}
|
|
1327
1328
|
});
|
|
1328
|
-
|
|
1329
|
+
_this3.connection.on("ReceiveAudioChunk", function (sessionId, base64Audio, contentType) {
|
|
1329
1330
|
if (base64Audio) {
|
|
1330
1331
|
var binaryString = atob(base64Audio);
|
|
1331
1332
|
var bytes = new Uint8Array(binaryString.length);
|
|
1332
1333
|
for (var i = 0; i < binaryString.length; i++) {
|
|
1333
1334
|
bytes[i] = binaryString.charCodeAt(i);
|
|
1334
1335
|
}
|
|
1335
|
-
|
|
1336
|
+
_this3.audioChunks.push(bytes);
|
|
1336
1337
|
}
|
|
1337
1338
|
});
|
|
1338
|
-
|
|
1339
|
-
|
|
1339
|
+
_this3.connection.on("ReceiveAudioComplete", function (sessionId) {
|
|
1340
|
+
_this3.playCollectedAudio();
|
|
1340
1341
|
});
|
|
1341
|
-
|
|
1342
|
-
|
|
1342
|
+
_this3.connection.on("ReceiveNotification", function (notification) {
|
|
1343
|
+
_this3.receiveNotification(notification);
|
|
1343
1344
|
});
|
|
1344
|
-
|
|
1345
|
-
|
|
1345
|
+
_this3.connection.on("UpdateNotification", function (notification) {
|
|
1346
|
+
_this3.updateNotification(notification);
|
|
1346
1347
|
});
|
|
1347
|
-
|
|
1348
|
-
|
|
1348
|
+
_this3.connection.on("RemoveNotification", function (notificationType) {
|
|
1349
|
+
_this3.removeNotification(notificationType);
|
|
1349
1350
|
});
|
|
1350
|
-
|
|
1351
|
+
_this3.connection.onreconnecting(function () {
|
|
1351
1352
|
console.warn("SignalR: reconnecting...");
|
|
1352
1353
|
});
|
|
1353
|
-
|
|
1354
|
+
_this3.connection.onreconnected(function () {
|
|
1354
1355
|
console.info("SignalR: reconnected.");
|
|
1355
|
-
if (
|
|
1356
|
-
|
|
1357
|
-
} else if (config.autoCreateSession) {
|
|
1358
|
-
_this4.startNewSession();
|
|
1356
|
+
if (_this3.isSessionStarted) {
|
|
1357
|
+
_this3.reloadCurrentSession();
|
|
1359
1358
|
}
|
|
1360
1359
|
});
|
|
1361
|
-
|
|
1362
|
-
if (
|
|
1360
|
+
_this3.connection.onclose(function (error) {
|
|
1361
|
+
if (_this3.isNavigatingAway) {
|
|
1363
1362
|
return;
|
|
1364
1363
|
}
|
|
1365
1364
|
if (error) {
|
|
1366
1365
|
console.warn("SignalR connection closed with error:", error.message || error);
|
|
1367
1366
|
}
|
|
1368
1367
|
});
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
return
|
|
1368
|
+
_context6.p = 1;
|
|
1369
|
+
_context6.n = 2;
|
|
1370
|
+
return _this3.connection.start();
|
|
1372
1371
|
case 2:
|
|
1373
|
-
|
|
1372
|
+
_context6.n = 4;
|
|
1374
1373
|
break;
|
|
1375
1374
|
case 3:
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
console.error("SignalR Connection Error: ",
|
|
1375
|
+
_context6.p = 3;
|
|
1376
|
+
_t4 = _context6.v;
|
|
1377
|
+
console.error("SignalR Connection Error: ", _t4);
|
|
1379
1378
|
case 4:
|
|
1380
|
-
return
|
|
1379
|
+
return _context6.a(2);
|
|
1381
1380
|
}
|
|
1382
|
-
},
|
|
1381
|
+
}, _callee6, null, [[1, 3]]);
|
|
1383
1382
|
}))();
|
|
1384
1383
|
},
|
|
1385
1384
|
addMessageInternal: function addMessageInternal(message) {
|
|
1386
|
-
var
|
|
1385
|
+
var _this4 = this;
|
|
1387
1386
|
if (message.role === 'assistant') {
|
|
1388
1387
|
message.appearance = this.normalizeAssistantAppearance(message.appearance);
|
|
1389
1388
|
}
|
|
1390
1389
|
if (message.content && !message.htmlContent) {
|
|
1391
1390
|
message.htmlContent = parseMarkdownContent(message.content, message);
|
|
1392
1391
|
}
|
|
1393
|
-
this.fireEvent(new CustomEvent("
|
|
1392
|
+
this.fireEvent(new CustomEvent("addingCoreAIPromotMessage", {
|
|
1394
1393
|
detail: {
|
|
1395
1394
|
message: message
|
|
1396
1395
|
}
|
|
1397
1396
|
}));
|
|
1398
1397
|
this.messages.push(message);
|
|
1399
1398
|
this.$nextTick(function () {
|
|
1400
|
-
|
|
1399
|
+
_this4.fireEvent(new CustomEvent("addedCoreAIPromotMessage", {
|
|
1401
1400
|
detail: {
|
|
1402
1401
|
message: message
|
|
1403
1402
|
}
|
|
@@ -1405,105 +1404,32 @@ window.openAIChatManager = function () {
|
|
|
1405
1404
|
});
|
|
1406
1405
|
},
|
|
1407
1406
|
addMessage: function addMessage(message) {
|
|
1408
|
-
var
|
|
1407
|
+
var _this5 = this;
|
|
1409
1408
|
// Ensure userRating is always defined for Vue reactivity.
|
|
1410
1409
|
if (message.userRating === undefined) {
|
|
1411
1410
|
message.userRating = null;
|
|
1412
1411
|
}
|
|
1413
1412
|
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);
|
|
1413
|
+
var _message$rawContent;
|
|
1414
|
+
message.rawContent = (_message$rawContent = message.rawContent) !== null && _message$rawContent !== void 0 ? _message$rawContent : message.content;
|
|
1415
|
+
updateMessagePresentation(message, message.references);
|
|
1490
1416
|
}
|
|
1491
1417
|
this.addMessageInternal(message);
|
|
1492
1418
|
this.hidePlaceholder();
|
|
1493
1419
|
this.$nextTick(function () {
|
|
1494
1420
|
// Render any pending charts once the DOM is updated
|
|
1495
1421
|
renderChartsInMessage(message);
|
|
1496
|
-
|
|
1422
|
+
_this5.scrollToBottom();
|
|
1497
1423
|
});
|
|
1498
1424
|
},
|
|
1499
1425
|
addMessages: function addMessages(messages) {
|
|
1500
|
-
var
|
|
1426
|
+
var _this6 = this;
|
|
1501
1427
|
for (var i = 0; i < messages.length; i++) {
|
|
1502
1428
|
this.addMessageInternal(messages[i]);
|
|
1503
1429
|
}
|
|
1504
1430
|
this.hidePlaceholder();
|
|
1505
1431
|
this.$nextTick(function () {
|
|
1506
|
-
|
|
1432
|
+
_this6.scrollToBottom();
|
|
1507
1433
|
});
|
|
1508
1434
|
},
|
|
1509
1435
|
hidePlaceholder: function hidePlaceholder() {
|
|
@@ -1580,7 +1506,7 @@ window.openAIChatManager = function () {
|
|
|
1580
1506
|
this.prompt = '';
|
|
1581
1507
|
},
|
|
1582
1508
|
startRecording: function startRecording() {
|
|
1583
|
-
var
|
|
1509
|
+
var _this7 = this;
|
|
1584
1510
|
if (this.isRecording || !this.connection) {
|
|
1585
1511
|
return;
|
|
1586
1512
|
}
|
|
@@ -1592,27 +1518,27 @@ window.openAIChatManager = function () {
|
|
|
1592
1518
|
}
|
|
1593
1519
|
}).then(function (stream) {
|
|
1594
1520
|
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
|
-
|
|
1521
|
+
_this7.mediaRecorder = new MediaRecorder(stream, {
|
|
1596
1522
|
mimeType: mimeType,
|
|
1597
1523
|
audioBitsPerSecond: 128000
|
|
1598
1524
|
});
|
|
1599
|
-
|
|
1600
|
-
|
|
1525
|
+
_this7.preRecordingPrompt = _this7.prompt;
|
|
1526
|
+
_this7._audioInputSent = false;
|
|
1601
1527
|
var subject = new signalR.Subject();
|
|
1602
|
-
var profileId =
|
|
1603
|
-
var sessionId =
|
|
1528
|
+
var profileId = _this7.getProfileId();
|
|
1529
|
+
var sessionId = _this7.getSessionId() || '';
|
|
1604
1530
|
var pendingChunk = Promise.resolve();
|
|
1605
|
-
|
|
1531
|
+
_this7.mediaRecorder.addEventListener('dataavailable', function (e) {
|
|
1606
1532
|
if (e.data && e.data.size > 0) {
|
|
1607
|
-
pendingChunk = pendingChunk.then(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
1533
|
+
pendingChunk = pendingChunk.then(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee7() {
|
|
1608
1534
|
var data, uint8Array, binaryString, base64;
|
|
1609
|
-
return _regenerator().w(function (
|
|
1610
|
-
while (1) switch (
|
|
1535
|
+
return _regenerator().w(function (_context7) {
|
|
1536
|
+
while (1) switch (_context7.n) {
|
|
1611
1537
|
case 0:
|
|
1612
|
-
|
|
1538
|
+
_context7.n = 1;
|
|
1613
1539
|
return e.data.arrayBuffer();
|
|
1614
1540
|
case 1:
|
|
1615
|
-
data =
|
|
1541
|
+
data = _context7.v;
|
|
1616
1542
|
uint8Array = new Uint8Array(data);
|
|
1617
1543
|
binaryString = uint8Array.reduce(function (str, _byte) {
|
|
1618
1544
|
return str + String.fromCharCode(_byte);
|
|
@@ -1620,13 +1546,13 @@ window.openAIChatManager = function () {
|
|
|
1620
1546
|
base64 = btoa(binaryString);
|
|
1621
1547
|
subject.next(base64);
|
|
1622
1548
|
case 2:
|
|
1623
|
-
return
|
|
1549
|
+
return _context7.a(2);
|
|
1624
1550
|
}
|
|
1625
|
-
},
|
|
1551
|
+
}, _callee7);
|
|
1626
1552
|
})));
|
|
1627
1553
|
}
|
|
1628
1554
|
});
|
|
1629
|
-
|
|
1555
|
+
_this7.mediaRecorder.addEventListener('stop', function () {
|
|
1630
1556
|
stream.getTracks().forEach(function (track) {
|
|
1631
1557
|
return track.stop();
|
|
1632
1558
|
});
|
|
@@ -1635,10 +1561,10 @@ window.openAIChatManager = function () {
|
|
|
1635
1561
|
});
|
|
1636
1562
|
});
|
|
1637
1563
|
var language = navigator.language || document.documentElement.lang || 'en-US';
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1564
|
+
_this7.connection.send("SendAudioStream", profileId, sessionId, subject, mimeType, language);
|
|
1565
|
+
_this7.mediaRecorder.start(250);
|
|
1566
|
+
_this7.isRecording = true;
|
|
1567
|
+
_this7.updateMicButton();
|
|
1642
1568
|
})["catch"](function (err) {
|
|
1643
1569
|
console.error('Microphone access denied:', err);
|
|
1644
1570
|
});
|
|
@@ -1664,14 +1590,14 @@ window.openAIChatManager = function () {
|
|
|
1664
1590
|
}
|
|
1665
1591
|
if (this.isRecording) {
|
|
1666
1592
|
this.micButton.classList.add('stt-recording');
|
|
1667
|
-
this.micButton.innerHTML = '<
|
|
1593
|
+
this.micButton.innerHTML = '<i class="fa-solid fa-stop"></i>';
|
|
1668
1594
|
} else {
|
|
1669
1595
|
this.micButton.classList.remove('stt-recording');
|
|
1670
|
-
this.micButton.innerHTML = '<
|
|
1596
|
+
this.micButton.innerHTML = '<i class="fa-solid fa-microphone"></i>';
|
|
1671
1597
|
}
|
|
1672
1598
|
},
|
|
1673
1599
|
streamMessage: function streamMessage(profileId, trimmedPrompt, sessionProfileId) {
|
|
1674
|
-
var
|
|
1600
|
+
var _this8 = this;
|
|
1675
1601
|
if (this.stream) {
|
|
1676
1602
|
this.stream.dispose();
|
|
1677
1603
|
this.stream = null;
|
|
@@ -1688,14 +1614,14 @@ window.openAIChatManager = function () {
|
|
|
1688
1614
|
var currentSessionId = this.getSessionId();
|
|
1689
1615
|
this.stream = this.connection.stream("SendMessage", profileId, trimmedPrompt, currentSessionId, sessionProfileId).subscribe({
|
|
1690
1616
|
next: function next(chunk) {
|
|
1691
|
-
var message =
|
|
1617
|
+
var message = _this8.messages[messageIndex];
|
|
1692
1618
|
if (!message) {
|
|
1693
1619
|
if (chunk.sessionId && !currentSessionId) {
|
|
1694
|
-
|
|
1620
|
+
_this8.initializeSession(chunk.sessionId);
|
|
1695
1621
|
}
|
|
1696
|
-
|
|
1622
|
+
_this8.hideTypingIndicator();
|
|
1697
1623
|
// Re-assign the index after hiding the typing indicator.
|
|
1698
|
-
messageIndex =
|
|
1624
|
+
messageIndex = _this8.messages.length;
|
|
1699
1625
|
var newMessage = {
|
|
1700
1626
|
id: chunk.messageId,
|
|
1701
1627
|
role: "assistant",
|
|
@@ -1705,16 +1631,16 @@ window.openAIChatManager = function () {
|
|
|
1705
1631
|
isStreaming: true,
|
|
1706
1632
|
userRating: null
|
|
1707
1633
|
};
|
|
1708
|
-
|
|
1634
|
+
_this8.messages.push(newMessage);
|
|
1709
1635
|
message = newMessage;
|
|
1710
1636
|
}
|
|
1711
1637
|
if (chunk.title && (!message.title || message.title !== chunk.title)) {
|
|
1712
1638
|
message.title = chunk.title;
|
|
1713
1639
|
}
|
|
1714
1640
|
if (chunk.references && _typeof(chunk.references) === "object" && Object.keys(chunk.references).length) {
|
|
1715
|
-
for (var
|
|
1641
|
+
for (var _i4 = 0, _Object$entries2 = Object.entries(chunk.references); _i4 < _Object$entries2.length; _i4++) {
|
|
1716
1642
|
var _normalizeReference2;
|
|
1717
|
-
var _Object$entries2$_i = _slicedToArray(_Object$entries2[
|
|
1643
|
+
var _Object$entries2$_i = _slicedToArray(_Object$entries2[_i4], 2),
|
|
1718
1644
|
key = _Object$entries2$_i[0],
|
|
1719
1645
|
value = _Object$entries2$_i[1];
|
|
1720
1646
|
references[key] = (_normalizeReference2 = normalizeReference(value)) !== null && _normalizeReference2 !== void 0 ? _normalizeReference2 : {};
|
|
@@ -1729,62 +1655,52 @@ window.openAIChatManager = function () {
|
|
|
1729
1655
|
if (chunk.responseId) {
|
|
1730
1656
|
lastResponseId = chunk.responseId;
|
|
1731
1657
|
}
|
|
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>');
|
|
1658
|
+
content += chunk.content;
|
|
1743
1659
|
}
|
|
1744
1660
|
|
|
1745
1661
|
// Update the existing message
|
|
1746
|
-
message.
|
|
1747
|
-
message
|
|
1748
|
-
|
|
1749
|
-
|
|
1662
|
+
message.rawContent = content;
|
|
1663
|
+
updateMessagePresentation(message, references);
|
|
1664
|
+
_this8.messages[messageIndex] = message;
|
|
1665
|
+
_this8.$nextTick(function () {
|
|
1750
1666
|
renderChartsInMessage(message);
|
|
1751
|
-
|
|
1667
|
+
_this8.scrollToBottom();
|
|
1752
1668
|
});
|
|
1753
1669
|
},
|
|
1754
1670
|
complete: function complete() {
|
|
1755
|
-
var
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
var msg =
|
|
1671
|
+
var _this8$stream;
|
|
1672
|
+
_this8.processReferences(references, messageIndex);
|
|
1673
|
+
_this8.streamingFinished();
|
|
1674
|
+
var msg = _this8.messages[messageIndex];
|
|
1759
1675
|
if (msg) {
|
|
1760
1676
|
msg.isStreaming = false;
|
|
1761
1677
|
}
|
|
1762
1678
|
if (!msg || !msg.content) {
|
|
1763
1679
|
// No content received at all.
|
|
1764
|
-
|
|
1680
|
+
_this8.hideTypingIndicator();
|
|
1765
1681
|
}
|
|
1766
1682
|
|
|
1767
1683
|
// Trigger text-to-speech only in conversation mode.
|
|
1768
|
-
if (
|
|
1769
|
-
|
|
1684
|
+
if (_this8.isConversationMode && _this8.textToSpeechEnabled && msg && msg.content) {
|
|
1685
|
+
_this8.synthesizeSpeech(msg.content);
|
|
1770
1686
|
}
|
|
1771
|
-
(
|
|
1772
|
-
|
|
1687
|
+
(_this8$stream = _this8.stream) === null || _this8$stream === void 0 || _this8$stream.dispose();
|
|
1688
|
+
_this8.stream = null;
|
|
1773
1689
|
},
|
|
1774
1690
|
error: function error(err) {
|
|
1775
|
-
var
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
var msg =
|
|
1691
|
+
var _this8$stream2;
|
|
1692
|
+
_this8.processReferences(references, messageIndex);
|
|
1693
|
+
_this8.streamingFinished();
|
|
1694
|
+
var msg = _this8.messages[messageIndex];
|
|
1779
1695
|
if (msg) {
|
|
1780
1696
|
msg.isStreaming = false;
|
|
1781
1697
|
}
|
|
1782
|
-
|
|
1783
|
-
if (!
|
|
1784
|
-
|
|
1698
|
+
_this8.hideTypingIndicator();
|
|
1699
|
+
if (!_this8.isNavigatingAway) {
|
|
1700
|
+
_this8.addMessage(_this8.getServiceDownMessage());
|
|
1785
1701
|
}
|
|
1786
|
-
(
|
|
1787
|
-
|
|
1702
|
+
(_this8$stream2 = _this8.stream) === null || _this8$stream2 === void 0 || _this8$stream2.dispose();
|
|
1703
|
+
_this8.stream = null;
|
|
1788
1704
|
console.error("Stream error:", err);
|
|
1789
1705
|
}
|
|
1790
1706
|
});
|
|
@@ -1798,92 +1714,17 @@ window.openAIChatManager = function () {
|
|
|
1798
1714
|
return newMessage;
|
|
1799
1715
|
},
|
|
1800
1716
|
processReferences: function processReferences(references, messageIndex) {
|
|
1801
|
-
var
|
|
1717
|
+
var _this9 = this;
|
|
1802
1718
|
references = normalizeReferences(references);
|
|
1803
1719
|
if (Object.keys(references).length) {
|
|
1720
|
+
var _ref23, _message$rawContent2;
|
|
1804
1721
|
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);
|
|
1722
|
+
message.rawContent = (_ref23 = (_message$rawContent2 = message.rawContent) !== null && _message$rawContent2 !== void 0 ? _message$rawContent2 : message.content) !== null && _ref23 !== void 0 ? _ref23 : '';
|
|
1723
|
+
updateMessagePresentation(message, references);
|
|
1883
1724
|
this.messages[messageIndex] = message;
|
|
1884
1725
|
this.$nextTick(function () {
|
|
1885
1726
|
renderChartsInMessage(message);
|
|
1886
|
-
|
|
1727
|
+
_this9.scrollToBottom();
|
|
1887
1728
|
});
|
|
1888
1729
|
}
|
|
1889
1730
|
},
|
|
@@ -1934,22 +1775,48 @@ window.openAIChatManager = function () {
|
|
|
1934
1775
|
this.stopAudio(false);
|
|
1935
1776
|
},
|
|
1936
1777
|
updateTtsPlaybackButtons: function updateTtsPlaybackButtons() {
|
|
1937
|
-
var
|
|
1778
|
+
var _this0 = this;
|
|
1938
1779
|
if (!this.chatContainer) {
|
|
1939
1780
|
return;
|
|
1940
1781
|
}
|
|
1941
1782
|
var buttons = this.chatContainer.querySelectorAll('[data-tts-message-index]');
|
|
1942
1783
|
buttons.forEach(function (button) {
|
|
1943
1784
|
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>';
|
|
1785
|
+
var isPlaying = buttonIndex === _this0.ttsPlayingMessageIndex;
|
|
1946
1786
|
button.classList.toggle('tts-playing', isPlaying);
|
|
1947
1787
|
button.setAttribute('title', isPlaying ? 'Pause audio' : 'Read aloud');
|
|
1788
|
+
});
|
|
1789
|
+
},
|
|
1790
|
+
updateCopyButtons: function updateCopyButtons() {
|
|
1791
|
+
var _this1 = this;
|
|
1792
|
+
if (!this.chatContainer) {
|
|
1793
|
+
return;
|
|
1794
|
+
}
|
|
1795
|
+
var buttons = this.chatContainer.querySelectorAll('[data-copy-message-index]');
|
|
1796
|
+
buttons.forEach(function (button) {
|
|
1797
|
+
var buttonIndex = Number(button.getAttribute('data-copy-message-index'));
|
|
1798
|
+
var isCopied = buttonIndex === _this1.copiedMessageIndex;
|
|
1799
|
+
var iconHtml = isCopied ? '<i class="fa-solid fa-check"></i>' : '<i class="fa-solid fa-copy"></i>';
|
|
1800
|
+
button.classList.toggle('text-success', isCopied);
|
|
1801
|
+
button.classList.toggle('text-secondary', !isCopied);
|
|
1802
|
+
button.setAttribute('title', isCopied ? _this1.copiedTitle : _this1.copyTitle);
|
|
1948
1803
|
button.replaceChildren(DOMPurify.sanitize(iconHtml, {
|
|
1949
1804
|
RETURN_DOM_FRAGMENT: true
|
|
1950
1805
|
}));
|
|
1951
1806
|
});
|
|
1952
1807
|
},
|
|
1808
|
+
setCopyButtonState: function setCopyButtonState(button, isCopied) {
|
|
1809
|
+
if (!button) {
|
|
1810
|
+
return;
|
|
1811
|
+
}
|
|
1812
|
+
var iconHtml = isCopied ? '<i class="fa-solid fa-check"></i>' : '<i class="fa-solid fa-copy"></i>';
|
|
1813
|
+
button.classList.toggle('text-success', isCopied);
|
|
1814
|
+
button.classList.toggle('text-secondary', !isCopied);
|
|
1815
|
+
button.setAttribute('title', isCopied ? this.copiedTitle : this.copyTitle);
|
|
1816
|
+
button.replaceChildren(DOMPurify.sanitize(iconHtml, {
|
|
1817
|
+
RETURN_DOM_FRAGMENT: true
|
|
1818
|
+
}));
|
|
1819
|
+
},
|
|
1953
1820
|
synthesizeSpeech: function synthesizeSpeech(text, cacheIndex) {
|
|
1954
1821
|
var _this10 = this;
|
|
1955
1822
|
if (!this.textToSpeechEnabled || !text || !this.connection) {
|
|
@@ -2007,18 +1874,18 @@ window.openAIChatManager = function () {
|
|
|
2007
1874
|
}, 0);
|
|
2008
1875
|
var combined = new Uint8Array(totalLength);
|
|
2009
1876
|
var offset = 0;
|
|
2010
|
-
var
|
|
2011
|
-
|
|
1877
|
+
var _iterator6 = _createForOfIteratorHelper(this.audioChunks),
|
|
1878
|
+
_step6;
|
|
2012
1879
|
try {
|
|
2013
|
-
for (
|
|
2014
|
-
var chunk =
|
|
1880
|
+
for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
|
|
1881
|
+
var chunk = _step6.value;
|
|
2015
1882
|
combined.set(chunk, offset);
|
|
2016
1883
|
offset += chunk.length;
|
|
2017
1884
|
}
|
|
2018
1885
|
} catch (err) {
|
|
2019
|
-
|
|
1886
|
+
_iterator6.e(err);
|
|
2020
1887
|
} finally {
|
|
2021
|
-
|
|
1888
|
+
_iterator6.f();
|
|
2022
1889
|
}
|
|
2023
1890
|
this.audioChunks = [];
|
|
2024
1891
|
var blob = new Blob([combined], {
|
|
@@ -2173,15 +2040,15 @@ window.openAIChatManager = function () {
|
|
|
2173
2040
|
// Always send audio to STT — browser echo cancellation
|
|
2174
2041
|
// handles speaker echo; continuous audio avoids gaps
|
|
2175
2042
|
// that increase recognition latency.
|
|
2176
|
-
pendingChunk = pendingChunk.then(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
2043
|
+
pendingChunk = pendingChunk.then(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee8() {
|
|
2177
2044
|
var data, uint8Array, binaryString, base64;
|
|
2178
|
-
return _regenerator().w(function (
|
|
2179
|
-
while (1) switch (
|
|
2045
|
+
return _regenerator().w(function (_context8) {
|
|
2046
|
+
while (1) switch (_context8.n) {
|
|
2180
2047
|
case 0:
|
|
2181
|
-
|
|
2048
|
+
_context8.n = 1;
|
|
2182
2049
|
return e.data.arrayBuffer();
|
|
2183
2050
|
case 1:
|
|
2184
|
-
data =
|
|
2051
|
+
data = _context8.v;
|
|
2185
2052
|
uint8Array = new Uint8Array(data);
|
|
2186
2053
|
binaryString = uint8Array.reduce(function (str, _byte2) {
|
|
2187
2054
|
return str + String.fromCharCode(_byte2);
|
|
@@ -2193,9 +2060,9 @@ window.openAIChatManager = function () {
|
|
|
2193
2060
|
// Subject may have been completed already.
|
|
2194
2061
|
}
|
|
2195
2062
|
case 2:
|
|
2196
|
-
return
|
|
2063
|
+
return _context8.a(2);
|
|
2197
2064
|
}
|
|
2198
|
-
},
|
|
2065
|
+
}, _callee8);
|
|
2199
2066
|
})));
|
|
2200
2067
|
}
|
|
2201
2068
|
});
|
|
@@ -2426,26 +2293,25 @@ window.openAIChatManager = function () {
|
|
|
2426
2293
|
this.prompt = event.target.value;
|
|
2427
2294
|
},
|
|
2428
2295
|
getProfileId: function getProfileId() {
|
|
2429
|
-
return this.inputElement.getAttribute('data-profile-id');
|
|
2296
|
+
return this.inputElement ? this.inputElement.getAttribute('data-profile-id') : null;
|
|
2430
2297
|
},
|
|
2431
2298
|
setSessionId: function setSessionId(sessionId) {
|
|
2299
|
+
if (!this.inputElement) {
|
|
2300
|
+
return;
|
|
2301
|
+
}
|
|
2432
2302
|
this.inputElement.setAttribute('data-session-id', sessionId || '');
|
|
2433
2303
|
},
|
|
2434
2304
|
resetSession: function resetSession() {
|
|
2435
2305
|
this.stopRecording();
|
|
2306
|
+
this.rejectPendingSessionRequest('Session was reset.');
|
|
2436
2307
|
this.setSessionId('');
|
|
2437
2308
|
this.isSessionStarted = false;
|
|
2438
2309
|
this.sessionRating = null;
|
|
2439
|
-
if (this.widgetIsInitialized) {
|
|
2440
|
-
localStorage.removeItem(this.chatWidgetStateSession);
|
|
2441
|
-
}
|
|
2442
2310
|
this.messages = [];
|
|
2443
2311
|
this.documents = [];
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
if (config.autoCreateSession) {
|
|
2448
|
-
this.startNewSession();
|
|
2312
|
+
this.showPlaceholder();
|
|
2313
|
+
if (widgetBehavior && typeof widgetBehavior.onSessionReset === 'function') {
|
|
2314
|
+
widgetBehavior.onSessionReset(this, config);
|
|
2449
2315
|
}
|
|
2450
2316
|
},
|
|
2451
2317
|
startNewSession: function startNewSession() {
|
|
@@ -2456,22 +2322,98 @@ window.openAIChatManager = function () {
|
|
|
2456
2322
|
if (!profileId || !this.connection) {
|
|
2457
2323
|
return;
|
|
2458
2324
|
}
|
|
2459
|
-
this.
|
|
2325
|
+
this.requestNewSession(profileId)["catch"](function (err) {
|
|
2460
2326
|
return console.error(err);
|
|
2461
2327
|
});
|
|
2462
2328
|
},
|
|
2463
|
-
|
|
2329
|
+
ensureSessionForDocuments: function ensureSessionForDocuments(profileId) {
|
|
2464
2330
|
var _this20 = this;
|
|
2331
|
+
return _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee9() {
|
|
2332
|
+
var sessionId;
|
|
2333
|
+
return _regenerator().w(function (_context9) {
|
|
2334
|
+
while (1) switch (_context9.n) {
|
|
2335
|
+
case 0:
|
|
2336
|
+
sessionId = _this20.getSessionId();
|
|
2337
|
+
if (!sessionId) {
|
|
2338
|
+
_context9.n = 1;
|
|
2339
|
+
break;
|
|
2340
|
+
}
|
|
2341
|
+
return _context9.a(2, sessionId);
|
|
2342
|
+
case 1:
|
|
2343
|
+
if (!(!profileId || !_this20.connection)) {
|
|
2344
|
+
_context9.n = 2;
|
|
2345
|
+
break;
|
|
2346
|
+
}
|
|
2347
|
+
return _context9.a(2, null);
|
|
2348
|
+
case 2:
|
|
2349
|
+
_context9.n = 3;
|
|
2350
|
+
return _this20.requestNewSession(profileId);
|
|
2351
|
+
case 3:
|
|
2352
|
+
return _context9.a(2, _context9.v);
|
|
2353
|
+
}
|
|
2354
|
+
}, _callee9);
|
|
2355
|
+
}))();
|
|
2356
|
+
},
|
|
2357
|
+
requestNewSession: function requestNewSession(profileId) {
|
|
2358
|
+
var _this21 = this;
|
|
2359
|
+
if (this.pendingSessionPromise) {
|
|
2360
|
+
return this.pendingSessionPromise;
|
|
2361
|
+
}
|
|
2362
|
+
if (!profileId || !this.connection) {
|
|
2363
|
+
return Promise.resolve(null);
|
|
2364
|
+
}
|
|
2365
|
+
this.pendingSessionPromise = new Promise(function (resolve, reject) {
|
|
2366
|
+
_this21.pendingSessionResolver = resolve;
|
|
2367
|
+
_this21.pendingSessionRejector = reject;
|
|
2368
|
+
_this21.pendingSessionTimeoutId = window.setTimeout(function () {
|
|
2369
|
+
_this21.rejectPendingSessionRequest('Timed out while creating a chat session.');
|
|
2370
|
+
}, 15000);
|
|
2371
|
+
});
|
|
2372
|
+
this.connection.invoke("StartSession", profileId, null)["catch"](function (err) {
|
|
2373
|
+
_this21.rejectPendingSessionRequest(err);
|
|
2374
|
+
});
|
|
2375
|
+
return this.pendingSessionPromise;
|
|
2376
|
+
},
|
|
2377
|
+
resolvePendingSessionRequest: function resolvePendingSessionRequest(sessionId) {
|
|
2378
|
+
if (this.pendingSessionResolver) {
|
|
2379
|
+
this.pendingSessionResolver(sessionId);
|
|
2380
|
+
}
|
|
2381
|
+
this.clearPendingSessionRequest();
|
|
2382
|
+
},
|
|
2383
|
+
rejectPendingSessionRequest: function rejectPendingSessionRequest(error) {
|
|
2384
|
+
if (this.pendingSessionRejector) {
|
|
2385
|
+
this.pendingSessionRejector(error);
|
|
2386
|
+
}
|
|
2387
|
+
this.clearPendingSessionRequest();
|
|
2388
|
+
},
|
|
2389
|
+
clearPendingSessionRequest: function clearPendingSessionRequest() {
|
|
2390
|
+
if (this.pendingSessionTimeoutId) {
|
|
2391
|
+
window.clearTimeout(this.pendingSessionTimeoutId);
|
|
2392
|
+
}
|
|
2393
|
+
this.pendingSessionPromise = null;
|
|
2394
|
+
this.pendingSessionResolver = null;
|
|
2395
|
+
this.pendingSessionRejector = null;
|
|
2396
|
+
this.pendingSessionTimeoutId = null;
|
|
2397
|
+
},
|
|
2398
|
+
initializeApp: function initializeApp() {
|
|
2399
|
+
var _this22 = this;
|
|
2465
2400
|
this.inputElement = document.querySelector(config.inputElementSelector);
|
|
2466
2401
|
this.buttonElement = document.querySelector(config.sendButtonElementSelector);
|
|
2467
2402
|
this.chatContainer = document.querySelector(config.chatContainerElementSelector);
|
|
2468
2403
|
this.placeholder = document.querySelector(config.placeholderElementSelector);
|
|
2404
|
+
if (!this.inputElement || !this.buttonElement || !this.chatContainer || !this.placeholder) {
|
|
2405
|
+
console.error('AI chat app could not initialize because one or more required elements were not found.', {
|
|
2406
|
+
inputElementSelector: config.inputElementSelector,
|
|
2407
|
+
sendButtonElementSelector: config.sendButtonElementSelector,
|
|
2408
|
+
chatContainerElementSelector: config.chatContainerElementSelector,
|
|
2409
|
+
placeholderElementSelector: config.placeholderElementSelector
|
|
2410
|
+
});
|
|
2411
|
+
return false;
|
|
2412
|
+
}
|
|
2469
2413
|
this.applyOrchestratorAvailability();
|
|
2470
2414
|
var sessionId = this.getSessionId();
|
|
2471
2415
|
if (!hasWidgetConfig && sessionId) {
|
|
2472
2416
|
this.loadSession(sessionId);
|
|
2473
|
-
} else if (this.isOrchestratorAvailable() && config.autoCreateSession && !hasWidgetConfig && !sessionId) {
|
|
2474
|
-
this.startNewSession();
|
|
2475
2417
|
}
|
|
2476
2418
|
|
|
2477
2419
|
// Initialize document bar if enabled.
|
|
@@ -2490,7 +2432,7 @@ window.openAIChatManager = function () {
|
|
|
2490
2432
|
fileInput.accept = config.allowedExtensions;
|
|
2491
2433
|
}
|
|
2492
2434
|
fileInput.addEventListener('change', function (e) {
|
|
2493
|
-
return
|
|
2435
|
+
return _this22.handleFileInputChange(e);
|
|
2494
2436
|
});
|
|
2495
2437
|
this.documentBar.parentElement.appendChild(fileInput);
|
|
2496
2438
|
|
|
@@ -2498,13 +2440,13 @@ window.openAIChatManager = function () {
|
|
|
2498
2440
|
var inputArea = this.inputElement ? this.inputElement.closest('.ai-admin-widget-input, .text-bg-light') : null;
|
|
2499
2441
|
if (inputArea) {
|
|
2500
2442
|
inputArea.addEventListener('dragover', function (e) {
|
|
2501
|
-
return
|
|
2443
|
+
return _this22.handleDragOver(e);
|
|
2502
2444
|
});
|
|
2503
2445
|
inputArea.addEventListener('dragleave', function (e) {
|
|
2504
|
-
return
|
|
2446
|
+
return _this22.handleDragLeave(e);
|
|
2505
2447
|
});
|
|
2506
2448
|
inputArea.addEventListener('drop', function (e) {
|
|
2507
|
-
return
|
|
2449
|
+
return _this22.handleDrop(e);
|
|
2508
2450
|
});
|
|
2509
2451
|
}
|
|
2510
2452
|
}
|
|
@@ -2512,55 +2454,55 @@ window.openAIChatManager = function () {
|
|
|
2512
2454
|
|
|
2513
2455
|
// Pause auto-scroll when the user manually scrolls up during streaming.
|
|
2514
2456
|
this.chatContainer.addEventListener('scroll', function () {
|
|
2515
|
-
if (!
|
|
2457
|
+
if (!_this22.stream) {
|
|
2516
2458
|
return;
|
|
2517
2459
|
}
|
|
2518
2460
|
var threshold = 30;
|
|
2519
|
-
var atBottom =
|
|
2520
|
-
|
|
2461
|
+
var atBottom = _this22.chatContainer.scrollHeight - _this22.chatContainer.clientHeight - _this22.chatContainer.scrollTop <= threshold;
|
|
2462
|
+
_this22.autoScroll = atBottom;
|
|
2521
2463
|
});
|
|
2522
2464
|
this.inputElement.addEventListener('keydown', function (event) {
|
|
2523
|
-
if (
|
|
2465
|
+
if (_this22.stream != null) {
|
|
2524
2466
|
return;
|
|
2525
2467
|
}
|
|
2526
2468
|
if (event.key === "Enter" && !event.shiftKey) {
|
|
2527
2469
|
event.preventDefault();
|
|
2528
|
-
|
|
2470
|
+
_this22.buttonElement.click();
|
|
2529
2471
|
}
|
|
2530
2472
|
});
|
|
2531
2473
|
this.inputElement.addEventListener('input', function (e) {
|
|
2532
|
-
|
|
2474
|
+
_this22.handleUserInput(e);
|
|
2533
2475
|
if (e.target.value.trim()) {
|
|
2534
|
-
|
|
2476
|
+
_this22.buttonElement.removeAttribute('disabled');
|
|
2535
2477
|
} else {
|
|
2536
|
-
|
|
2478
|
+
_this22.buttonElement.setAttribute('disabled', true);
|
|
2537
2479
|
}
|
|
2538
2480
|
});
|
|
2539
2481
|
this.buttonElement.addEventListener('click', function () {
|
|
2540
|
-
if (
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2482
|
+
if (_this22.stream != null) {
|
|
2483
|
+
_this22.stream.dispose();
|
|
2484
|
+
_this22.stream = null;
|
|
2485
|
+
_this22.streamingFinished();
|
|
2486
|
+
_this22.hideTypingIndicator();
|
|
2545
2487
|
|
|
2546
2488
|
// Clean up: remove empty assistant message or stop streaming animation.
|
|
2547
|
-
if (
|
|
2548
|
-
var lastMsg =
|
|
2489
|
+
if (_this22.messages.length > 0) {
|
|
2490
|
+
var lastMsg = _this22.messages[_this22.messages.length - 1];
|
|
2549
2491
|
if (lastMsg.role === 'assistant' && !lastMsg.content) {
|
|
2550
|
-
|
|
2492
|
+
_this22.messages.pop();
|
|
2551
2493
|
} else if (lastMsg.isStreaming) {
|
|
2552
2494
|
lastMsg.isStreaming = false;
|
|
2553
2495
|
}
|
|
2554
2496
|
}
|
|
2555
2497
|
return;
|
|
2556
2498
|
}
|
|
2557
|
-
|
|
2499
|
+
_this22.sendMessage();
|
|
2558
2500
|
});
|
|
2559
2501
|
var promptGenerators = document.getElementsByClassName('profile-generated-prompt');
|
|
2560
2502
|
for (var i = 0; i < promptGenerators.length; i++) {
|
|
2561
2503
|
promptGenerators[i].addEventListener('click', function (e) {
|
|
2562
2504
|
e.preventDefault();
|
|
2563
|
-
|
|
2505
|
+
_this22.generatePrompt(e.target);
|
|
2564
2506
|
});
|
|
2565
2507
|
}
|
|
2566
2508
|
var chatSessions = document.getElementsByClassName('chat-session-history-item');
|
|
@@ -2572,17 +2514,18 @@ window.openAIChatManager = function () {
|
|
|
2572
2514
|
console.error('an element with the class chat-session-history-item with no data-session-id set.');
|
|
2573
2515
|
return;
|
|
2574
2516
|
}
|
|
2575
|
-
|
|
2576
|
-
|
|
2517
|
+
_this22.loadSession(sessionId);
|
|
2518
|
+
_this22.showChatScreen();
|
|
2577
2519
|
});
|
|
2578
2520
|
}
|
|
2579
|
-
|
|
2580
|
-
|
|
2521
|
+
var initialMessages = Array.isArray(config.messages) ? config.messages : [];
|
|
2522
|
+
for (var _i5 = 0; _i5 < initialMessages.length; _i5++) {
|
|
2523
|
+
this.addMessage(initialMessages[_i5]);
|
|
2581
2524
|
}
|
|
2582
2525
|
|
|
2583
2526
|
// Update feedback icons in the DOM after initial messages have rendered.
|
|
2584
2527
|
this.$nextTick(function () {
|
|
2585
|
-
|
|
2528
|
+
_this22.refreshAllFeedbackIcons();
|
|
2586
2529
|
});
|
|
2587
2530
|
|
|
2588
2531
|
// Delegate click for code block copy buttons.
|
|
@@ -2600,9 +2543,9 @@ window.openAIChatManager = function () {
|
|
|
2600
2543
|
if (codeEl) {
|
|
2601
2544
|
navigator.clipboard.writeText(codeEl.textContent);
|
|
2602
2545
|
var copiedText = config.codeCopiedText || 'Copied!';
|
|
2603
|
-
btn.innerHTML = '<
|
|
2546
|
+
btn.innerHTML = '<i class="fa-solid fa-check"></i> ' + copiedText;
|
|
2604
2547
|
setTimeout(function () {
|
|
2605
|
-
btn.innerHTML = '<
|
|
2548
|
+
btn.innerHTML = '<i class="fa-regular fa-copy"></i>';
|
|
2606
2549
|
}, 2000);
|
|
2607
2550
|
}
|
|
2608
2551
|
});
|
|
@@ -2614,7 +2557,7 @@ window.openAIChatManager = function () {
|
|
|
2614
2557
|
if (this.micButton) {
|
|
2615
2558
|
this.micButton.style.display = '';
|
|
2616
2559
|
this.micButton.addEventListener('click', function () {
|
|
2617
|
-
|
|
2560
|
+
_this22.toggleRecording();
|
|
2618
2561
|
});
|
|
2619
2562
|
}
|
|
2620
2563
|
}
|
|
@@ -2624,10 +2567,11 @@ window.openAIChatManager = function () {
|
|
|
2624
2567
|
this.conversationButton = document.querySelector(config.conversationButtonElementSelector);
|
|
2625
2568
|
if (this.conversationButton) {
|
|
2626
2569
|
this.conversationButton.addEventListener('click', function () {
|
|
2627
|
-
|
|
2570
|
+
_this22.toggleConversationMode();
|
|
2628
2571
|
});
|
|
2629
2572
|
}
|
|
2630
2573
|
}
|
|
2574
|
+
return true;
|
|
2631
2575
|
},
|
|
2632
2576
|
loadSession: function loadSession(sessionId) {
|
|
2633
2577
|
this.connection.invoke("LoadSession", sessionId)["catch"](function (err) {
|
|
@@ -2642,130 +2586,69 @@ window.openAIChatManager = function () {
|
|
|
2642
2586
|
},
|
|
2643
2587
|
initializeSession: function initializeSession(sessionId, force) {
|
|
2644
2588
|
if (this.isSessionStarted && !force) {
|
|
2589
|
+
if (sessionId && this.getSessionId() === sessionId) {
|
|
2590
|
+
this.resolvePendingSessionRequest(sessionId);
|
|
2591
|
+
}
|
|
2645
2592
|
return;
|
|
2646
2593
|
}
|
|
2647
|
-
this.fireEvent(new CustomEvent("
|
|
2594
|
+
this.fireEvent(new CustomEvent("initializingSessionCoreAIChat", {
|
|
2648
2595
|
detail: {
|
|
2649
2596
|
sessionId: sessionId
|
|
2650
2597
|
}
|
|
2651
2598
|
}));
|
|
2652
2599
|
this.setSessionId(sessionId);
|
|
2653
2600
|
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
|
-
});
|
|
2601
|
+
this.resolvePendingSessionRequest(sessionId);
|
|
2602
|
+
if (widgetBehavior && typeof widgetBehavior.onSessionInitialized === 'function') {
|
|
2603
|
+
widgetBehavior.onSessionInitialized(this, sessionId, config);
|
|
2713
2604
|
}
|
|
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;
|
|
2757
|
-
}
|
|
2758
|
-
this.chatHistorySection.classList.remove('show');
|
|
2759
2605
|
},
|
|
2760
2606
|
getSessionId: function getSessionId() {
|
|
2761
|
-
var sessionId = this.inputElement.getAttribute('data-session-id');
|
|
2762
|
-
if (!sessionId &&
|
|
2763
|
-
sessionId =
|
|
2607
|
+
var sessionId = this.inputElement ? this.inputElement.getAttribute('data-session-id') : null;
|
|
2608
|
+
if (!sessionId && widgetBehavior && typeof widgetBehavior.resolveSessionId === 'function') {
|
|
2609
|
+
sessionId = widgetBehavior.resolveSessionId(this, config);
|
|
2764
2610
|
}
|
|
2765
2611
|
return sessionId;
|
|
2766
2612
|
},
|
|
2767
|
-
|
|
2768
|
-
|
|
2613
|
+
clearCopiedMessageState: function clearCopiedMessageState() {
|
|
2614
|
+
if (this.copyResetTimeoutId) {
|
|
2615
|
+
window.clearTimeout(this.copyResetTimeoutId);
|
|
2616
|
+
this.copyResetTimeoutId = null;
|
|
2617
|
+
}
|
|
2618
|
+
if (this.activeCopyButton) {
|
|
2619
|
+
this.setCopyButtonState(this.activeCopyButton, false);
|
|
2620
|
+
this.activeCopyButton = null;
|
|
2621
|
+
}
|
|
2622
|
+
this.copiedMessageIndex = -1;
|
|
2623
|
+
},
|
|
2624
|
+
copyResponse: function copyResponse(message, index, event) {
|
|
2625
|
+
var _ref25,
|
|
2626
|
+
_message$copyContent,
|
|
2627
|
+
_event$target,
|
|
2628
|
+
_event$target$closest,
|
|
2629
|
+
_this23 = this;
|
|
2630
|
+
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 : '';
|
|
2631
|
+
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;
|
|
2632
|
+
navigator.clipboard.writeText(text).then(function () {
|
|
2633
|
+
_this23.clearCopiedMessageState();
|
|
2634
|
+
_this23.copiedMessageIndex = typeof index === 'number' ? index : -1;
|
|
2635
|
+
_this23.activeCopyButton = button;
|
|
2636
|
+
if (button) {
|
|
2637
|
+
_this23.setCopyButtonState(button, true);
|
|
2638
|
+
} else {
|
|
2639
|
+
_this23.$nextTick(function () {
|
|
2640
|
+
return _this23.updateCopyButtons();
|
|
2641
|
+
});
|
|
2642
|
+
}
|
|
2643
|
+
_this23.copyResetTimeoutId = window.setTimeout(function () {
|
|
2644
|
+
_this23.clearCopiedMessageState();
|
|
2645
|
+
_this23.$nextTick(function () {
|
|
2646
|
+
return _this23.updateCopyButtons();
|
|
2647
|
+
});
|
|
2648
|
+
}, Number(config.copyResetDelayMs) || 2000);
|
|
2649
|
+
})["catch"](function (err) {
|
|
2650
|
+
return console.error('Failed to copy response:', err);
|
|
2651
|
+
});
|
|
2769
2652
|
},
|
|
2770
2653
|
updateFeedbackIcons: function updateFeedbackIcons(container, userRating) {
|
|
2771
2654
|
if (!container) {
|
|
@@ -2844,16 +2727,28 @@ window.openAIChatManager = function () {
|
|
|
2844
2727
|
documents: {
|
|
2845
2728
|
handler: function handler() {
|
|
2846
2729
|
this.renderDocumentBar();
|
|
2730
|
+
if (widgetBehavior && typeof widgetBehavior.onDocumentsChanged === 'function') {
|
|
2731
|
+
widgetBehavior.onDocumentsChanged(this, this.documents, config);
|
|
2732
|
+
}
|
|
2847
2733
|
},
|
|
2848
2734
|
deep: true
|
|
2849
2735
|
},
|
|
2850
2736
|
isUploading: function isUploading() {
|
|
2851
2737
|
this.renderDocumentBar();
|
|
2852
2738
|
},
|
|
2739
|
+
isDocumentOperationPending: function isDocumentOperationPending() {
|
|
2740
|
+
this.renderDocumentBar();
|
|
2741
|
+
},
|
|
2853
2742
|
isPlayingAudio: function isPlayingAudio() {
|
|
2854
2743
|
// Reserved for future use — volume-based interrupt detection
|
|
2855
2744
|
// no longer mutes tracks; browser echo cancellation handles echo.
|
|
2856
2745
|
},
|
|
2746
|
+
copiedMessageIndex: function copiedMessageIndex() {
|
|
2747
|
+
var _this24 = this;
|
|
2748
|
+
this.$nextTick(function () {
|
|
2749
|
+
return _this24.updateCopyButtons();
|
|
2750
|
+
});
|
|
2751
|
+
},
|
|
2857
2752
|
isConversationMode: function isConversationMode(active) {
|
|
2858
2753
|
// Hide/show mic button.
|
|
2859
2754
|
if (this.micButton) {
|
|
@@ -2875,22 +2770,28 @@ window.openAIChatManager = function () {
|
|
|
2875
2770
|
}
|
|
2876
2771
|
},
|
|
2877
2772
|
mounted: function mounted() {
|
|
2878
|
-
var
|
|
2879
|
-
_asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
2880
|
-
|
|
2881
|
-
|
|
2773
|
+
var _this25 = this;
|
|
2774
|
+
_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee0() {
|
|
2775
|
+
var isInitialized;
|
|
2776
|
+
return _regenerator().w(function (_context0) {
|
|
2777
|
+
while (1) switch (_context0.n) {
|
|
2882
2778
|
case 0:
|
|
2883
|
-
|
|
2884
|
-
return
|
|
2779
|
+
_context0.n = 1;
|
|
2780
|
+
return _this25.startConnection();
|
|
2885
2781
|
case 1:
|
|
2886
|
-
|
|
2887
|
-
if (hasWidgetConfig) {
|
|
2888
|
-
|
|
2782
|
+
isInitialized = _this25.initializeApp();
|
|
2783
|
+
if (isInitialized && hasWidgetConfig && widgetBehavior && typeof widgetBehavior.onMounted === 'function') {
|
|
2784
|
+
widgetBehavior.onMounted(_this25, config);
|
|
2889
2785
|
}
|
|
2786
|
+
_this25.$nextTick(function () {
|
|
2787
|
+
_this25.updateCopyButtons();
|
|
2788
|
+
refreshFontAwesomeIcons(_this25.$el);
|
|
2789
|
+
_this25.fontAwesomeObserver = observeFontAwesomeIcons(_this25.$el);
|
|
2790
|
+
});
|
|
2890
2791
|
case 2:
|
|
2891
|
-
return
|
|
2792
|
+
return _context0.a(2);
|
|
2892
2793
|
}
|
|
2893
|
-
},
|
|
2794
|
+
}, _callee0);
|
|
2894
2795
|
}))();
|
|
2895
2796
|
window.addEventListener('beforeunload', this.handleBeforeUnload);
|
|
2896
2797
|
window.addEventListener('crestapps-ai-chat-stop-tts', this.handleExternalTtsStop);
|
|
@@ -2898,6 +2799,11 @@ window.openAIChatManager = function () {
|
|
|
2898
2799
|
beforeUnmount: function beforeUnmount() {
|
|
2899
2800
|
window.removeEventListener('beforeunload', this.handleBeforeUnload);
|
|
2900
2801
|
window.removeEventListener('crestapps-ai-chat-stop-tts', this.handleExternalTtsStop);
|
|
2802
|
+
if (this.fontAwesomeObserver) {
|
|
2803
|
+
this.fontAwesomeObserver.disconnect();
|
|
2804
|
+
this.fontAwesomeObserver = null;
|
|
2805
|
+
}
|
|
2806
|
+
this.clearCopiedMessageState();
|
|
2901
2807
|
this.stopAudio(false);
|
|
2902
2808
|
if (this.stream) {
|
|
2903
2809
|
this.stream.dispose();
|
|
@@ -2906,13 +2812,162 @@ window.openAIChatManager = function () {
|
|
|
2906
2812
|
if (this.connection) {
|
|
2907
2813
|
this.connection.stop();
|
|
2908
2814
|
}
|
|
2815
|
+
if (widgetBehavior && typeof widgetBehavior.onBeforeUnmount === 'function') {
|
|
2816
|
+
widgetBehavior.onBeforeUnmount(this, config);
|
|
2817
|
+
}
|
|
2909
2818
|
},
|
|
2910
2819
|
template: config.messageTemplate
|
|
2911
|
-
}
|
|
2820
|
+
};
|
|
2821
|
+
var app = Vue.createApp(appDefinition).mount(config.appElementSelector);
|
|
2822
|
+
if (widgetBehavior && typeof widgetBehavior.attach === 'function') {
|
|
2823
|
+
widgetBehavior.attach(app, config);
|
|
2824
|
+
}
|
|
2912
2825
|
return app;
|
|
2913
2826
|
};
|
|
2827
|
+
var autoInitializeSelector = '[data-coreai-chat-config],[data-coreai-chat-app-element-selector]';
|
|
2828
|
+
function getAttributeValue(element, attributeName) {
|
|
2829
|
+
var value = element.getAttribute(attributeName);
|
|
2830
|
+
return value === null || value === '' ? null : value;
|
|
2831
|
+
}
|
|
2832
|
+
function parseBooleanAttributeValue(value) {
|
|
2833
|
+
if (value === null || value === undefined) {
|
|
2834
|
+
return null;
|
|
2835
|
+
}
|
|
2836
|
+
if (typeof value === 'boolean') {
|
|
2837
|
+
return value;
|
|
2838
|
+
}
|
|
2839
|
+
var normalized = String(value).trim().toLowerCase();
|
|
2840
|
+
if (normalized === 'true') {
|
|
2841
|
+
return true;
|
|
2842
|
+
}
|
|
2843
|
+
if (normalized === 'false') {
|
|
2844
|
+
return false;
|
|
2845
|
+
}
|
|
2846
|
+
return null;
|
|
2847
|
+
}
|
|
2848
|
+
function parseJsonAttribute(element, attributeName, description) {
|
|
2849
|
+
var rawValue = getAttributeValue(element, attributeName);
|
|
2850
|
+
if (!rawValue) {
|
|
2851
|
+
return null;
|
|
2852
|
+
}
|
|
2853
|
+
try {
|
|
2854
|
+
return JSON.parse(rawValue);
|
|
2855
|
+
} catch (error) {
|
|
2856
|
+
console.error('Failed to parse ' + description + ' JSON.', error);
|
|
2857
|
+
return null;
|
|
2858
|
+
}
|
|
2859
|
+
}
|
|
2860
|
+
function buildConfigFromDataAttributes(element, options) {
|
|
2861
|
+
var _parseJsonAttribute, _parseJsonAttribute2;
|
|
2862
|
+
var settings = options || {};
|
|
2863
|
+
if (element.hasAttribute('data-coreai-chat-widget-container-selector') && settings.allowWidgetHost !== true) {
|
|
2864
|
+
return null;
|
|
2865
|
+
}
|
|
2866
|
+
var appElementSelector = getAttributeValue(element, 'data-coreai-chat-app-element-selector');
|
|
2867
|
+
if (!appElementSelector) {
|
|
2868
|
+
return null;
|
|
2869
|
+
}
|
|
2870
|
+
var config = {
|
|
2871
|
+
signalRHubUrl: getAttributeValue(element, 'data-coreai-chat-signalr-hub-url'),
|
|
2872
|
+
appElementSelector: appElementSelector,
|
|
2873
|
+
chatContainerElementSelector: getAttributeValue(element, 'data-coreai-chat-container-element-selector'),
|
|
2874
|
+
inputElementSelector: getAttributeValue(element, 'data-coreai-chat-input-element-selector'),
|
|
2875
|
+
sendButtonElementSelector: getAttributeValue(element, 'data-coreai-chat-send-button-element-selector'),
|
|
2876
|
+
placeholderElementSelector: getAttributeValue(element, 'data-coreai-chat-placeholder-element-selector'),
|
|
2877
|
+
messages: (_parseJsonAttribute = parseJsonAttribute(element, 'data-coreai-chat-messages', 'CoreAI chat messages')) !== null && _parseJsonAttribute !== void 0 ? _parseJsonAttribute : undefined,
|
|
2878
|
+
chatMode: getAttributeValue(element, 'data-coreai-chat-mode'),
|
|
2879
|
+
micButtonElementSelector: getAttributeValue(element, 'data-coreai-chat-mic-button-element-selector'),
|
|
2880
|
+
conversationButtonElementSelector: getAttributeValue(element, 'data-coreai-chat-conversation-button-element-selector'),
|
|
2881
|
+
ttsVoiceName: getAttributeValue(element, 'data-coreai-chat-tts-voice-name'),
|
|
2882
|
+
documentBarSelector: getAttributeValue(element, 'data-coreai-chat-document-bar-selector'),
|
|
2883
|
+
uploadDocumentUrl: getAttributeValue(element, 'data-coreai-chat-upload-document-url'),
|
|
2884
|
+
removeDocumentUrl: getAttributeValue(element, 'data-coreai-chat-remove-document-url'),
|
|
2885
|
+
allowedExtensions: getAttributeValue(element, 'data-coreai-chat-allowed-extensions'),
|
|
2886
|
+
supportedExtensionsText: getAttributeValue(element, 'data-coreai-chat-supported-extensions-text'),
|
|
2887
|
+
existingDocuments: (_parseJsonAttribute2 = parseJsonAttribute(element, 'data-coreai-chat-existing-documents', 'CoreAI chat existing documents')) !== null && _parseJsonAttribute2 !== void 0 ? _parseJsonAttribute2 : undefined,
|
|
2888
|
+
initialPrompt: getAttributeValue(element, 'data-coreai-chat-initial-prompt'),
|
|
2889
|
+
userLabel: getAttributeValue(element, 'data-coreai-chat-user-label'),
|
|
2890
|
+
assistantLabel: getAttributeValue(element, 'data-coreai-chat-assistant-label'),
|
|
2891
|
+
copyTitle: getAttributeValue(element, 'data-coreai-chat-copy-title'),
|
|
2892
|
+
copiedTitle: getAttributeValue(element, 'data-coreai-chat-copied-title')
|
|
2893
|
+
};
|
|
2894
|
+
var booleanAttributes = {
|
|
2895
|
+
metricsEnabled: 'data-coreai-chat-metrics-enabled',
|
|
2896
|
+
textToSpeechEnabled: 'data-coreai-chat-text-to-speech-enabled',
|
|
2897
|
+
sessionDocumentsEnabled: 'data-coreai-chat-session-documents-enabled',
|
|
2898
|
+
singleResponseMode: 'data-coreai-chat-single-response-mode'
|
|
2899
|
+
};
|
|
2900
|
+
Object.keys(booleanAttributes).forEach(function (key) {
|
|
2901
|
+
var parsed = parseBooleanAttributeValue(getAttributeValue(element, booleanAttributes[key]));
|
|
2902
|
+
if (parsed !== null) {
|
|
2903
|
+
config[key] = parsed;
|
|
2904
|
+
}
|
|
2905
|
+
});
|
|
2906
|
+
return compactObject(config);
|
|
2907
|
+
}
|
|
2908
|
+
function buildConfigFromElement(element, options) {
|
|
2909
|
+
var jsonConfig = parseJsonAttribute(element, 'data-coreai-chat-config', 'CoreAI chat config');
|
|
2910
|
+
var attributeConfig = buildConfigFromDataAttributes(element, options);
|
|
2911
|
+
if (!jsonConfig && !attributeConfig) {
|
|
2912
|
+
return null;
|
|
2913
|
+
}
|
|
2914
|
+
return Object.assign({}, jsonConfig || {}, attributeConfig || {});
|
|
2915
|
+
}
|
|
2916
|
+
function initializeFromElement(element) {
|
|
2917
|
+
if (!element || element.dataset.coreAiChatInitialized === 'true') {
|
|
2918
|
+
return element ? element.__coreAIChatApp || null : null;
|
|
2919
|
+
}
|
|
2920
|
+
var config = buildConfigFromElement(element);
|
|
2921
|
+
if (!config) {
|
|
2922
|
+
return null;
|
|
2923
|
+
}
|
|
2924
|
+
var app = initialize(config);
|
|
2925
|
+
if (!app) {
|
|
2926
|
+
return null;
|
|
2927
|
+
}
|
|
2928
|
+
element.dataset.coreAiChatInitialized = 'true';
|
|
2929
|
+
element.__coreAIChatApp = app;
|
|
2930
|
+
return app;
|
|
2931
|
+
}
|
|
2932
|
+
function scanForAutoInitialization(root) {
|
|
2933
|
+
if (!root || typeof root.querySelectorAll !== 'function') {
|
|
2934
|
+
return;
|
|
2935
|
+
}
|
|
2936
|
+
if (typeof root.matches === 'function' && root.matches(autoInitializeSelector)) {
|
|
2937
|
+
initializeFromElement(root);
|
|
2938
|
+
}
|
|
2939
|
+
root.querySelectorAll(autoInitializeSelector).forEach(initializeFromElement);
|
|
2940
|
+
}
|
|
2941
|
+
function startAutoInitialization() {
|
|
2942
|
+
scanForAutoInitialization(document);
|
|
2943
|
+
if (typeof MutationObserver === 'undefined') {
|
|
2944
|
+
return;
|
|
2945
|
+
}
|
|
2946
|
+
var observer = new MutationObserver(function (mutations) {
|
|
2947
|
+
mutations.forEach(function (mutation) {
|
|
2948
|
+
mutation.addedNodes.forEach(function (node) {
|
|
2949
|
+
if (node && node.nodeType === 1) {
|
|
2950
|
+
scanForAutoInitialization(node);
|
|
2951
|
+
}
|
|
2952
|
+
});
|
|
2953
|
+
});
|
|
2954
|
+
});
|
|
2955
|
+
observer.observe(document.body, {
|
|
2956
|
+
childList: true,
|
|
2957
|
+
subtree: true
|
|
2958
|
+
});
|
|
2959
|
+
}
|
|
2960
|
+
if (document.readyState === 'loading') {
|
|
2961
|
+
document.addEventListener('DOMContentLoaded', startAutoInitialization, {
|
|
2962
|
+
once: true
|
|
2963
|
+
});
|
|
2964
|
+
} else {
|
|
2965
|
+
startAutoInitialization();
|
|
2966
|
+
}
|
|
2914
2967
|
return {
|
|
2915
|
-
initialize: initialize
|
|
2968
|
+
initialize: initialize,
|
|
2969
|
+
initializeFromElement: initializeFromElement,
|
|
2970
|
+
buildConfigFromElement: buildConfigFromElement
|
|
2916
2971
|
};
|
|
2917
2972
|
}();
|
|
2918
2973
|
|