@crestapps/ai-chat-ui 1.0.0-preview.7 → 1.0.0-preview.73
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 +814 -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 +380 -0
- package/dist/ai-chat.css.map +1 -0
- package/dist/ai-chat.js +861 -966
- package/dist/ai-chat.js.map +1 -1
- package/dist/ai-chat.min.css +1 -0
- package/dist/ai-chat.min.js +1 -1
- package/dist/ai-chat.min.js.map +1 -1
- package/dist/chat-interaction-settings.js +234 -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 +951 -313
- 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 +106 -3
- package/dist/chat-widget.css.map +1 -1
- package/dist/chat-widget.min.css +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 +12 -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; } }
|
|
@@ -52,7 +55,7 @@ window.openAIChatManager = function () {
|
|
|
52
55
|
minWidth: 320,
|
|
53
56
|
minHeight: 420
|
|
54
57
|
},
|
|
55
|
-
messageTemplate: "\n <div class=\"ai-chat-messages\">\n <div v-for=\"(message, index) in messages\" :key=\"'msg-' + index\" class=\"ai-chat-message-item\">\n <div>\n <div v-if=\"message.role === 'user'\" class=\"ai-chat-msg-role ai-chat-msg-role-user\">{{ userLabel }}</div>\n <div v-else-if=\"message.role !== 'indicator'\" :class=\"getAssistantRoleClasses(message)\">\n <span :class=\"getAssistantIconClasses(message, index)\"><i :class=\"getAssistantIcon(message)\"></i></span>\n {{ getAssistantLabel(message) }}\n </div>\n <div class=\"ai-chat-message-body lh-base\">\n <h4 v-if=\"message.title\">{{ message.title }}</h4>\n <div v-html=\"message.htmlContent\"></div>\n <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 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 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 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 }\" @click=\"toggleMessageTts(message, index)\" :title=\"ttsPlayingMessageIndex === index ? 'Pause audio' : 'Read aloud'\">\n <
|
|
58
|
+
messageTemplate: "\n <div class=\"ai-chat-messages\">\n <div v-for=\"(message, index) in messages\" :key=\"'msg-' + index\" class=\"ai-chat-message-item\">\n <div>\n <div v-if=\"message.role === 'user'\" class=\"ai-chat-msg-role ai-chat-msg-role-user\">{{ userLabel }}</div>\n <div v-else-if=\"message.role !== 'indicator'\" :class=\"getAssistantRoleClasses(message)\">\n <span :class=\"getAssistantIconClasses(message, index)\"><i :class=\"getAssistantIcon(message)\"></i></span>\n {{ getAssistantLabel(message) }}\n </div>\n <div class=\"ai-chat-message-body lh-base\">\n <h4 v-if=\"message.title\">{{ message.title }}</h4>\n <div v-html=\"message.htmlContent\"></div>\n <ol v-if=\"message.citationReferences && message.citationReferences.length\" class=\"ai-chat-citation-list\">\n <li v-for=\"citation in message.citationReferences\" :key=\"'citation-' + (citation.referenceKey || citation.displayIndex)\" class=\"ai-chat-citation-item\">\n <a v-if=\"citation.link\" :href=\"citation.link\" :target=\"citation.isDownload ? null : '_blank'\" :rel=\"citation.isDownload ? null : 'noopener noreferrer'\">{{ citation.label }}</a>\n <span v-else>{{ citation.label }}</span>\n </li>\n </ol>\n <span class=\"message-buttons-container\" v-if=\"!isIndicator(message)\">\n <template v-if=\"metricsEnabled && message.role === 'assistant'\">\n <span class=\"ai-chat-message-assistant-feedback\" :data-message-id=\"message.id\">\n <button type=\"button\" class=\"btn btn-sm btn-link text-success p-0 me-2 button-message-toolbox rate-up-btn\" @click=\"rateMessage(message, true, $event)\" :title=\"thumbsUpTitle\">\n <i class=\"fa-regular fa-thumbs-up\"></i>\n </button>\n <button type=\"button\" class=\"btn btn-sm btn-link text-danger p-0 me-2 button-message-toolbox rate-down-btn\" @click=\"rateMessage(message, false, $event)\" :title=\"thumbsDownTitle\">\n <i class=\"fa-regular fa-thumbs-down\"></i>\n </button>\n </span>\n </template>\n <button type=\"button\" v-if=\"textToSpeechEnabled && !isConversationMode && message.role === 'assistant' && !message.isStreaming\" class=\"btn btn-sm btn-link text-secondary p-0 me-1 button-message-toolbox\" :class=\"{ 'tts-playing': ttsPlayingMessageIndex === index }\" :data-tts-message-index=\"index\" @click=\"toggleMessageTts(message, index)\" :title=\"ttsPlayingMessageIndex === index ? 'Pause audio' : 'Read aloud'\">\n <span :class=\"ttsPlayingMessageIndex === index ? 'fa-solid fa-circle-pause' : 'fa-solid fa-circle-play'\"></span>\n </button>\n <button type=\"button\" class=\"btn btn-sm btn-link text-secondary p-0 button-message-toolbox\" @click=\"copyResponse(message)\" :title=\"copyTitle\">\n <i class=\"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 ",
|
|
56
59
|
indicatorTemplate: "\n <div class=\"ai-chat-msg-role ai-chat-msg-role-assistant\">\n <span class=\"ai-streaming-icon\"><i class=\"fa fa-robot\" style=\"display: inline-block;\"></i></span>\n Assistant\n </div>\n "
|
|
57
60
|
};
|
|
58
61
|
|
|
@@ -72,6 +75,42 @@ window.openAIChatManager = function () {
|
|
|
72
75
|
span.textContent = text;
|
|
73
76
|
return span.innerHTML;
|
|
74
77
|
}
|
|
78
|
+
function containsFontAwesomePlaceholders(root) {
|
|
79
|
+
if (!root || root.nodeType !== 1) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
var selector = 'i[class*="fa-"],i.fa,i.fas,i.far,i.fab';
|
|
83
|
+
if (typeof root.matches === 'function' && root.matches(selector)) {
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
return typeof root.querySelector === 'function' && !!root.querySelector(selector);
|
|
87
|
+
}
|
|
88
|
+
function refreshFontAwesomeIcons(root) {
|
|
89
|
+
var fontAwesome = window.FontAwesome;
|
|
90
|
+
if (!containsFontAwesomePlaceholders(root) || !fontAwesome || !fontAwesome.dom || typeof fontAwesome.dom.i2svg !== 'function') {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
fontAwesome.dom.i2svg({
|
|
94
|
+
node: root
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
function observeFontAwesomeIcons(root) {
|
|
98
|
+
if (!root || typeof MutationObserver === 'undefined') {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
var observer = new MutationObserver(function (mutations) {
|
|
102
|
+
mutations.forEach(function (mutation) {
|
|
103
|
+
mutation.addedNodes.forEach(function (node) {
|
|
104
|
+
refreshFontAwesomeIcons(node);
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
observer.observe(root, {
|
|
109
|
+
childList: true,
|
|
110
|
+
subtree: true
|
|
111
|
+
});
|
|
112
|
+
return observer;
|
|
113
|
+
}
|
|
75
114
|
function parsePixelValue(value) {
|
|
76
115
|
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
77
116
|
return value;
|
|
@@ -86,16 +125,30 @@ window.openAIChatManager = function () {
|
|
|
86
125
|
return Math.min(Math.max(value, min), max);
|
|
87
126
|
}
|
|
88
127
|
function normalizeReference(reference) {
|
|
89
|
-
var _ref, _normalized$index, _ref2, _normalized$text, _ref3, _normalized$link;
|
|
128
|
+
var _ref, _normalized$index, _ref2, _normalized$text, _ref3, _normalized$title, _ref4, _normalized$link, _ref5, _normalized$reference;
|
|
90
129
|
if (!reference || _typeof(reference) !== 'object') {
|
|
91
130
|
return null;
|
|
92
131
|
}
|
|
93
132
|
var normalized = Object.assign({}, reference);
|
|
94
133
|
normalized.index = (_ref = (_normalized$index = normalized.index) !== null && _normalized$index !== void 0 ? _normalized$index : normalized.Index) !== null && _ref !== void 0 ? _ref : 0;
|
|
95
134
|
normalized.text = (_ref2 = (_normalized$text = normalized.text) !== null && _normalized$text !== void 0 ? _normalized$text : normalized.Text) !== null && _ref2 !== void 0 ? _ref2 : null;
|
|
96
|
-
normalized.
|
|
135
|
+
normalized.title = (_ref3 = (_normalized$title = normalized.title) !== null && _normalized$title !== void 0 ? _normalized$title : normalized.Title) !== null && _ref3 !== void 0 ? _ref3 : null;
|
|
136
|
+
normalized.link = sanitizeUrl((_ref4 = (_normalized$link = normalized.link) !== null && _normalized$link !== void 0 ? _normalized$link : normalized.Link) !== null && _ref4 !== void 0 ? _ref4 : null);
|
|
137
|
+
normalized.referenceType = (_ref5 = (_normalized$reference = normalized.referenceType) !== null && _normalized$reference !== void 0 ? _normalized$reference : normalized.ReferenceType) !== null && _ref5 !== void 0 ? _ref5 : null;
|
|
97
138
|
return normalized;
|
|
98
139
|
}
|
|
140
|
+
function isDownloadCitationReference(reference) {
|
|
141
|
+
if (!reference || _typeof(reference) !== 'object') {
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
if (typeof reference.referenceType === 'string' && reference.referenceType.toLowerCase() === 'document') {
|
|
145
|
+
return true;
|
|
146
|
+
}
|
|
147
|
+
if (typeof reference.link === 'string' && /\/ai\/documents\/.+\/download(?:$|\?)/i.test(reference.link)) {
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
99
152
|
function normalizeReferences(references) {
|
|
100
153
|
if (!references || _typeof(references) !== 'object') {
|
|
101
154
|
return {};
|
|
@@ -110,6 +163,125 @@ window.openAIChatManager = function () {
|
|
|
110
163
|
}
|
|
111
164
|
return normalized;
|
|
112
165
|
}
|
|
166
|
+
function getCitationLabel(reference, key) {
|
|
167
|
+
return reference.title || reference.text || key;
|
|
168
|
+
}
|
|
169
|
+
function buildCitationDisplay(content, references) {
|
|
170
|
+
var processedContent = (content || '').trim();
|
|
171
|
+
var messageReferences = normalizeReferences(references);
|
|
172
|
+
if (!processedContent || !Object.keys(messageReferences).length) {
|
|
173
|
+
return {
|
|
174
|
+
content: processedContent,
|
|
175
|
+
citations: []
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
var citedRefs = Object.entries(messageReferences).filter(function (_ref6) {
|
|
179
|
+
var _ref7 = _slicedToArray(_ref6, 1),
|
|
180
|
+
key = _ref7[0];
|
|
181
|
+
return processedContent.includes(key);
|
|
182
|
+
});
|
|
183
|
+
if (!citedRefs.length) {
|
|
184
|
+
return {
|
|
185
|
+
content: processedContent,
|
|
186
|
+
citations: []
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
citedRefs.sort(function (_ref8, _ref9) {
|
|
190
|
+
var _ref0 = _slicedToArray(_ref8, 2),
|
|
191
|
+
a = _ref0[1];
|
|
192
|
+
var _ref1 = _slicedToArray(_ref9, 2),
|
|
193
|
+
b = _ref1[1];
|
|
194
|
+
return a.index - b.index;
|
|
195
|
+
});
|
|
196
|
+
var citations = [];
|
|
197
|
+
var displayIndex = 1;
|
|
198
|
+
var _iterator = _createForOfIteratorHelper(citedRefs),
|
|
199
|
+
_step;
|
|
200
|
+
try {
|
|
201
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
202
|
+
var _step$value = _slicedToArray(_step.value, 2),
|
|
203
|
+
key = _step$value[0],
|
|
204
|
+
value = _step$value[1];
|
|
205
|
+
var placeholder = "__CITE_".concat(displayIndex, "_").concat(value.index || displayIndex, "__");
|
|
206
|
+
processedContent = processedContent.replaceAll(key, placeholder);
|
|
207
|
+
citations.push({
|
|
208
|
+
referenceKey: key,
|
|
209
|
+
displayIndex: displayIndex,
|
|
210
|
+
label: getCitationLabel(value, key),
|
|
211
|
+
link: value.link || null,
|
|
212
|
+
isDownload: isDownloadCitationReference(value),
|
|
213
|
+
placeholder: placeholder
|
|
214
|
+
});
|
|
215
|
+
displayIndex++;
|
|
216
|
+
}
|
|
217
|
+
} catch (err) {
|
|
218
|
+
_iterator.e(err);
|
|
219
|
+
} finally {
|
|
220
|
+
_iterator.f();
|
|
221
|
+
}
|
|
222
|
+
for (var _i2 = 0, _citations = citations; _i2 < _citations.length; _i2++) {
|
|
223
|
+
var citation = _citations[_i2];
|
|
224
|
+
processedContent = processedContent.replaceAll(citation.placeholder, "<sup>".concat(citation.displayIndex, "</sup>"));
|
|
225
|
+
}
|
|
226
|
+
processedContent = processedContent.replaceAll('</sup><sup>', '</sup><sup>,</sup><sup>');
|
|
227
|
+
return {
|
|
228
|
+
content: processedContent,
|
|
229
|
+
citations: citations.map(function (_ref10) {
|
|
230
|
+
var placeholder = _ref10.placeholder,
|
|
231
|
+
citation = _objectWithoutProperties(_ref10, _excluded);
|
|
232
|
+
return citation;
|
|
233
|
+
})
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
function buildCopyContent(content, citations) {
|
|
237
|
+
var copyContent = (content || '').trim();
|
|
238
|
+
if (!copyContent || !Array.isArray(citations) || citations.length === 0) {
|
|
239
|
+
return copyContent;
|
|
240
|
+
}
|
|
241
|
+
var _iterator2 = _createForOfIteratorHelper(citations),
|
|
242
|
+
_step2;
|
|
243
|
+
try {
|
|
244
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
245
|
+
var citation = _step2.value;
|
|
246
|
+
copyContent = copyContent.replaceAll(citation.referenceKey, "[".concat(citation.displayIndex, "]"));
|
|
247
|
+
}
|
|
248
|
+
} catch (err) {
|
|
249
|
+
_iterator2.e(err);
|
|
250
|
+
} finally {
|
|
251
|
+
_iterator2.f();
|
|
252
|
+
}
|
|
253
|
+
copyContent += '\n\nReferences:\n';
|
|
254
|
+
var _iterator3 = _createForOfIteratorHelper(citations),
|
|
255
|
+
_step3;
|
|
256
|
+
try {
|
|
257
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
258
|
+
var _citation = _step3.value;
|
|
259
|
+
copyContent += "".concat(_citation.displayIndex, ". ").concat(_citation.label);
|
|
260
|
+
if (_citation.link) {
|
|
261
|
+
copyContent += " - ".concat(_citation.link);
|
|
262
|
+
}
|
|
263
|
+
copyContent += '\n';
|
|
264
|
+
}
|
|
265
|
+
} catch (err) {
|
|
266
|
+
_iterator3.e(err);
|
|
267
|
+
} finally {
|
|
268
|
+
_iterator3.f();
|
|
269
|
+
}
|
|
270
|
+
return copyContent.trimEnd();
|
|
271
|
+
}
|
|
272
|
+
function updateMessagePresentation(message, references) {
|
|
273
|
+
var messageReferences = normalizeReferences(references !== null && references !== void 0 ? references : message.references);
|
|
274
|
+
var rawContent = typeof message.rawContent === 'string' ? message.rawContent : typeof message.content === 'string' ? message.content : '';
|
|
275
|
+
var citationDisplay = buildCitationDisplay(rawContent, messageReferences);
|
|
276
|
+
message.rawContent = rawContent;
|
|
277
|
+
message.content = rawContent;
|
|
278
|
+
message.displayContent = citationDisplay.content;
|
|
279
|
+
message.references = messageReferences;
|
|
280
|
+
message.citationReferences = citationDisplay.citations;
|
|
281
|
+
message.copyContent = buildCopyContent(rawContent, citationDisplay.citations);
|
|
282
|
+
message.htmlContent = parseMarkdownContent(citationDisplay.content, message);
|
|
283
|
+
return message;
|
|
284
|
+
}
|
|
113
285
|
var renderer = new marked.Renderer();
|
|
114
286
|
|
|
115
287
|
// Modify the link rendering to open in a new tab
|
|
@@ -275,17 +447,17 @@ window.openAIChatManager = function () {
|
|
|
275
447
|
// Defer to requestAnimationFrame so the browser has fully laid out the
|
|
276
448
|
// canvas elements before Chart.js reads their dimensions.
|
|
277
449
|
requestAnimationFrame(function () {
|
|
278
|
-
var
|
|
279
|
-
|
|
450
|
+
var _iterator4 = _createForOfIteratorHelper(charts),
|
|
451
|
+
_step4;
|
|
280
452
|
try {
|
|
281
|
-
for (
|
|
282
|
-
var c =
|
|
453
|
+
for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
|
|
454
|
+
var c = _step4.value;
|
|
283
455
|
renderChartOnCanvas(c.chartId, c.config);
|
|
284
456
|
}
|
|
285
457
|
} catch (err) {
|
|
286
|
-
|
|
458
|
+
_iterator4.e(err);
|
|
287
459
|
} finally {
|
|
288
|
-
|
|
460
|
+
_iterator4.f();
|
|
289
461
|
}
|
|
290
462
|
});
|
|
291
463
|
}
|
|
@@ -338,8 +510,8 @@ window.openAIChatManager = function () {
|
|
|
338
510
|
return;
|
|
339
511
|
}
|
|
340
512
|
requestAnimationFrame(function () {
|
|
341
|
-
for (var
|
|
342
|
-
var chartId = _Object$keys[
|
|
513
|
+
for (var _i3 = 0, _Object$keys = Object.keys(configs); _i3 < _Object$keys.length; _i3++) {
|
|
514
|
+
var chartId = _Object$keys[_i3];
|
|
343
515
|
renderChartOnCanvas(chartId, configs[chartId]);
|
|
344
516
|
}
|
|
345
517
|
});
|
|
@@ -363,6 +535,7 @@ window.openAIChatManager = function () {
|
|
|
363
535
|
var config = Object.assign({}, defaultConfig, instanceConfig);
|
|
364
536
|
config.widget = Object.assign({}, defaultConfig.widget || {}, instanceConfig && instanceConfig.widget ? instanceConfig.widget : {});
|
|
365
537
|
var hasWidgetConfig = !!(instanceConfig && instanceConfig.widget && instanceConfig.widget.chatWidgetContainer && instanceConfig.widget.chatWidgetStateName);
|
|
538
|
+
var widgetBehavior = window.openAIChatWidgetBehavior || null;
|
|
366
539
|
// Keep defaultConfig in sync so renderers use overridden values
|
|
367
540
|
defaultConfig = config;
|
|
368
541
|
if (!config.signalRHubUrl) {
|
|
@@ -385,7 +558,7 @@ window.openAIChatManager = function () {
|
|
|
385
558
|
console.error('The sendButtonElementSelector is required.');
|
|
386
559
|
return;
|
|
387
560
|
}
|
|
388
|
-
var
|
|
561
|
+
var appDefinition = {
|
|
389
562
|
data: function data() {
|
|
390
563
|
return {
|
|
391
564
|
inputElement: null,
|
|
@@ -394,18 +567,6 @@ window.openAIChatManager = function () {
|
|
|
394
567
|
placeholder: null,
|
|
395
568
|
isSessionStarted: false,
|
|
396
569
|
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
570
|
isStreaming: false,
|
|
410
571
|
isNavigatingAway: false,
|
|
411
572
|
autoScroll: true,
|
|
@@ -415,6 +576,8 @@ window.openAIChatManager = function () {
|
|
|
415
576
|
prompt: '',
|
|
416
577
|
documents: config.existingDocuments || [],
|
|
417
578
|
isUploading: false,
|
|
579
|
+
isDocumentOperationPending: false,
|
|
580
|
+
documentOperationQueue: null,
|
|
418
581
|
uploadErrors: [],
|
|
419
582
|
isDragOver: false,
|
|
420
583
|
documentBar: null,
|
|
@@ -444,7 +607,11 @@ window.openAIChatManager = function () {
|
|
|
444
607
|
conversationModeEnabled: config.chatMode === 'Conversation',
|
|
445
608
|
conversationButton: null,
|
|
446
609
|
isConversationMode: false,
|
|
447
|
-
notificationDismissTimers: {}
|
|
610
|
+
notificationDismissTimers: {},
|
|
611
|
+
pendingSessionPromise: null,
|
|
612
|
+
pendingSessionResolver: null,
|
|
613
|
+
pendingSessionRejector: null,
|
|
614
|
+
pendingSessionTimeoutId: null
|
|
448
615
|
};
|
|
449
616
|
},
|
|
450
617
|
computed: {
|
|
@@ -461,255 +628,6 @@ window.openAIChatManager = function () {
|
|
|
461
628
|
handleBeforeUnload: function handleBeforeUnload() {
|
|
462
629
|
this.isNavigatingAway = true;
|
|
463
630
|
},
|
|
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.toggle !== undefined) {
|
|
486
|
-
nextLayout.toggle = Object.assign({}, currentLayout.toggle || {}, partialLayout.toggle || {});
|
|
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
|
-
clampWidgetPosition: function clampWidgetPosition(left, top, width, height) {
|
|
505
|
-
var viewportPadding = 8;
|
|
506
|
-
var maxLeft = Math.max(viewportPadding, window.innerWidth - width - viewportPadding);
|
|
507
|
-
var maxTop = Math.max(viewportPadding, window.innerHeight - height - viewportPadding);
|
|
508
|
-
return {
|
|
509
|
-
left: Math.round(clamp(left, viewportPadding, maxLeft)),
|
|
510
|
-
top: Math.round(clamp(top, viewportPadding, maxTop))
|
|
511
|
-
};
|
|
512
|
-
},
|
|
513
|
-
applyAbsolutePosition: function applyAbsolutePosition(element, left, top) {
|
|
514
|
-
if (!element) {
|
|
515
|
-
return;
|
|
516
|
-
}
|
|
517
|
-
element.style.left = left + 'px';
|
|
518
|
-
element.style.top = top + 'px';
|
|
519
|
-
element.style.right = 'auto';
|
|
520
|
-
element.style.bottom = 'auto';
|
|
521
|
-
},
|
|
522
|
-
getWidgetDefaultSize: function getWidgetDefaultSize() {
|
|
523
|
-
return {
|
|
524
|
-
width: this.widgetDefaultWidth || parsePixelValue(config.widget.defaultWidth) || 380,
|
|
525
|
-
height: this.widgetDefaultHeight || parsePixelValue(config.widget.defaultHeight) || 520
|
|
526
|
-
};
|
|
527
|
-
},
|
|
528
|
-
persistWidgetPanelPosition: function persistWidgetPanelPosition() {
|
|
529
|
-
if (!this.widgetContainerElement || !config.widget.persistLayout) {
|
|
530
|
-
return;
|
|
531
|
-
}
|
|
532
|
-
var panelRect = this.widgetContainerElement.getBoundingClientRect();
|
|
533
|
-
this.saveStoredWidgetLayout({
|
|
534
|
-
panel: {
|
|
535
|
-
left: Math.round(panelRect.left),
|
|
536
|
-
top: Math.round(panelRect.top)
|
|
537
|
-
}
|
|
538
|
-
});
|
|
539
|
-
},
|
|
540
|
-
persistWidgetTogglePosition: function persistWidgetTogglePosition() {
|
|
541
|
-
if (!this.widgetToggleButtonElement || !config.widget.persistLayout) {
|
|
542
|
-
return;
|
|
543
|
-
}
|
|
544
|
-
var toggleRect = this.widgetToggleButtonElement.getBoundingClientRect();
|
|
545
|
-
this.saveStoredWidgetLayout({
|
|
546
|
-
toggle: {
|
|
547
|
-
left: Math.round(toggleRect.left),
|
|
548
|
-
top: Math.round(toggleRect.top)
|
|
549
|
-
}
|
|
550
|
-
});
|
|
551
|
-
},
|
|
552
|
-
persistWidgetPanelSize: function persistWidgetPanelSize() {
|
|
553
|
-
if (!this.widgetContainerElement || !config.widget.enableResizing || !config.widget.persistLayout) {
|
|
554
|
-
return;
|
|
555
|
-
}
|
|
556
|
-
var defaultSize = this.getWidgetDefaultSize();
|
|
557
|
-
var currentSize = this.getElementSize(this.widgetContainerElement, defaultSize.width, defaultSize.height);
|
|
558
|
-
this.saveStoredWidgetLayout({
|
|
559
|
-
panel: {
|
|
560
|
-
width: Math.abs(currentSize.width - defaultSize.width) <= 1 ? null : currentSize.width,
|
|
561
|
-
height: Math.abs(currentSize.height - defaultSize.height) <= 1 ? null : currentSize.height
|
|
562
|
-
}
|
|
563
|
-
});
|
|
564
|
-
},
|
|
565
|
-
updateWidgetResetSizeButtonVisibility: function updateWidgetResetSizeButtonVisibility() {
|
|
566
|
-
if (!this.widgetResetSizeButtonElement) {
|
|
567
|
-
return;
|
|
568
|
-
}
|
|
569
|
-
if (!config.widget.enableResizing || !this.widgetContainerElement) {
|
|
570
|
-
this.widgetResetSizeButtonElement.classList.add('d-none');
|
|
571
|
-
return;
|
|
572
|
-
}
|
|
573
|
-
var defaultSize = this.getWidgetDefaultSize();
|
|
574
|
-
var currentSize = this.getElementSize(this.widgetContainerElement, defaultSize.width, defaultSize.height);
|
|
575
|
-
var isResized = Math.abs(currentSize.width - defaultSize.width) > 1 || Math.abs(currentSize.height - defaultSize.height) > 1 || !!this.widgetContainerElement.style.width || !!this.widgetContainerElement.style.height;
|
|
576
|
-
this.widgetResetSizeButtonElement.classList.toggle('d-none', !isResized);
|
|
577
|
-
},
|
|
578
|
-
resetWidgetSize: function resetWidgetSize() {
|
|
579
|
-
if (!this.widgetContainerElement || !config.widget.enableResizing) {
|
|
580
|
-
return;
|
|
581
|
-
}
|
|
582
|
-
this.widgetContainerElement.style.removeProperty('width');
|
|
583
|
-
this.widgetContainerElement.style.removeProperty('height');
|
|
584
|
-
this.persistWidgetPanelSize();
|
|
585
|
-
this.constrainWidgetElementsToViewport();
|
|
586
|
-
this.updateWidgetResetSizeButtonVisibility();
|
|
587
|
-
},
|
|
588
|
-
restoreWidgetLayout: function restoreWidgetLayout() {
|
|
589
|
-
var storedLayout = this.getStoredWidgetLayout();
|
|
590
|
-
if (this.widgetContainerElement && config.widget.enableResizing) {
|
|
591
|
-
if (Number.isFinite(storedLayout.panel && storedLayout.panel.width)) {
|
|
592
|
-
this.widgetContainerElement.style.width = storedLayout.panel.width + 'px';
|
|
593
|
-
} else {
|
|
594
|
-
this.widgetContainerElement.style.removeProperty('width');
|
|
595
|
-
}
|
|
596
|
-
if (Number.isFinite(storedLayout.panel && storedLayout.panel.height)) {
|
|
597
|
-
this.widgetContainerElement.style.height = storedLayout.panel.height + 'px';
|
|
598
|
-
} else {
|
|
599
|
-
this.widgetContainerElement.style.removeProperty('height');
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
if (this.widgetContainerElement && config.widget.enableDragging && Number.isFinite(storedLayout.panel && storedLayout.panel.left) && Number.isFinite(storedLayout.panel && storedLayout.panel.top)) {
|
|
603
|
-
this.applyAbsolutePosition(this.widgetContainerElement, storedLayout.panel.left, storedLayout.panel.top);
|
|
604
|
-
}
|
|
605
|
-
if (this.widgetToggleButtonElement && config.widget.enableDragging && Number.isFinite(storedLayout.toggle && storedLayout.toggle.left) && Number.isFinite(storedLayout.toggle && storedLayout.toggle.top)) {
|
|
606
|
-
this.applyAbsolutePosition(this.widgetToggleButtonElement, storedLayout.toggle.left, storedLayout.toggle.top);
|
|
607
|
-
}
|
|
608
|
-
this.constrainWidgetElementsToViewport();
|
|
609
|
-
this.updateWidgetResetSizeButtonVisibility();
|
|
610
|
-
},
|
|
611
|
-
attachDraggableWidgetElement: function attachDraggableWidgetElement(element, handle, layoutKey, suppressClickOnDrag) {
|
|
612
|
-
var _this = this;
|
|
613
|
-
if (!element || !handle || !config.widget.enableDragging) {
|
|
614
|
-
return;
|
|
615
|
-
}
|
|
616
|
-
var activePointerId = null;
|
|
617
|
-
var startX = 0;
|
|
618
|
-
var startY = 0;
|
|
619
|
-
var startLeft = 0;
|
|
620
|
-
var startTop = 0;
|
|
621
|
-
var dragged = false;
|
|
622
|
-
var dragThreshold = 4;
|
|
623
|
-
var interactiveSelector = 'button, a, input, textarea, select, option, label';
|
|
624
|
-
var _stopDragging = function stopDragging(event) {
|
|
625
|
-
if (activePointerId === null) {
|
|
626
|
-
return;
|
|
627
|
-
}
|
|
628
|
-
if (event && event.pointerId !== undefined && event.pointerId !== activePointerId) {
|
|
629
|
-
return;
|
|
630
|
-
}
|
|
631
|
-
document.removeEventListener('pointermove', onPointerMove);
|
|
632
|
-
document.removeEventListener('pointerup', _stopDragging);
|
|
633
|
-
document.removeEventListener('pointercancel', _stopDragging);
|
|
634
|
-
element.classList.remove('ai-chat-widget-dragging');
|
|
635
|
-
activePointerId = null;
|
|
636
|
-
if (!dragged) {
|
|
637
|
-
return;
|
|
638
|
-
}
|
|
639
|
-
if (layoutKey === 'panel') {
|
|
640
|
-
_this.persistWidgetPanelPosition();
|
|
641
|
-
} else if (layoutKey === 'toggle') {
|
|
642
|
-
_this.persistWidgetTogglePosition();
|
|
643
|
-
}
|
|
644
|
-
if (suppressClickOnDrag) {
|
|
645
|
-
element.dataset.dragSuppressClick = 'true';
|
|
646
|
-
window.setTimeout(function () {
|
|
647
|
-
if (element.dataset.dragSuppressClick === 'true') {
|
|
648
|
-
element.dataset.dragSuppressClick = 'false';
|
|
649
|
-
}
|
|
650
|
-
}, 0);
|
|
651
|
-
}
|
|
652
|
-
};
|
|
653
|
-
var onPointerMove = function onPointerMove(event) {
|
|
654
|
-
if (activePointerId === null || event.pointerId !== activePointerId) {
|
|
655
|
-
return;
|
|
656
|
-
}
|
|
657
|
-
var deltaX = event.clientX - startX;
|
|
658
|
-
var deltaY = event.clientY - startY;
|
|
659
|
-
if (!dragged && Math.hypot(deltaX, deltaY) < dragThreshold) {
|
|
660
|
-
return;
|
|
661
|
-
}
|
|
662
|
-
dragged = true;
|
|
663
|
-
var defaultSize = _this.getWidgetDefaultSize();
|
|
664
|
-
var currentSize = _this.getElementSize(element, layoutKey === 'panel' ? defaultSize.width : 52, layoutKey === 'panel' ? defaultSize.height : 52);
|
|
665
|
-
var nextPosition = _this.clampWidgetPosition(startLeft + deltaX, startTop + deltaY, currentSize.width, currentSize.height);
|
|
666
|
-
_this.applyAbsolutePosition(element, nextPosition.left, nextPosition.top);
|
|
667
|
-
};
|
|
668
|
-
handle.addEventListener('pointerdown', function (event) {
|
|
669
|
-
if (event.button !== 0) {
|
|
670
|
-
return;
|
|
671
|
-
}
|
|
672
|
-
if (layoutKey === 'panel' && event.target.closest(interactiveSelector)) {
|
|
673
|
-
return;
|
|
674
|
-
}
|
|
675
|
-
var rect = element.getBoundingClientRect();
|
|
676
|
-
startX = event.clientX;
|
|
677
|
-
startY = event.clientY;
|
|
678
|
-
startLeft = rect.left;
|
|
679
|
-
startTop = rect.top;
|
|
680
|
-
dragged = false;
|
|
681
|
-
activePointerId = event.pointerId;
|
|
682
|
-
element.classList.add('ai-chat-widget-dragging');
|
|
683
|
-
if (handle.setPointerCapture) {
|
|
684
|
-
handle.setPointerCapture(event.pointerId);
|
|
685
|
-
}
|
|
686
|
-
document.addEventListener('pointermove', onPointerMove);
|
|
687
|
-
document.addEventListener('pointerup', _stopDragging);
|
|
688
|
-
document.addEventListener('pointercancel', _stopDragging);
|
|
689
|
-
event.preventDefault();
|
|
690
|
-
});
|
|
691
|
-
},
|
|
692
|
-
constrainWidgetElementsToViewport: function constrainWidgetElementsToViewport() {
|
|
693
|
-
if (this.widgetContainerElement && this.widgetContainerElement.style.left) {
|
|
694
|
-
var panelDefaultSize = this.getWidgetDefaultSize();
|
|
695
|
-
var panelSize = this.getElementSize(this.widgetContainerElement, panelDefaultSize.width, panelDefaultSize.height);
|
|
696
|
-
var panelRect = this.widgetContainerElement.getBoundingClientRect();
|
|
697
|
-
var clampedPanel = this.clampWidgetPosition(panelRect.left, panelRect.top, panelSize.width, panelSize.height);
|
|
698
|
-
this.applyAbsolutePosition(this.widgetContainerElement, clampedPanel.left, clampedPanel.top);
|
|
699
|
-
if (config.widget.persistLayout) {
|
|
700
|
-
this.persistWidgetPanelPosition();
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
if (this.widgetToggleButtonElement && this.widgetToggleButtonElement.style.left) {
|
|
704
|
-
var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);
|
|
705
|
-
var toggleRect = this.widgetToggleButtonElement.getBoundingClientRect();
|
|
706
|
-
var clampedToggle = this.clampWidgetPosition(toggleRect.left, toggleRect.top, toggleSize.width, toggleSize.height);
|
|
707
|
-
this.applyAbsolutePosition(this.widgetToggleButtonElement, clampedToggle.left, clampedToggle.top);
|
|
708
|
-
if (config.widget.persistLayout) {
|
|
709
|
-
this.persistWidgetTogglePosition();
|
|
710
|
-
}
|
|
711
|
-
}
|
|
712
|
-
},
|
|
713
631
|
handleDragOver: function handleDragOver(e) {
|
|
714
632
|
if (!config.sessionDocumentsEnabled) return;
|
|
715
633
|
e.preventDefault();
|
|
@@ -734,180 +652,272 @@ window.openAIChatManager = function () {
|
|
|
734
652
|
var inputArea = this.inputElement ? this.inputElement.closest('.ai-admin-widget-input, .text-bg-light') : null;
|
|
735
653
|
if (inputArea) inputArea.classList.remove('ai-chat-drag-over');
|
|
736
654
|
if (e.dataTransfer && e.dataTransfer.files && e.dataTransfer.files.length > 0) {
|
|
737
|
-
this.uploadFiles(e.dataTransfer.files);
|
|
655
|
+
this.uploadFiles(Array.from(e.dataTransfer.files));
|
|
738
656
|
}
|
|
739
657
|
},
|
|
740
658
|
triggerFileInput: function triggerFileInput() {
|
|
741
|
-
if (!config.sessionDocumentsEnabled) return;
|
|
659
|
+
if (!config.sessionDocumentsEnabled || this.isDocumentOperationPending) return;
|
|
742
660
|
var fileInput = document.getElementById('ai-chat-doc-input');
|
|
743
661
|
if (fileInput) fileInput.click();
|
|
744
662
|
},
|
|
745
663
|
handleFileInputChange: function handleFileInputChange(e) {
|
|
746
|
-
var files = e.target.files;
|
|
664
|
+
var files = e.target.files ? Array.from(e.target.files) : [];
|
|
747
665
|
if (files && files.length > 0) {
|
|
748
666
|
this.uploadFiles(files);
|
|
749
667
|
}
|
|
750
668
|
e.target.value = '';
|
|
751
669
|
},
|
|
752
|
-
|
|
753
|
-
var
|
|
754
|
-
|
|
755
|
-
|
|
670
|
+
queueDocumentOperation: function queueDocumentOperation(operation) {
|
|
671
|
+
var self = this;
|
|
672
|
+
var previousOperation = this.documentOperationQueue || Promise.resolve();
|
|
673
|
+
var nextOperation = previousOperation["catch"](function () {}).then(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee() {
|
|
756
674
|
return _regenerator().w(function (_context) {
|
|
757
675
|
while (1) switch (_context.p = _context.n) {
|
|
676
|
+
case 0:
|
|
677
|
+
self.isDocumentOperationPending = true;
|
|
678
|
+
_context.p = 1;
|
|
679
|
+
_context.n = 2;
|
|
680
|
+
return operation();
|
|
681
|
+
case 2:
|
|
682
|
+
return _context.a(2, _context.v);
|
|
683
|
+
case 3:
|
|
684
|
+
_context.p = 3;
|
|
685
|
+
self.isDocumentOperationPending = false;
|
|
686
|
+
return _context.f(3);
|
|
687
|
+
case 4:
|
|
688
|
+
return _context.a(2);
|
|
689
|
+
}
|
|
690
|
+
}, _callee, null, [[1,, 3, 4]]);
|
|
691
|
+
})));
|
|
692
|
+
this.documentOperationQueue = nextOperation["finally"](function () {
|
|
693
|
+
if (self.documentOperationQueue === nextOperation) {
|
|
694
|
+
self.documentOperationQueue = null;
|
|
695
|
+
}
|
|
696
|
+
});
|
|
697
|
+
return this.documentOperationQueue;
|
|
698
|
+
},
|
|
699
|
+
uploadFiles: function uploadFiles(files) {
|
|
700
|
+
var _this = this;
|
|
701
|
+
return _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3() {
|
|
702
|
+
var filesToUpload;
|
|
703
|
+
return _regenerator().w(function (_context3) {
|
|
704
|
+
while (1) switch (_context3.n) {
|
|
758
705
|
case 0:
|
|
759
706
|
if (config.uploadDocumentUrl) {
|
|
760
|
-
|
|
707
|
+
_context3.n = 1;
|
|
761
708
|
break;
|
|
762
709
|
}
|
|
763
|
-
return
|
|
710
|
+
return _context3.a(2);
|
|
764
711
|
case 1:
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
_context.n = 2;
|
|
712
|
+
filesToUpload = Array.isArray(files) ? files.slice() : Array.from(files || []);
|
|
713
|
+
if (!(filesToUpload.length === 0)) {
|
|
714
|
+
_context3.n = 2;
|
|
769
715
|
break;
|
|
770
716
|
}
|
|
771
|
-
|
|
772
|
-
return _context.a(2);
|
|
717
|
+
return _context3.a(2);
|
|
773
718
|
case 2:
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
719
|
+
return _context3.a(2, _this.queueDocumentOperation(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2() {
|
|
720
|
+
var sessionId, profileId, formData, i, response, errorText, uploadError, result, _t, _t2;
|
|
721
|
+
return _regenerator().w(function (_context2) {
|
|
722
|
+
while (1) switch (_context2.p = _context2.n) {
|
|
723
|
+
case 0:
|
|
724
|
+
sessionId = _this.getSessionId();
|
|
725
|
+
profileId = _this.getProfileId();
|
|
726
|
+
if (sessionId) {
|
|
727
|
+
_context2.n = 4;
|
|
728
|
+
break;
|
|
729
|
+
}
|
|
730
|
+
_context2.p = 1;
|
|
731
|
+
_context2.n = 2;
|
|
732
|
+
return _this.ensureSessionForDocuments(profileId);
|
|
733
|
+
case 2:
|
|
734
|
+
sessionId = _context2.v;
|
|
735
|
+
_context2.n = 4;
|
|
736
|
+
break;
|
|
737
|
+
case 3:
|
|
738
|
+
_context2.p = 3;
|
|
739
|
+
_t = _context2.v;
|
|
740
|
+
console.error('Failed to create a chat session for document upload:', _t);
|
|
741
|
+
_this.uploadErrors = [{
|
|
742
|
+
fileName: '',
|
|
743
|
+
error: 'Could not create a chat session for the upload.'
|
|
744
|
+
}];
|
|
745
|
+
_this.renderDocumentBar();
|
|
746
|
+
return _context2.a(2);
|
|
747
|
+
case 4:
|
|
748
|
+
if (sessionId) {
|
|
749
|
+
_context2.n = 5;
|
|
750
|
+
break;
|
|
751
|
+
}
|
|
752
|
+
console.warn('Cannot upload documents without a session or profile.');
|
|
753
|
+
_this.uploadErrors = [{
|
|
754
|
+
fileName: '',
|
|
755
|
+
error: 'Could not create a chat session for the upload.'
|
|
756
|
+
}];
|
|
757
|
+
_this.renderDocumentBar();
|
|
758
|
+
return _context2.a(2);
|
|
759
|
+
case 5:
|
|
760
|
+
_this.isUploading = true;
|
|
761
|
+
_this.uploadErrors = [];
|
|
762
|
+
_this.renderDocumentBar();
|
|
763
|
+
_context2.p = 6;
|
|
764
|
+
formData = new FormData();
|
|
765
|
+
formData.append('sessionId', sessionId);
|
|
766
|
+
for (i = 0; i < filesToUpload.length; i++) {
|
|
767
|
+
formData.append('files', filesToUpload[i]);
|
|
768
|
+
}
|
|
769
|
+
_context2.n = 7;
|
|
770
|
+
return fetch(config.uploadDocumentUrl, {
|
|
771
|
+
method: 'POST',
|
|
772
|
+
body: formData
|
|
773
|
+
});
|
|
774
|
+
case 7:
|
|
775
|
+
response = _context2.v;
|
|
776
|
+
if (response.ok) {
|
|
777
|
+
_context2.n = 9;
|
|
778
|
+
break;
|
|
779
|
+
}
|
|
780
|
+
_context2.n = 8;
|
|
781
|
+
return response.text();
|
|
782
|
+
case 8:
|
|
783
|
+
errorText = _context2.v;
|
|
784
|
+
uploadError = _this.extractReadableErrorMessage(errorText, 'Upload failed. Please try again.');
|
|
785
|
+
console.error('Upload failed:', errorText);
|
|
786
|
+
_this.uploadErrors = [{
|
|
787
|
+
fileName: '',
|
|
788
|
+
error: uploadError
|
|
789
|
+
}];
|
|
790
|
+
return _context2.a(2);
|
|
791
|
+
case 9:
|
|
792
|
+
_context2.n = 10;
|
|
793
|
+
return response.json();
|
|
794
|
+
case 10:
|
|
795
|
+
result = _context2.v;
|
|
796
|
+
if (result.sessionId && result.sessionId !== _this.getSessionId()) {
|
|
797
|
+
_this.initializeSession(result.sessionId);
|
|
798
|
+
}
|
|
799
|
+
if (Array.isArray(result.documents)) {
|
|
800
|
+
_this.documents = result.documents;
|
|
801
|
+
} else if (result.uploaded && result.uploaded.length > 0) {
|
|
802
|
+
_this.documents = _this.documents.concat(result.uploaded);
|
|
803
|
+
}
|
|
804
|
+
if (result.failed && result.failed.length > 0) {
|
|
805
|
+
_this.uploadErrors = result.failed;
|
|
806
|
+
}
|
|
807
|
+
_context2.n = 12;
|
|
808
|
+
break;
|
|
809
|
+
case 11:
|
|
810
|
+
_context2.p = 11;
|
|
811
|
+
_t2 = _context2.v;
|
|
812
|
+
console.error('Upload error:', _t2);
|
|
813
|
+
_this.uploadErrors = [{
|
|
814
|
+
fileName: '',
|
|
815
|
+
error: 'Upload failed. Please try again.'
|
|
816
|
+
}];
|
|
817
|
+
if (_this.getSessionId()) {
|
|
818
|
+
_this.reloadCurrentSession();
|
|
819
|
+
}
|
|
820
|
+
case 12:
|
|
821
|
+
_context2.p = 12;
|
|
822
|
+
_this.isUploading = false;
|
|
823
|
+
_this.renderDocumentBar();
|
|
824
|
+
return _context2.f(12);
|
|
825
|
+
case 13:
|
|
826
|
+
return _context2.a(2);
|
|
827
|
+
}
|
|
828
|
+
}, _callee2, null, [[6, 11, 12, 13], [1, 3]]);
|
|
829
|
+
}))));
|
|
843
830
|
}
|
|
844
|
-
},
|
|
831
|
+
}, _callee3);
|
|
845
832
|
}))();
|
|
846
833
|
},
|
|
847
834
|
removeDocument: function removeDocument(doc) {
|
|
848
|
-
var
|
|
849
|
-
return _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
while (1) switch (_context2.p = _context2.n) {
|
|
835
|
+
var _this2 = this;
|
|
836
|
+
return _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee5() {
|
|
837
|
+
return _regenerator().w(function (_context5) {
|
|
838
|
+
while (1) switch (_context5.n) {
|
|
853
839
|
case 0:
|
|
854
840
|
if (config.removeDocumentUrl) {
|
|
855
|
-
|
|
841
|
+
_context5.n = 1;
|
|
856
842
|
break;
|
|
857
843
|
}
|
|
858
|
-
return
|
|
844
|
+
return _context5.a(2);
|
|
859
845
|
case 1:
|
|
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
|
-
|
|
846
|
+
return _context5.a(2, _this2.queueDocumentOperation(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4() {
|
|
847
|
+
var sessionId, response, result, idx, errorText, removeError, _t3;
|
|
848
|
+
return _regenerator().w(function (_context4) {
|
|
849
|
+
while (1) switch (_context4.p = _context4.n) {
|
|
850
|
+
case 0:
|
|
851
|
+
_context4.p = 0;
|
|
852
|
+
sessionId = _this2.getSessionId();
|
|
853
|
+
_context4.n = 1;
|
|
854
|
+
return fetch(config.removeDocumentUrl, {
|
|
855
|
+
method: 'POST',
|
|
856
|
+
headers: {
|
|
857
|
+
'Content-Type': 'application/json'
|
|
858
|
+
},
|
|
859
|
+
body: JSON.stringify({
|
|
860
|
+
itemId: sessionId,
|
|
861
|
+
documentId: doc.documentId
|
|
862
|
+
})
|
|
863
|
+
});
|
|
864
|
+
case 1:
|
|
865
|
+
response = _context4.v;
|
|
866
|
+
if (!response.ok) {
|
|
867
|
+
_context4.n = 3;
|
|
868
|
+
break;
|
|
869
|
+
}
|
|
870
|
+
_context4.n = 2;
|
|
871
|
+
return response.json();
|
|
872
|
+
case 2:
|
|
873
|
+
result = _context4.v;
|
|
874
|
+
if (Array.isArray(result.documents)) {
|
|
875
|
+
_this2.documents = result.documents;
|
|
876
|
+
} else {
|
|
877
|
+
idx = _this2.documents.indexOf(doc);
|
|
878
|
+
if (idx > -1) {
|
|
879
|
+
_this2.documents.splice(idx, 1);
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
_context4.n = 5;
|
|
883
|
+
break;
|
|
884
|
+
case 3:
|
|
885
|
+
_context4.n = 4;
|
|
886
|
+
return response.text();
|
|
887
|
+
case 4:
|
|
888
|
+
errorText = _context4.v;
|
|
889
|
+
removeError = _this2.extractReadableErrorMessage(errorText, 'Failed to remove document. Please try again.');
|
|
890
|
+
console.error('Failed to remove document:', response.status, errorText);
|
|
891
|
+
_this2.uploadErrors = [{
|
|
892
|
+
fileName: doc.fileName || '',
|
|
893
|
+
error: removeError
|
|
894
|
+
}];
|
|
895
|
+
if (sessionId) {
|
|
896
|
+
_this2.reloadCurrentSession();
|
|
897
|
+
}
|
|
898
|
+
_this2.renderDocumentBar();
|
|
899
|
+
case 5:
|
|
900
|
+
_context4.n = 7;
|
|
901
|
+
break;
|
|
902
|
+
case 6:
|
|
903
|
+
_context4.p = 6;
|
|
904
|
+
_t3 = _context4.v;
|
|
905
|
+
console.error('Remove document error:', _t3);
|
|
906
|
+
_this2.uploadErrors = [{
|
|
907
|
+
fileName: doc.fileName || '',
|
|
908
|
+
error: 'Failed to remove document. Please try again.'
|
|
909
|
+
}];
|
|
910
|
+
if (_this2.getSessionId()) {
|
|
911
|
+
_this2.reloadCurrentSession();
|
|
912
|
+
}
|
|
913
|
+
_this2.renderDocumentBar();
|
|
914
|
+
case 7:
|
|
915
|
+
return _context4.a(2);
|
|
916
|
+
}
|
|
917
|
+
}, _callee4, null, [[0, 6]]);
|
|
918
|
+
}))));
|
|
909
919
|
}
|
|
910
|
-
},
|
|
920
|
+
}, _callee5);
|
|
911
921
|
}))();
|
|
912
922
|
},
|
|
913
923
|
formatFileSize: function formatFileSize(bytes) {
|
|
@@ -931,7 +941,7 @@ window.openAIChatManager = function () {
|
|
|
931
941
|
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 || '') + '">';
|
|
932
942
|
html += '<i class="fa-solid fa-file-lines" style="font-size: 0.7rem;"></i> ';
|
|
933
943
|
html += this.escapeHtml(name);
|
|
934
|
-
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>';
|
|
944
|
+
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>';
|
|
935
945
|
html += '</span>';
|
|
936
946
|
}
|
|
937
947
|
for (var m = 0; m < this.uploadErrors.length; m++) {
|
|
@@ -950,7 +960,7 @@ window.openAIChatManager = function () {
|
|
|
950
960
|
html += '<span class="spinner-border spinner-border-sm" style="width: 0.7rem; height: 0.7rem;"></span> Uploading...';
|
|
951
961
|
html += '</span>';
|
|
952
962
|
}
|
|
953
|
-
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">';
|
|
963
|
+
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' : '') + '>';
|
|
954
964
|
html += '<i class="fa-solid fa-paperclip"></i>';
|
|
955
965
|
if (this.documents.length === 0 && !this.isUploading) {
|
|
956
966
|
html += ' <span>Attach files</span>';
|
|
@@ -973,6 +983,9 @@ window.openAIChatManager = function () {
|
|
|
973
983
|
return function (e) {
|
|
974
984
|
e.preventDefault();
|
|
975
985
|
e.stopPropagation();
|
|
986
|
+
if (self.isDocumentOperationPending) {
|
|
987
|
+
return;
|
|
988
|
+
}
|
|
976
989
|
var docToRemove = self.documents[idx];
|
|
977
990
|
if (docToRemove) self.removeDocument(docToRemove);
|
|
978
991
|
};
|
|
@@ -997,6 +1010,9 @@ window.openAIChatManager = function () {
|
|
|
997
1010
|
if (addBtn) {
|
|
998
1011
|
addBtn.addEventListener('click', function (e) {
|
|
999
1012
|
e.preventDefault();
|
|
1013
|
+
if (self.isDocumentOperationPending) {
|
|
1014
|
+
return;
|
|
1015
|
+
}
|
|
1000
1016
|
self.triggerFileInput();
|
|
1001
1017
|
});
|
|
1002
1018
|
}
|
|
@@ -1073,139 +1089,135 @@ window.openAIChatManager = function () {
|
|
|
1073
1089
|
return !!message && message.isStreaming && index === this.lastAssistantIndex && !(appearance && appearance.disableStreamingAnimation);
|
|
1074
1090
|
},
|
|
1075
1091
|
startConnection: function startConnection() {
|
|
1076
|
-
var
|
|
1077
|
-
return _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
1078
|
-
var
|
|
1079
|
-
return _regenerator().w(function (
|
|
1080
|
-
while (1) switch (
|
|
1092
|
+
var _this3 = this;
|
|
1093
|
+
return _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee6() {
|
|
1094
|
+
var _t4;
|
|
1095
|
+
return _regenerator().w(function (_context6) {
|
|
1096
|
+
while (1) switch (_context6.p = _context6.n) {
|
|
1081
1097
|
case 0:
|
|
1082
|
-
|
|
1098
|
+
_this3.connection = new signalR.HubConnectionBuilder().withUrl(config.signalRHubUrl).withAutomaticReconnect().build();
|
|
1083
1099
|
|
|
1084
1100
|
// Allow long-running operations (e.g., multi-step MCP tool calls)
|
|
1085
1101
|
// without the client disconnecting prematurely.
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1102
|
+
_this3.connection.serverTimeoutInMilliseconds = 600000;
|
|
1103
|
+
_this3.connection.keepAliveIntervalInMilliseconds = 15000;
|
|
1104
|
+
_this3.connection.on("LoadSession", function (data) {
|
|
1089
1105
|
var _data$messages;
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1106
|
+
_this3.initializeSession(data.sessionId, true);
|
|
1107
|
+
_this3.messages = [];
|
|
1108
|
+
_this3.documents = data.documents || [];
|
|
1109
|
+
_this3.uploadErrors = [];
|
|
1093
1110
|
((_data$messages = data.messages) !== null && _data$messages !== void 0 ? _data$messages : []).forEach(function (msg) {
|
|
1094
|
-
|
|
1095
|
-
|
|
1111
|
+
_this3.addMessage(msg);
|
|
1112
|
+
_this3.$nextTick(function () {
|
|
1096
1113
|
renderChartsInMessage(msg);
|
|
1097
1114
|
});
|
|
1098
1115
|
});
|
|
1099
1116
|
|
|
1100
1117
|
// Update feedback icons in the DOM after all messages have rendered.
|
|
1101
|
-
|
|
1102
|
-
|
|
1118
|
+
_this3.$nextTick(function () {
|
|
1119
|
+
_this3.refreshAllFeedbackIcons();
|
|
1103
1120
|
});
|
|
1104
1121
|
|
|
1105
1122
|
// When the session is new (no messages) and an initial prompt is configured,
|
|
1106
1123
|
// automatically send it as the first user message to trigger an AI response.
|
|
1107
|
-
if (
|
|
1108
|
-
|
|
1109
|
-
|
|
1124
|
+
if (_this3.messages.length === 0 && config.initialPrompt) {
|
|
1125
|
+
_this3.prompt = config.initialPrompt;
|
|
1126
|
+
_this3.sendMessage();
|
|
1110
1127
|
}
|
|
1111
1128
|
});
|
|
1112
|
-
|
|
1129
|
+
_this3.connection.on("ReceiveError", function (error) {
|
|
1113
1130
|
console.error("SignalR Error: ", error);
|
|
1114
|
-
if (
|
|
1115
|
-
|
|
1131
|
+
if (_this3.isRecording) {
|
|
1132
|
+
_this3.stopRecording();
|
|
1116
1133
|
}
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
// clear the cached session and start fresh with the current profile.
|
|
1120
|
-
if (_this4.widgetIsInitialized && !_this4.isSessionStarted && !_this4._attemptedSessionRecovery) {
|
|
1121
|
-
_this4._attemptedSessionRecovery = true;
|
|
1122
|
-
localStorage.removeItem(_this4.chatWidgetStateSession);
|
|
1123
|
-
_this4.startNewSession();
|
|
1134
|
+
if (widgetBehavior && typeof widgetBehavior.handleReceiveError === 'function') {
|
|
1135
|
+
widgetBehavior.handleReceiveError(_this3, error, config);
|
|
1124
1136
|
}
|
|
1125
1137
|
});
|
|
1126
|
-
|
|
1127
|
-
var msg =
|
|
1138
|
+
_this3.connection.on("MessageRated", function (messageId, userRating) {
|
|
1139
|
+
var msg = _this3.messages.find(function (m) {
|
|
1128
1140
|
return m.id === messageId;
|
|
1129
1141
|
});
|
|
1130
1142
|
if (msg) {
|
|
1131
1143
|
msg.userRating = userRating;
|
|
1132
1144
|
}
|
|
1133
1145
|
});
|
|
1134
|
-
|
|
1135
|
-
if (
|
|
1146
|
+
_this3.connection.on("ReceiveTranscript", function (sessionId, text, isFinal) {
|
|
1147
|
+
if (_this3.isConversationMode) {
|
|
1136
1148
|
if (!isFinal && text) {
|
|
1137
|
-
|
|
1149
|
+
_this3._conversationPartialTranscript = text;
|
|
1138
1150
|
var escaped = text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
1139
1151
|
var html = '<p class="ai-partial-transcript">' + escaped + '</p>';
|
|
1140
1152
|
|
|
1141
1153
|
// Show partial transcript as a live user message.
|
|
1142
|
-
if (!
|
|
1143
|
-
|
|
1144
|
-
|
|
1154
|
+
if (!_this3._conversationPartialMessage) {
|
|
1155
|
+
_this3.hidePlaceholder();
|
|
1156
|
+
_this3._conversationPartialMessage = {
|
|
1145
1157
|
role: 'user',
|
|
1146
1158
|
content: text,
|
|
1147
1159
|
htmlContent: html,
|
|
1148
1160
|
isPartial: true
|
|
1149
1161
|
};
|
|
1150
|
-
|
|
1162
|
+
_this3.messages.push(_this3._conversationPartialMessage);
|
|
1151
1163
|
} else {
|
|
1152
|
-
|
|
1153
|
-
|
|
1164
|
+
_this3._conversationPartialMessage.content = text;
|
|
1165
|
+
_this3._conversationPartialMessage.htmlContent = html;
|
|
1154
1166
|
}
|
|
1155
|
-
|
|
1167
|
+
_this3.scrollToBottom();
|
|
1156
1168
|
}
|
|
1157
1169
|
return;
|
|
1158
1170
|
}
|
|
1159
|
-
if (text && !
|
|
1160
|
-
|
|
1161
|
-
if (
|
|
1162
|
-
|
|
1163
|
-
|
|
1171
|
+
if (text && !_this3._audioInputSent) {
|
|
1172
|
+
_this3.prompt = _this3.preRecordingPrompt + text;
|
|
1173
|
+
if (_this3.inputElement) {
|
|
1174
|
+
_this3.inputElement.value = _this3.prompt;
|
|
1175
|
+
_this3.inputElement.dispatchEvent(new Event('input'));
|
|
1164
1176
|
}
|
|
1165
1177
|
}
|
|
1166
1178
|
});
|
|
1167
|
-
|
|
1179
|
+
_this3.connection.on("ReceiveConversationUserMessage", function (sessionId, text) {
|
|
1168
1180
|
if (text) {
|
|
1169
|
-
|
|
1181
|
+
_this3.stopAudio();
|
|
1170
1182
|
|
|
1171
1183
|
// If there's an interrupted assistant message still streaming,
|
|
1172
1184
|
// mark it as done to stop the spinner animation.
|
|
1173
|
-
if (
|
|
1174
|
-
var oldMsg =
|
|
1185
|
+
if (_this3._conversationAssistantMessage) {
|
|
1186
|
+
var oldMsg = _this3.messages[_this3._conversationAssistantMessage.index];
|
|
1175
1187
|
if (oldMsg) {
|
|
1176
1188
|
oldMsg.isStreaming = false;
|
|
1177
1189
|
}
|
|
1178
|
-
|
|
1190
|
+
_this3._conversationAssistantMessage = null;
|
|
1179
1191
|
}
|
|
1180
1192
|
|
|
1181
1193
|
// Replace the partial transcript message with the final one.
|
|
1182
|
-
if (
|
|
1194
|
+
if (_this3._conversationPartialMessage) {
|
|
1183
1195
|
var escaped = text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1196
|
+
_this3._conversationPartialMessage.content = text;
|
|
1197
|
+
_this3._conversationPartialMessage.htmlContent = '<p>' + escaped + '</p>';
|
|
1198
|
+
_this3._conversationPartialMessage.isPartial = false;
|
|
1199
|
+
_this3._conversationPartialMessage = null;
|
|
1188
1200
|
} else {
|
|
1189
|
-
|
|
1201
|
+
_this3.addMessage({
|
|
1190
1202
|
role: 'user',
|
|
1191
1203
|
content: text
|
|
1192
1204
|
});
|
|
1193
1205
|
}
|
|
1194
|
-
|
|
1206
|
+
_this3.scrollToBottom();
|
|
1195
1207
|
}
|
|
1196
1208
|
});
|
|
1197
|
-
|
|
1198
|
-
if (!
|
|
1199
|
-
|
|
1200
|
-
|
|
1209
|
+
_this3.connection.on("ReceiveConversationAssistantToken", function (sessionId, messageId, token, responseId, references, appearance) {
|
|
1210
|
+
if (!_this3._conversationAssistantMessage) {
|
|
1211
|
+
_this3.stopAudio();
|
|
1212
|
+
_this3.hideTypingIndicator();
|
|
1201
1213
|
|
|
1202
1214
|
// Ensure no stale streaming indicators remain from prior messages.
|
|
1203
|
-
for (var j = 0; j <
|
|
1204
|
-
if (
|
|
1205
|
-
|
|
1215
|
+
for (var j = 0; j < _this3.messages.length; j++) {
|
|
1216
|
+
if (_this3.messages[j].isStreaming) {
|
|
1217
|
+
_this3.messages[j].isStreaming = false;
|
|
1206
1218
|
}
|
|
1207
1219
|
}
|
|
1208
|
-
var msgIndex =
|
|
1220
|
+
var msgIndex = _this3.messages.length;
|
|
1209
1221
|
var newMessage = {
|
|
1210
1222
|
id: messageId,
|
|
1211
1223
|
role: "assistant",
|
|
@@ -1213,96 +1225,100 @@ window.openAIChatManager = function () {
|
|
|
1213
1225
|
htmlContent: "",
|
|
1214
1226
|
isStreaming: true,
|
|
1215
1227
|
userRating: null,
|
|
1216
|
-
appearance:
|
|
1228
|
+
appearance: _this3.normalizeAssistantAppearance(appearance),
|
|
1229
|
+
references: {}
|
|
1217
1230
|
};
|
|
1218
|
-
|
|
1219
|
-
|
|
1231
|
+
_this3.messages.push(newMessage);
|
|
1232
|
+
_this3._conversationAssistantMessage = {
|
|
1220
1233
|
index: msgIndex,
|
|
1221
1234
|
content: ''
|
|
1222
1235
|
};
|
|
1223
1236
|
}
|
|
1224
|
-
|
|
1225
|
-
var msg =
|
|
1237
|
+
_this3._conversationAssistantMessage.content += token;
|
|
1238
|
+
var msg = _this3.messages[_this3._conversationAssistantMessage.index];
|
|
1226
1239
|
if (msg) {
|
|
1227
1240
|
if (!msg.appearance) {
|
|
1228
|
-
msg.appearance =
|
|
1241
|
+
msg.appearance = _this3.normalizeAssistantAppearance(appearance);
|
|
1229
1242
|
}
|
|
1230
|
-
msg.
|
|
1231
|
-
msg.
|
|
1232
|
-
|
|
1243
|
+
msg.rawContent = _this3._conversationAssistantMessage.content;
|
|
1244
|
+
msg.references = normalizeReferences(Object.assign({}, msg.references || {}, references || {}));
|
|
1245
|
+
updateMessagePresentation(msg, msg.references);
|
|
1246
|
+
_this3.$nextTick(function () {
|
|
1233
1247
|
renderChartsInMessage(msg);
|
|
1234
|
-
|
|
1248
|
+
_this3.scrollToBottom();
|
|
1235
1249
|
});
|
|
1236
1250
|
}
|
|
1237
1251
|
});
|
|
1238
|
-
|
|
1239
|
-
if (
|
|
1240
|
-
var msg =
|
|
1252
|
+
_this3.connection.on("ReceiveConversationAssistantComplete", function (sessionId, messageId, references) {
|
|
1253
|
+
if (_this3._conversationAssistantMessage) {
|
|
1254
|
+
var msg = _this3.messages[_this3._conversationAssistantMessage.index];
|
|
1241
1255
|
if (msg) {
|
|
1242
1256
|
msg.isStreaming = false;
|
|
1257
|
+
msg.references = normalizeReferences(Object.assign({}, msg.references || {}, references || {}));
|
|
1258
|
+
updateMessagePresentation(msg, msg.references);
|
|
1243
1259
|
}
|
|
1244
|
-
|
|
1260
|
+
_this3._conversationAssistantMessage = null;
|
|
1245
1261
|
}
|
|
1246
1262
|
});
|
|
1247
|
-
|
|
1263
|
+
_this3.connection.on("ReceiveAudioChunk", function (sessionId, base64Audio, contentType) {
|
|
1248
1264
|
if (base64Audio) {
|
|
1249
1265
|
var binaryString = atob(base64Audio);
|
|
1250
1266
|
var bytes = new Uint8Array(binaryString.length);
|
|
1251
1267
|
for (var i = 0; i < binaryString.length; i++) {
|
|
1252
1268
|
bytes[i] = binaryString.charCodeAt(i);
|
|
1253
1269
|
}
|
|
1254
|
-
|
|
1270
|
+
_this3.audioChunks.push(bytes);
|
|
1255
1271
|
}
|
|
1256
1272
|
});
|
|
1257
|
-
|
|
1258
|
-
|
|
1273
|
+
_this3.connection.on("ReceiveAudioComplete", function (sessionId) {
|
|
1274
|
+
_this3.playCollectedAudio();
|
|
1259
1275
|
});
|
|
1260
|
-
|
|
1261
|
-
|
|
1276
|
+
_this3.connection.on("ReceiveNotification", function (notification) {
|
|
1277
|
+
_this3.receiveNotification(notification);
|
|
1262
1278
|
});
|
|
1263
|
-
|
|
1264
|
-
|
|
1279
|
+
_this3.connection.on("UpdateNotification", function (notification) {
|
|
1280
|
+
_this3.updateNotification(notification);
|
|
1265
1281
|
});
|
|
1266
|
-
|
|
1267
|
-
|
|
1282
|
+
_this3.connection.on("RemoveNotification", function (notificationType) {
|
|
1283
|
+
_this3.removeNotification(notificationType);
|
|
1268
1284
|
});
|
|
1269
|
-
|
|
1285
|
+
_this3.connection.onreconnecting(function () {
|
|
1270
1286
|
console.warn("SignalR: reconnecting...");
|
|
1271
1287
|
});
|
|
1272
|
-
|
|
1288
|
+
_this3.connection.onreconnected(function () {
|
|
1273
1289
|
console.info("SignalR: reconnected.");
|
|
1274
|
-
if (
|
|
1275
|
-
|
|
1290
|
+
if (_this3.isSessionStarted) {
|
|
1291
|
+
_this3.reloadCurrentSession();
|
|
1276
1292
|
} else if (config.autoCreateSession) {
|
|
1277
|
-
|
|
1293
|
+
_this3.startNewSession();
|
|
1278
1294
|
}
|
|
1279
1295
|
});
|
|
1280
|
-
|
|
1281
|
-
if (
|
|
1296
|
+
_this3.connection.onclose(function (error) {
|
|
1297
|
+
if (_this3.isNavigatingAway) {
|
|
1282
1298
|
return;
|
|
1283
1299
|
}
|
|
1284
1300
|
if (error) {
|
|
1285
1301
|
console.warn("SignalR connection closed with error:", error.message || error);
|
|
1286
1302
|
}
|
|
1287
1303
|
});
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
return
|
|
1304
|
+
_context6.p = 1;
|
|
1305
|
+
_context6.n = 2;
|
|
1306
|
+
return _this3.connection.start();
|
|
1291
1307
|
case 2:
|
|
1292
|
-
|
|
1308
|
+
_context6.n = 4;
|
|
1293
1309
|
break;
|
|
1294
1310
|
case 3:
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
console.error("SignalR Connection Error: ",
|
|
1311
|
+
_context6.p = 3;
|
|
1312
|
+
_t4 = _context6.v;
|
|
1313
|
+
console.error("SignalR Connection Error: ", _t4);
|
|
1298
1314
|
case 4:
|
|
1299
|
-
return
|
|
1315
|
+
return _context6.a(2);
|
|
1300
1316
|
}
|
|
1301
|
-
},
|
|
1317
|
+
}, _callee6, null, [[1, 3]]);
|
|
1302
1318
|
}))();
|
|
1303
1319
|
},
|
|
1304
1320
|
addMessageInternal: function addMessageInternal(message) {
|
|
1305
|
-
var
|
|
1321
|
+
var _this4 = this;
|
|
1306
1322
|
if (message.role === 'assistant') {
|
|
1307
1323
|
message.appearance = this.normalizeAssistantAppearance(message.appearance);
|
|
1308
1324
|
}
|
|
@@ -1316,7 +1332,7 @@ window.openAIChatManager = function () {
|
|
|
1316
1332
|
}));
|
|
1317
1333
|
this.messages.push(message);
|
|
1318
1334
|
this.$nextTick(function () {
|
|
1319
|
-
|
|
1335
|
+
_this4.fireEvent(new CustomEvent("addedOpenAIPromotMessage", {
|
|
1320
1336
|
detail: {
|
|
1321
1337
|
message: message
|
|
1322
1338
|
}
|
|
@@ -1324,105 +1340,32 @@ window.openAIChatManager = function () {
|
|
|
1324
1340
|
});
|
|
1325
1341
|
},
|
|
1326
1342
|
addMessage: function addMessage(message) {
|
|
1327
|
-
var
|
|
1343
|
+
var _this5 = this;
|
|
1328
1344
|
// Ensure userRating is always defined for Vue reactivity.
|
|
1329
1345
|
if (message.userRating === undefined) {
|
|
1330
1346
|
message.userRating = null;
|
|
1331
1347
|
}
|
|
1332
1348
|
if (message.content) {
|
|
1333
|
-
var
|
|
1334
|
-
message.
|
|
1335
|
-
|
|
1336
|
-
// Only include references that were actually cited in the response.
|
|
1337
|
-
var citedRefs = Object.entries(message.references).filter(function (_ref4) {
|
|
1338
|
-
var _ref5 = _slicedToArray(_ref4, 1),
|
|
1339
|
-
key = _ref5[0];
|
|
1340
|
-
return processedContent.includes(key);
|
|
1341
|
-
});
|
|
1342
|
-
if (citedRefs.length) {
|
|
1343
|
-
// Sort by original index so display indices follow a natural order.
|
|
1344
|
-
citedRefs.sort(function (_ref6, _ref7) {
|
|
1345
|
-
var _ref8 = _slicedToArray(_ref6, 2),
|
|
1346
|
-
a = _ref8[1];
|
|
1347
|
-
var _ref9 = _slicedToArray(_ref7, 2),
|
|
1348
|
-
b = _ref9[1];
|
|
1349
|
-
return a.index - b.index;
|
|
1350
|
-
});
|
|
1351
|
-
|
|
1352
|
-
// Phase 1: Replace all markers with unique placeholders.
|
|
1353
|
-
var displayIndex = 1;
|
|
1354
|
-
var _iterator2 = _createForOfIteratorHelper(citedRefs),
|
|
1355
|
-
_step2;
|
|
1356
|
-
try {
|
|
1357
|
-
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
1358
|
-
var _step2$value = _slicedToArray(_step2.value, 2),
|
|
1359
|
-
key = _step2$value[0],
|
|
1360
|
-
value = _step2$value[1];
|
|
1361
|
-
var placeholder = "__CITE_".concat(value.index, "__");
|
|
1362
|
-
processedContent = processedContent.replaceAll(key, placeholder);
|
|
1363
|
-
value._displayIndex = displayIndex++;
|
|
1364
|
-
value._placeholder = placeholder;
|
|
1365
|
-
}
|
|
1366
|
-
|
|
1367
|
-
// Phase 2: Replace placeholders with sequential display indices.
|
|
1368
|
-
} catch (err) {
|
|
1369
|
-
_iterator2.e(err);
|
|
1370
|
-
} finally {
|
|
1371
|
-
_iterator2.f();
|
|
1372
|
-
}
|
|
1373
|
-
var _iterator3 = _createForOfIteratorHelper(citedRefs),
|
|
1374
|
-
_step3;
|
|
1375
|
-
try {
|
|
1376
|
-
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
1377
|
-
var _step3$value = _slicedToArray(_step3.value, 2),
|
|
1378
|
-
_value = _step3$value[1];
|
|
1379
|
-
processedContent = processedContent.replaceAll(_value._placeholder, "<sup><strong>".concat(_value._displayIndex, "</strong></sup>"));
|
|
1380
|
-
}
|
|
1381
|
-
|
|
1382
|
-
// if we have multiple references, add a comma to ensure we don't concatenate numbers.
|
|
1383
|
-
} catch (err) {
|
|
1384
|
-
_iterator3.e(err);
|
|
1385
|
-
} finally {
|
|
1386
|
-
_iterator3.f();
|
|
1387
|
-
}
|
|
1388
|
-
processedContent = processedContent.replaceAll('</strong></sup><sup>', '</strong></sup><sup>,</sup><sup>');
|
|
1389
|
-
processedContent += '<br><br>';
|
|
1390
|
-
var _iterator4 = _createForOfIteratorHelper(citedRefs),
|
|
1391
|
-
_step4;
|
|
1392
|
-
try {
|
|
1393
|
-
for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
|
|
1394
|
-
var _step4$value = _slicedToArray(_step4.value, 2),
|
|
1395
|
-
_key = _step4$value[0],
|
|
1396
|
-
_value2 = _step4$value[1];
|
|
1397
|
-
var label = _value2.text || _key;
|
|
1398
|
-
processedContent += _value2.link ? "**".concat(_value2._displayIndex, "**. [").concat(label, "](").concat(_value2.link, ")<br>") : "**".concat(_value2._displayIndex, "**. ").concat(label, "<br>");
|
|
1399
|
-
}
|
|
1400
|
-
} catch (err) {
|
|
1401
|
-
_iterator4.e(err);
|
|
1402
|
-
} finally {
|
|
1403
|
-
_iterator4.f();
|
|
1404
|
-
}
|
|
1405
|
-
}
|
|
1406
|
-
}
|
|
1407
|
-
message.content = processedContent;
|
|
1408
|
-
message.htmlContent = parseMarkdownContent(processedContent, message);
|
|
1349
|
+
var _message$rawContent;
|
|
1350
|
+
message.rawContent = (_message$rawContent = message.rawContent) !== null && _message$rawContent !== void 0 ? _message$rawContent : message.content;
|
|
1351
|
+
updateMessagePresentation(message, message.references);
|
|
1409
1352
|
}
|
|
1410
1353
|
this.addMessageInternal(message);
|
|
1411
1354
|
this.hidePlaceholder();
|
|
1412
1355
|
this.$nextTick(function () {
|
|
1413
1356
|
// Render any pending charts once the DOM is updated
|
|
1414
1357
|
renderChartsInMessage(message);
|
|
1415
|
-
|
|
1358
|
+
_this5.scrollToBottom();
|
|
1416
1359
|
});
|
|
1417
1360
|
},
|
|
1418
1361
|
addMessages: function addMessages(messages) {
|
|
1419
|
-
var
|
|
1362
|
+
var _this6 = this;
|
|
1420
1363
|
for (var i = 0; i < messages.length; i++) {
|
|
1421
1364
|
this.addMessageInternal(messages[i]);
|
|
1422
1365
|
}
|
|
1423
1366
|
this.hidePlaceholder();
|
|
1424
1367
|
this.$nextTick(function () {
|
|
1425
|
-
|
|
1368
|
+
_this6.scrollToBottom();
|
|
1426
1369
|
});
|
|
1427
1370
|
},
|
|
1428
1371
|
hidePlaceholder: function hidePlaceholder() {
|
|
@@ -1499,7 +1442,7 @@ window.openAIChatManager = function () {
|
|
|
1499
1442
|
this.prompt = '';
|
|
1500
1443
|
},
|
|
1501
1444
|
startRecording: function startRecording() {
|
|
1502
|
-
var
|
|
1445
|
+
var _this7 = this;
|
|
1503
1446
|
if (this.isRecording || !this.connection) {
|
|
1504
1447
|
return;
|
|
1505
1448
|
}
|
|
@@ -1511,27 +1454,27 @@ window.openAIChatManager = function () {
|
|
|
1511
1454
|
}
|
|
1512
1455
|
}).then(function (stream) {
|
|
1513
1456
|
var mimeType = MediaRecorder.isTypeSupported('audio/ogg;codecs=opus') ? 'audio/ogg;codecs=opus' : MediaRecorder.isTypeSupported('audio/webm;codecs=opus') ? 'audio/webm;codecs=opus' : 'audio/webm';
|
|
1514
|
-
|
|
1457
|
+
_this7.mediaRecorder = new MediaRecorder(stream, {
|
|
1515
1458
|
mimeType: mimeType,
|
|
1516
1459
|
audioBitsPerSecond: 128000
|
|
1517
1460
|
});
|
|
1518
|
-
|
|
1519
|
-
|
|
1461
|
+
_this7.preRecordingPrompt = _this7.prompt;
|
|
1462
|
+
_this7._audioInputSent = false;
|
|
1520
1463
|
var subject = new signalR.Subject();
|
|
1521
|
-
var profileId =
|
|
1522
|
-
var sessionId =
|
|
1464
|
+
var profileId = _this7.getProfileId();
|
|
1465
|
+
var sessionId = _this7.getSessionId() || '';
|
|
1523
1466
|
var pendingChunk = Promise.resolve();
|
|
1524
|
-
|
|
1467
|
+
_this7.mediaRecorder.addEventListener('dataavailable', function (e) {
|
|
1525
1468
|
if (e.data && e.data.size > 0) {
|
|
1526
|
-
pendingChunk = pendingChunk.then(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
1469
|
+
pendingChunk = pendingChunk.then(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee7() {
|
|
1527
1470
|
var data, uint8Array, binaryString, base64;
|
|
1528
|
-
return _regenerator().w(function (
|
|
1529
|
-
while (1) switch (
|
|
1471
|
+
return _regenerator().w(function (_context7) {
|
|
1472
|
+
while (1) switch (_context7.n) {
|
|
1530
1473
|
case 0:
|
|
1531
|
-
|
|
1474
|
+
_context7.n = 1;
|
|
1532
1475
|
return e.data.arrayBuffer();
|
|
1533
1476
|
case 1:
|
|
1534
|
-
data =
|
|
1477
|
+
data = _context7.v;
|
|
1535
1478
|
uint8Array = new Uint8Array(data);
|
|
1536
1479
|
binaryString = uint8Array.reduce(function (str, _byte) {
|
|
1537
1480
|
return str + String.fromCharCode(_byte);
|
|
@@ -1539,13 +1482,13 @@ window.openAIChatManager = function () {
|
|
|
1539
1482
|
base64 = btoa(binaryString);
|
|
1540
1483
|
subject.next(base64);
|
|
1541
1484
|
case 2:
|
|
1542
|
-
return
|
|
1485
|
+
return _context7.a(2);
|
|
1543
1486
|
}
|
|
1544
|
-
},
|
|
1487
|
+
}, _callee7);
|
|
1545
1488
|
})));
|
|
1546
1489
|
}
|
|
1547
1490
|
});
|
|
1548
|
-
|
|
1491
|
+
_this7.mediaRecorder.addEventListener('stop', function () {
|
|
1549
1492
|
stream.getTracks().forEach(function (track) {
|
|
1550
1493
|
return track.stop();
|
|
1551
1494
|
});
|
|
@@ -1554,10 +1497,10 @@ window.openAIChatManager = function () {
|
|
|
1554
1497
|
});
|
|
1555
1498
|
});
|
|
1556
1499
|
var language = navigator.language || document.documentElement.lang || 'en-US';
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1500
|
+
_this7.connection.send("SendAudioStream", profileId, sessionId, subject, mimeType, language);
|
|
1501
|
+
_this7.mediaRecorder.start(250);
|
|
1502
|
+
_this7.isRecording = true;
|
|
1503
|
+
_this7.updateMicButton();
|
|
1561
1504
|
})["catch"](function (err) {
|
|
1562
1505
|
console.error('Microphone access denied:', err);
|
|
1563
1506
|
});
|
|
@@ -1590,7 +1533,7 @@ window.openAIChatManager = function () {
|
|
|
1590
1533
|
}
|
|
1591
1534
|
},
|
|
1592
1535
|
streamMessage: function streamMessage(profileId, trimmedPrompt, sessionProfileId) {
|
|
1593
|
-
var
|
|
1536
|
+
var _this8 = this;
|
|
1594
1537
|
if (this.stream) {
|
|
1595
1538
|
this.stream.dispose();
|
|
1596
1539
|
this.stream = null;
|
|
@@ -1607,14 +1550,14 @@ window.openAIChatManager = function () {
|
|
|
1607
1550
|
var currentSessionId = this.getSessionId();
|
|
1608
1551
|
this.stream = this.connection.stream("SendMessage", profileId, trimmedPrompt, currentSessionId, sessionProfileId).subscribe({
|
|
1609
1552
|
next: function next(chunk) {
|
|
1610
|
-
var message =
|
|
1553
|
+
var message = _this8.messages[messageIndex];
|
|
1611
1554
|
if (!message) {
|
|
1612
1555
|
if (chunk.sessionId && !currentSessionId) {
|
|
1613
|
-
|
|
1556
|
+
_this8.initializeSession(chunk.sessionId);
|
|
1614
1557
|
}
|
|
1615
|
-
|
|
1558
|
+
_this8.hideTypingIndicator();
|
|
1616
1559
|
// Re-assign the index after hiding the typing indicator.
|
|
1617
|
-
messageIndex =
|
|
1560
|
+
messageIndex = _this8.messages.length;
|
|
1618
1561
|
var newMessage = {
|
|
1619
1562
|
id: chunk.messageId,
|
|
1620
1563
|
role: "assistant",
|
|
@@ -1624,16 +1567,16 @@ window.openAIChatManager = function () {
|
|
|
1624
1567
|
isStreaming: true,
|
|
1625
1568
|
userRating: null
|
|
1626
1569
|
};
|
|
1627
|
-
|
|
1570
|
+
_this8.messages.push(newMessage);
|
|
1628
1571
|
message = newMessage;
|
|
1629
1572
|
}
|
|
1630
1573
|
if (chunk.title && (!message.title || message.title !== chunk.title)) {
|
|
1631
1574
|
message.title = chunk.title;
|
|
1632
1575
|
}
|
|
1633
1576
|
if (chunk.references && _typeof(chunk.references) === "object" && Object.keys(chunk.references).length) {
|
|
1634
|
-
for (var
|
|
1577
|
+
for (var _i4 = 0, _Object$entries2 = Object.entries(chunk.references); _i4 < _Object$entries2.length; _i4++) {
|
|
1635
1578
|
var _normalizeReference2;
|
|
1636
|
-
var _Object$entries2$_i = _slicedToArray(_Object$entries2[
|
|
1579
|
+
var _Object$entries2$_i = _slicedToArray(_Object$entries2[_i4], 2),
|
|
1637
1580
|
key = _Object$entries2$_i[0],
|
|
1638
1581
|
value = _Object$entries2$_i[1];
|
|
1639
1582
|
references[key] = (_normalizeReference2 = normalizeReference(value)) !== null && _normalizeReference2 !== void 0 ? _normalizeReference2 : {};
|
|
@@ -1648,62 +1591,52 @@ window.openAIChatManager = function () {
|
|
|
1648
1591
|
if (chunk.responseId) {
|
|
1649
1592
|
lastResponseId = chunk.responseId;
|
|
1650
1593
|
}
|
|
1651
|
-
|
|
1652
|
-
for (var _i4 = 0, _Object$entries3 = Object.entries(references); _i4 < _Object$entries3.length; _i4++) {
|
|
1653
|
-
var _Object$entries3$_i = _slicedToArray(_Object$entries3[_i4], 2),
|
|
1654
|
-
_key2 = _Object$entries3$_i[0],
|
|
1655
|
-
_value3 = _Object$entries3$_i[1];
|
|
1656
|
-
processedContent = processedContent.replaceAll(_key2, "<sup><strong>".concat(_value3.index, "</strong></sup>"));
|
|
1657
|
-
}
|
|
1658
|
-
|
|
1659
|
-
// Append processed content to the message.
|
|
1660
|
-
// if we have multiple references, add a comma to ensure we don't concatenate numbers.
|
|
1661
|
-
content += processedContent.replaceAll('</strong></sup><sup>', '</strong></sup><sup>,</sup><sup>');
|
|
1594
|
+
content += chunk.content;
|
|
1662
1595
|
}
|
|
1663
1596
|
|
|
1664
1597
|
// Update the existing message
|
|
1665
|
-
message.
|
|
1666
|
-
message
|
|
1667
|
-
|
|
1668
|
-
|
|
1598
|
+
message.rawContent = content;
|
|
1599
|
+
updateMessagePresentation(message, references);
|
|
1600
|
+
_this8.messages[messageIndex] = message;
|
|
1601
|
+
_this8.$nextTick(function () {
|
|
1669
1602
|
renderChartsInMessage(message);
|
|
1670
|
-
|
|
1603
|
+
_this8.scrollToBottom();
|
|
1671
1604
|
});
|
|
1672
1605
|
},
|
|
1673
1606
|
complete: function complete() {
|
|
1674
|
-
var
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
var msg =
|
|
1607
|
+
var _this8$stream;
|
|
1608
|
+
_this8.processReferences(references, messageIndex);
|
|
1609
|
+
_this8.streamingFinished();
|
|
1610
|
+
var msg = _this8.messages[messageIndex];
|
|
1678
1611
|
if (msg) {
|
|
1679
1612
|
msg.isStreaming = false;
|
|
1680
1613
|
}
|
|
1681
1614
|
if (!msg || !msg.content) {
|
|
1682
1615
|
// No content received at all.
|
|
1683
|
-
|
|
1616
|
+
_this8.hideTypingIndicator();
|
|
1684
1617
|
}
|
|
1685
1618
|
|
|
1686
1619
|
// Trigger text-to-speech only in conversation mode.
|
|
1687
|
-
if (
|
|
1688
|
-
|
|
1620
|
+
if (_this8.isConversationMode && _this8.textToSpeechEnabled && msg && msg.content) {
|
|
1621
|
+
_this8.synthesizeSpeech(msg.content);
|
|
1689
1622
|
}
|
|
1690
|
-
(
|
|
1691
|
-
|
|
1623
|
+
(_this8$stream = _this8.stream) === null || _this8$stream === void 0 || _this8$stream.dispose();
|
|
1624
|
+
_this8.stream = null;
|
|
1692
1625
|
},
|
|
1693
1626
|
error: function error(err) {
|
|
1694
|
-
var
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
var msg =
|
|
1627
|
+
var _this8$stream2;
|
|
1628
|
+
_this8.processReferences(references, messageIndex);
|
|
1629
|
+
_this8.streamingFinished();
|
|
1630
|
+
var msg = _this8.messages[messageIndex];
|
|
1698
1631
|
if (msg) {
|
|
1699
1632
|
msg.isStreaming = false;
|
|
1700
1633
|
}
|
|
1701
|
-
|
|
1702
|
-
if (!
|
|
1703
|
-
|
|
1634
|
+
_this8.hideTypingIndicator();
|
|
1635
|
+
if (!_this8.isNavigatingAway) {
|
|
1636
|
+
_this8.addMessage(_this8.getServiceDownMessage());
|
|
1704
1637
|
}
|
|
1705
|
-
(
|
|
1706
|
-
|
|
1638
|
+
(_this8$stream2 = _this8.stream) === null || _this8$stream2 === void 0 || _this8$stream2.dispose();
|
|
1639
|
+
_this8.stream = null;
|
|
1707
1640
|
console.error("Stream error:", err);
|
|
1708
1641
|
}
|
|
1709
1642
|
});
|
|
@@ -1717,92 +1650,17 @@ window.openAIChatManager = function () {
|
|
|
1717
1650
|
return newMessage;
|
|
1718
1651
|
},
|
|
1719
1652
|
processReferences: function processReferences(references, messageIndex) {
|
|
1720
|
-
var
|
|
1653
|
+
var _this9 = this;
|
|
1721
1654
|
references = normalizeReferences(references);
|
|
1722
1655
|
if (Object.keys(references).length) {
|
|
1656
|
+
var _ref15, _message$rawContent2;
|
|
1723
1657
|
var message = this.messages[messageIndex];
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
// Only include references that were actually cited in the response.
|
|
1727
|
-
// Check both raw [doc:N] markers and already-rendered <sup> tags from streaming.
|
|
1728
|
-
var citedRefs = Object.entries(references).filter(function (_ref1) {
|
|
1729
|
-
var _ref10 = _slicedToArray(_ref1, 2),
|
|
1730
|
-
key = _ref10[0],
|
|
1731
|
-
value = _ref10[1];
|
|
1732
|
-
return content.includes(key) || content.includes("<sup><strong>".concat(value.index, "</strong></sup>"));
|
|
1733
|
-
});
|
|
1734
|
-
if (!citedRefs.length) {
|
|
1735
|
-
return;
|
|
1736
|
-
}
|
|
1737
|
-
|
|
1738
|
-
// Sort by original index so display indices follow a natural order.
|
|
1739
|
-
citedRefs.sort(function (_ref11, _ref12) {
|
|
1740
|
-
var _ref13 = _slicedToArray(_ref11, 2),
|
|
1741
|
-
a = _ref13[1];
|
|
1742
|
-
var _ref14 = _slicedToArray(_ref12, 2),
|
|
1743
|
-
b = _ref14[1];
|
|
1744
|
-
return a.index - b.index;
|
|
1745
|
-
});
|
|
1746
|
-
|
|
1747
|
-
// Phase 1: Replace all markers with unique placeholders to avoid collisions during remapping.
|
|
1748
|
-
var processed = content.trim();
|
|
1749
|
-
var displayIndex = 1;
|
|
1750
|
-
var _iterator5 = _createForOfIteratorHelper(citedRefs),
|
|
1751
|
-
_step5;
|
|
1752
|
-
try {
|
|
1753
|
-
for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
|
|
1754
|
-
var _step5$value = _slicedToArray(_step5.value, 2),
|
|
1755
|
-
key = _step5$value[0],
|
|
1756
|
-
value = _step5$value[1];
|
|
1757
|
-
var placeholder = "__CITE_".concat(value.index, "__");
|
|
1758
|
-
processed = processed.replaceAll(key, placeholder);
|
|
1759
|
-
processed = processed.replaceAll("<sup><strong>".concat(value.index, "</strong></sup>"), placeholder);
|
|
1760
|
-
value._displayIndex = displayIndex++;
|
|
1761
|
-
value._placeholder = placeholder;
|
|
1762
|
-
}
|
|
1763
|
-
|
|
1764
|
-
// Phase 2: Replace placeholders with sequential display indices.
|
|
1765
|
-
} catch (err) {
|
|
1766
|
-
_iterator5.e(err);
|
|
1767
|
-
} finally {
|
|
1768
|
-
_iterator5.f();
|
|
1769
|
-
}
|
|
1770
|
-
var _iterator6 = _createForOfIteratorHelper(citedRefs),
|
|
1771
|
-
_step6;
|
|
1772
|
-
try {
|
|
1773
|
-
for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
|
|
1774
|
-
var _step6$value = _slicedToArray(_step6.value, 2),
|
|
1775
|
-
_value4 = _step6$value[1];
|
|
1776
|
-
processed = processed.replaceAll(_value4._placeholder, "<sup><strong>".concat(_value4._displayIndex, "</strong></sup>"));
|
|
1777
|
-
}
|
|
1778
|
-
} catch (err) {
|
|
1779
|
-
_iterator6.e(err);
|
|
1780
|
-
} finally {
|
|
1781
|
-
_iterator6.f();
|
|
1782
|
-
}
|
|
1783
|
-
processed = processed.replaceAll('</strong></sup><sup>', '</strong></sup><sup>,</sup><sup>');
|
|
1784
|
-
processed += '<br><br>';
|
|
1785
|
-
var _iterator7 = _createForOfIteratorHelper(citedRefs),
|
|
1786
|
-
_step7;
|
|
1787
|
-
try {
|
|
1788
|
-
for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
|
|
1789
|
-
var _step7$value = _slicedToArray(_step7.value, 2),
|
|
1790
|
-
_key3 = _step7$value[0],
|
|
1791
|
-
_value5 = _step7$value[1];
|
|
1792
|
-
var label = _value5.text || _key3;
|
|
1793
|
-
processed += _value5.link ? "**".concat(_value5._displayIndex, "**. [").concat(label, "](").concat(_value5.link, ")<br>") : "**".concat(_value5._displayIndex, "**. ").concat(label, "<br>");
|
|
1794
|
-
}
|
|
1795
|
-
} catch (err) {
|
|
1796
|
-
_iterator7.e(err);
|
|
1797
|
-
} finally {
|
|
1798
|
-
_iterator7.f();
|
|
1799
|
-
}
|
|
1800
|
-
message.content = processed;
|
|
1801
|
-
message.htmlContent = parseMarkdownContent(processed, message);
|
|
1658
|
+
message.rawContent = (_ref15 = (_message$rawContent2 = message.rawContent) !== null && _message$rawContent2 !== void 0 ? _message$rawContent2 : message.content) !== null && _ref15 !== void 0 ? _ref15 : '';
|
|
1659
|
+
updateMessagePresentation(message, references);
|
|
1802
1660
|
this.messages[messageIndex] = message;
|
|
1803
1661
|
this.$nextTick(function () {
|
|
1804
1662
|
renderChartsInMessage(message);
|
|
1805
|
-
|
|
1663
|
+
_this9.scrollToBottom();
|
|
1806
1664
|
});
|
|
1807
1665
|
}
|
|
1808
1666
|
},
|
|
@@ -1852,6 +1710,19 @@ window.openAIChatManager = function () {
|
|
|
1852
1710
|
}
|
|
1853
1711
|
this.stopAudio(false);
|
|
1854
1712
|
},
|
|
1713
|
+
updateTtsPlaybackButtons: function updateTtsPlaybackButtons() {
|
|
1714
|
+
var _this0 = this;
|
|
1715
|
+
if (!this.chatContainer) {
|
|
1716
|
+
return;
|
|
1717
|
+
}
|
|
1718
|
+
var buttons = this.chatContainer.querySelectorAll('[data-tts-message-index]');
|
|
1719
|
+
buttons.forEach(function (button) {
|
|
1720
|
+
var buttonIndex = Number(button.getAttribute('data-tts-message-index'));
|
|
1721
|
+
var isPlaying = buttonIndex === _this0.ttsPlayingMessageIndex;
|
|
1722
|
+
button.classList.toggle('tts-playing', isPlaying);
|
|
1723
|
+
button.setAttribute('title', isPlaying ? 'Pause audio' : 'Read aloud');
|
|
1724
|
+
});
|
|
1725
|
+
},
|
|
1855
1726
|
synthesizeSpeech: function synthesizeSpeech(text, cacheIndex) {
|
|
1856
1727
|
var _this1 = this;
|
|
1857
1728
|
if (!this.textToSpeechEnabled || !text || !this.connection) {
|
|
@@ -1865,9 +1736,13 @@ window.openAIChatManager = function () {
|
|
|
1865
1736
|
_this1.isPlayingAudio = false;
|
|
1866
1737
|
_this1.ttsPlayingMessageIndex = -1;
|
|
1867
1738
|
_this1._ttsCacheIndex = -1;
|
|
1739
|
+
_this1.$nextTick(function () {
|
|
1740
|
+
return _this1.updateTtsPlaybackButtons();
|
|
1741
|
+
});
|
|
1868
1742
|
});
|
|
1869
1743
|
},
|
|
1870
1744
|
toggleMessageTts: function toggleMessageTts(message, index) {
|
|
1745
|
+
var _this10 = this;
|
|
1871
1746
|
if (this.ttsPlayingMessageIndex === index) {
|
|
1872
1747
|
this.stopAudio();
|
|
1873
1748
|
return;
|
|
@@ -1879,6 +1754,9 @@ window.openAIChatManager = function () {
|
|
|
1879
1754
|
}
|
|
1880
1755
|
}));
|
|
1881
1756
|
this.ttsPlayingMessageIndex = index;
|
|
1757
|
+
this.$nextTick(function () {
|
|
1758
|
+
return _this10.updateTtsPlaybackButtons();
|
|
1759
|
+
});
|
|
1882
1760
|
if (this.ttsAudioCache[index]) {
|
|
1883
1761
|
this.playAudioBlob(this.ttsAudioCache[index]);
|
|
1884
1762
|
return;
|
|
@@ -1886,10 +1764,14 @@ window.openAIChatManager = function () {
|
|
|
1886
1764
|
this.synthesizeSpeech(message.content, index);
|
|
1887
1765
|
},
|
|
1888
1766
|
playCollectedAudio: function playCollectedAudio() {
|
|
1767
|
+
var _this11 = this;
|
|
1889
1768
|
if (this.audioChunks.length === 0) {
|
|
1890
1769
|
if (!this.currentAudioElement && this.audioPlayQueue.length === 0) {
|
|
1891
1770
|
this.isPlayingAudio = false;
|
|
1892
1771
|
this.ttsPlayingMessageIndex = -1;
|
|
1772
|
+
this.$nextTick(function () {
|
|
1773
|
+
return _this11.updateTtsPlaybackButtons();
|
|
1774
|
+
});
|
|
1893
1775
|
}
|
|
1894
1776
|
return;
|
|
1895
1777
|
}
|
|
@@ -1898,18 +1780,18 @@ window.openAIChatManager = function () {
|
|
|
1898
1780
|
}, 0);
|
|
1899
1781
|
var combined = new Uint8Array(totalLength);
|
|
1900
1782
|
var offset = 0;
|
|
1901
|
-
var
|
|
1902
|
-
|
|
1783
|
+
var _iterator5 = _createForOfIteratorHelper(this.audioChunks),
|
|
1784
|
+
_step5;
|
|
1903
1785
|
try {
|
|
1904
|
-
for (
|
|
1905
|
-
var chunk =
|
|
1786
|
+
for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
|
|
1787
|
+
var chunk = _step5.value;
|
|
1906
1788
|
combined.set(chunk, offset);
|
|
1907
1789
|
offset += chunk.length;
|
|
1908
1790
|
}
|
|
1909
1791
|
} catch (err) {
|
|
1910
|
-
|
|
1792
|
+
_iterator5.e(err);
|
|
1911
1793
|
} finally {
|
|
1912
|
-
|
|
1794
|
+
_iterator5.f();
|
|
1913
1795
|
}
|
|
1914
1796
|
this.audioChunks = [];
|
|
1915
1797
|
var blob = new Blob([combined], {
|
|
@@ -1928,45 +1810,53 @@ window.openAIChatManager = function () {
|
|
|
1928
1810
|
this.playAudioBlob(blob);
|
|
1929
1811
|
},
|
|
1930
1812
|
playAudioBlob: function playAudioBlob(blob) {
|
|
1931
|
-
var
|
|
1813
|
+
var _this12 = this;
|
|
1932
1814
|
var url = URL.createObjectURL(blob);
|
|
1933
1815
|
var audio = new Audio(url);
|
|
1934
1816
|
this.currentAudioUrl = url;
|
|
1935
1817
|
this.currentAudioElement = audio;
|
|
1936
1818
|
this.isPlayingAudio = true;
|
|
1937
1819
|
audio.addEventListener('ended', function () {
|
|
1938
|
-
|
|
1939
|
-
|
|
1820
|
+
_this12.currentAudioElement = null;
|
|
1821
|
+
_this12.currentAudioUrl = null;
|
|
1940
1822
|
URL.revokeObjectURL(url);
|
|
1941
|
-
|
|
1823
|
+
_this12.playNextInQueue();
|
|
1942
1824
|
});
|
|
1943
1825
|
audio.addEventListener('error', function () {
|
|
1944
|
-
|
|
1945
|
-
|
|
1826
|
+
_this12.currentAudioElement = null;
|
|
1827
|
+
_this12.currentAudioUrl = null;
|
|
1946
1828
|
URL.revokeObjectURL(url);
|
|
1947
|
-
|
|
1829
|
+
_this12.playNextInQueue();
|
|
1948
1830
|
});
|
|
1949
1831
|
audio.play()["catch"](function (err) {
|
|
1950
1832
|
console.error("Audio playback error:", err);
|
|
1951
|
-
|
|
1952
|
-
|
|
1833
|
+
_this12.currentAudioElement = null;
|
|
1834
|
+
_this12.currentAudioUrl = null;
|
|
1953
1835
|
URL.revokeObjectURL(url);
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1836
|
+
_this12.audioPlayQueue = [];
|
|
1837
|
+
_this12.isPlayingAudio = false;
|
|
1838
|
+
_this12.ttsPlayingMessageIndex = -1;
|
|
1839
|
+
_this12.$nextTick(function () {
|
|
1840
|
+
return _this12.updateTtsPlaybackButtons();
|
|
1841
|
+
});
|
|
1957
1842
|
});
|
|
1958
1843
|
},
|
|
1959
1844
|
playNextInQueue: function playNextInQueue() {
|
|
1845
|
+
var _this13 = this;
|
|
1960
1846
|
if (this.audioPlayQueue.length > 0) {
|
|
1961
1847
|
var nextBlob = this.audioPlayQueue.shift();
|
|
1962
1848
|
this.playAudioBlob(nextBlob);
|
|
1963
1849
|
} else {
|
|
1964
1850
|
this.isPlayingAudio = false;
|
|
1965
1851
|
this.ttsPlayingMessageIndex = -1;
|
|
1852
|
+
this.$nextTick(function () {
|
|
1853
|
+
return _this13.updateTtsPlaybackButtons();
|
|
1854
|
+
});
|
|
1966
1855
|
this.conversationModeOnAudioEnded();
|
|
1967
1856
|
}
|
|
1968
1857
|
},
|
|
1969
1858
|
stopAudio: function stopAudio() {
|
|
1859
|
+
var _this14 = this;
|
|
1970
1860
|
if (this.currentAudioElement) {
|
|
1971
1861
|
this.currentAudioElement.pause();
|
|
1972
1862
|
this.currentAudioElement.currentTime = 0;
|
|
@@ -1980,6 +1870,9 @@ window.openAIChatManager = function () {
|
|
|
1980
1870
|
this.audioPlayQueue = [];
|
|
1981
1871
|
this.isPlayingAudio = false;
|
|
1982
1872
|
this.ttsPlayingMessageIndex = -1;
|
|
1873
|
+
this.$nextTick(function () {
|
|
1874
|
+
return _this14.updateTtsPlaybackButtons();
|
|
1875
|
+
});
|
|
1983
1876
|
},
|
|
1984
1877
|
toggleConversationMode: function toggleConversationMode() {
|
|
1985
1878
|
if (this.isConversationMode) {
|
|
@@ -1989,7 +1882,7 @@ window.openAIChatManager = function () {
|
|
|
1989
1882
|
}
|
|
1990
1883
|
},
|
|
1991
1884
|
startConversationMode: function startConversationMode() {
|
|
1992
|
-
var
|
|
1885
|
+
var _this15 = this;
|
|
1993
1886
|
if (!this.conversationModeEnabled || this.isConversationMode || !this.connection) {
|
|
1994
1887
|
return;
|
|
1995
1888
|
}
|
|
@@ -2009,12 +1902,12 @@ window.openAIChatManager = function () {
|
|
|
2009
1902
|
}
|
|
2010
1903
|
}).then(function (stream) {
|
|
2011
1904
|
var mimeType = MediaRecorder.isTypeSupported('audio/ogg;codecs=opus') ? 'audio/ogg;codecs=opus' : MediaRecorder.isTypeSupported('audio/webm;codecs=opus') ? 'audio/webm;codecs=opus' : 'audio/webm';
|
|
2012
|
-
|
|
1905
|
+
_this15.mediaRecorder = new MediaRecorder(stream, {
|
|
2013
1906
|
mimeType: mimeType,
|
|
2014
1907
|
audioBitsPerSecond: 128000
|
|
2015
1908
|
});
|
|
2016
|
-
|
|
2017
|
-
|
|
1909
|
+
_this15._conversationSubject = new signalR.Subject();
|
|
1910
|
+
_this15._conversationStream = stream;
|
|
2018
1911
|
|
|
2019
1912
|
// Create an AnalyserNode for volume-based interrupt detection.
|
|
2020
1913
|
// During TTS playback, detect when the user speaks above
|
|
@@ -2023,20 +1916,20 @@ window.openAIChatManager = function () {
|
|
|
2023
1916
|
// speaker echo so the STT stream has no gaps.
|
|
2024
1917
|
var AudioCtx = window.AudioContext || window.webkitAudioContext;
|
|
2025
1918
|
if (AudioCtx) {
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
var micSource =
|
|
2030
|
-
micSource.connect(
|
|
1919
|
+
_this15._conversationAudioCtx = new AudioCtx();
|
|
1920
|
+
_this15._conversationAnalyser = _this15._conversationAudioCtx.createAnalyser();
|
|
1921
|
+
_this15._conversationAnalyser.fftSize = 256;
|
|
1922
|
+
var micSource = _this15._conversationAudioCtx.createMediaStreamSource(stream);
|
|
1923
|
+
micSource.connect(_this15._conversationAnalyser);
|
|
2031
1924
|
}
|
|
2032
1925
|
var pendingChunk = Promise.resolve();
|
|
2033
|
-
var analyser =
|
|
1926
|
+
var analyser = _this15._conversationAnalyser;
|
|
2034
1927
|
var interruptVolumeThreshold = 30;
|
|
2035
|
-
|
|
1928
|
+
_this15.mediaRecorder.addEventListener('dataavailable', function (e) {
|
|
2036
1929
|
if (e.data && e.data.size > 0) {
|
|
2037
1930
|
// During TTS playback, check mic volume to detect
|
|
2038
1931
|
// user interruption (speaking above threshold).
|
|
2039
|
-
if (
|
|
1932
|
+
if (_this15.isPlayingAudio && analyser) {
|
|
2040
1933
|
var freqData = new Uint8Array(analyser.frequencyBinCount);
|
|
2041
1934
|
analyser.getByteFrequencyData(freqData);
|
|
2042
1935
|
var sum = 0;
|
|
@@ -2046,61 +1939,61 @@ window.openAIChatManager = function () {
|
|
|
2046
1939
|
var avg = sum / freqData.length;
|
|
2047
1940
|
if (avg >= interruptVolumeThreshold) {
|
|
2048
1941
|
// User is speaking — interrupt TTS playback.
|
|
2049
|
-
|
|
1942
|
+
_this15.stopAudio();
|
|
2050
1943
|
}
|
|
2051
1944
|
}
|
|
2052
1945
|
|
|
2053
1946
|
// Always send audio to STT — browser echo cancellation
|
|
2054
1947
|
// handles speaker echo; continuous audio avoids gaps
|
|
2055
1948
|
// that increase recognition latency.
|
|
2056
|
-
pendingChunk = pendingChunk.then(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
1949
|
+
pendingChunk = pendingChunk.then(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee8() {
|
|
2057
1950
|
var data, uint8Array, binaryString, base64;
|
|
2058
|
-
return _regenerator().w(function (
|
|
2059
|
-
while (1) switch (
|
|
1951
|
+
return _regenerator().w(function (_context8) {
|
|
1952
|
+
while (1) switch (_context8.n) {
|
|
2060
1953
|
case 0:
|
|
2061
|
-
|
|
1954
|
+
_context8.n = 1;
|
|
2062
1955
|
return e.data.arrayBuffer();
|
|
2063
1956
|
case 1:
|
|
2064
|
-
data =
|
|
1957
|
+
data = _context8.v;
|
|
2065
1958
|
uint8Array = new Uint8Array(data);
|
|
2066
1959
|
binaryString = uint8Array.reduce(function (str, _byte2) {
|
|
2067
1960
|
return str + String.fromCharCode(_byte2);
|
|
2068
1961
|
}, '');
|
|
2069
1962
|
base64 = btoa(binaryString);
|
|
2070
1963
|
try {
|
|
2071
|
-
|
|
1964
|
+
_this15._conversationSubject.next(base64);
|
|
2072
1965
|
} catch (err) {
|
|
2073
1966
|
// Subject may have been completed already.
|
|
2074
1967
|
}
|
|
2075
1968
|
case 2:
|
|
2076
|
-
return
|
|
1969
|
+
return _context8.a(2);
|
|
2077
1970
|
}
|
|
2078
|
-
},
|
|
1971
|
+
}, _callee8);
|
|
2079
1972
|
})));
|
|
2080
1973
|
}
|
|
2081
1974
|
});
|
|
2082
|
-
|
|
1975
|
+
_this15.mediaRecorder.addEventListener('stop', function () {
|
|
2083
1976
|
stream.getTracks().forEach(function (track) {
|
|
2084
1977
|
return track.stop();
|
|
2085
1978
|
});
|
|
2086
1979
|
pendingChunk.then(function () {
|
|
2087
1980
|
try {
|
|
2088
|
-
|
|
1981
|
+
_this15._conversationSubject.complete();
|
|
2089
1982
|
} catch (err) {
|
|
2090
1983
|
// Already completed.
|
|
2091
1984
|
}
|
|
2092
1985
|
});
|
|
2093
1986
|
});
|
|
2094
|
-
var profileId =
|
|
2095
|
-
var sessionId =
|
|
1987
|
+
var profileId = _this15.getProfileId();
|
|
1988
|
+
var sessionId = _this15.getSessionId() || '';
|
|
2096
1989
|
var language = navigator.language || document.documentElement.lang || 'en-US';
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
1990
|
+
_this15.connection.send("StartConversation", profileId, sessionId, _this15._conversationSubject, mimeType, language);
|
|
1991
|
+
_this15.mediaRecorder.start(250);
|
|
1992
|
+
_this15.isRecording = true;
|
|
2100
1993
|
})["catch"](function (err) {
|
|
2101
1994
|
console.error('Microphone access denied:', err);
|
|
2102
|
-
|
|
2103
|
-
|
|
1995
|
+
_this15.isConversationMode = false;
|
|
1996
|
+
_this15.updateConversationButton();
|
|
2104
1997
|
});
|
|
2105
1998
|
},
|
|
2106
1999
|
stopConversationMode: function stopConversationMode() {
|
|
@@ -2227,7 +2120,7 @@ window.openAIChatManager = function () {
|
|
|
2227
2120
|
return removedCount;
|
|
2228
2121
|
},
|
|
2229
2122
|
receiveNotification: function receiveNotification(notification) {
|
|
2230
|
-
var
|
|
2123
|
+
var _this16 = this;
|
|
2231
2124
|
if (!notification || !notification.type) {
|
|
2232
2125
|
return;
|
|
2233
2126
|
}
|
|
@@ -2242,7 +2135,7 @@ window.openAIChatManager = function () {
|
|
|
2242
2135
|
}
|
|
2243
2136
|
this.scheduleNotificationDismiss(notification);
|
|
2244
2137
|
this.$nextTick(function () {
|
|
2245
|
-
|
|
2138
|
+
_this16.scrollToBottom();
|
|
2246
2139
|
});
|
|
2247
2140
|
},
|
|
2248
2141
|
updateNotification: function updateNotification(notification) {
|
|
@@ -2259,12 +2152,12 @@ window.openAIChatManager = function () {
|
|
|
2259
2152
|
}
|
|
2260
2153
|
},
|
|
2261
2154
|
scheduleNotificationDismiss: function scheduleNotificationDismiss(notification) {
|
|
2262
|
-
var
|
|
2155
|
+
var _this17 = this;
|
|
2263
2156
|
if (!notification || !notification.type || !notification.autoDismissMs || notification.autoDismissMs <= 0) {
|
|
2264
2157
|
return;
|
|
2265
2158
|
}
|
|
2266
2159
|
this.notificationDismissTimers[notification.type] = setTimeout(function () {
|
|
2267
|
-
|
|
2160
|
+
_this17.removeNotification(notification.type);
|
|
2268
2161
|
}, notification.autoDismissMs);
|
|
2269
2162
|
},
|
|
2270
2163
|
clearNotificationDismiss: function clearNotificationDismiss(notificationType) {
|
|
@@ -2294,31 +2187,32 @@ window.openAIChatManager = function () {
|
|
|
2294
2187
|
});
|
|
2295
2188
|
},
|
|
2296
2189
|
scrollToBottom: function scrollToBottom() {
|
|
2297
|
-
var
|
|
2190
|
+
var _this18 = this;
|
|
2298
2191
|
if (!this.autoScroll) {
|
|
2299
2192
|
return;
|
|
2300
2193
|
}
|
|
2301
2194
|
setTimeout(function () {
|
|
2302
|
-
|
|
2195
|
+
_this18.chatContainer.scrollTop = _this18.chatContainer.scrollHeight - _this18.chatContainer.clientHeight;
|
|
2303
2196
|
}, 50);
|
|
2304
2197
|
},
|
|
2305
2198
|
handleUserInput: function handleUserInput(event) {
|
|
2306
2199
|
this.prompt = event.target.value;
|
|
2307
2200
|
},
|
|
2308
2201
|
getProfileId: function getProfileId() {
|
|
2309
|
-
return this.inputElement.getAttribute('data-profile-id');
|
|
2202
|
+
return this.inputElement ? this.inputElement.getAttribute('data-profile-id') : null;
|
|
2310
2203
|
},
|
|
2311
2204
|
setSessionId: function setSessionId(sessionId) {
|
|
2205
|
+
if (!this.inputElement) {
|
|
2206
|
+
return;
|
|
2207
|
+
}
|
|
2312
2208
|
this.inputElement.setAttribute('data-session-id', sessionId || '');
|
|
2313
2209
|
},
|
|
2314
2210
|
resetSession: function resetSession() {
|
|
2315
2211
|
this.stopRecording();
|
|
2212
|
+
this.rejectPendingSessionRequest('Session was reset.');
|
|
2316
2213
|
this.setSessionId('');
|
|
2317
2214
|
this.isSessionStarted = false;
|
|
2318
2215
|
this.sessionRating = null;
|
|
2319
|
-
if (this.widgetIsInitialized) {
|
|
2320
|
-
localStorage.removeItem(this.chatWidgetStateSession);
|
|
2321
|
-
}
|
|
2322
2216
|
this.messages = [];
|
|
2323
2217
|
this.documents = [];
|
|
2324
2218
|
if (!config.autoCreateSession) {
|
|
@@ -2327,6 +2221,9 @@ window.openAIChatManager = function () {
|
|
|
2327
2221
|
if (config.autoCreateSession) {
|
|
2328
2222
|
this.startNewSession();
|
|
2329
2223
|
}
|
|
2224
|
+
if (widgetBehavior && typeof widgetBehavior.onSessionReset === 'function') {
|
|
2225
|
+
widgetBehavior.onSessionReset(this, config);
|
|
2226
|
+
}
|
|
2330
2227
|
},
|
|
2331
2228
|
startNewSession: function startNewSession() {
|
|
2332
2229
|
if (!this.applyOrchestratorAvailability()) {
|
|
@@ -2336,16 +2233,94 @@ window.openAIChatManager = function () {
|
|
|
2336
2233
|
if (!profileId || !this.connection) {
|
|
2337
2234
|
return;
|
|
2338
2235
|
}
|
|
2339
|
-
this.
|
|
2236
|
+
this.requestNewSession(profileId)["catch"](function (err) {
|
|
2340
2237
|
return console.error(err);
|
|
2341
2238
|
});
|
|
2342
2239
|
},
|
|
2240
|
+
ensureSessionForDocuments: function ensureSessionForDocuments(profileId) {
|
|
2241
|
+
var _this19 = this;
|
|
2242
|
+
return _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee9() {
|
|
2243
|
+
var sessionId;
|
|
2244
|
+
return _regenerator().w(function (_context9) {
|
|
2245
|
+
while (1) switch (_context9.n) {
|
|
2246
|
+
case 0:
|
|
2247
|
+
sessionId = _this19.getSessionId();
|
|
2248
|
+
if (!sessionId) {
|
|
2249
|
+
_context9.n = 1;
|
|
2250
|
+
break;
|
|
2251
|
+
}
|
|
2252
|
+
return _context9.a(2, sessionId);
|
|
2253
|
+
case 1:
|
|
2254
|
+
if (!(!profileId || !_this19.connection)) {
|
|
2255
|
+
_context9.n = 2;
|
|
2256
|
+
break;
|
|
2257
|
+
}
|
|
2258
|
+
return _context9.a(2, null);
|
|
2259
|
+
case 2:
|
|
2260
|
+
_context9.n = 3;
|
|
2261
|
+
return _this19.requestNewSession(profileId);
|
|
2262
|
+
case 3:
|
|
2263
|
+
return _context9.a(2, _context9.v);
|
|
2264
|
+
}
|
|
2265
|
+
}, _callee9);
|
|
2266
|
+
}))();
|
|
2267
|
+
},
|
|
2268
|
+
requestNewSession: function requestNewSession(profileId) {
|
|
2269
|
+
var _this20 = this;
|
|
2270
|
+
if (this.pendingSessionPromise) {
|
|
2271
|
+
return this.pendingSessionPromise;
|
|
2272
|
+
}
|
|
2273
|
+
if (!profileId || !this.connection) {
|
|
2274
|
+
return Promise.resolve(null);
|
|
2275
|
+
}
|
|
2276
|
+
this.pendingSessionPromise = new Promise(function (resolve, reject) {
|
|
2277
|
+
_this20.pendingSessionResolver = resolve;
|
|
2278
|
+
_this20.pendingSessionRejector = reject;
|
|
2279
|
+
_this20.pendingSessionTimeoutId = window.setTimeout(function () {
|
|
2280
|
+
_this20.rejectPendingSessionRequest('Timed out while creating a chat session.');
|
|
2281
|
+
}, 15000);
|
|
2282
|
+
});
|
|
2283
|
+
this.connection.invoke("StartSession", profileId, null)["catch"](function (err) {
|
|
2284
|
+
_this20.rejectPendingSessionRequest(err);
|
|
2285
|
+
});
|
|
2286
|
+
return this.pendingSessionPromise;
|
|
2287
|
+
},
|
|
2288
|
+
resolvePendingSessionRequest: function resolvePendingSessionRequest(sessionId) {
|
|
2289
|
+
if (this.pendingSessionResolver) {
|
|
2290
|
+
this.pendingSessionResolver(sessionId);
|
|
2291
|
+
}
|
|
2292
|
+
this.clearPendingSessionRequest();
|
|
2293
|
+
},
|
|
2294
|
+
rejectPendingSessionRequest: function rejectPendingSessionRequest(error) {
|
|
2295
|
+
if (this.pendingSessionRejector) {
|
|
2296
|
+
this.pendingSessionRejector(error);
|
|
2297
|
+
}
|
|
2298
|
+
this.clearPendingSessionRequest();
|
|
2299
|
+
},
|
|
2300
|
+
clearPendingSessionRequest: function clearPendingSessionRequest() {
|
|
2301
|
+
if (this.pendingSessionTimeoutId) {
|
|
2302
|
+
window.clearTimeout(this.pendingSessionTimeoutId);
|
|
2303
|
+
}
|
|
2304
|
+
this.pendingSessionPromise = null;
|
|
2305
|
+
this.pendingSessionResolver = null;
|
|
2306
|
+
this.pendingSessionRejector = null;
|
|
2307
|
+
this.pendingSessionTimeoutId = null;
|
|
2308
|
+
},
|
|
2343
2309
|
initializeApp: function initializeApp() {
|
|
2344
|
-
var
|
|
2310
|
+
var _this21 = this;
|
|
2345
2311
|
this.inputElement = document.querySelector(config.inputElementSelector);
|
|
2346
2312
|
this.buttonElement = document.querySelector(config.sendButtonElementSelector);
|
|
2347
2313
|
this.chatContainer = document.querySelector(config.chatContainerElementSelector);
|
|
2348
2314
|
this.placeholder = document.querySelector(config.placeholderElementSelector);
|
|
2315
|
+
if (!this.inputElement || !this.buttonElement || !this.chatContainer || !this.placeholder) {
|
|
2316
|
+
console.error('AI chat app could not initialize because one or more required elements were not found.', {
|
|
2317
|
+
inputElementSelector: config.inputElementSelector,
|
|
2318
|
+
sendButtonElementSelector: config.sendButtonElementSelector,
|
|
2319
|
+
chatContainerElementSelector: config.chatContainerElementSelector,
|
|
2320
|
+
placeholderElementSelector: config.placeholderElementSelector
|
|
2321
|
+
});
|
|
2322
|
+
return false;
|
|
2323
|
+
}
|
|
2349
2324
|
this.applyOrchestratorAvailability();
|
|
2350
2325
|
var sessionId = this.getSessionId();
|
|
2351
2326
|
if (!hasWidgetConfig && sessionId) {
|
|
@@ -2370,7 +2345,7 @@ window.openAIChatManager = function () {
|
|
|
2370
2345
|
fileInput.accept = config.allowedExtensions;
|
|
2371
2346
|
}
|
|
2372
2347
|
fileInput.addEventListener('change', function (e) {
|
|
2373
|
-
return
|
|
2348
|
+
return _this21.handleFileInputChange(e);
|
|
2374
2349
|
});
|
|
2375
2350
|
this.documentBar.parentElement.appendChild(fileInput);
|
|
2376
2351
|
|
|
@@ -2378,13 +2353,13 @@ window.openAIChatManager = function () {
|
|
|
2378
2353
|
var inputArea = this.inputElement ? this.inputElement.closest('.ai-admin-widget-input, .text-bg-light') : null;
|
|
2379
2354
|
if (inputArea) {
|
|
2380
2355
|
inputArea.addEventListener('dragover', function (e) {
|
|
2381
|
-
return
|
|
2356
|
+
return _this21.handleDragOver(e);
|
|
2382
2357
|
});
|
|
2383
2358
|
inputArea.addEventListener('dragleave', function (e) {
|
|
2384
|
-
return
|
|
2359
|
+
return _this21.handleDragLeave(e);
|
|
2385
2360
|
});
|
|
2386
2361
|
inputArea.addEventListener('drop', function (e) {
|
|
2387
|
-
return
|
|
2362
|
+
return _this21.handleDrop(e);
|
|
2388
2363
|
});
|
|
2389
2364
|
}
|
|
2390
2365
|
}
|
|
@@ -2392,55 +2367,55 @@ window.openAIChatManager = function () {
|
|
|
2392
2367
|
|
|
2393
2368
|
// Pause auto-scroll when the user manually scrolls up during streaming.
|
|
2394
2369
|
this.chatContainer.addEventListener('scroll', function () {
|
|
2395
|
-
if (!
|
|
2370
|
+
if (!_this21.stream) {
|
|
2396
2371
|
return;
|
|
2397
2372
|
}
|
|
2398
2373
|
var threshold = 30;
|
|
2399
|
-
var atBottom =
|
|
2400
|
-
|
|
2374
|
+
var atBottom = _this21.chatContainer.scrollHeight - _this21.chatContainer.clientHeight - _this21.chatContainer.scrollTop <= threshold;
|
|
2375
|
+
_this21.autoScroll = atBottom;
|
|
2401
2376
|
});
|
|
2402
2377
|
this.inputElement.addEventListener('keydown', function (event) {
|
|
2403
|
-
if (
|
|
2378
|
+
if (_this21.stream != null) {
|
|
2404
2379
|
return;
|
|
2405
2380
|
}
|
|
2406
2381
|
if (event.key === "Enter" && !event.shiftKey) {
|
|
2407
2382
|
event.preventDefault();
|
|
2408
|
-
|
|
2383
|
+
_this21.buttonElement.click();
|
|
2409
2384
|
}
|
|
2410
2385
|
});
|
|
2411
2386
|
this.inputElement.addEventListener('input', function (e) {
|
|
2412
|
-
|
|
2387
|
+
_this21.handleUserInput(e);
|
|
2413
2388
|
if (e.target.value.trim()) {
|
|
2414
|
-
|
|
2389
|
+
_this21.buttonElement.removeAttribute('disabled');
|
|
2415
2390
|
} else {
|
|
2416
|
-
|
|
2391
|
+
_this21.buttonElement.setAttribute('disabled', true);
|
|
2417
2392
|
}
|
|
2418
2393
|
});
|
|
2419
2394
|
this.buttonElement.addEventListener('click', function () {
|
|
2420
|
-
if (
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2395
|
+
if (_this21.stream != null) {
|
|
2396
|
+
_this21.stream.dispose();
|
|
2397
|
+
_this21.stream = null;
|
|
2398
|
+
_this21.streamingFinished();
|
|
2399
|
+
_this21.hideTypingIndicator();
|
|
2425
2400
|
|
|
2426
2401
|
// Clean up: remove empty assistant message or stop streaming animation.
|
|
2427
|
-
if (
|
|
2428
|
-
var lastMsg =
|
|
2402
|
+
if (_this21.messages.length > 0) {
|
|
2403
|
+
var lastMsg = _this21.messages[_this21.messages.length - 1];
|
|
2429
2404
|
if (lastMsg.role === 'assistant' && !lastMsg.content) {
|
|
2430
|
-
|
|
2405
|
+
_this21.messages.pop();
|
|
2431
2406
|
} else if (lastMsg.isStreaming) {
|
|
2432
2407
|
lastMsg.isStreaming = false;
|
|
2433
2408
|
}
|
|
2434
2409
|
}
|
|
2435
2410
|
return;
|
|
2436
2411
|
}
|
|
2437
|
-
|
|
2412
|
+
_this21.sendMessage();
|
|
2438
2413
|
});
|
|
2439
2414
|
var promptGenerators = document.getElementsByClassName('profile-generated-prompt');
|
|
2440
2415
|
for (var i = 0; i < promptGenerators.length; i++) {
|
|
2441
2416
|
promptGenerators[i].addEventListener('click', function (e) {
|
|
2442
2417
|
e.preventDefault();
|
|
2443
|
-
|
|
2418
|
+
_this21.generatePrompt(e.target);
|
|
2444
2419
|
});
|
|
2445
2420
|
}
|
|
2446
2421
|
var chatSessions = document.getElementsByClassName('chat-session-history-item');
|
|
@@ -2452,8 +2427,8 @@ window.openAIChatManager = function () {
|
|
|
2452
2427
|
console.error('an element with the class chat-session-history-item with no data-session-id set.');
|
|
2453
2428
|
return;
|
|
2454
2429
|
}
|
|
2455
|
-
|
|
2456
|
-
|
|
2430
|
+
_this21.loadSession(sessionId);
|
|
2431
|
+
_this21.showChatScreen();
|
|
2457
2432
|
});
|
|
2458
2433
|
}
|
|
2459
2434
|
for (var _i5 = 0; _i5 < config.messages.length; _i5++) {
|
|
@@ -2462,7 +2437,7 @@ window.openAIChatManager = function () {
|
|
|
2462
2437
|
|
|
2463
2438
|
// Update feedback icons in the DOM after initial messages have rendered.
|
|
2464
2439
|
this.$nextTick(function () {
|
|
2465
|
-
|
|
2440
|
+
_this21.refreshAllFeedbackIcons();
|
|
2466
2441
|
});
|
|
2467
2442
|
|
|
2468
2443
|
// Delegate click for code block copy buttons.
|
|
@@ -2494,7 +2469,7 @@ window.openAIChatManager = function () {
|
|
|
2494
2469
|
if (this.micButton) {
|
|
2495
2470
|
this.micButton.style.display = '';
|
|
2496
2471
|
this.micButton.addEventListener('click', function () {
|
|
2497
|
-
|
|
2472
|
+
_this21.toggleRecording();
|
|
2498
2473
|
});
|
|
2499
2474
|
}
|
|
2500
2475
|
}
|
|
@@ -2504,10 +2479,11 @@ window.openAIChatManager = function () {
|
|
|
2504
2479
|
this.conversationButton = document.querySelector(config.conversationButtonElementSelector);
|
|
2505
2480
|
if (this.conversationButton) {
|
|
2506
2481
|
this.conversationButton.addEventListener('click', function () {
|
|
2507
|
-
|
|
2482
|
+
_this21.toggleConversationMode();
|
|
2508
2483
|
});
|
|
2509
2484
|
}
|
|
2510
2485
|
}
|
|
2486
|
+
return true;
|
|
2511
2487
|
},
|
|
2512
2488
|
loadSession: function loadSession(sessionId) {
|
|
2513
2489
|
this.connection.invoke("LoadSession", sessionId)["catch"](function (err) {
|
|
@@ -2522,6 +2498,9 @@ window.openAIChatManager = function () {
|
|
|
2522
2498
|
},
|
|
2523
2499
|
initializeSession: function initializeSession(sessionId, force) {
|
|
2524
2500
|
if (this.isSessionStarted && !force) {
|
|
2501
|
+
if (sessionId && this.getSessionId() === sessionId) {
|
|
2502
|
+
this.resolvePendingSessionRequest(sessionId);
|
|
2503
|
+
}
|
|
2525
2504
|
return;
|
|
2526
2505
|
}
|
|
2527
2506
|
this.fireEvent(new CustomEvent("initializingSessionOpenAIChat", {
|
|
@@ -2531,121 +2510,22 @@ window.openAIChatManager = function () {
|
|
|
2531
2510
|
}));
|
|
2532
2511
|
this.setSessionId(sessionId);
|
|
2533
2512
|
this.isSessionStarted = true;
|
|
2534
|
-
|
|
2535
|
-
|
|
2513
|
+
this.resolvePendingSessionRequest(sessionId);
|
|
2514
|
+
if (widgetBehavior && typeof widgetBehavior.onSessionInitialized === 'function') {
|
|
2515
|
+
widgetBehavior.onSessionInitialized(this, sessionId, config);
|
|
2536
2516
|
}
|
|
2537
2517
|
},
|
|
2538
|
-
initializeWidget: function initializeWidget() {
|
|
2539
|
-
var _this16 = this;
|
|
2540
|
-
if (!config.widget.chatWidgetContainer) {
|
|
2541
|
-
console.error('The widget chatWidgetContainer is required.');
|
|
2542
|
-
return;
|
|
2543
|
-
}
|
|
2544
|
-
if (!config.widget.chatWidgetStateName) {
|
|
2545
|
-
console.error('The widget chatWidgetStateName is required.');
|
|
2546
|
-
return;
|
|
2547
|
-
}
|
|
2548
|
-
var chatWidgetContainer = document.querySelector(config.widget.chatWidgetContainer);
|
|
2549
|
-
if (!chatWidgetContainer) {
|
|
2550
|
-
return;
|
|
2551
|
-
}
|
|
2552
|
-
if (config.widget.chatHistorySection) {
|
|
2553
|
-
this.chatHistorySection = document.querySelector(config.widget.chatHistorySection);
|
|
2554
|
-
}
|
|
2555
|
-
this.chatWidgetStateName = config.widget.chatWidgetStateName;
|
|
2556
|
-
this.chatWidgetStateSession = config.widget.chatWidgetStateName + 'Session';
|
|
2557
|
-
this.chatWidgetLayoutKey = config.widget.chatWidgetStateName + 'Layout';
|
|
2558
|
-
this.widgetContainerElement = chatWidgetContainer;
|
|
2559
|
-
this.widgetToggleButtonElement = config.widget.toggleButtonSelector ? document.querySelector(config.widget.toggleButtonSelector) : null;
|
|
2560
|
-
this.widgetResetSizeButtonElement = config.widget.resetSizeButtonSelector ? document.querySelector(config.widget.resetSizeButtonSelector) : null;
|
|
2561
|
-
this.widgetDefaultWidth = parsePixelValue(config.widget.defaultWidth) || parsePixelValue(window.getComputedStyle(chatWidgetContainer).width) || 380;
|
|
2562
|
-
this.widgetDefaultHeight = parsePixelValue(config.widget.defaultHeight) || parsePixelValue(window.getComputedStyle(chatWidgetContainer).height) || 520;
|
|
2563
|
-
this.widgetIsInitialized = true;
|
|
2564
|
-
if (config.widget.enableResizing) {
|
|
2565
|
-
chatWidgetContainer.classList.add('ai-chat-widget-resizable');
|
|
2566
|
-
chatWidgetContainer.style.minWidth = (parsePixelValue(config.widget.minWidth) || 320) + 'px';
|
|
2567
|
-
chatWidgetContainer.style.minHeight = (parsePixelValue(config.widget.minHeight) || 420) + 'px';
|
|
2568
|
-
if (typeof ResizeObserver !== 'undefined') {
|
|
2569
|
-
this.widgetResizeObserver = new ResizeObserver(function () {
|
|
2570
|
-
_this16.persistWidgetPanelSize();
|
|
2571
|
-
_this16.constrainWidgetElementsToViewport();
|
|
2572
|
-
_this16.updateWidgetResetSizeButtonVisibility();
|
|
2573
|
-
});
|
|
2574
|
-
this.widgetResizeObserver.observe(chatWidgetContainer);
|
|
2575
|
-
}
|
|
2576
|
-
}
|
|
2577
|
-
var dragHandleSelector = config.widget.dragHandleSelector || '.ai-chat-widget-header';
|
|
2578
|
-
var dragHandle = chatWidgetContainer.querySelector(dragHandleSelector);
|
|
2579
|
-
if (config.widget.enableDragging && dragHandle) {
|
|
2580
|
-
dragHandle.classList.add('ai-chat-widget-drag-handle');
|
|
2581
|
-
chatWidgetContainer.classList.add('ai-chat-widget-draggable');
|
|
2582
|
-
this.attachDraggableWidgetElement(chatWidgetContainer, dragHandle, 'panel', false);
|
|
2583
|
-
}
|
|
2584
|
-
if (config.widget.enableDragging && this.widgetToggleButtonElement) {
|
|
2585
|
-
this.widgetToggleButtonElement.classList.add('ai-chat-widget-draggable');
|
|
2586
|
-
this.attachDraggableWidgetElement(this.widgetToggleButtonElement, this.widgetToggleButtonElement, 'toggle', true);
|
|
2587
|
-
}
|
|
2588
|
-
if (this.widgetResetSizeButtonElement) {
|
|
2589
|
-
this.widgetResetSizeButtonElement.addEventListener('click', function (event) {
|
|
2590
|
-
event.preventDefault();
|
|
2591
|
-
_this16.resetWidgetSize();
|
|
2592
|
-
});
|
|
2593
|
-
}
|
|
2594
|
-
this.restoreWidgetLayout();
|
|
2595
|
-
if (!this.widgetViewportResizeHandler) {
|
|
2596
|
-
this.widgetViewportResizeHandler = function () {
|
|
2597
|
-
_this16.constrainWidgetElementsToViewport();
|
|
2598
|
-
_this16.updateWidgetResetSizeButtonVisibility();
|
|
2599
|
-
};
|
|
2600
|
-
window.addEventListener('resize', this.widgetViewportResizeHandler);
|
|
2601
|
-
}
|
|
2602
|
-
|
|
2603
|
-
// Auto-load the last session so the user always sees previous chat history.
|
|
2604
|
-
this.reloadCurrentSession();
|
|
2605
|
-
if (config.autoCreateSession && !this.getSessionId()) {
|
|
2606
|
-
this.startNewSession();
|
|
2607
|
-
}
|
|
2608
|
-
if (config.widget.showHistoryButton && this.chatHistorySection) {
|
|
2609
|
-
var showHistoryButton = document.querySelector(config.widget.showHistoryButton);
|
|
2610
|
-
if (showHistoryButton) {
|
|
2611
|
-
showHistoryButton.addEventListener('click', function () {
|
|
2612
|
-
_this16.chatHistorySection.classList.toggle('show');
|
|
2613
|
-
});
|
|
2614
|
-
}
|
|
2615
|
-
if (config.widget.closeHistoryButton) {
|
|
2616
|
-
var closeHistoryButton = document.querySelector(config.widget.closeHistoryButton);
|
|
2617
|
-
if (closeHistoryButton) {
|
|
2618
|
-
closeHistoryButton.addEventListener('click', function () {
|
|
2619
|
-
_this16.showChatScreen();
|
|
2620
|
-
});
|
|
2621
|
-
}
|
|
2622
|
-
}
|
|
2623
|
-
}
|
|
2624
|
-
if (config.widget.newChatButton) {
|
|
2625
|
-
var newChatButton = document.querySelector(config.widget.newChatButton);
|
|
2626
|
-
if (newChatButton) {
|
|
2627
|
-
newChatButton.addEventListener('click', function () {
|
|
2628
|
-
_this16.resetSession();
|
|
2629
|
-
_this16.showChatScreen();
|
|
2630
|
-
});
|
|
2631
|
-
}
|
|
2632
|
-
}
|
|
2633
|
-
},
|
|
2634
|
-
showChatScreen: function showChatScreen() {
|
|
2635
|
-
if (!this.chatHistorySection) {
|
|
2636
|
-
return;
|
|
2637
|
-
}
|
|
2638
|
-
this.chatHistorySection.classList.remove('show');
|
|
2639
|
-
},
|
|
2640
2518
|
getSessionId: function getSessionId() {
|
|
2641
|
-
var sessionId = this.inputElement.getAttribute('data-session-id');
|
|
2642
|
-
if (!sessionId &&
|
|
2643
|
-
sessionId =
|
|
2519
|
+
var sessionId = this.inputElement ? this.inputElement.getAttribute('data-session-id') : null;
|
|
2520
|
+
if (!sessionId && widgetBehavior && typeof widgetBehavior.resolveSessionId === 'function') {
|
|
2521
|
+
sessionId = widgetBehavior.resolveSessionId(this, config);
|
|
2644
2522
|
}
|
|
2645
2523
|
return sessionId;
|
|
2646
2524
|
},
|
|
2647
2525
|
copyResponse: function copyResponse(message) {
|
|
2648
|
-
|
|
2526
|
+
var _ref17, _message$copyContent;
|
|
2527
|
+
var text = message && _typeof(message) === 'object' ? (_ref17 = (_message$copyContent = message.copyContent) !== null && _message$copyContent !== void 0 ? _message$copyContent : message.content) !== null && _ref17 !== void 0 ? _ref17 : '' : message !== null && message !== void 0 ? message : '';
|
|
2528
|
+
navigator.clipboard.writeText(text);
|
|
2649
2529
|
},
|
|
2650
2530
|
updateFeedbackIcons: function updateFeedbackIcons(container, userRating) {
|
|
2651
2531
|
if (!container) {
|
|
@@ -2654,11 +2534,11 @@ window.openAIChatManager = function () {
|
|
|
2654
2534
|
var upBtn = container.querySelector('.rate-up-btn');
|
|
2655
2535
|
var downBtn = container.querySelector('.rate-down-btn');
|
|
2656
2536
|
|
|
2657
|
-
//
|
|
2658
|
-
//
|
|
2537
|
+
// Keep feedback icons as simple span-based Font Awesome markup so
|
|
2538
|
+
// later state updates do not depend on i2svg replacement.
|
|
2659
2539
|
if (upBtn) {
|
|
2660
2540
|
var upClass = userRating === true ? 'fa-solid fa-thumbs-up' : 'fa-regular fa-thumbs-up';
|
|
2661
|
-
var upIcon = document.createElement('
|
|
2541
|
+
var upIcon = document.createElement('span');
|
|
2662
2542
|
upIcon.className = upClass;
|
|
2663
2543
|
upIcon.style.fontSize = '0.9rem';
|
|
2664
2544
|
upBtn.textContent = '';
|
|
@@ -2666,19 +2546,12 @@ window.openAIChatManager = function () {
|
|
|
2666
2546
|
}
|
|
2667
2547
|
if (downBtn) {
|
|
2668
2548
|
var downClass = userRating === false ? 'fa-solid fa-thumbs-down' : 'fa-regular fa-thumbs-down';
|
|
2669
|
-
var downIcon = document.createElement('
|
|
2549
|
+
var downIcon = document.createElement('span');
|
|
2670
2550
|
downIcon.className = downClass;
|
|
2671
2551
|
downIcon.style.fontSize = '0.9rem';
|
|
2672
2552
|
downBtn.textContent = '';
|
|
2673
2553
|
downBtn.appendChild(downIcon);
|
|
2674
2554
|
}
|
|
2675
|
-
|
|
2676
|
-
// Trigger Font Awesome SVG+JS to convert the new <i> elements.
|
|
2677
|
-
if (window.FontAwesome && FontAwesome.dom && FontAwesome.dom.i2svg) {
|
|
2678
|
-
FontAwesome.dom.i2svg({
|
|
2679
|
-
node: container
|
|
2680
|
-
});
|
|
2681
|
-
}
|
|
2682
2555
|
},
|
|
2683
2556
|
refreshAllFeedbackIcons: function refreshAllFeedbackIcons() {
|
|
2684
2557
|
var containers = this.$el.querySelectorAll('.ai-chat-message-assistant-feedback');
|
|
@@ -2731,12 +2604,18 @@ window.openAIChatManager = function () {
|
|
|
2731
2604
|
documents: {
|
|
2732
2605
|
handler: function handler() {
|
|
2733
2606
|
this.renderDocumentBar();
|
|
2607
|
+
if (widgetBehavior && typeof widgetBehavior.onDocumentsChanged === 'function') {
|
|
2608
|
+
widgetBehavior.onDocumentsChanged(this, this.documents, config);
|
|
2609
|
+
}
|
|
2734
2610
|
},
|
|
2735
2611
|
deep: true
|
|
2736
2612
|
},
|
|
2737
2613
|
isUploading: function isUploading() {
|
|
2738
2614
|
this.renderDocumentBar();
|
|
2739
2615
|
},
|
|
2616
|
+
isDocumentOperationPending: function isDocumentOperationPending() {
|
|
2617
|
+
this.renderDocumentBar();
|
|
2618
|
+
},
|
|
2740
2619
|
isPlayingAudio: function isPlayingAudio() {
|
|
2741
2620
|
// Reserved for future use — volume-based interrupt detection
|
|
2742
2621
|
// no longer mutes tracks; browser echo cancellation handles echo.
|
|
@@ -2762,22 +2641,27 @@ window.openAIChatManager = function () {
|
|
|
2762
2641
|
}
|
|
2763
2642
|
},
|
|
2764
2643
|
mounted: function mounted() {
|
|
2765
|
-
var
|
|
2766
|
-
_asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
2767
|
-
|
|
2768
|
-
|
|
2644
|
+
var _this22 = this;
|
|
2645
|
+
_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee0() {
|
|
2646
|
+
var isInitialized;
|
|
2647
|
+
return _regenerator().w(function (_context0) {
|
|
2648
|
+
while (1) switch (_context0.n) {
|
|
2769
2649
|
case 0:
|
|
2770
|
-
|
|
2771
|
-
return
|
|
2650
|
+
_context0.n = 1;
|
|
2651
|
+
return _this22.startConnection();
|
|
2772
2652
|
case 1:
|
|
2773
|
-
|
|
2774
|
-
if (hasWidgetConfig) {
|
|
2775
|
-
|
|
2653
|
+
isInitialized = _this22.initializeApp();
|
|
2654
|
+
if (isInitialized && hasWidgetConfig && widgetBehavior && typeof widgetBehavior.onMounted === 'function') {
|
|
2655
|
+
widgetBehavior.onMounted(_this22, config);
|
|
2776
2656
|
}
|
|
2657
|
+
_this22.$nextTick(function () {
|
|
2658
|
+
refreshFontAwesomeIcons(_this22.$el);
|
|
2659
|
+
_this22.fontAwesomeObserver = observeFontAwesomeIcons(_this22.$el);
|
|
2660
|
+
});
|
|
2777
2661
|
case 2:
|
|
2778
|
-
return
|
|
2662
|
+
return _context0.a(2);
|
|
2779
2663
|
}
|
|
2780
|
-
},
|
|
2664
|
+
}, _callee0);
|
|
2781
2665
|
}))();
|
|
2782
2666
|
window.addEventListener('beforeunload', this.handleBeforeUnload);
|
|
2783
2667
|
window.addEventListener('crestapps-ai-chat-stop-tts', this.handleExternalTtsStop);
|
|
@@ -2785,6 +2669,10 @@ window.openAIChatManager = function () {
|
|
|
2785
2669
|
beforeUnmount: function beforeUnmount() {
|
|
2786
2670
|
window.removeEventListener('beforeunload', this.handleBeforeUnload);
|
|
2787
2671
|
window.removeEventListener('crestapps-ai-chat-stop-tts', this.handleExternalTtsStop);
|
|
2672
|
+
if (this.fontAwesomeObserver) {
|
|
2673
|
+
this.fontAwesomeObserver.disconnect();
|
|
2674
|
+
this.fontAwesomeObserver = null;
|
|
2675
|
+
}
|
|
2788
2676
|
this.stopAudio(false);
|
|
2789
2677
|
if (this.stream) {
|
|
2790
2678
|
this.stream.dispose();
|
|
@@ -2793,9 +2681,16 @@ window.openAIChatManager = function () {
|
|
|
2793
2681
|
if (this.connection) {
|
|
2794
2682
|
this.connection.stop();
|
|
2795
2683
|
}
|
|
2684
|
+
if (widgetBehavior && typeof widgetBehavior.onBeforeUnmount === 'function') {
|
|
2685
|
+
widgetBehavior.onBeforeUnmount(this, config);
|
|
2686
|
+
}
|
|
2796
2687
|
},
|
|
2797
2688
|
template: config.messageTemplate
|
|
2798
|
-
}
|
|
2689
|
+
};
|
|
2690
|
+
var app = Vue.createApp(appDefinition).mount(config.appElementSelector);
|
|
2691
|
+
if (widgetBehavior && typeof widgetBehavior.attach === 'function') {
|
|
2692
|
+
widgetBehavior.attach(app, config);
|
|
2693
|
+
}
|
|
2799
2694
|
return app;
|
|
2800
2695
|
};
|
|
2801
2696
|
return {
|