@crestapps/ai-chat-ui 1.0.0-preview.14 → 1.0.0-preview.153
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai-chat-widget.js +158 -12
- package/dist/ai-chat-widget.js.map +1 -1
- package/dist/ai-chat-widget.min.js +1 -1
- package/dist/ai-chat-widget.min.js.map +1 -1
- package/dist/ai-chat.css +67 -17
- package/dist/ai-chat.css.map +1 -1
- package/dist/ai-chat.js +683 -328
- package/dist/ai-chat.js.map +1 -1
- package/dist/ai-chat.min.css +1 -1
- package/dist/ai-chat.min.js +1 -1
- package/dist/ai-chat.min.js.map +1 -1
- package/dist/chat-interaction-settings.js +297 -0
- package/dist/chat-interaction-settings.js.map +1 -0
- package/dist/chat-interaction-settings.min.js +2 -0
- package/dist/chat-interaction-settings.min.js.map +1 -0
- package/dist/chat-interaction.js +1198 -338
- package/dist/chat-interaction.js.map +1 -1
- package/dist/chat-interaction.min.js +1 -1
- package/dist/chat-interaction.min.js.map +1 -1
- package/dist/chat-widget.css +86 -35
- package/dist/chat-widget.css.map +1 -1
- package/dist/chat-widget.min.css +1 -1
- package/dist/document-drop-zone.css +10 -10
- package/dist/document-drop-zone.css.map +1 -1
- package/dist/document-drop-zone.js +92 -14
- package/dist/document-drop-zone.js.map +1 -1
- package/dist/document-drop-zone.min.css +1 -1
- package/dist/document-drop-zone.min.js +1 -1
- package/dist/document-drop-zone.min.js.map +1 -1
- package/dist/technical-name-generator.js +36 -8
- package/dist/technical-name-generator.js.map +1 -1
- package/dist/technical-name-generator.min.js +1 -1
- package/dist/technical-name-generator.min.js.map +1 -1
- package/package.json +5 -1
- package/README.md +0 -145
package/dist/ai-chat.js
CHANGED
|
@@ -3,15 +3,18 @@
|
|
|
3
3
|
** Any changes made directly to this file will be overwritten next time its asset group is processed by Gulp.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
var _excluded = ["placeholder"];
|
|
6
7
|
function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i["return"]) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
|
|
7
8
|
function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); }
|
|
8
9
|
function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
|
|
9
10
|
function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
|
|
10
|
-
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
|
|
11
11
|
function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
|
|
12
12
|
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
13
13
|
function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
|
|
14
14
|
function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }
|
|
15
|
+
function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
|
|
16
|
+
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
|
|
17
|
+
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
|
|
15
18
|
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
|
|
16
19
|
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
17
20
|
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
@@ -19,7 +22,7 @@ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length)
|
|
|
19
22
|
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
20
23
|
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
|
|
21
24
|
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
22
|
-
window.
|
|
25
|
+
window.coreAIChatManager = function () {
|
|
23
26
|
// Defaults (can be overridden by instanceConfig)
|
|
24
27
|
var defaultConfig = {
|
|
25
28
|
// UI defaults for generated media
|
|
@@ -33,7 +36,9 @@ window.openAIChatManager = function () {
|
|
|
33
36
|
thumbsUpTitle: 'Thumbs up',
|
|
34
37
|
thumbsDownTitle: 'Thumbs down',
|
|
35
38
|
copyTitle: 'Click here to copy response to clipboard.',
|
|
39
|
+
copiedTitle: 'Response copied to clipboard.',
|
|
36
40
|
codeCopiedText: 'Copied!',
|
|
41
|
+
copyResetDelayMs: 2000,
|
|
37
42
|
widget: {
|
|
38
43
|
chatWidgetContainer: null,
|
|
39
44
|
chatWidgetStateName: null,
|
|
@@ -52,8 +57,8 @@ window.openAIChatManager = function () {
|
|
|
52
57
|
minWidth: 320,
|
|
53
58
|
minHeight: 420
|
|
54
59
|
},
|
|
55
|
-
messageTemplate: "\n <div class=\"ai-chat-messages\">\n <div v-for=\"(message, index) in messages\" :key=\"'msg-' + index\" class=\"ai-chat-message-item\">\n <div>\n <div v-if=\"message.role === 'user'\" class=\"ai-chat-msg-role ai-chat-msg-role-user\">{{ userLabel }}</div>\n <div v-else-if=\"message.role !== 'indicator'\" :class=\"getAssistantRoleClasses(message)\">\n
|
|
56
|
-
indicatorTemplate: "\n <div class=\"ai-chat-msg-role ai-chat-msg-role-assistant\">\n
|
|
60
|
+
messageTemplate: "\n <div class=\"ai-chat-messages\">\n <div v-for=\"(message, index) in messages\" :key=\"'msg-' + index\" class=\"ai-chat-message-item\">\n <div>\n <div v-if=\"message.role === 'user'\" class=\"ai-chat-message-heading ai-chat-message-heading-user\">\n <span class=\"ai-chat-msg-role ai-chat-msg-role-user\">{{ userLabel }}</span>\n </div>\n <div v-else-if=\"message.role !== 'indicator'\" class=\"ai-chat-message-heading ai-chat-message-heading-assistant\">\n <div :class=\"getAssistantRoleClasses(message)\">\n <span :class=\"getAssistantIconClasses(message, index)\"><i :class=\"getAssistantIcon(message)\"></i></span>\n <span class=\"ai-chat-message-role-label\">{{ getAssistantLabel(message) }}</span>\n </div>\n </div>\n <div class=\"ai-chat-message-body lh-base\">\n <h4 v-if=\"message.title\">{{ message.title }}</h4>\n <div v-html=\"message.htmlContent\"></div>\n <ol v-if=\"message.citationReferences && message.citationReferences.length\" class=\"ai-chat-citation-list\">\n <li v-for=\"citation in message.citationReferences\" :key=\"'citation-' + (citation.referenceKey || citation.displayIndex)\" class=\"ai-chat-citation-item\">\n <a v-if=\"citation.link\" :href=\"citation.link\" :target=\"citation.isDownload ? null : '_blank'\" :rel=\"citation.isDownload ? null : 'noopener noreferrer'\">{{ citation.label }}</a>\n <span v-else>{{ citation.label }}</span>\n </li>\n </ol>\n <span class=\"message-buttons-container\" v-if=\"!isIndicator(message)\">\n <template v-if=\"metricsEnabled && message.role === 'assistant'\">\n <span class=\"ai-chat-message-assistant-feedback\" :data-message-id=\"message.id\">\n <button type=\"button\" class=\"btn btn-sm btn-link text-success p-0 me-2 button-message-toolbox rate-up-btn\" @click=\"rateMessage(message, true, $event)\" :title=\"thumbsUpTitle\">\n <i class=\"fa-regular fa-thumbs-up\"></i>\n </button>\n <button type=\"button\" class=\"btn btn-sm btn-link text-danger p-0 me-2 button-message-toolbox rate-down-btn\" @click=\"rateMessage(message, false, $event)\" :title=\"thumbsDownTitle\">\n <i class=\"fa-regular fa-thumbs-down\"></i>\n </button>\n </span>\n </template>\n <button type=\"button\" v-if=\"textToSpeechEnabled && !isConversationMode && message.role === 'assistant' && !message.isStreaming\" class=\"btn btn-sm btn-link text-secondary p-0 me-1 button-message-toolbox\" :class=\"{ 'tts-playing': ttsPlayingMessageIndex === index }\" :data-tts-message-index=\"index\" @click=\"toggleMessageTts(message, index)\" :title=\"ttsPlayingMessageIndex === index ? 'Pause audio' : 'Read aloud'\">\n <span :class=\"ttsPlayingMessageIndex === index ? 'fa-solid fa-circle-pause' : 'fa-solid fa-circle-play'\"></span>\n </button>\n <button type=\"button\" class=\"btn btn-sm btn-link p-0 button-message-toolbox ai-response-copy-btn\" :class=\"copiedMessageIndex === index ? 'text-success' : 'text-secondary'\" :data-copy-message-index=\"index\" @click=\"copyResponse(message, index, $event)\" :title=\"copiedMessageIndex === index ? copiedTitle : copyTitle\">\n <i :class=\"copiedMessageIndex === index ? 'fa-solid fa-check' : 'fa-solid fa-copy'\"></i>\n </button>\n </span>\n </div>\n </div>\n </div>\n <div v-for=\"notification in notifications\" :key=\"'notif-' + notification.type\" class=\"ai-chat-notification\" :class=\"'ai-chat-notification-' + (notification.type || 'info') + ' ' + (notification.cssClass || '')\">\n <div class=\"ai-chat-notification-content\">\n <i v-if=\"notification.icon\" :class=\"notification.icon\" class=\"ai-chat-notification-icon\"></i>\n <span class=\"ai-chat-notification-text\">{{ notification.content }}</span>\n <button type=\"button\" v-if=\"notification.dismissible\" class=\"btn btn-sm btn-link p-0 ms-2 ai-chat-notification-dismiss\" @click=\"dismissNotification(notification.type)\" title=\"Dismiss\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n <div v-if=\"notification.actions && notification.actions.length\" class=\"ai-chat-notification-actions\">\n <button type=\"button\" v-for=\"action in notification.actions\" :key=\"action.name\" class=\"btn btn-sm\" :class=\"action.cssClass || 'btn-outline-secondary'\" @click=\"handleNotificationAction(notification.type, action.name)\">\n <i v-if=\"action.icon\" :class=\"action.icon\" class=\"me-1\"></i>\n {{ action.label }}\n </button>\n </div>\n </div>\n </div>\n ",
|
|
61
|
+
indicatorTemplate: "\n <div class=\"ai-chat-message-heading ai-chat-message-heading-assistant\">\n <div class=\"ai-chat-msg-role ai-chat-msg-role-assistant\">\n <span class=\"ai-streaming-icon\"><i class=\"fa fa-robot\" style=\"display: inline-block;\"></i></span>\n <span class=\"ai-chat-message-role-label\">Assistant</span>\n </div>\n </div>\n "
|
|
57
62
|
};
|
|
58
63
|
|
|
59
64
|
// Sanitize URLs to prevent javascript: protocol injection.
|
|
@@ -72,6 +77,42 @@ window.openAIChatManager = function () {
|
|
|
72
77
|
span.textContent = text;
|
|
73
78
|
return span.innerHTML;
|
|
74
79
|
}
|
|
80
|
+
function containsFontAwesomePlaceholders(root) {
|
|
81
|
+
if (!root || root.nodeType !== 1) {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
var selector = 'i[class*="fa-"],i.fa,i.fas,i.far,i.fab';
|
|
85
|
+
if (typeof root.matches === 'function' && root.matches(selector)) {
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
return typeof root.querySelector === 'function' && !!root.querySelector(selector);
|
|
89
|
+
}
|
|
90
|
+
function refreshFontAwesomeIcons(root) {
|
|
91
|
+
var fontAwesome = window.FontAwesome;
|
|
92
|
+
if (!containsFontAwesomePlaceholders(root) || !fontAwesome || !fontAwesome.dom || typeof fontAwesome.dom.i2svg !== 'function') {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
fontAwesome.dom.i2svg({
|
|
96
|
+
node: root
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
function observeFontAwesomeIcons(root) {
|
|
100
|
+
if (!root || typeof MutationObserver === 'undefined') {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
var observer = new MutationObserver(function (mutations) {
|
|
104
|
+
mutations.forEach(function (mutation) {
|
|
105
|
+
mutation.addedNodes.forEach(function (node) {
|
|
106
|
+
refreshFontAwesomeIcons(node);
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
observer.observe(root, {
|
|
111
|
+
childList: true,
|
|
112
|
+
subtree: true
|
|
113
|
+
});
|
|
114
|
+
return observer;
|
|
115
|
+
}
|
|
75
116
|
function parsePixelValue(value) {
|
|
76
117
|
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
77
118
|
return value;
|
|
@@ -86,16 +127,31 @@ window.openAIChatManager = function () {
|
|
|
86
127
|
return Math.min(Math.max(value, min), max);
|
|
87
128
|
}
|
|
88
129
|
function normalizeReference(reference) {
|
|
89
|
-
var _ref, _normalized$index, _ref2, _normalized$text, _ref3, _normalized$link;
|
|
130
|
+
var _ref, _normalized$index, _ref2, _normalized$text, _ref3, _normalized$title, _ref4, _normalized$link, _ref5, _normalized$reference, _normalized$isGenerat;
|
|
90
131
|
if (!reference || _typeof(reference) !== 'object') {
|
|
91
132
|
return null;
|
|
92
133
|
}
|
|
93
134
|
var normalized = Object.assign({}, reference);
|
|
94
135
|
normalized.index = (_ref = (_normalized$index = normalized.index) !== null && _normalized$index !== void 0 ? _normalized$index : normalized.Index) !== null && _ref !== void 0 ? _ref : 0;
|
|
95
136
|
normalized.text = (_ref2 = (_normalized$text = normalized.text) !== null && _normalized$text !== void 0 ? _normalized$text : normalized.Text) !== null && _ref2 !== void 0 ? _ref2 : null;
|
|
96
|
-
normalized.
|
|
137
|
+
normalized.title = (_ref3 = (_normalized$title = normalized.title) !== null && _normalized$title !== void 0 ? _normalized$title : normalized.Title) !== null && _ref3 !== void 0 ? _ref3 : null;
|
|
138
|
+
normalized.link = sanitizeUrl((_ref4 = (_normalized$link = normalized.link) !== null && _normalized$link !== void 0 ? _normalized$link : normalized.Link) !== null && _ref4 !== void 0 ? _ref4 : null);
|
|
139
|
+
normalized.referenceType = (_ref5 = (_normalized$reference = normalized.referenceType) !== null && _normalized$reference !== void 0 ? _normalized$reference : normalized.ReferenceType) !== null && _ref5 !== void 0 ? _ref5 : null;
|
|
140
|
+
normalized.isGenerated = ((_normalized$isGenerat = normalized.isGenerated) !== null && _normalized$isGenerat !== void 0 ? _normalized$isGenerat : normalized.IsGenerated) === true;
|
|
97
141
|
return normalized;
|
|
98
142
|
}
|
|
143
|
+
function isDownloadCitationReference(reference) {
|
|
144
|
+
if (!reference || _typeof(reference) !== 'object') {
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
if (typeof reference.referenceType === 'string' && reference.referenceType.toLowerCase() === 'document') {
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
if (typeof reference.link === 'string' && /\/ai\/documents\/.+\/download(?:$|\?)/i.test(reference.link)) {
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
99
155
|
function normalizeReferences(references) {
|
|
100
156
|
if (!references || _typeof(references) !== 'object') {
|
|
101
157
|
return {};
|
|
@@ -110,6 +166,164 @@ window.openAIChatManager = function () {
|
|
|
110
166
|
}
|
|
111
167
|
return normalized;
|
|
112
168
|
}
|
|
169
|
+
function getCitationLabel(reference, key) {
|
|
170
|
+
return reference.title || reference.text || key;
|
|
171
|
+
}
|
|
172
|
+
function buildCitationDisplay(content, references) {
|
|
173
|
+
var processedContent = (content || '').trim();
|
|
174
|
+
var messageReferences = normalizeReferences(references);
|
|
175
|
+
var referenceEntries = Object.entries(messageReferences);
|
|
176
|
+
if (!referenceEntries.length) {
|
|
177
|
+
return {
|
|
178
|
+
content: processedContent,
|
|
179
|
+
citations: []
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
var citedRefs = referenceEntries.filter(function (_ref6) {
|
|
183
|
+
var _ref7 = _slicedToArray(_ref6, 1),
|
|
184
|
+
key = _ref7[0];
|
|
185
|
+
return processedContent.includes(key);
|
|
186
|
+
});
|
|
187
|
+
var generatedRefs = referenceEntries.filter(function (_ref8) {
|
|
188
|
+
var _ref9 = _slicedToArray(_ref8, 2),
|
|
189
|
+
key = _ref9[0],
|
|
190
|
+
value = _ref9[1];
|
|
191
|
+
return value.isGenerated && !processedContent.includes(key);
|
|
192
|
+
});
|
|
193
|
+
if (!citedRefs.length && !generatedRefs.length) {
|
|
194
|
+
return {
|
|
195
|
+
content: processedContent,
|
|
196
|
+
citations: []
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
citedRefs.sort(function (_ref0, _ref1) {
|
|
200
|
+
var _ref10 = _slicedToArray(_ref0, 2),
|
|
201
|
+
a = _ref10[1];
|
|
202
|
+
var _ref11 = _slicedToArray(_ref1, 2),
|
|
203
|
+
b = _ref11[1];
|
|
204
|
+
return a.index - b.index;
|
|
205
|
+
});
|
|
206
|
+
generatedRefs.sort(function (_ref12, _ref13) {
|
|
207
|
+
var _ref14 = _slicedToArray(_ref12, 2),
|
|
208
|
+
a = _ref14[1];
|
|
209
|
+
var _ref15 = _slicedToArray(_ref13, 2),
|
|
210
|
+
b = _ref15[1];
|
|
211
|
+
return a.index - b.index;
|
|
212
|
+
});
|
|
213
|
+
var citations = [];
|
|
214
|
+
var displayIndex = 1;
|
|
215
|
+
var _iterator = _createForOfIteratorHelper(citedRefs),
|
|
216
|
+
_step;
|
|
217
|
+
try {
|
|
218
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
219
|
+
var _step$value = _slicedToArray(_step.value, 2),
|
|
220
|
+
key = _step$value[0],
|
|
221
|
+
value = _step$value[1];
|
|
222
|
+
var placeholder = "__CITE_".concat(displayIndex, "_").concat(value.index || displayIndex, "__");
|
|
223
|
+
processedContent = processedContent.replaceAll(key, placeholder);
|
|
224
|
+
citations.push({
|
|
225
|
+
referenceKey: key,
|
|
226
|
+
displayIndex: displayIndex,
|
|
227
|
+
label: getCitationLabel(value, key),
|
|
228
|
+
link: value.link || null,
|
|
229
|
+
isDownload: isDownloadCitationReference(value),
|
|
230
|
+
placeholder: placeholder
|
|
231
|
+
});
|
|
232
|
+
displayIndex++;
|
|
233
|
+
}
|
|
234
|
+
} catch (err) {
|
|
235
|
+
_iterator.e(err);
|
|
236
|
+
} finally {
|
|
237
|
+
_iterator.f();
|
|
238
|
+
}
|
|
239
|
+
for (var _i2 = 0, _citations = citations; _i2 < _citations.length; _i2++) {
|
|
240
|
+
var citation = _citations[_i2];
|
|
241
|
+
processedContent = processedContent.replaceAll(citation.placeholder, "<sup>".concat(citation.displayIndex, "</sup>"));
|
|
242
|
+
}
|
|
243
|
+
processedContent = processedContent.replaceAll('</sup><sup>', '</sup><sup>,</sup><sup>');
|
|
244
|
+
|
|
245
|
+
// Generated files (such as exported tabular data) are always offered as a download even when
|
|
246
|
+
// the model does not cite them inline, so the user never loses access to the produced file.
|
|
247
|
+
var _iterator2 = _createForOfIteratorHelper(generatedRefs),
|
|
248
|
+
_step2;
|
|
249
|
+
try {
|
|
250
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
251
|
+
var _step2$value = _slicedToArray(_step2.value, 2),
|
|
252
|
+
_key = _step2$value[0],
|
|
253
|
+
_value = _step2$value[1];
|
|
254
|
+
citations.push({
|
|
255
|
+
referenceKey: _key,
|
|
256
|
+
displayIndex: displayIndex,
|
|
257
|
+
label: getCitationLabel(_value, _key),
|
|
258
|
+
link: _value.link || null,
|
|
259
|
+
isDownload: true,
|
|
260
|
+
placeholder: null
|
|
261
|
+
});
|
|
262
|
+
displayIndex++;
|
|
263
|
+
}
|
|
264
|
+
} catch (err) {
|
|
265
|
+
_iterator2.e(err);
|
|
266
|
+
} finally {
|
|
267
|
+
_iterator2.f();
|
|
268
|
+
}
|
|
269
|
+
return {
|
|
270
|
+
content: processedContent,
|
|
271
|
+
citations: citations.map(function (_ref16) {
|
|
272
|
+
var placeholder = _ref16.placeholder,
|
|
273
|
+
citation = _objectWithoutProperties(_ref16, _excluded);
|
|
274
|
+
return citation;
|
|
275
|
+
})
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
function buildCopyContent(content, citations) {
|
|
279
|
+
var copyContent = (content || '').trim();
|
|
280
|
+
if (!copyContent || !Array.isArray(citations) || citations.length === 0) {
|
|
281
|
+
return copyContent;
|
|
282
|
+
}
|
|
283
|
+
var _iterator3 = _createForOfIteratorHelper(citations),
|
|
284
|
+
_step3;
|
|
285
|
+
try {
|
|
286
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
287
|
+
var citation = _step3.value;
|
|
288
|
+
copyContent = copyContent.replaceAll(citation.referenceKey, "[".concat(citation.displayIndex, "]"));
|
|
289
|
+
}
|
|
290
|
+
} catch (err) {
|
|
291
|
+
_iterator3.e(err);
|
|
292
|
+
} finally {
|
|
293
|
+
_iterator3.f();
|
|
294
|
+
}
|
|
295
|
+
copyContent += '\n\nReferences:\n';
|
|
296
|
+
var _iterator4 = _createForOfIteratorHelper(citations),
|
|
297
|
+
_step4;
|
|
298
|
+
try {
|
|
299
|
+
for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
|
|
300
|
+
var _citation = _step4.value;
|
|
301
|
+
copyContent += "".concat(_citation.displayIndex, ". ").concat(_citation.label);
|
|
302
|
+
if (_citation.link) {
|
|
303
|
+
copyContent += " - ".concat(_citation.link);
|
|
304
|
+
}
|
|
305
|
+
copyContent += '\n';
|
|
306
|
+
}
|
|
307
|
+
} catch (err) {
|
|
308
|
+
_iterator4.e(err);
|
|
309
|
+
} finally {
|
|
310
|
+
_iterator4.f();
|
|
311
|
+
}
|
|
312
|
+
return copyContent.trimEnd();
|
|
313
|
+
}
|
|
314
|
+
function updateMessagePresentation(message, references) {
|
|
315
|
+
var messageReferences = normalizeReferences(references !== null && references !== void 0 ? references : message.references);
|
|
316
|
+
var rawContent = typeof message.rawContent === 'string' ? message.rawContent : typeof message.content === 'string' ? message.content : '';
|
|
317
|
+
var citationDisplay = buildCitationDisplay(rawContent, messageReferences);
|
|
318
|
+
message.rawContent = rawContent;
|
|
319
|
+
message.content = rawContent;
|
|
320
|
+
message.displayContent = citationDisplay.content;
|
|
321
|
+
message.references = messageReferences;
|
|
322
|
+
message.citationReferences = citationDisplay.citations;
|
|
323
|
+
message.copyContent = buildCopyContent(rawContent, citationDisplay.citations);
|
|
324
|
+
message.htmlContent = parseMarkdownContent(citationDisplay.content, message);
|
|
325
|
+
return message;
|
|
326
|
+
}
|
|
113
327
|
var renderer = new marked.Renderer();
|
|
114
328
|
|
|
115
329
|
// Modify the link rendering to open in a new tab
|
|
@@ -140,7 +354,7 @@ window.openAIChatManager = function () {
|
|
|
140
354
|
highlighted = escapeHtmlEntities(code);
|
|
141
355
|
}
|
|
142
356
|
var langDisplay = lang ? escapeHtmlEntities(lang) : 'code';
|
|
143
|
-
return "<div class=\"ai-code-block\"><div class=\"ai-code-header\"><span class=\"ai-code-lang\"><
|
|
357
|
+
return "<div class=\"ai-code-block\"><div class=\"ai-code-header\"><span class=\"ai-code-lang\"><i class=\"fa-solid fa-code\"></i> ".concat(langDisplay, "</span><button type=\"button\" class=\"ai-code-copy-btn\" title=\"Copy code\"><i class=\"fa-regular fa-copy\"></i></button></div><pre><code class=\"hljs").concat(lang ? ' language-' + lang : '', "\">").concat(highlighted, "</code></pre></div>");
|
|
144
358
|
};
|
|
145
359
|
|
|
146
360
|
// Custom image renderer for generated images with thumbnail styling and download button.
|
|
@@ -150,7 +364,7 @@ window.openAIChatManager = function () {
|
|
|
150
364
|
if (!src) return '';
|
|
151
365
|
var alt = data.text || defaultConfig.generatedImageAltText;
|
|
152
366
|
var maxWidth = defaultConfig.generatedImageMaxWidth;
|
|
153
|
-
return "<div class=\"generated-image-container\">\n <img src=\"".concat(src, "\" alt=\"").concat(alt, "\" class=\"img-thumbnail\" style=\"max-width: ").concat(maxWidth, "px; height: auto;\" />\n <div class=\"mt-2\">\n <a href=\"").concat(src, "\" target=\"_blank\" download=\"").concat(alt, "\" title=\"").concat(defaultConfig.downloadImageTitle, "\" class=\"btn btn-sm btn-outline-secondary ai-download-image\">\n <
|
|
367
|
+
return "<div class=\"generated-image-container\">\n <img src=\"".concat(src, "\" alt=\"").concat(alt, "\" class=\"img-thumbnail\" style=\"max-width: ").concat(maxWidth, "px; height: auto;\" />\n <div class=\"mt-2\">\n <a href=\"").concat(src, "\" target=\"_blank\" download=\"").concat(alt, "\" title=\"").concat(defaultConfig.downloadImageTitle, "\" class=\"btn btn-sm btn-outline-secondary ai-download-image\">\n <i class=\"fa-solid fa-download\"></i>\n </a>\n </div>\n </div>");
|
|
154
368
|
};
|
|
155
369
|
|
|
156
370
|
// Chart counter for unique IDs
|
|
@@ -164,7 +378,7 @@ window.openAIChatManager = function () {
|
|
|
164
378
|
// its DOM update to render charts it didn't create itself.
|
|
165
379
|
window.__chartConfigs = window.__chartConfigs || {};
|
|
166
380
|
function createChartHtml(chartId) {
|
|
167
|
-
return "<div class=\"chart-container\" style=\"position: relative; width: 100%; max-width: 560px; min-height: 420px;\">" + "<canvas id=\"".concat(chartId, "\"></canvas>") + "</div>" + "<div class=\"mt-2\">" + "<button type=\"button\" class=\"btn btn-sm btn-outline-secondary download-chart-btn\" data-chart-id=\"".concat(chartId, "\" title=\"").concat(defaultConfig.downloadChartTitle, "\">") + "<
|
|
381
|
+
return "<div class=\"chart-container\" style=\"position: relative; width: 100%; max-width: 560px; min-height: 420px;\">" + "<canvas id=\"".concat(chartId, "\"></canvas>") + "</div>" + "<div class=\"mt-2\">" + "<button type=\"button\" class=\"btn btn-sm btn-outline-secondary download-chart-btn\" data-chart-id=\"".concat(chartId, "\" title=\"").concat(defaultConfig.downloadChartTitle, "\">") + "<i class=\"fa-solid fa-download\"></i> ".concat(defaultConfig.downloadChartButtonText) + "</button>" + "</div>";
|
|
168
382
|
}
|
|
169
383
|
|
|
170
384
|
// Register [chart:{...json...}] as a native marked block extension so the
|
|
@@ -275,17 +489,17 @@ window.openAIChatManager = function () {
|
|
|
275
489
|
// Defer to requestAnimationFrame so the browser has fully laid out the
|
|
276
490
|
// canvas elements before Chart.js reads their dimensions.
|
|
277
491
|
requestAnimationFrame(function () {
|
|
278
|
-
var
|
|
279
|
-
|
|
492
|
+
var _iterator5 = _createForOfIteratorHelper(charts),
|
|
493
|
+
_step5;
|
|
280
494
|
try {
|
|
281
|
-
for (
|
|
282
|
-
var c =
|
|
495
|
+
for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
|
|
496
|
+
var c = _step5.value;
|
|
283
497
|
renderChartOnCanvas(c.chartId, c.config);
|
|
284
498
|
}
|
|
285
499
|
} catch (err) {
|
|
286
|
-
|
|
500
|
+
_iterator5.e(err);
|
|
287
501
|
} finally {
|
|
288
|
-
|
|
502
|
+
_iterator5.f();
|
|
289
503
|
}
|
|
290
504
|
});
|
|
291
505
|
}
|
|
@@ -338,8 +552,8 @@ window.openAIChatManager = function () {
|
|
|
338
552
|
return;
|
|
339
553
|
}
|
|
340
554
|
requestAnimationFrame(function () {
|
|
341
|
-
for (var
|
|
342
|
-
var chartId = _Object$keys[
|
|
555
|
+
for (var _i3 = 0, _Object$keys = Object.keys(configs); _i3 < _Object$keys.length; _i3++) {
|
|
556
|
+
var chartId = _Object$keys[_i3];
|
|
343
557
|
renderChartOnCanvas(chartId, configs[chartId]);
|
|
344
558
|
}
|
|
345
559
|
});
|
|
@@ -359,11 +573,31 @@ window.openAIChatManager = function () {
|
|
|
359
573
|
ADD_ATTR: ['target']
|
|
360
574
|
});
|
|
361
575
|
}
|
|
576
|
+
function compactObject(source) {
|
|
577
|
+
if (!source || _typeof(source) !== 'object') {
|
|
578
|
+
return {};
|
|
579
|
+
}
|
|
580
|
+
return Object.fromEntries(Object.entries(source).filter(function (_ref17) {
|
|
581
|
+
var _ref18 = _slicedToArray(_ref17, 2),
|
|
582
|
+
value = _ref18[1];
|
|
583
|
+
return value !== undefined;
|
|
584
|
+
}));
|
|
585
|
+
}
|
|
586
|
+
function resolveIndicatorTemplate(template, assistantLabel) {
|
|
587
|
+
if (!template) {
|
|
588
|
+
return template;
|
|
589
|
+
}
|
|
590
|
+
var encodedAssistantLabel = escapeHtmlEntities(assistantLabel || 'Assistant');
|
|
591
|
+
return template.replace(/\{\{\s*assistantLabel\s*\}\}/g, encodedAssistantLabel);
|
|
592
|
+
}
|
|
362
593
|
var initialize = function initialize(instanceConfig) {
|
|
363
|
-
var
|
|
364
|
-
|
|
365
|
-
var
|
|
366
|
-
|
|
594
|
+
var normalizedInstanceConfig = compactObject(instanceConfig);
|
|
595
|
+
var normalizedWidgetConfig = compactObject(normalizedInstanceConfig.widget);
|
|
596
|
+
var config = Object.assign({}, defaultConfig, normalizedInstanceConfig);
|
|
597
|
+
config.widget = Object.assign({}, defaultConfig.widget || {}, normalizedWidgetConfig);
|
|
598
|
+
config.indicatorTemplate = resolveIndicatorTemplate(config.indicatorTemplate, config.assistantLabel);
|
|
599
|
+
var hasWidgetConfig = !!(normalizedWidgetConfig.chatWidgetContainer && normalizedWidgetConfig.chatWidgetStateName);
|
|
600
|
+
var widgetBehavior = window.coreAIChatWidgetBehavior || null;
|
|
367
601
|
// Keep defaultConfig in sync so renderers use overridden values
|
|
368
602
|
defaultConfig = config;
|
|
369
603
|
if (!config.signalRHubUrl) {
|
|
@@ -415,6 +649,7 @@ window.openAIChatManager = function () {
|
|
|
415
649
|
thumbsUpTitle: config.thumbsUpTitle,
|
|
416
650
|
thumbsDownTitle: config.thumbsDownTitle,
|
|
417
651
|
copyTitle: config.copyTitle,
|
|
652
|
+
copiedTitle: config.copiedTitle,
|
|
418
653
|
isRecording: false,
|
|
419
654
|
mediaRecorder: null,
|
|
420
655
|
preRecordingPrompt: '',
|
|
@@ -439,7 +674,10 @@ window.openAIChatManager = function () {
|
|
|
439
674
|
pendingSessionPromise: null,
|
|
440
675
|
pendingSessionResolver: null,
|
|
441
676
|
pendingSessionRejector: null,
|
|
442
|
-
pendingSessionTimeoutId: null
|
|
677
|
+
pendingSessionTimeoutId: null,
|
|
678
|
+
copiedMessageIndex: -1,
|
|
679
|
+
copyResetTimeoutId: null,
|
|
680
|
+
activeCopyButton: null
|
|
443
681
|
};
|
|
444
682
|
},
|
|
445
683
|
computed: {
|
|
@@ -767,7 +1005,7 @@ window.openAIChatManager = function () {
|
|
|
767
1005
|
var name = doc.fileName || 'Document';
|
|
768
1006
|
if (name.length > 20) name = name.substring(0, 17) + '...';
|
|
769
1007
|
html += '<span class="badge bg-secondary bg-opacity-25 text-dark d-inline-flex align-items-center gap-1 px-2 py-1" style="font-size: 0.8rem;" title="' + this.escapeHtml(doc.fileName || '') + '">';
|
|
770
|
-
html += '<
|
|
1008
|
+
html += '<i class="fa-solid fa-file-lines" style="font-size: 0.7rem;"></i> ';
|
|
771
1009
|
html += this.escapeHtml(name);
|
|
772
1010
|
html += ' <button type="button" class="btn-close btn-close-sm ms-1" style="font-size: 0.5rem;" data-doc-index="' + i + '" aria-label="Remove"' + (this.isDocumentOperationPending ? ' disabled' : '') + '></button>';
|
|
773
1011
|
html += '</span>';
|
|
@@ -778,7 +1016,7 @@ window.openAIChatManager = function () {
|
|
|
778
1016
|
var errorMsg = failedItem.error || 'Upload failed';
|
|
779
1017
|
if (failedName.length > 15) failedName = failedName.substring(0, 12) + '...';
|
|
780
1018
|
html += '<span class="badge bg-danger bg-opacity-25 text-danger d-inline-flex align-items-center gap-1 px-2 py-1" style="font-size: 0.8rem;" title="' + this.escapeHtml((failedItem.fileName || '') + ': ' + errorMsg) + '">';
|
|
781
|
-
html += '<
|
|
1019
|
+
html += '<i class="fa-solid fa-circle-exclamation" style="font-size: 0.7rem;"></i> ';
|
|
782
1020
|
html += this.escapeHtml(failedName);
|
|
783
1021
|
html += ' <button type="button" class="btn-close btn-close-sm ms-1" style="font-size: 0.5rem;" data-error-index="' + m + '" aria-label="Dismiss"></button>';
|
|
784
1022
|
html += '</span>';
|
|
@@ -789,7 +1027,7 @@ window.openAIChatManager = function () {
|
|
|
789
1027
|
html += '</span>';
|
|
790
1028
|
}
|
|
791
1029
|
html += '<button type="button" class="btn btn-sm btn-outline-secondary rounded-pill ai-chat-doc-add-btn d-inline-flex align-items-center gap-1" style="font-size: 0.75rem; padding: 0.15rem 0.5rem;" title="Attach documents"' + (this.isDocumentOperationPending ? ' disabled' : '') + '>';
|
|
792
|
-
html += '<
|
|
1030
|
+
html += '<i class="fa-solid fa-paperclip"></i>';
|
|
793
1031
|
if (this.documents.length === 0 && !this.isUploading) {
|
|
794
1032
|
html += ' <span>Attach files</span>';
|
|
795
1033
|
}
|
|
@@ -948,10 +1186,12 @@ window.openAIChatManager = function () {
|
|
|
948
1186
|
});
|
|
949
1187
|
|
|
950
1188
|
// When the session is new (no messages) and an initial prompt is configured,
|
|
951
|
-
//
|
|
1189
|
+
// display it as the first assistant message without invoking the AI.
|
|
952
1190
|
if (_this3.messages.length === 0 && config.initialPrompt) {
|
|
953
|
-
_this3.
|
|
954
|
-
|
|
1191
|
+
_this3.addMessage({
|
|
1192
|
+
role: 'assistant',
|
|
1193
|
+
content: config.initialPrompt
|
|
1194
|
+
});
|
|
955
1195
|
}
|
|
956
1196
|
});
|
|
957
1197
|
_this3.connection.on("ReceiveError", function (error) {
|
|
@@ -959,8 +1199,29 @@ window.openAIChatManager = function () {
|
|
|
959
1199
|
if (_this3.isRecording) {
|
|
960
1200
|
_this3.stopRecording();
|
|
961
1201
|
}
|
|
1202
|
+
|
|
1203
|
+
// A server-side error (for example a session-start rate-limit rejection) ends the
|
|
1204
|
+
// in-flight request. Reject any pending new-session promise so the UI stops waiting
|
|
1205
|
+
// until it times out, and clear the typing indicator that a send may have shown.
|
|
1206
|
+
_this3.rejectPendingSessionRequest(error);
|
|
1207
|
+
_this3.hideTypingIndicator();
|
|
962
1208
|
if (widgetBehavior && typeof widgetBehavior.handleReceiveError === 'function') {
|
|
963
1209
|
widgetBehavior.handleReceiveError(_this3, error, config);
|
|
1210
|
+
} else if (!_this3.isNavigatingAway) {
|
|
1211
|
+
// Surface the message to the user instead of failing silently.
|
|
1212
|
+
_this3.addMessage(_this3.getErrorMessage(error));
|
|
1213
|
+
}
|
|
1214
|
+
});
|
|
1215
|
+
_this3.connection.on("ReceiveSessionStartRejected", function (reason) {
|
|
1216
|
+
// A rate-limit rejection is a definitive "wait and retry", not a recoverable
|
|
1217
|
+
// session/connection error. Unblock any pending new-session request, clear the
|
|
1218
|
+
// typing indicator, and show the message for every host (main app and widget)
|
|
1219
|
+
// without triggering the widget's clear-and-retry recovery, which would wipe the
|
|
1220
|
+
// visitor's state and fire another throttled StartSession.
|
|
1221
|
+
_this3.rejectPendingSessionRequest(reason);
|
|
1222
|
+
_this3.hideTypingIndicator();
|
|
1223
|
+
if (!_this3.isNavigatingAway) {
|
|
1224
|
+
_this3.addMessage(_this3.getErrorMessage(reason));
|
|
964
1225
|
}
|
|
965
1226
|
});
|
|
966
1227
|
_this3.connection.on("MessageRated", function (messageId, userRating) {
|
|
@@ -1034,7 +1295,7 @@ window.openAIChatManager = function () {
|
|
|
1034
1295
|
_this3.scrollToBottom();
|
|
1035
1296
|
}
|
|
1036
1297
|
});
|
|
1037
|
-
_this3.connection.on("ReceiveConversationAssistantToken", function (sessionId, messageId, token, responseId, appearance) {
|
|
1298
|
+
_this3.connection.on("ReceiveConversationAssistantToken", function (sessionId, messageId, token, responseId, references, appearance) {
|
|
1038
1299
|
if (!_this3._conversationAssistantMessage) {
|
|
1039
1300
|
_this3.stopAudio();
|
|
1040
1301
|
_this3.hideTypingIndicator();
|
|
@@ -1053,7 +1314,8 @@ window.openAIChatManager = function () {
|
|
|
1053
1314
|
htmlContent: "",
|
|
1054
1315
|
isStreaming: true,
|
|
1055
1316
|
userRating: null,
|
|
1056
|
-
appearance: _this3.normalizeAssistantAppearance(appearance)
|
|
1317
|
+
appearance: _this3.normalizeAssistantAppearance(appearance),
|
|
1318
|
+
references: {}
|
|
1057
1319
|
};
|
|
1058
1320
|
_this3.messages.push(newMessage);
|
|
1059
1321
|
_this3._conversationAssistantMessage = {
|
|
@@ -1067,19 +1329,22 @@ window.openAIChatManager = function () {
|
|
|
1067
1329
|
if (!msg.appearance) {
|
|
1068
1330
|
msg.appearance = _this3.normalizeAssistantAppearance(appearance);
|
|
1069
1331
|
}
|
|
1070
|
-
msg.
|
|
1071
|
-
msg.
|
|
1332
|
+
msg.rawContent = _this3._conversationAssistantMessage.content;
|
|
1333
|
+
msg.references = normalizeReferences(Object.assign({}, msg.references || {}, references || {}));
|
|
1334
|
+
updateMessagePresentation(msg, msg.references);
|
|
1072
1335
|
_this3.$nextTick(function () {
|
|
1073
1336
|
renderChartsInMessage(msg);
|
|
1074
1337
|
_this3.scrollToBottom();
|
|
1075
1338
|
});
|
|
1076
1339
|
}
|
|
1077
1340
|
});
|
|
1078
|
-
_this3.connection.on("ReceiveConversationAssistantComplete", function (sessionId, messageId) {
|
|
1341
|
+
_this3.connection.on("ReceiveConversationAssistantComplete", function (sessionId, messageId, references) {
|
|
1079
1342
|
if (_this3._conversationAssistantMessage) {
|
|
1080
1343
|
var msg = _this3.messages[_this3._conversationAssistantMessage.index];
|
|
1081
1344
|
if (msg) {
|
|
1082
1345
|
msg.isStreaming = false;
|
|
1346
|
+
msg.references = normalizeReferences(Object.assign({}, msg.references || {}, references || {}));
|
|
1347
|
+
updateMessagePresentation(msg, msg.references);
|
|
1083
1348
|
}
|
|
1084
1349
|
_this3._conversationAssistantMessage = null;
|
|
1085
1350
|
}
|
|
@@ -1113,8 +1378,6 @@ window.openAIChatManager = function () {
|
|
|
1113
1378
|
console.info("SignalR: reconnected.");
|
|
1114
1379
|
if (_this3.isSessionStarted) {
|
|
1115
1380
|
_this3.reloadCurrentSession();
|
|
1116
|
-
} else if (config.autoCreateSession) {
|
|
1117
|
-
_this3.startNewSession();
|
|
1118
1381
|
}
|
|
1119
1382
|
});
|
|
1120
1383
|
_this3.connection.onclose(function (error) {
|
|
@@ -1149,14 +1412,14 @@ window.openAIChatManager = function () {
|
|
|
1149
1412
|
if (message.content && !message.htmlContent) {
|
|
1150
1413
|
message.htmlContent = parseMarkdownContent(message.content, message);
|
|
1151
1414
|
}
|
|
1152
|
-
this.fireEvent(new CustomEvent("
|
|
1415
|
+
this.fireEvent(new CustomEvent("addingCoreAIPromotMessage", {
|
|
1153
1416
|
detail: {
|
|
1154
1417
|
message: message
|
|
1155
1418
|
}
|
|
1156
1419
|
}));
|
|
1157
1420
|
this.messages.push(message);
|
|
1158
1421
|
this.$nextTick(function () {
|
|
1159
|
-
_this4.fireEvent(new CustomEvent("
|
|
1422
|
+
_this4.fireEvent(new CustomEvent("addedCoreAIPromotMessage", {
|
|
1160
1423
|
detail: {
|
|
1161
1424
|
message: message
|
|
1162
1425
|
}
|
|
@@ -1170,82 +1433,9 @@ window.openAIChatManager = function () {
|
|
|
1170
1433
|
message.userRating = null;
|
|
1171
1434
|
}
|
|
1172
1435
|
if (message.content) {
|
|
1173
|
-
var
|
|
1174
|
-
message.
|
|
1175
|
-
|
|
1176
|
-
// Only include references that were actually cited in the response.
|
|
1177
|
-
var citedRefs = Object.entries(message.references).filter(function (_ref7) {
|
|
1178
|
-
var _ref8 = _slicedToArray(_ref7, 1),
|
|
1179
|
-
key = _ref8[0];
|
|
1180
|
-
return processedContent.includes(key);
|
|
1181
|
-
});
|
|
1182
|
-
if (citedRefs.length) {
|
|
1183
|
-
// Sort by original index so display indices follow a natural order.
|
|
1184
|
-
citedRefs.sort(function (_ref9, _ref0) {
|
|
1185
|
-
var _ref1 = _slicedToArray(_ref9, 2),
|
|
1186
|
-
a = _ref1[1];
|
|
1187
|
-
var _ref10 = _slicedToArray(_ref0, 2),
|
|
1188
|
-
b = _ref10[1];
|
|
1189
|
-
return a.index - b.index;
|
|
1190
|
-
});
|
|
1191
|
-
|
|
1192
|
-
// Phase 1: Replace all markers with unique placeholders.
|
|
1193
|
-
var displayIndex = 1;
|
|
1194
|
-
var _iterator2 = _createForOfIteratorHelper(citedRefs),
|
|
1195
|
-
_step2;
|
|
1196
|
-
try {
|
|
1197
|
-
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
1198
|
-
var _step2$value = _slicedToArray(_step2.value, 2),
|
|
1199
|
-
key = _step2$value[0],
|
|
1200
|
-
value = _step2$value[1];
|
|
1201
|
-
var placeholder = "__CITE_".concat(value.index, "__");
|
|
1202
|
-
processedContent = processedContent.replaceAll(key, placeholder);
|
|
1203
|
-
value._displayIndex = displayIndex++;
|
|
1204
|
-
value._placeholder = placeholder;
|
|
1205
|
-
}
|
|
1206
|
-
|
|
1207
|
-
// Phase 2: Replace placeholders with sequential display indices.
|
|
1208
|
-
} catch (err) {
|
|
1209
|
-
_iterator2.e(err);
|
|
1210
|
-
} finally {
|
|
1211
|
-
_iterator2.f();
|
|
1212
|
-
}
|
|
1213
|
-
var _iterator3 = _createForOfIteratorHelper(citedRefs),
|
|
1214
|
-
_step3;
|
|
1215
|
-
try {
|
|
1216
|
-
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
1217
|
-
var _step3$value = _slicedToArray(_step3.value, 2),
|
|
1218
|
-
_value = _step3$value[1];
|
|
1219
|
-
processedContent = processedContent.replaceAll(_value._placeholder, "<sup><strong>".concat(_value._displayIndex, "</strong></sup>"));
|
|
1220
|
-
}
|
|
1221
|
-
|
|
1222
|
-
// if we have multiple references, add a comma to ensure we don't concatenate numbers.
|
|
1223
|
-
} catch (err) {
|
|
1224
|
-
_iterator3.e(err);
|
|
1225
|
-
} finally {
|
|
1226
|
-
_iterator3.f();
|
|
1227
|
-
}
|
|
1228
|
-
processedContent = processedContent.replaceAll('</strong></sup><sup>', '</strong></sup><sup>,</sup><sup>');
|
|
1229
|
-
processedContent += '<br><br>';
|
|
1230
|
-
var _iterator4 = _createForOfIteratorHelper(citedRefs),
|
|
1231
|
-
_step4;
|
|
1232
|
-
try {
|
|
1233
|
-
for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
|
|
1234
|
-
var _step4$value = _slicedToArray(_step4.value, 2),
|
|
1235
|
-
_key = _step4$value[0],
|
|
1236
|
-
_value2 = _step4$value[1];
|
|
1237
|
-
var label = _value2.text || _key;
|
|
1238
|
-
processedContent += _value2.link ? "**".concat(_value2._displayIndex, "**. [").concat(label, "](").concat(_value2.link, ")<br>") : "**".concat(_value2._displayIndex, "**. ").concat(label, "<br>");
|
|
1239
|
-
}
|
|
1240
|
-
} catch (err) {
|
|
1241
|
-
_iterator4.e(err);
|
|
1242
|
-
} finally {
|
|
1243
|
-
_iterator4.f();
|
|
1244
|
-
}
|
|
1245
|
-
}
|
|
1246
|
-
}
|
|
1247
|
-
message.content = processedContent;
|
|
1248
|
-
message.htmlContent = parseMarkdownContent(processedContent, message);
|
|
1436
|
+
var _message$rawContent;
|
|
1437
|
+
message.rawContent = (_message$rawContent = message.rawContent) !== null && _message$rawContent !== void 0 ? _message$rawContent : message.content;
|
|
1438
|
+
updateMessagePresentation(message, message.references);
|
|
1249
1439
|
}
|
|
1250
1440
|
this.addMessageInternal(message);
|
|
1251
1441
|
this.hidePlaceholder();
|
|
@@ -1423,10 +1613,10 @@ window.openAIChatManager = function () {
|
|
|
1423
1613
|
}
|
|
1424
1614
|
if (this.isRecording) {
|
|
1425
1615
|
this.micButton.classList.add('stt-recording');
|
|
1426
|
-
this.micButton.innerHTML = '<
|
|
1616
|
+
this.micButton.innerHTML = '<i class="fa-solid fa-stop"></i>';
|
|
1427
1617
|
} else {
|
|
1428
1618
|
this.micButton.classList.remove('stt-recording');
|
|
1429
|
-
this.micButton.innerHTML = '<
|
|
1619
|
+
this.micButton.innerHTML = '<i class="fa-solid fa-microphone"></i>';
|
|
1430
1620
|
}
|
|
1431
1621
|
},
|
|
1432
1622
|
streamMessage: function streamMessage(profileId, trimmedPrompt, sessionProfileId) {
|
|
@@ -1471,9 +1661,9 @@ window.openAIChatManager = function () {
|
|
|
1471
1661
|
message.title = chunk.title;
|
|
1472
1662
|
}
|
|
1473
1663
|
if (chunk.references && _typeof(chunk.references) === "object" && Object.keys(chunk.references).length) {
|
|
1474
|
-
for (var
|
|
1664
|
+
for (var _i4 = 0, _Object$entries2 = Object.entries(chunk.references); _i4 < _Object$entries2.length; _i4++) {
|
|
1475
1665
|
var _normalizeReference2;
|
|
1476
|
-
var _Object$entries2$_i = _slicedToArray(_Object$entries2[
|
|
1666
|
+
var _Object$entries2$_i = _slicedToArray(_Object$entries2[_i4], 2),
|
|
1477
1667
|
key = _Object$entries2$_i[0],
|
|
1478
1668
|
value = _Object$entries2$_i[1];
|
|
1479
1669
|
references[key] = (_normalizeReference2 = normalizeReference(value)) !== null && _normalizeReference2 !== void 0 ? _normalizeReference2 : {};
|
|
@@ -1488,22 +1678,12 @@ window.openAIChatManager = function () {
|
|
|
1488
1678
|
if (chunk.responseId) {
|
|
1489
1679
|
lastResponseId = chunk.responseId;
|
|
1490
1680
|
}
|
|
1491
|
-
|
|
1492
|
-
for (var _i4 = 0, _Object$entries3 = Object.entries(references); _i4 < _Object$entries3.length; _i4++) {
|
|
1493
|
-
var _Object$entries3$_i = _slicedToArray(_Object$entries3[_i4], 2),
|
|
1494
|
-
_key2 = _Object$entries3$_i[0],
|
|
1495
|
-
_value3 = _Object$entries3$_i[1];
|
|
1496
|
-
processedContent = processedContent.replaceAll(_key2, "<sup><strong>".concat(_value3.index, "</strong></sup>"));
|
|
1497
|
-
}
|
|
1498
|
-
|
|
1499
|
-
// Append processed content to the message.
|
|
1500
|
-
// if we have multiple references, add a comma to ensure we don't concatenate numbers.
|
|
1501
|
-
content += processedContent.replaceAll('</strong></sup><sup>', '</strong></sup><sup>,</sup><sup>');
|
|
1681
|
+
content += chunk.content;
|
|
1502
1682
|
}
|
|
1503
1683
|
|
|
1504
1684
|
// Update the existing message
|
|
1505
|
-
message.
|
|
1506
|
-
message
|
|
1685
|
+
message.rawContent = content;
|
|
1686
|
+
updateMessagePresentation(message, references);
|
|
1507
1687
|
_this8.messages[messageIndex] = message;
|
|
1508
1688
|
_this8.$nextTick(function () {
|
|
1509
1689
|
renderChartsInMessage(message);
|
|
@@ -1556,89 +1736,22 @@ window.openAIChatManager = function () {
|
|
|
1556
1736
|
};
|
|
1557
1737
|
return newMessage;
|
|
1558
1738
|
},
|
|
1739
|
+
getErrorMessage: function getErrorMessage(error) {
|
|
1740
|
+
var content = typeof error === 'string' && error.trim() ? error : "Something went wrong. Please try again.";
|
|
1741
|
+
return {
|
|
1742
|
+
role: "assistant",
|
|
1743
|
+
content: content,
|
|
1744
|
+
htmlContent: ""
|
|
1745
|
+
};
|
|
1746
|
+
},
|
|
1559
1747
|
processReferences: function processReferences(references, messageIndex) {
|
|
1560
1748
|
var _this9 = this;
|
|
1561
1749
|
references = normalizeReferences(references);
|
|
1562
1750
|
if (Object.keys(references).length) {
|
|
1751
|
+
var _ref23, _message$rawContent2;
|
|
1563
1752
|
var message = this.messages[messageIndex];
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
// Only include references that were actually cited in the response.
|
|
1567
|
-
// Check both raw [doc:N] markers and already-rendered <sup> tags from streaming.
|
|
1568
|
-
var citedRefs = Object.entries(references).filter(function (_ref12) {
|
|
1569
|
-
var _ref13 = _slicedToArray(_ref12, 2),
|
|
1570
|
-
key = _ref13[0],
|
|
1571
|
-
value = _ref13[1];
|
|
1572
|
-
return content.includes(key) || content.includes("<sup><strong>".concat(value.index, "</strong></sup>"));
|
|
1573
|
-
});
|
|
1574
|
-
if (!citedRefs.length) {
|
|
1575
|
-
return;
|
|
1576
|
-
}
|
|
1577
|
-
|
|
1578
|
-
// Sort by original index so display indices follow a natural order.
|
|
1579
|
-
citedRefs.sort(function (_ref14, _ref15) {
|
|
1580
|
-
var _ref16 = _slicedToArray(_ref14, 2),
|
|
1581
|
-
a = _ref16[1];
|
|
1582
|
-
var _ref17 = _slicedToArray(_ref15, 2),
|
|
1583
|
-
b = _ref17[1];
|
|
1584
|
-
return a.index - b.index;
|
|
1585
|
-
});
|
|
1586
|
-
|
|
1587
|
-
// Phase 1: Replace all markers with unique placeholders to avoid collisions during remapping.
|
|
1588
|
-
var processed = content.trim();
|
|
1589
|
-
var displayIndex = 1;
|
|
1590
|
-
var _iterator5 = _createForOfIteratorHelper(citedRefs),
|
|
1591
|
-
_step5;
|
|
1592
|
-
try {
|
|
1593
|
-
for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
|
|
1594
|
-
var _step5$value = _slicedToArray(_step5.value, 2),
|
|
1595
|
-
key = _step5$value[0],
|
|
1596
|
-
value = _step5$value[1];
|
|
1597
|
-
var placeholder = "__CITE_".concat(value.index, "__");
|
|
1598
|
-
processed = processed.replaceAll(key, placeholder);
|
|
1599
|
-
processed = processed.replaceAll("<sup><strong>".concat(value.index, "</strong></sup>"), placeholder);
|
|
1600
|
-
value._displayIndex = displayIndex++;
|
|
1601
|
-
value._placeholder = placeholder;
|
|
1602
|
-
}
|
|
1603
|
-
|
|
1604
|
-
// Phase 2: Replace placeholders with sequential display indices.
|
|
1605
|
-
} catch (err) {
|
|
1606
|
-
_iterator5.e(err);
|
|
1607
|
-
} finally {
|
|
1608
|
-
_iterator5.f();
|
|
1609
|
-
}
|
|
1610
|
-
var _iterator6 = _createForOfIteratorHelper(citedRefs),
|
|
1611
|
-
_step6;
|
|
1612
|
-
try {
|
|
1613
|
-
for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
|
|
1614
|
-
var _step6$value = _slicedToArray(_step6.value, 2),
|
|
1615
|
-
_value4 = _step6$value[1];
|
|
1616
|
-
processed = processed.replaceAll(_value4._placeholder, "<sup><strong>".concat(_value4._displayIndex, "</strong></sup>"));
|
|
1617
|
-
}
|
|
1618
|
-
} catch (err) {
|
|
1619
|
-
_iterator6.e(err);
|
|
1620
|
-
} finally {
|
|
1621
|
-
_iterator6.f();
|
|
1622
|
-
}
|
|
1623
|
-
processed = processed.replaceAll('</strong></sup><sup>', '</strong></sup><sup>,</sup><sup>');
|
|
1624
|
-
processed += '<br><br>';
|
|
1625
|
-
var _iterator7 = _createForOfIteratorHelper(citedRefs),
|
|
1626
|
-
_step7;
|
|
1627
|
-
try {
|
|
1628
|
-
for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
|
|
1629
|
-
var _step7$value = _slicedToArray(_step7.value, 2),
|
|
1630
|
-
_key3 = _step7$value[0],
|
|
1631
|
-
_value5 = _step7$value[1];
|
|
1632
|
-
var label = _value5.text || _key3;
|
|
1633
|
-
processed += _value5.link ? "**".concat(_value5._displayIndex, "**. [").concat(label, "](").concat(_value5.link, ")<br>") : "**".concat(_value5._displayIndex, "**. ").concat(label, "<br>");
|
|
1634
|
-
}
|
|
1635
|
-
} catch (err) {
|
|
1636
|
-
_iterator7.e(err);
|
|
1637
|
-
} finally {
|
|
1638
|
-
_iterator7.f();
|
|
1639
|
-
}
|
|
1640
|
-
message.content = processed;
|
|
1641
|
-
message.htmlContent = parseMarkdownContent(processed, message);
|
|
1753
|
+
message.rawContent = (_ref23 = (_message$rawContent2 = message.rawContent) !== null && _message$rawContent2 !== void 0 ? _message$rawContent2 : message.content) !== null && _ref23 !== void 0 ? _ref23 : '';
|
|
1754
|
+
updateMessagePresentation(message, references);
|
|
1642
1755
|
this.messages[messageIndex] = message;
|
|
1643
1756
|
this.$nextTick(function () {
|
|
1644
1757
|
renderChartsInMessage(message);
|
|
@@ -1701,16 +1814,42 @@ window.openAIChatManager = function () {
|
|
|
1701
1814
|
buttons.forEach(function (button) {
|
|
1702
1815
|
var buttonIndex = Number(button.getAttribute('data-tts-message-index'));
|
|
1703
1816
|
var isPlaying = buttonIndex === _this0.ttsPlayingMessageIndex;
|
|
1704
|
-
var iconHtml = isPlaying ? '<span class="fa-solid fa-circle-pause"></span>' : '<span class="fa-solid fa-circle-play"></span>';
|
|
1705
1817
|
button.classList.toggle('tts-playing', isPlaying);
|
|
1706
1818
|
button.setAttribute('title', isPlaying ? 'Pause audio' : 'Read aloud');
|
|
1819
|
+
});
|
|
1820
|
+
},
|
|
1821
|
+
updateCopyButtons: function updateCopyButtons() {
|
|
1822
|
+
var _this1 = this;
|
|
1823
|
+
if (!this.chatContainer) {
|
|
1824
|
+
return;
|
|
1825
|
+
}
|
|
1826
|
+
var buttons = this.chatContainer.querySelectorAll('[data-copy-message-index]');
|
|
1827
|
+
buttons.forEach(function (button) {
|
|
1828
|
+
var buttonIndex = Number(button.getAttribute('data-copy-message-index'));
|
|
1829
|
+
var isCopied = buttonIndex === _this1.copiedMessageIndex;
|
|
1830
|
+
var iconHtml = isCopied ? '<i class="fa-solid fa-check"></i>' : '<i class="fa-solid fa-copy"></i>';
|
|
1831
|
+
button.classList.toggle('text-success', isCopied);
|
|
1832
|
+
button.classList.toggle('text-secondary', !isCopied);
|
|
1833
|
+
button.setAttribute('title', isCopied ? _this1.copiedTitle : _this1.copyTitle);
|
|
1707
1834
|
button.replaceChildren(DOMPurify.sanitize(iconHtml, {
|
|
1708
1835
|
RETURN_DOM_FRAGMENT: true
|
|
1709
1836
|
}));
|
|
1710
1837
|
});
|
|
1711
1838
|
},
|
|
1839
|
+
setCopyButtonState: function setCopyButtonState(button, isCopied) {
|
|
1840
|
+
if (!button) {
|
|
1841
|
+
return;
|
|
1842
|
+
}
|
|
1843
|
+
var iconHtml = isCopied ? '<i class="fa-solid fa-check"></i>' : '<i class="fa-solid fa-copy"></i>';
|
|
1844
|
+
button.classList.toggle('text-success', isCopied);
|
|
1845
|
+
button.classList.toggle('text-secondary', !isCopied);
|
|
1846
|
+
button.setAttribute('title', isCopied ? this.copiedTitle : this.copyTitle);
|
|
1847
|
+
button.replaceChildren(DOMPurify.sanitize(iconHtml, {
|
|
1848
|
+
RETURN_DOM_FRAGMENT: true
|
|
1849
|
+
}));
|
|
1850
|
+
},
|
|
1712
1851
|
synthesizeSpeech: function synthesizeSpeech(text, cacheIndex) {
|
|
1713
|
-
var
|
|
1852
|
+
var _this10 = this;
|
|
1714
1853
|
if (!this.textToSpeechEnabled || !text || !this.connection) {
|
|
1715
1854
|
return;
|
|
1716
1855
|
}
|
|
@@ -1719,16 +1858,16 @@ window.openAIChatManager = function () {
|
|
|
1719
1858
|
this._ttsCacheIndex = cacheIndex !== undefined ? cacheIndex : -1;
|
|
1720
1859
|
this.connection.invoke("SynthesizeSpeech", this.getProfileId(), this.getSessionId(), text, this.ttsVoiceName)["catch"](function (err) {
|
|
1721
1860
|
console.error("TTS synthesis error:", err);
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
return
|
|
1861
|
+
_this10.isPlayingAudio = false;
|
|
1862
|
+
_this10.ttsPlayingMessageIndex = -1;
|
|
1863
|
+
_this10._ttsCacheIndex = -1;
|
|
1864
|
+
_this10.$nextTick(function () {
|
|
1865
|
+
return _this10.updateTtsPlaybackButtons();
|
|
1727
1866
|
});
|
|
1728
1867
|
});
|
|
1729
1868
|
},
|
|
1730
1869
|
toggleMessageTts: function toggleMessageTts(message, index) {
|
|
1731
|
-
var
|
|
1870
|
+
var _this11 = this;
|
|
1732
1871
|
if (this.ttsPlayingMessageIndex === index) {
|
|
1733
1872
|
this.stopAudio();
|
|
1734
1873
|
return;
|
|
@@ -1741,7 +1880,7 @@ window.openAIChatManager = function () {
|
|
|
1741
1880
|
}));
|
|
1742
1881
|
this.ttsPlayingMessageIndex = index;
|
|
1743
1882
|
this.$nextTick(function () {
|
|
1744
|
-
return
|
|
1883
|
+
return _this11.updateTtsPlaybackButtons();
|
|
1745
1884
|
});
|
|
1746
1885
|
if (this.ttsAudioCache[index]) {
|
|
1747
1886
|
this.playAudioBlob(this.ttsAudioCache[index]);
|
|
@@ -1750,13 +1889,13 @@ window.openAIChatManager = function () {
|
|
|
1750
1889
|
this.synthesizeSpeech(message.content, index);
|
|
1751
1890
|
},
|
|
1752
1891
|
playCollectedAudio: function playCollectedAudio() {
|
|
1753
|
-
var
|
|
1892
|
+
var _this12 = this;
|
|
1754
1893
|
if (this.audioChunks.length === 0) {
|
|
1755
1894
|
if (!this.currentAudioElement && this.audioPlayQueue.length === 0) {
|
|
1756
1895
|
this.isPlayingAudio = false;
|
|
1757
1896
|
this.ttsPlayingMessageIndex = -1;
|
|
1758
1897
|
this.$nextTick(function () {
|
|
1759
|
-
return
|
|
1898
|
+
return _this12.updateTtsPlaybackButtons();
|
|
1760
1899
|
});
|
|
1761
1900
|
}
|
|
1762
1901
|
return;
|
|
@@ -1766,18 +1905,18 @@ window.openAIChatManager = function () {
|
|
|
1766
1905
|
}, 0);
|
|
1767
1906
|
var combined = new Uint8Array(totalLength);
|
|
1768
1907
|
var offset = 0;
|
|
1769
|
-
var
|
|
1770
|
-
|
|
1908
|
+
var _iterator6 = _createForOfIteratorHelper(this.audioChunks),
|
|
1909
|
+
_step6;
|
|
1771
1910
|
try {
|
|
1772
|
-
for (
|
|
1773
|
-
var chunk =
|
|
1911
|
+
for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
|
|
1912
|
+
var chunk = _step6.value;
|
|
1774
1913
|
combined.set(chunk, offset);
|
|
1775
1914
|
offset += chunk.length;
|
|
1776
1915
|
}
|
|
1777
1916
|
} catch (err) {
|
|
1778
|
-
|
|
1917
|
+
_iterator6.e(err);
|
|
1779
1918
|
} finally {
|
|
1780
|
-
|
|
1919
|
+
_iterator6.f();
|
|
1781
1920
|
}
|
|
1782
1921
|
this.audioChunks = [];
|
|
1783
1922
|
var blob = new Blob([combined], {
|
|
@@ -1796,39 +1935,39 @@ window.openAIChatManager = function () {
|
|
|
1796
1935
|
this.playAudioBlob(blob);
|
|
1797
1936
|
},
|
|
1798
1937
|
playAudioBlob: function playAudioBlob(blob) {
|
|
1799
|
-
var
|
|
1938
|
+
var _this13 = this;
|
|
1800
1939
|
var url = URL.createObjectURL(blob);
|
|
1801
1940
|
var audio = new Audio(url);
|
|
1802
1941
|
this.currentAudioUrl = url;
|
|
1803
1942
|
this.currentAudioElement = audio;
|
|
1804
1943
|
this.isPlayingAudio = true;
|
|
1805
1944
|
audio.addEventListener('ended', function () {
|
|
1806
|
-
|
|
1807
|
-
|
|
1945
|
+
_this13.currentAudioElement = null;
|
|
1946
|
+
_this13.currentAudioUrl = null;
|
|
1808
1947
|
URL.revokeObjectURL(url);
|
|
1809
|
-
|
|
1948
|
+
_this13.playNextInQueue();
|
|
1810
1949
|
});
|
|
1811
1950
|
audio.addEventListener('error', function () {
|
|
1812
|
-
|
|
1813
|
-
|
|
1951
|
+
_this13.currentAudioElement = null;
|
|
1952
|
+
_this13.currentAudioUrl = null;
|
|
1814
1953
|
URL.revokeObjectURL(url);
|
|
1815
|
-
|
|
1954
|
+
_this13.playNextInQueue();
|
|
1816
1955
|
});
|
|
1817
1956
|
audio.play()["catch"](function (err) {
|
|
1818
1957
|
console.error("Audio playback error:", err);
|
|
1819
|
-
|
|
1820
|
-
|
|
1958
|
+
_this13.currentAudioElement = null;
|
|
1959
|
+
_this13.currentAudioUrl = null;
|
|
1821
1960
|
URL.revokeObjectURL(url);
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
return
|
|
1961
|
+
_this13.audioPlayQueue = [];
|
|
1962
|
+
_this13.isPlayingAudio = false;
|
|
1963
|
+
_this13.ttsPlayingMessageIndex = -1;
|
|
1964
|
+
_this13.$nextTick(function () {
|
|
1965
|
+
return _this13.updateTtsPlaybackButtons();
|
|
1827
1966
|
});
|
|
1828
1967
|
});
|
|
1829
1968
|
},
|
|
1830
1969
|
playNextInQueue: function playNextInQueue() {
|
|
1831
|
-
var
|
|
1970
|
+
var _this14 = this;
|
|
1832
1971
|
if (this.audioPlayQueue.length > 0) {
|
|
1833
1972
|
var nextBlob = this.audioPlayQueue.shift();
|
|
1834
1973
|
this.playAudioBlob(nextBlob);
|
|
@@ -1836,13 +1975,13 @@ window.openAIChatManager = function () {
|
|
|
1836
1975
|
this.isPlayingAudio = false;
|
|
1837
1976
|
this.ttsPlayingMessageIndex = -1;
|
|
1838
1977
|
this.$nextTick(function () {
|
|
1839
|
-
return
|
|
1978
|
+
return _this14.updateTtsPlaybackButtons();
|
|
1840
1979
|
});
|
|
1841
1980
|
this.conversationModeOnAudioEnded();
|
|
1842
1981
|
}
|
|
1843
1982
|
},
|
|
1844
1983
|
stopAudio: function stopAudio() {
|
|
1845
|
-
var
|
|
1984
|
+
var _this15 = this;
|
|
1846
1985
|
if (this.currentAudioElement) {
|
|
1847
1986
|
this.currentAudioElement.pause();
|
|
1848
1987
|
this.currentAudioElement.currentTime = 0;
|
|
@@ -1857,7 +1996,7 @@ window.openAIChatManager = function () {
|
|
|
1857
1996
|
this.isPlayingAudio = false;
|
|
1858
1997
|
this.ttsPlayingMessageIndex = -1;
|
|
1859
1998
|
this.$nextTick(function () {
|
|
1860
|
-
return
|
|
1999
|
+
return _this15.updateTtsPlaybackButtons();
|
|
1861
2000
|
});
|
|
1862
2001
|
},
|
|
1863
2002
|
toggleConversationMode: function toggleConversationMode() {
|
|
@@ -1868,7 +2007,7 @@ window.openAIChatManager = function () {
|
|
|
1868
2007
|
}
|
|
1869
2008
|
},
|
|
1870
2009
|
startConversationMode: function startConversationMode() {
|
|
1871
|
-
var
|
|
2010
|
+
var _this16 = this;
|
|
1872
2011
|
if (!this.conversationModeEnabled || this.isConversationMode || !this.connection) {
|
|
1873
2012
|
return;
|
|
1874
2013
|
}
|
|
@@ -1888,12 +2027,12 @@ window.openAIChatManager = function () {
|
|
|
1888
2027
|
}
|
|
1889
2028
|
}).then(function (stream) {
|
|
1890
2029
|
var mimeType = MediaRecorder.isTypeSupported('audio/ogg;codecs=opus') ? 'audio/ogg;codecs=opus' : MediaRecorder.isTypeSupported('audio/webm;codecs=opus') ? 'audio/webm;codecs=opus' : 'audio/webm';
|
|
1891
|
-
|
|
2030
|
+
_this16.mediaRecorder = new MediaRecorder(stream, {
|
|
1892
2031
|
mimeType: mimeType,
|
|
1893
2032
|
audioBitsPerSecond: 128000
|
|
1894
2033
|
});
|
|
1895
|
-
|
|
1896
|
-
|
|
2034
|
+
_this16._conversationSubject = new signalR.Subject();
|
|
2035
|
+
_this16._conversationStream = stream;
|
|
1897
2036
|
|
|
1898
2037
|
// Create an AnalyserNode for volume-based interrupt detection.
|
|
1899
2038
|
// During TTS playback, detect when the user speaks above
|
|
@@ -1902,20 +2041,20 @@ window.openAIChatManager = function () {
|
|
|
1902
2041
|
// speaker echo so the STT stream has no gaps.
|
|
1903
2042
|
var AudioCtx = window.AudioContext || window.webkitAudioContext;
|
|
1904
2043
|
if (AudioCtx) {
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
var micSource =
|
|
1909
|
-
micSource.connect(
|
|
2044
|
+
_this16._conversationAudioCtx = new AudioCtx();
|
|
2045
|
+
_this16._conversationAnalyser = _this16._conversationAudioCtx.createAnalyser();
|
|
2046
|
+
_this16._conversationAnalyser.fftSize = 256;
|
|
2047
|
+
var micSource = _this16._conversationAudioCtx.createMediaStreamSource(stream);
|
|
2048
|
+
micSource.connect(_this16._conversationAnalyser);
|
|
1910
2049
|
}
|
|
1911
2050
|
var pendingChunk = Promise.resolve();
|
|
1912
|
-
var analyser =
|
|
2051
|
+
var analyser = _this16._conversationAnalyser;
|
|
1913
2052
|
var interruptVolumeThreshold = 30;
|
|
1914
|
-
|
|
2053
|
+
_this16.mediaRecorder.addEventListener('dataavailable', function (e) {
|
|
1915
2054
|
if (e.data && e.data.size > 0) {
|
|
1916
2055
|
// During TTS playback, check mic volume to detect
|
|
1917
2056
|
// user interruption (speaking above threshold).
|
|
1918
|
-
if (
|
|
2057
|
+
if (_this16.isPlayingAudio && analyser) {
|
|
1919
2058
|
var freqData = new Uint8Array(analyser.frequencyBinCount);
|
|
1920
2059
|
analyser.getByteFrequencyData(freqData);
|
|
1921
2060
|
var sum = 0;
|
|
@@ -1925,7 +2064,7 @@ window.openAIChatManager = function () {
|
|
|
1925
2064
|
var avg = sum / freqData.length;
|
|
1926
2065
|
if (avg >= interruptVolumeThreshold) {
|
|
1927
2066
|
// User is speaking — interrupt TTS playback.
|
|
1928
|
-
|
|
2067
|
+
_this16.stopAudio();
|
|
1929
2068
|
}
|
|
1930
2069
|
}
|
|
1931
2070
|
|
|
@@ -1947,7 +2086,7 @@ window.openAIChatManager = function () {
|
|
|
1947
2086
|
}, '');
|
|
1948
2087
|
base64 = btoa(binaryString);
|
|
1949
2088
|
try {
|
|
1950
|
-
|
|
2089
|
+
_this16._conversationSubject.next(base64);
|
|
1951
2090
|
} catch (err) {
|
|
1952
2091
|
// Subject may have been completed already.
|
|
1953
2092
|
}
|
|
@@ -1958,28 +2097,28 @@ window.openAIChatManager = function () {
|
|
|
1958
2097
|
})));
|
|
1959
2098
|
}
|
|
1960
2099
|
});
|
|
1961
|
-
|
|
2100
|
+
_this16.mediaRecorder.addEventListener('stop', function () {
|
|
1962
2101
|
stream.getTracks().forEach(function (track) {
|
|
1963
2102
|
return track.stop();
|
|
1964
2103
|
});
|
|
1965
2104
|
pendingChunk.then(function () {
|
|
1966
2105
|
try {
|
|
1967
|
-
|
|
2106
|
+
_this16._conversationSubject.complete();
|
|
1968
2107
|
} catch (err) {
|
|
1969
2108
|
// Already completed.
|
|
1970
2109
|
}
|
|
1971
2110
|
});
|
|
1972
2111
|
});
|
|
1973
|
-
var profileId =
|
|
1974
|
-
var sessionId =
|
|
2112
|
+
var profileId = _this16.getProfileId();
|
|
2113
|
+
var sessionId = _this16.getSessionId() || '';
|
|
1975
2114
|
var language = navigator.language || document.documentElement.lang || 'en-US';
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
2115
|
+
_this16.connection.send("StartConversation", profileId, sessionId, _this16._conversationSubject, mimeType, language);
|
|
2116
|
+
_this16.mediaRecorder.start(250);
|
|
2117
|
+
_this16.isRecording = true;
|
|
1979
2118
|
})["catch"](function (err) {
|
|
1980
2119
|
console.error('Microphone access denied:', err);
|
|
1981
|
-
|
|
1982
|
-
|
|
2120
|
+
_this16.isConversationMode = false;
|
|
2121
|
+
_this16.updateConversationButton();
|
|
1983
2122
|
});
|
|
1984
2123
|
},
|
|
1985
2124
|
stopConversationMode: function stopConversationMode() {
|
|
@@ -2106,7 +2245,7 @@ window.openAIChatManager = function () {
|
|
|
2106
2245
|
return removedCount;
|
|
2107
2246
|
},
|
|
2108
2247
|
receiveNotification: function receiveNotification(notification) {
|
|
2109
|
-
var
|
|
2248
|
+
var _this17 = this;
|
|
2110
2249
|
if (!notification || !notification.type) {
|
|
2111
2250
|
return;
|
|
2112
2251
|
}
|
|
@@ -2121,7 +2260,7 @@ window.openAIChatManager = function () {
|
|
|
2121
2260
|
}
|
|
2122
2261
|
this.scheduleNotificationDismiss(notification);
|
|
2123
2262
|
this.$nextTick(function () {
|
|
2124
|
-
|
|
2263
|
+
_this17.scrollToBottom();
|
|
2125
2264
|
});
|
|
2126
2265
|
},
|
|
2127
2266
|
updateNotification: function updateNotification(notification) {
|
|
@@ -2138,12 +2277,12 @@ window.openAIChatManager = function () {
|
|
|
2138
2277
|
}
|
|
2139
2278
|
},
|
|
2140
2279
|
scheduleNotificationDismiss: function scheduleNotificationDismiss(notification) {
|
|
2141
|
-
var
|
|
2280
|
+
var _this18 = this;
|
|
2142
2281
|
if (!notification || !notification.type || !notification.autoDismissMs || notification.autoDismissMs <= 0) {
|
|
2143
2282
|
return;
|
|
2144
2283
|
}
|
|
2145
2284
|
this.notificationDismissTimers[notification.type] = setTimeout(function () {
|
|
2146
|
-
|
|
2285
|
+
_this18.removeNotification(notification.type);
|
|
2147
2286
|
}, notification.autoDismissMs);
|
|
2148
2287
|
},
|
|
2149
2288
|
clearNotificationDismiss: function clearNotificationDismiss(notificationType) {
|
|
@@ -2173,12 +2312,12 @@ window.openAIChatManager = function () {
|
|
|
2173
2312
|
});
|
|
2174
2313
|
},
|
|
2175
2314
|
scrollToBottom: function scrollToBottom() {
|
|
2176
|
-
var
|
|
2315
|
+
var _this19 = this;
|
|
2177
2316
|
if (!this.autoScroll) {
|
|
2178
2317
|
return;
|
|
2179
2318
|
}
|
|
2180
2319
|
setTimeout(function () {
|
|
2181
|
-
|
|
2320
|
+
_this19.chatContainer.scrollTop = _this19.chatContainer.scrollHeight - _this19.chatContainer.clientHeight;
|
|
2182
2321
|
}, 50);
|
|
2183
2322
|
},
|
|
2184
2323
|
handleUserInput: function handleUserInput(event) {
|
|
@@ -2201,12 +2340,17 @@ window.openAIChatManager = function () {
|
|
|
2201
2340
|
this.sessionRating = null;
|
|
2202
2341
|
this.messages = [];
|
|
2203
2342
|
this.documents = [];
|
|
2204
|
-
|
|
2343
|
+
|
|
2344
|
+
// When an initial prompt is configured, show it as the first
|
|
2345
|
+
// assistant message instead of the generic placeholder.
|
|
2346
|
+
if (config.initialPrompt) {
|
|
2347
|
+
this.addMessage({
|
|
2348
|
+
role: 'assistant',
|
|
2349
|
+
content: config.initialPrompt
|
|
2350
|
+
});
|
|
2351
|
+
} else {
|
|
2205
2352
|
this.showPlaceholder();
|
|
2206
2353
|
}
|
|
2207
|
-
if (config.autoCreateSession) {
|
|
2208
|
-
this.startNewSession();
|
|
2209
|
-
}
|
|
2210
2354
|
if (widgetBehavior && typeof widgetBehavior.onSessionReset === 'function') {
|
|
2211
2355
|
widgetBehavior.onSessionReset(this, config);
|
|
2212
2356
|
}
|
|
@@ -2224,27 +2368,27 @@ window.openAIChatManager = function () {
|
|
|
2224
2368
|
});
|
|
2225
2369
|
},
|
|
2226
2370
|
ensureSessionForDocuments: function ensureSessionForDocuments(profileId) {
|
|
2227
|
-
var
|
|
2371
|
+
var _this20 = this;
|
|
2228
2372
|
return _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee9() {
|
|
2229
2373
|
var sessionId;
|
|
2230
2374
|
return _regenerator().w(function (_context9) {
|
|
2231
2375
|
while (1) switch (_context9.n) {
|
|
2232
2376
|
case 0:
|
|
2233
|
-
sessionId =
|
|
2377
|
+
sessionId = _this20.getSessionId();
|
|
2234
2378
|
if (!sessionId) {
|
|
2235
2379
|
_context9.n = 1;
|
|
2236
2380
|
break;
|
|
2237
2381
|
}
|
|
2238
2382
|
return _context9.a(2, sessionId);
|
|
2239
2383
|
case 1:
|
|
2240
|
-
if (!(!profileId || !
|
|
2384
|
+
if (!(!profileId || !_this20.connection)) {
|
|
2241
2385
|
_context9.n = 2;
|
|
2242
2386
|
break;
|
|
2243
2387
|
}
|
|
2244
2388
|
return _context9.a(2, null);
|
|
2245
2389
|
case 2:
|
|
2246
2390
|
_context9.n = 3;
|
|
2247
|
-
return
|
|
2391
|
+
return _this20.requestNewSession(profileId);
|
|
2248
2392
|
case 3:
|
|
2249
2393
|
return _context9.a(2, _context9.v);
|
|
2250
2394
|
}
|
|
@@ -2252,7 +2396,7 @@ window.openAIChatManager = function () {
|
|
|
2252
2396
|
}))();
|
|
2253
2397
|
},
|
|
2254
2398
|
requestNewSession: function requestNewSession(profileId) {
|
|
2255
|
-
var
|
|
2399
|
+
var _this21 = this;
|
|
2256
2400
|
if (this.pendingSessionPromise) {
|
|
2257
2401
|
return this.pendingSessionPromise;
|
|
2258
2402
|
}
|
|
@@ -2260,14 +2404,14 @@ window.openAIChatManager = function () {
|
|
|
2260
2404
|
return Promise.resolve(null);
|
|
2261
2405
|
}
|
|
2262
2406
|
this.pendingSessionPromise = new Promise(function (resolve, reject) {
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2407
|
+
_this21.pendingSessionResolver = resolve;
|
|
2408
|
+
_this21.pendingSessionRejector = reject;
|
|
2409
|
+
_this21.pendingSessionTimeoutId = window.setTimeout(function () {
|
|
2410
|
+
_this21.rejectPendingSessionRequest('Timed out while creating a chat session.');
|
|
2267
2411
|
}, 15000);
|
|
2268
2412
|
});
|
|
2269
2413
|
this.connection.invoke("StartSession", profileId, null)["catch"](function (err) {
|
|
2270
|
-
|
|
2414
|
+
_this21.rejectPendingSessionRequest(err);
|
|
2271
2415
|
});
|
|
2272
2416
|
return this.pendingSessionPromise;
|
|
2273
2417
|
},
|
|
@@ -2293,7 +2437,7 @@ window.openAIChatManager = function () {
|
|
|
2293
2437
|
this.pendingSessionTimeoutId = null;
|
|
2294
2438
|
},
|
|
2295
2439
|
initializeApp: function initializeApp() {
|
|
2296
|
-
var
|
|
2440
|
+
var _this22 = this;
|
|
2297
2441
|
this.inputElement = document.querySelector(config.inputElementSelector);
|
|
2298
2442
|
this.buttonElement = document.querySelector(config.sendButtonElementSelector);
|
|
2299
2443
|
this.chatContainer = document.querySelector(config.chatContainerElementSelector);
|
|
@@ -2311,8 +2455,6 @@ window.openAIChatManager = function () {
|
|
|
2311
2455
|
var sessionId = this.getSessionId();
|
|
2312
2456
|
if (!hasWidgetConfig && sessionId) {
|
|
2313
2457
|
this.loadSession(sessionId);
|
|
2314
|
-
} else if (this.isOrchestratorAvailable() && config.autoCreateSession && !hasWidgetConfig && !sessionId) {
|
|
2315
|
-
this.startNewSession();
|
|
2316
2458
|
}
|
|
2317
2459
|
|
|
2318
2460
|
// Initialize document bar if enabled.
|
|
@@ -2331,7 +2473,7 @@ window.openAIChatManager = function () {
|
|
|
2331
2473
|
fileInput.accept = config.allowedExtensions;
|
|
2332
2474
|
}
|
|
2333
2475
|
fileInput.addEventListener('change', function (e) {
|
|
2334
|
-
return
|
|
2476
|
+
return _this22.handleFileInputChange(e);
|
|
2335
2477
|
});
|
|
2336
2478
|
this.documentBar.parentElement.appendChild(fileInput);
|
|
2337
2479
|
|
|
@@ -2339,13 +2481,13 @@ window.openAIChatManager = function () {
|
|
|
2339
2481
|
var inputArea = this.inputElement ? this.inputElement.closest('.ai-admin-widget-input, .text-bg-light') : null;
|
|
2340
2482
|
if (inputArea) {
|
|
2341
2483
|
inputArea.addEventListener('dragover', function (e) {
|
|
2342
|
-
return
|
|
2484
|
+
return _this22.handleDragOver(e);
|
|
2343
2485
|
});
|
|
2344
2486
|
inputArea.addEventListener('dragleave', function (e) {
|
|
2345
|
-
return
|
|
2487
|
+
return _this22.handleDragLeave(e);
|
|
2346
2488
|
});
|
|
2347
2489
|
inputArea.addEventListener('drop', function (e) {
|
|
2348
|
-
return
|
|
2490
|
+
return _this22.handleDrop(e);
|
|
2349
2491
|
});
|
|
2350
2492
|
}
|
|
2351
2493
|
}
|
|
@@ -2353,55 +2495,55 @@ window.openAIChatManager = function () {
|
|
|
2353
2495
|
|
|
2354
2496
|
// Pause auto-scroll when the user manually scrolls up during streaming.
|
|
2355
2497
|
this.chatContainer.addEventListener('scroll', function () {
|
|
2356
|
-
if (!
|
|
2498
|
+
if (!_this22.stream) {
|
|
2357
2499
|
return;
|
|
2358
2500
|
}
|
|
2359
2501
|
var threshold = 30;
|
|
2360
|
-
var atBottom =
|
|
2361
|
-
|
|
2502
|
+
var atBottom = _this22.chatContainer.scrollHeight - _this22.chatContainer.clientHeight - _this22.chatContainer.scrollTop <= threshold;
|
|
2503
|
+
_this22.autoScroll = atBottom;
|
|
2362
2504
|
});
|
|
2363
2505
|
this.inputElement.addEventListener('keydown', function (event) {
|
|
2364
|
-
if (
|
|
2506
|
+
if (_this22.stream != null) {
|
|
2365
2507
|
return;
|
|
2366
2508
|
}
|
|
2367
2509
|
if (event.key === "Enter" && !event.shiftKey) {
|
|
2368
2510
|
event.preventDefault();
|
|
2369
|
-
|
|
2511
|
+
_this22.buttonElement.click();
|
|
2370
2512
|
}
|
|
2371
2513
|
});
|
|
2372
2514
|
this.inputElement.addEventListener('input', function (e) {
|
|
2373
|
-
|
|
2515
|
+
_this22.handleUserInput(e);
|
|
2374
2516
|
if (e.target.value.trim()) {
|
|
2375
|
-
|
|
2517
|
+
_this22.buttonElement.removeAttribute('disabled');
|
|
2376
2518
|
} else {
|
|
2377
|
-
|
|
2519
|
+
_this22.buttonElement.setAttribute('disabled', true);
|
|
2378
2520
|
}
|
|
2379
2521
|
});
|
|
2380
2522
|
this.buttonElement.addEventListener('click', function () {
|
|
2381
|
-
if (
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2523
|
+
if (_this22.stream != null) {
|
|
2524
|
+
_this22.stream.dispose();
|
|
2525
|
+
_this22.stream = null;
|
|
2526
|
+
_this22.streamingFinished();
|
|
2527
|
+
_this22.hideTypingIndicator();
|
|
2386
2528
|
|
|
2387
2529
|
// Clean up: remove empty assistant message or stop streaming animation.
|
|
2388
|
-
if (
|
|
2389
|
-
var lastMsg =
|
|
2530
|
+
if (_this22.messages.length > 0) {
|
|
2531
|
+
var lastMsg = _this22.messages[_this22.messages.length - 1];
|
|
2390
2532
|
if (lastMsg.role === 'assistant' && !lastMsg.content) {
|
|
2391
|
-
|
|
2533
|
+
_this22.messages.pop();
|
|
2392
2534
|
} else if (lastMsg.isStreaming) {
|
|
2393
2535
|
lastMsg.isStreaming = false;
|
|
2394
2536
|
}
|
|
2395
2537
|
}
|
|
2396
2538
|
return;
|
|
2397
2539
|
}
|
|
2398
|
-
|
|
2540
|
+
_this22.sendMessage();
|
|
2399
2541
|
});
|
|
2400
2542
|
var promptGenerators = document.getElementsByClassName('profile-generated-prompt');
|
|
2401
2543
|
for (var i = 0; i < promptGenerators.length; i++) {
|
|
2402
2544
|
promptGenerators[i].addEventListener('click', function (e) {
|
|
2403
2545
|
e.preventDefault();
|
|
2404
|
-
|
|
2546
|
+
_this22.generatePrompt(e.target);
|
|
2405
2547
|
});
|
|
2406
2548
|
}
|
|
2407
2549
|
var chatSessions = document.getElementsByClassName('chat-session-history-item');
|
|
@@ -2413,17 +2555,27 @@ window.openAIChatManager = function () {
|
|
|
2413
2555
|
console.error('an element with the class chat-session-history-item with no data-session-id set.');
|
|
2414
2556
|
return;
|
|
2415
2557
|
}
|
|
2416
|
-
|
|
2417
|
-
|
|
2558
|
+
_this22.loadSession(sessionId);
|
|
2559
|
+
_this22.showChatScreen();
|
|
2418
2560
|
});
|
|
2419
2561
|
}
|
|
2420
|
-
|
|
2421
|
-
|
|
2562
|
+
var initialMessages = Array.isArray(config.messages) ? config.messages : [];
|
|
2563
|
+
for (var _i5 = 0; _i5 < initialMessages.length; _i5++) {
|
|
2564
|
+
this.addMessage(initialMessages[_i5]);
|
|
2565
|
+
}
|
|
2566
|
+
|
|
2567
|
+
// When no messages were loaded and an initial prompt is configured,
|
|
2568
|
+
// display it as the first assistant message without invoking the AI.
|
|
2569
|
+
if (this.messages.length === 0 && config.initialPrompt) {
|
|
2570
|
+
this.addMessage({
|
|
2571
|
+
role: 'assistant',
|
|
2572
|
+
content: config.initialPrompt
|
|
2573
|
+
});
|
|
2422
2574
|
}
|
|
2423
2575
|
|
|
2424
2576
|
// Update feedback icons in the DOM after initial messages have rendered.
|
|
2425
2577
|
this.$nextTick(function () {
|
|
2426
|
-
|
|
2578
|
+
_this22.refreshAllFeedbackIcons();
|
|
2427
2579
|
});
|
|
2428
2580
|
|
|
2429
2581
|
// Delegate click for code block copy buttons.
|
|
@@ -2441,9 +2593,9 @@ window.openAIChatManager = function () {
|
|
|
2441
2593
|
if (codeEl) {
|
|
2442
2594
|
navigator.clipboard.writeText(codeEl.textContent);
|
|
2443
2595
|
var copiedText = config.codeCopiedText || 'Copied!';
|
|
2444
|
-
btn.innerHTML = '<
|
|
2596
|
+
btn.innerHTML = '<i class="fa-solid fa-check"></i> ' + copiedText;
|
|
2445
2597
|
setTimeout(function () {
|
|
2446
|
-
btn.innerHTML = '<
|
|
2598
|
+
btn.innerHTML = '<i class="fa-regular fa-copy"></i>';
|
|
2447
2599
|
}, 2000);
|
|
2448
2600
|
}
|
|
2449
2601
|
});
|
|
@@ -2455,7 +2607,7 @@ window.openAIChatManager = function () {
|
|
|
2455
2607
|
if (this.micButton) {
|
|
2456
2608
|
this.micButton.style.display = '';
|
|
2457
2609
|
this.micButton.addEventListener('click', function () {
|
|
2458
|
-
|
|
2610
|
+
_this22.toggleRecording();
|
|
2459
2611
|
});
|
|
2460
2612
|
}
|
|
2461
2613
|
}
|
|
@@ -2465,7 +2617,7 @@ window.openAIChatManager = function () {
|
|
|
2465
2617
|
this.conversationButton = document.querySelector(config.conversationButtonElementSelector);
|
|
2466
2618
|
if (this.conversationButton) {
|
|
2467
2619
|
this.conversationButton.addEventListener('click', function () {
|
|
2468
|
-
|
|
2620
|
+
_this22.toggleConversationMode();
|
|
2469
2621
|
});
|
|
2470
2622
|
}
|
|
2471
2623
|
}
|
|
@@ -2489,7 +2641,7 @@ window.openAIChatManager = function () {
|
|
|
2489
2641
|
}
|
|
2490
2642
|
return;
|
|
2491
2643
|
}
|
|
2492
|
-
this.fireEvent(new CustomEvent("
|
|
2644
|
+
this.fireEvent(new CustomEvent("initializingSessionCoreAIChat", {
|
|
2493
2645
|
detail: {
|
|
2494
2646
|
sessionId: sessionId
|
|
2495
2647
|
}
|
|
@@ -2500,6 +2652,13 @@ window.openAIChatManager = function () {
|
|
|
2500
2652
|
if (widgetBehavior && typeof widgetBehavior.onSessionInitialized === 'function') {
|
|
2501
2653
|
widgetBehavior.onSessionInitialized(this, sessionId, config);
|
|
2502
2654
|
}
|
|
2655
|
+
|
|
2656
|
+
// For non-widget pages, update the browser URL so that a page
|
|
2657
|
+
// refresh reloads the correct session instead of starting fresh.
|
|
2658
|
+
if (!hasWidgetConfig && sessionId && config.sessionUrlTemplate && typeof history !== 'undefined' && history.replaceState) {
|
|
2659
|
+
var sessionUrl = config.sessionUrlTemplate.replace('{sessionId}', encodeURIComponent(sessionId));
|
|
2660
|
+
history.replaceState(null, '', sessionUrl);
|
|
2661
|
+
}
|
|
2503
2662
|
},
|
|
2504
2663
|
getSessionId: function getSessionId() {
|
|
2505
2664
|
var sessionId = this.inputElement ? this.inputElement.getAttribute('data-session-id') : null;
|
|
@@ -2508,8 +2667,45 @@ window.openAIChatManager = function () {
|
|
|
2508
2667
|
}
|
|
2509
2668
|
return sessionId;
|
|
2510
2669
|
},
|
|
2511
|
-
|
|
2512
|
-
|
|
2670
|
+
clearCopiedMessageState: function clearCopiedMessageState() {
|
|
2671
|
+
if (this.copyResetTimeoutId) {
|
|
2672
|
+
window.clearTimeout(this.copyResetTimeoutId);
|
|
2673
|
+
this.copyResetTimeoutId = null;
|
|
2674
|
+
}
|
|
2675
|
+
if (this.activeCopyButton) {
|
|
2676
|
+
this.setCopyButtonState(this.activeCopyButton, false);
|
|
2677
|
+
this.activeCopyButton = null;
|
|
2678
|
+
}
|
|
2679
|
+
this.copiedMessageIndex = -1;
|
|
2680
|
+
},
|
|
2681
|
+
copyResponse: function copyResponse(message, index, event) {
|
|
2682
|
+
var _ref25,
|
|
2683
|
+
_message$copyContent,
|
|
2684
|
+
_event$target,
|
|
2685
|
+
_event$target$closest,
|
|
2686
|
+
_this23 = this;
|
|
2687
|
+
var text = message && _typeof(message) === 'object' ? (_ref25 = (_message$copyContent = message.copyContent) !== null && _message$copyContent !== void 0 ? _message$copyContent : message.content) !== null && _ref25 !== void 0 ? _ref25 : '' : message !== null && message !== void 0 ? message : '';
|
|
2688
|
+
var button = (event === null || event === void 0 ? void 0 : event.currentTarget) || (event === null || event === void 0 || (_event$target = event.target) === null || _event$target === void 0 || (_event$target$closest = _event$target.closest) === null || _event$target$closest === void 0 ? void 0 : _event$target$closest.call(_event$target, '[data-copy-message-index]')) || null;
|
|
2689
|
+
navigator.clipboard.writeText(text).then(function () {
|
|
2690
|
+
_this23.clearCopiedMessageState();
|
|
2691
|
+
_this23.copiedMessageIndex = typeof index === 'number' ? index : -1;
|
|
2692
|
+
_this23.activeCopyButton = button;
|
|
2693
|
+
if (button) {
|
|
2694
|
+
_this23.setCopyButtonState(button, true);
|
|
2695
|
+
} else {
|
|
2696
|
+
_this23.$nextTick(function () {
|
|
2697
|
+
return _this23.updateCopyButtons();
|
|
2698
|
+
});
|
|
2699
|
+
}
|
|
2700
|
+
_this23.copyResetTimeoutId = window.setTimeout(function () {
|
|
2701
|
+
_this23.clearCopiedMessageState();
|
|
2702
|
+
_this23.$nextTick(function () {
|
|
2703
|
+
return _this23.updateCopyButtons();
|
|
2704
|
+
});
|
|
2705
|
+
}, Number(config.copyResetDelayMs) || 2000);
|
|
2706
|
+
})["catch"](function (err) {
|
|
2707
|
+
return console.error('Failed to copy response:', err);
|
|
2708
|
+
});
|
|
2513
2709
|
},
|
|
2514
2710
|
updateFeedbackIcons: function updateFeedbackIcons(container, userRating) {
|
|
2515
2711
|
if (!container) {
|
|
@@ -2604,6 +2800,12 @@ window.openAIChatManager = function () {
|
|
|
2604
2800
|
// Reserved for future use — volume-based interrupt detection
|
|
2605
2801
|
// no longer mutes tracks; browser echo cancellation handles echo.
|
|
2606
2802
|
},
|
|
2803
|
+
copiedMessageIndex: function copiedMessageIndex() {
|
|
2804
|
+
var _this24 = this;
|
|
2805
|
+
this.$nextTick(function () {
|
|
2806
|
+
return _this24.updateCopyButtons();
|
|
2807
|
+
});
|
|
2808
|
+
},
|
|
2607
2809
|
isConversationMode: function isConversationMode(active) {
|
|
2608
2810
|
// Hide/show mic button.
|
|
2609
2811
|
if (this.micButton) {
|
|
@@ -2625,19 +2827,24 @@ window.openAIChatManager = function () {
|
|
|
2625
2827
|
}
|
|
2626
2828
|
},
|
|
2627
2829
|
mounted: function mounted() {
|
|
2628
|
-
var
|
|
2830
|
+
var _this25 = this;
|
|
2629
2831
|
_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee0() {
|
|
2630
2832
|
var isInitialized;
|
|
2631
2833
|
return _regenerator().w(function (_context0) {
|
|
2632
2834
|
while (1) switch (_context0.n) {
|
|
2633
2835
|
case 0:
|
|
2634
2836
|
_context0.n = 1;
|
|
2635
|
-
return
|
|
2837
|
+
return _this25.startConnection();
|
|
2636
2838
|
case 1:
|
|
2637
|
-
isInitialized =
|
|
2839
|
+
isInitialized = _this25.initializeApp();
|
|
2638
2840
|
if (isInitialized && hasWidgetConfig && widgetBehavior && typeof widgetBehavior.onMounted === 'function') {
|
|
2639
|
-
widgetBehavior.onMounted(
|
|
2841
|
+
widgetBehavior.onMounted(_this25, config);
|
|
2640
2842
|
}
|
|
2843
|
+
_this25.$nextTick(function () {
|
|
2844
|
+
_this25.updateCopyButtons();
|
|
2845
|
+
refreshFontAwesomeIcons(_this25.$el);
|
|
2846
|
+
_this25.fontAwesomeObserver = observeFontAwesomeIcons(_this25.$el);
|
|
2847
|
+
});
|
|
2641
2848
|
case 2:
|
|
2642
2849
|
return _context0.a(2);
|
|
2643
2850
|
}
|
|
@@ -2649,6 +2856,11 @@ window.openAIChatManager = function () {
|
|
|
2649
2856
|
beforeUnmount: function beforeUnmount() {
|
|
2650
2857
|
window.removeEventListener('beforeunload', this.handleBeforeUnload);
|
|
2651
2858
|
window.removeEventListener('crestapps-ai-chat-stop-tts', this.handleExternalTtsStop);
|
|
2859
|
+
if (this.fontAwesomeObserver) {
|
|
2860
|
+
this.fontAwesomeObserver.disconnect();
|
|
2861
|
+
this.fontAwesomeObserver = null;
|
|
2862
|
+
}
|
|
2863
|
+
this.clearCopiedMessageState();
|
|
2652
2864
|
this.stopAudio(false);
|
|
2653
2865
|
if (this.stream) {
|
|
2654
2866
|
this.stream.dispose();
|
|
@@ -2669,8 +2881,151 @@ window.openAIChatManager = function () {
|
|
|
2669
2881
|
}
|
|
2670
2882
|
return app;
|
|
2671
2883
|
};
|
|
2884
|
+
var autoInitializeSelector = '[data-coreai-chat-config],[data-coreai-chat-app-element-selector]';
|
|
2885
|
+
function getAttributeValue(element, attributeName) {
|
|
2886
|
+
var value = element.getAttribute(attributeName);
|
|
2887
|
+
return value === null || value === '' ? null : value;
|
|
2888
|
+
}
|
|
2889
|
+
function parseBooleanAttributeValue(value) {
|
|
2890
|
+
if (value === null || value === undefined) {
|
|
2891
|
+
return null;
|
|
2892
|
+
}
|
|
2893
|
+
if (typeof value === 'boolean') {
|
|
2894
|
+
return value;
|
|
2895
|
+
}
|
|
2896
|
+
var normalized = String(value).trim().toLowerCase();
|
|
2897
|
+
if (normalized === 'true') {
|
|
2898
|
+
return true;
|
|
2899
|
+
}
|
|
2900
|
+
if (normalized === 'false') {
|
|
2901
|
+
return false;
|
|
2902
|
+
}
|
|
2903
|
+
return null;
|
|
2904
|
+
}
|
|
2905
|
+
function parseJsonAttribute(element, attributeName, description) {
|
|
2906
|
+
var rawValue = getAttributeValue(element, attributeName);
|
|
2907
|
+
if (!rawValue) {
|
|
2908
|
+
return null;
|
|
2909
|
+
}
|
|
2910
|
+
try {
|
|
2911
|
+
return JSON.parse(rawValue);
|
|
2912
|
+
} catch (error) {
|
|
2913
|
+
console.error('Failed to parse ' + description + ' JSON.', error);
|
|
2914
|
+
return null;
|
|
2915
|
+
}
|
|
2916
|
+
}
|
|
2917
|
+
function buildConfigFromDataAttributes(element, options) {
|
|
2918
|
+
var _parseJsonAttribute, _parseJsonAttribute2;
|
|
2919
|
+
var settings = options || {};
|
|
2920
|
+
if (element.hasAttribute('data-coreai-chat-widget-container-selector') && settings.allowWidgetHost !== true) {
|
|
2921
|
+
return null;
|
|
2922
|
+
}
|
|
2923
|
+
var appElementSelector = getAttributeValue(element, 'data-coreai-chat-app-element-selector');
|
|
2924
|
+
if (!appElementSelector) {
|
|
2925
|
+
return null;
|
|
2926
|
+
}
|
|
2927
|
+
var config = {
|
|
2928
|
+
signalRHubUrl: getAttributeValue(element, 'data-coreai-chat-signalr-hub-url'),
|
|
2929
|
+
appElementSelector: appElementSelector,
|
|
2930
|
+
chatContainerElementSelector: getAttributeValue(element, 'data-coreai-chat-container-element-selector'),
|
|
2931
|
+
inputElementSelector: getAttributeValue(element, 'data-coreai-chat-input-element-selector'),
|
|
2932
|
+
sendButtonElementSelector: getAttributeValue(element, 'data-coreai-chat-send-button-element-selector'),
|
|
2933
|
+
placeholderElementSelector: getAttributeValue(element, 'data-coreai-chat-placeholder-element-selector'),
|
|
2934
|
+
messages: (_parseJsonAttribute = parseJsonAttribute(element, 'data-coreai-chat-messages', 'CoreAI chat messages')) !== null && _parseJsonAttribute !== void 0 ? _parseJsonAttribute : undefined,
|
|
2935
|
+
chatMode: getAttributeValue(element, 'data-coreai-chat-mode'),
|
|
2936
|
+
micButtonElementSelector: getAttributeValue(element, 'data-coreai-chat-mic-button-element-selector'),
|
|
2937
|
+
conversationButtonElementSelector: getAttributeValue(element, 'data-coreai-chat-conversation-button-element-selector'),
|
|
2938
|
+
ttsVoiceName: getAttributeValue(element, 'data-coreai-chat-tts-voice-name'),
|
|
2939
|
+
documentBarSelector: getAttributeValue(element, 'data-coreai-chat-document-bar-selector'),
|
|
2940
|
+
uploadDocumentUrl: getAttributeValue(element, 'data-coreai-chat-upload-document-url'),
|
|
2941
|
+
removeDocumentUrl: getAttributeValue(element, 'data-coreai-chat-remove-document-url'),
|
|
2942
|
+
allowedExtensions: getAttributeValue(element, 'data-coreai-chat-allowed-extensions'),
|
|
2943
|
+
supportedExtensionsText: getAttributeValue(element, 'data-coreai-chat-supported-extensions-text'),
|
|
2944
|
+
existingDocuments: (_parseJsonAttribute2 = parseJsonAttribute(element, 'data-coreai-chat-existing-documents', 'CoreAI chat existing documents')) !== null && _parseJsonAttribute2 !== void 0 ? _parseJsonAttribute2 : undefined,
|
|
2945
|
+
initialPrompt: getAttributeValue(element, 'data-coreai-chat-initial-prompt'),
|
|
2946
|
+
sessionUrlTemplate: getAttributeValue(element, 'data-coreai-chat-session-url-template'),
|
|
2947
|
+
userLabel: getAttributeValue(element, 'data-coreai-chat-user-label'),
|
|
2948
|
+
assistantLabel: getAttributeValue(element, 'data-coreai-chat-assistant-label'),
|
|
2949
|
+
copyTitle: getAttributeValue(element, 'data-coreai-chat-copy-title'),
|
|
2950
|
+
copiedTitle: getAttributeValue(element, 'data-coreai-chat-copied-title')
|
|
2951
|
+
};
|
|
2952
|
+
var booleanAttributes = {
|
|
2953
|
+
metricsEnabled: 'data-coreai-chat-metrics-enabled',
|
|
2954
|
+
textToSpeechEnabled: 'data-coreai-chat-text-to-speech-enabled',
|
|
2955
|
+
sessionDocumentsEnabled: 'data-coreai-chat-session-documents-enabled',
|
|
2956
|
+
singleResponseMode: 'data-coreai-chat-single-response-mode'
|
|
2957
|
+
};
|
|
2958
|
+
Object.keys(booleanAttributes).forEach(function (key) {
|
|
2959
|
+
var parsed = parseBooleanAttributeValue(getAttributeValue(element, booleanAttributes[key]));
|
|
2960
|
+
if (parsed !== null) {
|
|
2961
|
+
config[key] = parsed;
|
|
2962
|
+
}
|
|
2963
|
+
});
|
|
2964
|
+
return compactObject(config);
|
|
2965
|
+
}
|
|
2966
|
+
function buildConfigFromElement(element, options) {
|
|
2967
|
+
var jsonConfig = parseJsonAttribute(element, 'data-coreai-chat-config', 'CoreAI chat config');
|
|
2968
|
+
var attributeConfig = buildConfigFromDataAttributes(element, options);
|
|
2969
|
+
if (!jsonConfig && !attributeConfig) {
|
|
2970
|
+
return null;
|
|
2971
|
+
}
|
|
2972
|
+
return Object.assign({}, jsonConfig || {}, attributeConfig || {});
|
|
2973
|
+
}
|
|
2974
|
+
function initializeFromElement(element) {
|
|
2975
|
+
if (!element || element.dataset.coreAiChatInitialized === 'true') {
|
|
2976
|
+
return element ? element.__coreAIChatApp || null : null;
|
|
2977
|
+
}
|
|
2978
|
+
var config = buildConfigFromElement(element);
|
|
2979
|
+
if (!config) {
|
|
2980
|
+
return null;
|
|
2981
|
+
}
|
|
2982
|
+
var app = initialize(config);
|
|
2983
|
+
if (!app) {
|
|
2984
|
+
return null;
|
|
2985
|
+
}
|
|
2986
|
+
element.dataset.coreAiChatInitialized = 'true';
|
|
2987
|
+
element.__coreAIChatApp = app;
|
|
2988
|
+
return app;
|
|
2989
|
+
}
|
|
2990
|
+
function scanForAutoInitialization(root) {
|
|
2991
|
+
if (!root || typeof root.querySelectorAll !== 'function') {
|
|
2992
|
+
return;
|
|
2993
|
+
}
|
|
2994
|
+
if (typeof root.matches === 'function' && root.matches(autoInitializeSelector)) {
|
|
2995
|
+
initializeFromElement(root);
|
|
2996
|
+
}
|
|
2997
|
+
root.querySelectorAll(autoInitializeSelector).forEach(initializeFromElement);
|
|
2998
|
+
}
|
|
2999
|
+
function startAutoInitialization() {
|
|
3000
|
+
scanForAutoInitialization(document);
|
|
3001
|
+
if (typeof MutationObserver === 'undefined') {
|
|
3002
|
+
return;
|
|
3003
|
+
}
|
|
3004
|
+
var observer = new MutationObserver(function (mutations) {
|
|
3005
|
+
mutations.forEach(function (mutation) {
|
|
3006
|
+
mutation.addedNodes.forEach(function (node) {
|
|
3007
|
+
if (node && node.nodeType === 1) {
|
|
3008
|
+
scanForAutoInitialization(node);
|
|
3009
|
+
}
|
|
3010
|
+
});
|
|
3011
|
+
});
|
|
3012
|
+
});
|
|
3013
|
+
observer.observe(document.body, {
|
|
3014
|
+
childList: true,
|
|
3015
|
+
subtree: true
|
|
3016
|
+
});
|
|
3017
|
+
}
|
|
3018
|
+
if (document.readyState === 'loading') {
|
|
3019
|
+
document.addEventListener('DOMContentLoaded', startAutoInitialization, {
|
|
3020
|
+
once: true
|
|
3021
|
+
});
|
|
3022
|
+
} else {
|
|
3023
|
+
startAutoInitialization();
|
|
3024
|
+
}
|
|
2672
3025
|
return {
|
|
2673
|
-
initialize: initialize
|
|
3026
|
+
initialize: initialize,
|
|
3027
|
+
initializeFromElement: initializeFromElement,
|
|
3028
|
+
buildConfigFromElement: buildConfigFromElement
|
|
2674
3029
|
};
|
|
2675
3030
|
}();
|
|
2676
3031
|
|