@crestapps/ai-chat-ui 1.0.0-rc.7 → 1.0.0
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 -8
- 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 +49 -17
- package/dist/ai-chat.css.map +1 -1
- package/dist/ai-chat.js +471 -169
- 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 +63 -0
- package/dist/chat-interaction-settings.js.map +1 -1
- package/dist/chat-interaction-settings.min.js +1 -1
- package/dist/chat-interaction-settings.min.js.map +1 -1
- package/dist/chat-interaction.js +424 -163
- 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/package.json +1 -1
package/dist/chat-interaction.js
CHANGED
|
@@ -32,8 +32,11 @@ window.chatInteractionManager = function () {
|
|
|
32
32
|
downloadChartTitle: 'Download chart as image',
|
|
33
33
|
downloadChartButtonText: 'Download',
|
|
34
34
|
codeCopiedText: 'Copied!',
|
|
35
|
+
copyTitle: 'Click here to copy response to clipboard.',
|
|
36
|
+
copiedTitle: 'Response copied to clipboard.',
|
|
37
|
+
copyResetDelayMs: 2000,
|
|
35
38
|
assistantLabel: 'Assistant',
|
|
36
|
-
messageTemplate: "\n <div class=\"ai-chat-messages\">\n <div v-for=\"(message, index) in messages\" :key=\"index\" class=\"ai-chat-message-item\">\n <div>\n <div v-if=\"message.role === 'user'\" class=\"ai-chat-msg-role ai-chat-msg-role-user\">You</div>\n <div v-else-if=\"message.role !== 'indicator'\" :class=\"getAssistantRoleClasses(message)\">\n <span :class=\"getAssistantIconClasses(message, index)\"><i :class=\"getAssistantIcon(message)\"></i></span>\n {{ getAssistantLabel(message) }}\n </div>\n <div class=\"ai-chat-message-body lh-base\">\n <h4 v-if=\"message.title\">{{ message.title }}</h4>\n <div v-html=\"message.htmlContent\"></div>\n <ol v-if=\"message.citationReferences && message.citationReferences.length\" class=\"ai-chat-citation-list\">\n <li v-for=\"citation in message.citationReferences\" :key=\"'citation-' + (citation.referenceKey || citation.displayIndex)\" class=\"ai-chat-citation-item\">\n <a v-if=\"citation.link\" :href=\"citation.link\" :target=\"citation.isDownload ? null : '_blank'\" :rel=\"citation.isDownload ? null : 'noopener noreferrer'\">{{ citation.label }}</a>\n <span v-else>{{ citation.label }}</span>\n </li>\n </ol>\n <span class=\"message-buttons-container\" v-if=\"!isIndicator(message)\">\n <button v-if=\"textToSpeechEnabled && !isConversationMode && message.role === 'assistant' && !message.isStreaming\" class=\"btn btn-sm btn-link text-secondary p-0 me-1 button-message-toolbox\" :class=\"{ 'tts-playing': ttsPlayingMessageIndex === index }\" :data-tts-message-index=\"index\" @click=\"toggleMessageTts(message, index)\" :title=\"ttsPlayingMessageIndex === index ? 'Pause audio' : 'Read aloud'\">\n <i :class=\"ttsPlayingMessageIndex === index ? 'fa-solid fa-circle-pause' : 'fa-solid fa-circle-play'\"></i>\n </button>\n <button class=\"btn btn-sm btn-link
|
|
39
|
+
messageTemplate: "\n <div class=\"ai-chat-messages\">\n <div v-for=\"(message, index) in messages\" :key=\"index\" class=\"ai-chat-message-item\">\n <div>\n <div v-if=\"message.role === 'user'\" class=\"ai-chat-msg-role ai-chat-msg-role-user\">You</div>\n <div v-else-if=\"message.role !== 'indicator'\" :class=\"getAssistantRoleClasses(message)\">\n <span :class=\"getAssistantIconClasses(message, index)\"><i :class=\"getAssistantIcon(message)\"></i></span>\n {{ getAssistantLabel(message) }}\n </div>\n <div class=\"ai-chat-message-body lh-base\">\n <h4 v-if=\"message.title\">{{ message.title }}</h4>\n <div v-html=\"message.htmlContent\"></div>\n <ol v-if=\"message.citationReferences && message.citationReferences.length\" class=\"ai-chat-citation-list\">\n <li v-for=\"citation in message.citationReferences\" :key=\"'citation-' + (citation.referenceKey || citation.displayIndex)\" class=\"ai-chat-citation-item\">\n <a v-if=\"citation.link\" :href=\"citation.link\" :target=\"citation.isDownload ? null : '_blank'\" :rel=\"citation.isDownload ? null : 'noopener noreferrer'\">{{ citation.label }}</a>\n <span v-else>{{ citation.label }}</span>\n </li>\n </ol>\n <span class=\"message-buttons-container\" v-if=\"!isIndicator(message)\">\n <button v-if=\"textToSpeechEnabled && !isConversationMode && message.role === 'assistant' && !message.isStreaming\" class=\"btn btn-sm btn-link text-secondary p-0 me-1 button-message-toolbox\" :class=\"{ 'tts-playing': ttsPlayingMessageIndex === index }\" :data-tts-message-index=\"index\" @click=\"toggleMessageTts(message, index)\" :title=\"ttsPlayingMessageIndex === index ? 'Pause audio' : 'Read aloud'\">\n <i :class=\"ttsPlayingMessageIndex === index ? 'fa-solid fa-circle-pause' : 'fa-solid fa-circle-play'\"></i>\n </button>\n <button type=\"button\" class=\"btn btn-sm btn-link p-0 button-message-toolbox ai-response-copy-btn\" :class=\"copiedMessageIndex === index ? 'text-success' : 'text-secondary'\" :data-copy-message-index=\"index\" @click=\"copyResponse(message, index, $event)\" :title=\"copiedMessageIndex === index ? copiedTitle : copyTitle\">\n <i :class=\"copiedMessageIndex === index ? 'fa-solid fa-check' : 'fa-solid fa-copy'\"></i>\n </button>\n </span>\n </div>\n </div>\n </div>\n <div v-for=\"notification in notifications\" :key=\"'notif-' + notification.type\" class=\"ai-chat-notification\" :class=\"'ai-chat-notification-' + (notification.type || 'info') + ' ' + (notification.cssClass || '')\">\n <div class=\"ai-chat-notification-content\">\n <i v-if=\"notification.icon\" :class=\"notification.icon\" class=\"ai-chat-notification-icon\"></i>\n <span class=\"ai-chat-notification-text\">{{ notification.content }}</span>\n <button v-if=\"notification.dismissible\" class=\"btn btn-sm btn-link p-0 ms-2 ai-chat-notification-dismiss\" @click=\"dismissNotification(notification.type)\" title=\"Dismiss\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n <div v-if=\"notification.actions && notification.actions.length\" class=\"ai-chat-notification-actions\">\n <button v-for=\"action in notification.actions\" :key=\"action.name\" class=\"btn btn-sm\" :class=\"action.cssClass || 'btn-outline-secondary'\" @click=\"handleNotificationAction(notification.type, action.name)\">\n <i v-if=\"action.icon\" :class=\"action.icon\" class=\"me-1\"></i>\n {{ action.label }}\n </button>\n </div>\n </div>\n </div>\n ",
|
|
37
40
|
indicatorTemplate: "\n <div class=\"ai-chat-msg-role ai-chat-msg-role-assistant\">\n <span class=\"ai-streaming-icon\"><i class=\"fa fa-robot\" style=\"display: inline-block;\"></i></span>\n Assistant\n </div>\n ",
|
|
38
41
|
// Localizable strings
|
|
39
42
|
untitledText: 'Untitled',
|
|
@@ -96,7 +99,7 @@ window.chatInteractionManager = function () {
|
|
|
96
99
|
return observer;
|
|
97
100
|
}
|
|
98
101
|
function normalizeReference(reference) {
|
|
99
|
-
var _ref, _normalized$index, _ref2, _normalized$text, _ref3, _normalized$title, _ref4, _normalized$link, _ref5, _normalized$reference;
|
|
102
|
+
var _ref, _normalized$index, _ref2, _normalized$text, _ref3, _normalized$title, _ref4, _normalized$link, _ref5, _normalized$reference, _normalized$isGenerat;
|
|
100
103
|
if (!reference || _typeof(reference) !== 'object') {
|
|
101
104
|
return null;
|
|
102
105
|
}
|
|
@@ -106,6 +109,7 @@ window.chatInteractionManager = function () {
|
|
|
106
109
|
normalized.title = (_ref3 = (_normalized$title = normalized.title) !== null && _normalized$title !== void 0 ? _normalized$title : normalized.Title) !== null && _ref3 !== void 0 ? _ref3 : null;
|
|
107
110
|
normalized.link = sanitizeUrl((_ref4 = (_normalized$link = normalized.link) !== null && _normalized$link !== void 0 ? _normalized$link : normalized.Link) !== null && _ref4 !== void 0 ? _ref4 : null);
|
|
108
111
|
normalized.referenceType = (_ref5 = (_normalized$reference = normalized.referenceType) !== null && _normalized$reference !== void 0 ? _normalized$reference : normalized.ReferenceType) !== null && _ref5 !== void 0 ? _ref5 : null;
|
|
112
|
+
normalized.isGenerated = ((_normalized$isGenerat = normalized.isGenerated) !== null && _normalized$isGenerat !== void 0 ? _normalized$isGenerat : normalized.IsGenerated) === true;
|
|
109
113
|
return normalized;
|
|
110
114
|
}
|
|
111
115
|
function isDownloadCitationReference(reference) {
|
|
@@ -140,28 +144,42 @@ window.chatInteractionManager = function () {
|
|
|
140
144
|
function buildCitationDisplay(content, references) {
|
|
141
145
|
var processedContent = (content || '').trim();
|
|
142
146
|
var messageReferences = normalizeReferences(references);
|
|
143
|
-
|
|
147
|
+
var referenceEntries = Object.entries(messageReferences);
|
|
148
|
+
if (!referenceEntries.length) {
|
|
144
149
|
return {
|
|
145
150
|
content: processedContent,
|
|
146
151
|
citations: []
|
|
147
152
|
};
|
|
148
153
|
}
|
|
149
|
-
var citedRefs =
|
|
154
|
+
var citedRefs = referenceEntries.filter(function (_ref6) {
|
|
150
155
|
var _ref7 = _slicedToArray(_ref6, 1),
|
|
151
156
|
key = _ref7[0];
|
|
152
157
|
return processedContent.includes(key);
|
|
153
158
|
});
|
|
154
|
-
|
|
159
|
+
var generatedRefs = referenceEntries.filter(function (_ref8) {
|
|
160
|
+
var _ref9 = _slicedToArray(_ref8, 2),
|
|
161
|
+
key = _ref9[0],
|
|
162
|
+
value = _ref9[1];
|
|
163
|
+
return value.isGenerated && !processedContent.includes(key);
|
|
164
|
+
});
|
|
165
|
+
if (!citedRefs.length && !generatedRefs.length) {
|
|
155
166
|
return {
|
|
156
167
|
content: processedContent,
|
|
157
168
|
citations: []
|
|
158
169
|
};
|
|
159
170
|
}
|
|
160
|
-
citedRefs.sort(function (
|
|
161
|
-
var
|
|
162
|
-
a =
|
|
163
|
-
var
|
|
164
|
-
b =
|
|
171
|
+
citedRefs.sort(function (_ref0, _ref1) {
|
|
172
|
+
var _ref10 = _slicedToArray(_ref0, 2),
|
|
173
|
+
a = _ref10[1];
|
|
174
|
+
var _ref11 = _slicedToArray(_ref1, 2),
|
|
175
|
+
b = _ref11[1];
|
|
176
|
+
return a.index - b.index;
|
|
177
|
+
});
|
|
178
|
+
generatedRefs.sort(function (_ref12, _ref13) {
|
|
179
|
+
var _ref14 = _slicedToArray(_ref12, 2),
|
|
180
|
+
a = _ref14[1];
|
|
181
|
+
var _ref15 = _slicedToArray(_ref13, 2),
|
|
182
|
+
b = _ref15[1];
|
|
165
183
|
return a.index - b.index;
|
|
166
184
|
});
|
|
167
185
|
var citations = [];
|
|
@@ -195,11 +213,36 @@ window.chatInteractionManager = function () {
|
|
|
195
213
|
processedContent = processedContent.replaceAll(citation.placeholder, "<sup>".concat(citation.displayIndex, "</sup>"));
|
|
196
214
|
}
|
|
197
215
|
processedContent = processedContent.replaceAll('</sup><sup>', '</sup><sup>,</sup><sup>');
|
|
216
|
+
|
|
217
|
+
// Generated files (such as exported tabular data) are always offered as a download even when
|
|
218
|
+
// the model does not cite them inline, so the user never loses access to the produced file.
|
|
219
|
+
var _iterator2 = _createForOfIteratorHelper(generatedRefs),
|
|
220
|
+
_step2;
|
|
221
|
+
try {
|
|
222
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
223
|
+
var _step2$value = _slicedToArray(_step2.value, 2),
|
|
224
|
+
_key = _step2$value[0],
|
|
225
|
+
_value = _step2$value[1];
|
|
226
|
+
citations.push({
|
|
227
|
+
referenceKey: _key,
|
|
228
|
+
displayIndex: displayIndex,
|
|
229
|
+
label: getCitationLabel(_value, _key),
|
|
230
|
+
link: _value.link || null,
|
|
231
|
+
isDownload: true,
|
|
232
|
+
placeholder: null
|
|
233
|
+
});
|
|
234
|
+
displayIndex++;
|
|
235
|
+
}
|
|
236
|
+
} catch (err) {
|
|
237
|
+
_iterator2.e(err);
|
|
238
|
+
} finally {
|
|
239
|
+
_iterator2.f();
|
|
240
|
+
}
|
|
198
241
|
return {
|
|
199
242
|
content: processedContent,
|
|
200
|
-
citations: citations.map(function (
|
|
201
|
-
var placeholder =
|
|
202
|
-
citation = _objectWithoutProperties(
|
|
243
|
+
citations: citations.map(function (_ref16) {
|
|
244
|
+
var placeholder = _ref16.placeholder,
|
|
245
|
+
citation = _objectWithoutProperties(_ref16, _excluded);
|
|
203
246
|
return citation;
|
|
204
247
|
})
|
|
205
248
|
};
|
|
@@ -209,24 +252,24 @@ window.chatInteractionManager = function () {
|
|
|
209
252
|
if (!copyContent || !Array.isArray(citations) || citations.length === 0) {
|
|
210
253
|
return copyContent;
|
|
211
254
|
}
|
|
212
|
-
var
|
|
213
|
-
|
|
255
|
+
var _iterator3 = _createForOfIteratorHelper(citations),
|
|
256
|
+
_step3;
|
|
214
257
|
try {
|
|
215
|
-
for (
|
|
216
|
-
var citation =
|
|
258
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
259
|
+
var citation = _step3.value;
|
|
217
260
|
copyContent = copyContent.replaceAll(citation.referenceKey, "[".concat(citation.displayIndex, "]"));
|
|
218
261
|
}
|
|
219
262
|
} catch (err) {
|
|
220
|
-
|
|
263
|
+
_iterator3.e(err);
|
|
221
264
|
} finally {
|
|
222
|
-
|
|
265
|
+
_iterator3.f();
|
|
223
266
|
}
|
|
224
267
|
copyContent += '\n\nReferences:\n';
|
|
225
|
-
var
|
|
226
|
-
|
|
268
|
+
var _iterator4 = _createForOfIteratorHelper(citations),
|
|
269
|
+
_step4;
|
|
227
270
|
try {
|
|
228
|
-
for (
|
|
229
|
-
var _citation =
|
|
271
|
+
for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
|
|
272
|
+
var _citation = _step4.value;
|
|
230
273
|
copyContent += "".concat(_citation.displayIndex, ". ").concat(_citation.label);
|
|
231
274
|
if (_citation.link) {
|
|
232
275
|
copyContent += " - ".concat(_citation.link);
|
|
@@ -234,9 +277,9 @@ window.chatInteractionManager = function () {
|
|
|
234
277
|
copyContent += '\n';
|
|
235
278
|
}
|
|
236
279
|
} catch (err) {
|
|
237
|
-
|
|
280
|
+
_iterator4.e(err);
|
|
238
281
|
} finally {
|
|
239
|
-
|
|
282
|
+
_iterator4.f();
|
|
240
283
|
}
|
|
241
284
|
return copyContent.trimEnd();
|
|
242
285
|
}
|
|
@@ -416,11 +459,11 @@ window.chatInteractionManager = function () {
|
|
|
416
459
|
// Defer to requestAnimationFrame so the browser has fully laid out the
|
|
417
460
|
// canvas elements before Chart.js reads their dimensions.
|
|
418
461
|
requestAnimationFrame(function () {
|
|
419
|
-
var
|
|
420
|
-
|
|
462
|
+
var _iterator5 = _createForOfIteratorHelper(charts),
|
|
463
|
+
_step5;
|
|
421
464
|
try {
|
|
422
|
-
for (
|
|
423
|
-
var c =
|
|
465
|
+
for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
|
|
466
|
+
var c = _step5.value;
|
|
424
467
|
var canvas = document.getElementById(c.chartId);
|
|
425
468
|
if (!canvas) {
|
|
426
469
|
continue;
|
|
@@ -453,9 +496,9 @@ window.chatInteractionManager = function () {
|
|
|
453
496
|
}
|
|
454
497
|
}
|
|
455
498
|
} catch (err) {
|
|
456
|
-
|
|
499
|
+
_iterator5.e(err);
|
|
457
500
|
} finally {
|
|
458
|
-
|
|
501
|
+
_iterator5.f();
|
|
459
502
|
}
|
|
460
503
|
});
|
|
461
504
|
}
|
|
@@ -474,8 +517,18 @@ window.chatInteractionManager = function () {
|
|
|
474
517
|
ADD_ATTR: ['target']
|
|
475
518
|
});
|
|
476
519
|
}
|
|
520
|
+
function compactObject(source) {
|
|
521
|
+
if (!source || _typeof(source) !== 'object') {
|
|
522
|
+
return {};
|
|
523
|
+
}
|
|
524
|
+
return Object.fromEntries(Object.entries(source).filter(function (_ref17) {
|
|
525
|
+
var _ref18 = _slicedToArray(_ref17, 2),
|
|
526
|
+
value = _ref18[1];
|
|
527
|
+
return value !== undefined;
|
|
528
|
+
}));
|
|
529
|
+
}
|
|
477
530
|
var initialize = function initialize(instanceConfig) {
|
|
478
|
-
var config = Object.assign({}, defaultConfig, instanceConfig);
|
|
531
|
+
var config = Object.assign({}, defaultConfig, compactObject(instanceConfig));
|
|
479
532
|
// Keep defaultConfig in sync so renderers use overridden values
|
|
480
533
|
defaultConfig = config;
|
|
481
534
|
if (!config.signalRHubUrl) {
|
|
@@ -536,7 +589,12 @@ window.chatInteractionManager = function () {
|
|
|
536
589
|
conversationButton: null,
|
|
537
590
|
isConversationMode: false,
|
|
538
591
|
notifications: [],
|
|
539
|
-
notificationDismissTimers: {}
|
|
592
|
+
notificationDismissTimers: {},
|
|
593
|
+
copyTitle: config.copyTitle,
|
|
594
|
+
copiedTitle: config.copiedTitle,
|
|
595
|
+
copiedMessageIndex: -1,
|
|
596
|
+
copyResetTimeoutId: null,
|
|
597
|
+
activeCopyButton: null
|
|
540
598
|
};
|
|
541
599
|
},
|
|
542
600
|
computed: {
|
|
@@ -1035,9 +1093,9 @@ window.chatInteractionManager = function () {
|
|
|
1035
1093
|
var _this6 = this;
|
|
1036
1094
|
references = normalizeReferences(references);
|
|
1037
1095
|
if (Object.keys(references).length) {
|
|
1038
|
-
var
|
|
1096
|
+
var _ref19, _message$rawContent2;
|
|
1039
1097
|
var message = this.messages[messageIndex];
|
|
1040
|
-
message.rawContent = (
|
|
1098
|
+
message.rawContent = (_ref19 = (_message$rawContent2 = message.rawContent) !== null && _message$rawContent2 !== void 0 ? _message$rawContent2 : message.content) !== null && _ref19 !== void 0 ? _ref19 : '';
|
|
1041
1099
|
updateMessagePresentation(message, references);
|
|
1042
1100
|
this.messages[messageIndex] = message;
|
|
1043
1101
|
this.$nextTick(function () {
|
|
@@ -1107,8 +1165,38 @@ window.chatInteractionManager = function () {
|
|
|
1107
1165
|
}));
|
|
1108
1166
|
});
|
|
1109
1167
|
},
|
|
1110
|
-
|
|
1168
|
+
updateCopyButtons: function updateCopyButtons() {
|
|
1111
1169
|
var _this8 = this;
|
|
1170
|
+
if (!this.chatContainer) {
|
|
1171
|
+
return;
|
|
1172
|
+
}
|
|
1173
|
+
var buttons = this.chatContainer.querySelectorAll('[data-copy-message-index]');
|
|
1174
|
+
buttons.forEach(function (button) {
|
|
1175
|
+
var buttonIndex = Number(button.getAttribute('data-copy-message-index'));
|
|
1176
|
+
var isCopied = buttonIndex === _this8.copiedMessageIndex;
|
|
1177
|
+
var iconHtml = isCopied ? '<i class="fa-solid fa-check"></i>' : '<i class="fa-solid fa-copy"></i>';
|
|
1178
|
+
button.classList.toggle('text-success', isCopied);
|
|
1179
|
+
button.classList.toggle('text-secondary', !isCopied);
|
|
1180
|
+
button.setAttribute('title', isCopied ? _this8.copiedTitle : _this8.copyTitle);
|
|
1181
|
+
button.replaceChildren(DOMPurify.sanitize(iconHtml, {
|
|
1182
|
+
RETURN_DOM_FRAGMENT: true
|
|
1183
|
+
}));
|
|
1184
|
+
});
|
|
1185
|
+
},
|
|
1186
|
+
setCopyButtonState: function setCopyButtonState(button, isCopied) {
|
|
1187
|
+
if (!button) {
|
|
1188
|
+
return;
|
|
1189
|
+
}
|
|
1190
|
+
var iconHtml = isCopied ? '<i class="fa-solid fa-check"></i>' : '<i class="fa-solid fa-copy"></i>';
|
|
1191
|
+
button.classList.toggle('text-success', isCopied);
|
|
1192
|
+
button.classList.toggle('text-secondary', !isCopied);
|
|
1193
|
+
button.setAttribute('title', isCopied ? this.copiedTitle : this.copyTitle);
|
|
1194
|
+
button.replaceChildren(DOMPurify.sanitize(iconHtml, {
|
|
1195
|
+
RETURN_DOM_FRAGMENT: true
|
|
1196
|
+
}));
|
|
1197
|
+
},
|
|
1198
|
+
synthesizeSpeech: function synthesizeSpeech(text, cacheIndex) {
|
|
1199
|
+
var _this9 = this;
|
|
1112
1200
|
if (!this.textToSpeechEnabled || !text || !this.connection) {
|
|
1113
1201
|
return;
|
|
1114
1202
|
}
|
|
@@ -1117,16 +1205,16 @@ window.chatInteractionManager = function () {
|
|
|
1117
1205
|
this._ttsCacheIndex = cacheIndex !== undefined ? cacheIndex : -1;
|
|
1118
1206
|
this.connection.invoke("SynthesizeSpeech", this.getItemId(), text, this.ttsVoiceName)["catch"](function (err) {
|
|
1119
1207
|
console.error("TTS synthesis error:", err);
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
return
|
|
1208
|
+
_this9.isPlayingAudio = false;
|
|
1209
|
+
_this9.ttsPlayingMessageIndex = -1;
|
|
1210
|
+
_this9._ttsCacheIndex = -1;
|
|
1211
|
+
_this9.$nextTick(function () {
|
|
1212
|
+
return _this9.updateTtsPlaybackButtons();
|
|
1125
1213
|
});
|
|
1126
1214
|
});
|
|
1127
1215
|
},
|
|
1128
1216
|
toggleMessageTts: function toggleMessageTts(message, index) {
|
|
1129
|
-
var
|
|
1217
|
+
var _this0 = this;
|
|
1130
1218
|
if (this.ttsPlayingMessageIndex === index) {
|
|
1131
1219
|
this.stopAudio();
|
|
1132
1220
|
return;
|
|
@@ -1139,7 +1227,7 @@ window.chatInteractionManager = function () {
|
|
|
1139
1227
|
}));
|
|
1140
1228
|
this.ttsPlayingMessageIndex = index;
|
|
1141
1229
|
this.$nextTick(function () {
|
|
1142
|
-
return
|
|
1230
|
+
return _this0.updateTtsPlaybackButtons();
|
|
1143
1231
|
});
|
|
1144
1232
|
if (this.ttsAudioCache[index]) {
|
|
1145
1233
|
this.playAudioBlob(this.ttsAudioCache[index]);
|
|
@@ -1148,13 +1236,13 @@ window.chatInteractionManager = function () {
|
|
|
1148
1236
|
this.synthesizeSpeech(message.content, index);
|
|
1149
1237
|
},
|
|
1150
1238
|
playCollectedAudio: function playCollectedAudio() {
|
|
1151
|
-
var
|
|
1239
|
+
var _this1 = this;
|
|
1152
1240
|
if (this.audioChunks.length === 0) {
|
|
1153
1241
|
if (!this.isPlayingAudio && this.audioPlayQueue.length === 0) {
|
|
1154
1242
|
this.isPlayingAudio = false;
|
|
1155
1243
|
this.ttsPlayingMessageIndex = -1;
|
|
1156
1244
|
this.$nextTick(function () {
|
|
1157
|
-
return
|
|
1245
|
+
return _this1.updateTtsPlaybackButtons();
|
|
1158
1246
|
});
|
|
1159
1247
|
}
|
|
1160
1248
|
return;
|
|
@@ -1164,18 +1252,18 @@ window.chatInteractionManager = function () {
|
|
|
1164
1252
|
}, 0);
|
|
1165
1253
|
var combined = new Uint8Array(totalLength);
|
|
1166
1254
|
var offset = 0;
|
|
1167
|
-
var
|
|
1168
|
-
|
|
1255
|
+
var _iterator6 = _createForOfIteratorHelper(this.audioChunks),
|
|
1256
|
+
_step6;
|
|
1169
1257
|
try {
|
|
1170
|
-
for (
|
|
1171
|
-
var chunk =
|
|
1258
|
+
for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
|
|
1259
|
+
var chunk = _step6.value;
|
|
1172
1260
|
combined.set(chunk, offset);
|
|
1173
1261
|
offset += chunk.length;
|
|
1174
1262
|
}
|
|
1175
1263
|
} catch (err) {
|
|
1176
|
-
|
|
1264
|
+
_iterator6.e(err);
|
|
1177
1265
|
} finally {
|
|
1178
|
-
|
|
1266
|
+
_iterator6.f();
|
|
1179
1267
|
}
|
|
1180
1268
|
this.audioChunks = [];
|
|
1181
1269
|
var blob = new Blob([combined], {
|
|
@@ -1194,39 +1282,39 @@ window.chatInteractionManager = function () {
|
|
|
1194
1282
|
this.playAudioBlob(blob);
|
|
1195
1283
|
},
|
|
1196
1284
|
playAudioBlob: function playAudioBlob(blob) {
|
|
1197
|
-
var
|
|
1285
|
+
var _this10 = this;
|
|
1198
1286
|
var url = URL.createObjectURL(blob);
|
|
1199
1287
|
var audio = new Audio(url);
|
|
1200
1288
|
this.currentAudioUrl = url;
|
|
1201
1289
|
this.currentAudioElement = audio;
|
|
1202
1290
|
this.isPlayingAudio = true;
|
|
1203
1291
|
audio.addEventListener('ended', function () {
|
|
1204
|
-
|
|
1205
|
-
|
|
1292
|
+
_this10.currentAudioElement = null;
|
|
1293
|
+
_this10.currentAudioUrl = null;
|
|
1206
1294
|
URL.revokeObjectURL(url);
|
|
1207
|
-
|
|
1295
|
+
_this10.playNextInQueue();
|
|
1208
1296
|
});
|
|
1209
1297
|
audio.addEventListener('error', function () {
|
|
1210
|
-
|
|
1211
|
-
|
|
1298
|
+
_this10.currentAudioElement = null;
|
|
1299
|
+
_this10.currentAudioUrl = null;
|
|
1212
1300
|
URL.revokeObjectURL(url);
|
|
1213
|
-
|
|
1301
|
+
_this10.playNextInQueue();
|
|
1214
1302
|
});
|
|
1215
1303
|
audio.play()["catch"](function (err) {
|
|
1216
1304
|
console.error("Audio playback error:", err);
|
|
1217
|
-
|
|
1218
|
-
|
|
1305
|
+
_this10.currentAudioElement = null;
|
|
1306
|
+
_this10.currentAudioUrl = null;
|
|
1219
1307
|
URL.revokeObjectURL(url);
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
return
|
|
1308
|
+
_this10.audioPlayQueue = [];
|
|
1309
|
+
_this10.isPlayingAudio = false;
|
|
1310
|
+
_this10.ttsPlayingMessageIndex = -1;
|
|
1311
|
+
_this10.$nextTick(function () {
|
|
1312
|
+
return _this10.updateTtsPlaybackButtons();
|
|
1225
1313
|
});
|
|
1226
1314
|
});
|
|
1227
1315
|
},
|
|
1228
1316
|
playNextInQueue: function playNextInQueue() {
|
|
1229
|
-
var
|
|
1317
|
+
var _this11 = this;
|
|
1230
1318
|
if (this.audioPlayQueue.length > 0) {
|
|
1231
1319
|
var nextBlob = this.audioPlayQueue.shift();
|
|
1232
1320
|
this.playAudioBlob(nextBlob);
|
|
@@ -1234,13 +1322,13 @@ window.chatInteractionManager = function () {
|
|
|
1234
1322
|
this.isPlayingAudio = false;
|
|
1235
1323
|
this.ttsPlayingMessageIndex = -1;
|
|
1236
1324
|
this.$nextTick(function () {
|
|
1237
|
-
return
|
|
1325
|
+
return _this11.updateTtsPlaybackButtons();
|
|
1238
1326
|
});
|
|
1239
1327
|
this.conversationModeOnAudioEnded();
|
|
1240
1328
|
}
|
|
1241
1329
|
},
|
|
1242
1330
|
stopAudio: function stopAudio() {
|
|
1243
|
-
var
|
|
1331
|
+
var _this12 = this;
|
|
1244
1332
|
if (this.currentAudioElement) {
|
|
1245
1333
|
this.currentAudioElement.pause();
|
|
1246
1334
|
this.currentAudioElement.currentTime = 0;
|
|
@@ -1255,7 +1343,7 @@ window.chatInteractionManager = function () {
|
|
|
1255
1343
|
this.isPlayingAudio = false;
|
|
1256
1344
|
this.ttsPlayingMessageIndex = -1;
|
|
1257
1345
|
this.$nextTick(function () {
|
|
1258
|
-
return
|
|
1346
|
+
return _this12.updateTtsPlaybackButtons();
|
|
1259
1347
|
});
|
|
1260
1348
|
},
|
|
1261
1349
|
toggleConversationMode: function toggleConversationMode() {
|
|
@@ -1266,7 +1354,7 @@ window.chatInteractionManager = function () {
|
|
|
1266
1354
|
}
|
|
1267
1355
|
},
|
|
1268
1356
|
startConversationMode: function startConversationMode() {
|
|
1269
|
-
var
|
|
1357
|
+
var _this13 = this;
|
|
1270
1358
|
if (!this.conversationModeEnabled || this.isConversationMode || !this.connection) {
|
|
1271
1359
|
return;
|
|
1272
1360
|
}
|
|
@@ -1286,30 +1374,30 @@ window.chatInteractionManager = function () {
|
|
|
1286
1374
|
}
|
|
1287
1375
|
}).then(function (stream) {
|
|
1288
1376
|
var mimeType = MediaRecorder.isTypeSupported('audio/ogg;codecs=opus') ? 'audio/ogg;codecs=opus' : MediaRecorder.isTypeSupported('audio/webm;codecs=opus') ? 'audio/webm;codecs=opus' : 'audio/webm';
|
|
1289
|
-
|
|
1377
|
+
_this13.mediaRecorder = new MediaRecorder(stream, {
|
|
1290
1378
|
mimeType: mimeType,
|
|
1291
1379
|
audioBitsPerSecond: 128000
|
|
1292
1380
|
});
|
|
1293
|
-
|
|
1294
|
-
|
|
1381
|
+
_this13._conversationSubject = new signalR.Subject();
|
|
1382
|
+
_this13._conversationStream = stream;
|
|
1295
1383
|
|
|
1296
1384
|
// Create an AnalyserNode for volume-based interrupt detection.
|
|
1297
1385
|
var AudioCtx = window.AudioContext || window.webkitAudioContext;
|
|
1298
1386
|
if (AudioCtx) {
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
var micSource =
|
|
1303
|
-
micSource.connect(
|
|
1387
|
+
_this13._conversationAudioCtx = new AudioCtx();
|
|
1388
|
+
_this13._conversationAnalyser = _this13._conversationAudioCtx.createAnalyser();
|
|
1389
|
+
_this13._conversationAnalyser.fftSize = 256;
|
|
1390
|
+
var micSource = _this13._conversationAudioCtx.createMediaStreamSource(stream);
|
|
1391
|
+
micSource.connect(_this13._conversationAnalyser);
|
|
1304
1392
|
}
|
|
1305
1393
|
var pendingChunk = Promise.resolve();
|
|
1306
|
-
var analyser =
|
|
1394
|
+
var analyser = _this13._conversationAnalyser;
|
|
1307
1395
|
var interruptVolumeThreshold = 30;
|
|
1308
|
-
|
|
1396
|
+
_this13.mediaRecorder.addEventListener('dataavailable', function (e) {
|
|
1309
1397
|
if (e.data && e.data.size > 0) {
|
|
1310
1398
|
// During TTS playback, check mic volume to detect
|
|
1311
1399
|
// user interruption (speaking above threshold).
|
|
1312
|
-
if (
|
|
1400
|
+
if (_this13.isPlayingAudio && analyser) {
|
|
1313
1401
|
var freqData = new Uint8Array(analyser.frequencyBinCount);
|
|
1314
1402
|
analyser.getByteFrequencyData(freqData);
|
|
1315
1403
|
var sum = 0;
|
|
@@ -1319,7 +1407,7 @@ window.chatInteractionManager = function () {
|
|
|
1319
1407
|
var avg = sum / freqData.length;
|
|
1320
1408
|
if (avg >= interruptVolumeThreshold) {
|
|
1321
1409
|
// User is speaking — interrupt TTS playback.
|
|
1322
|
-
|
|
1410
|
+
_this13.stopAudio();
|
|
1323
1411
|
}
|
|
1324
1412
|
}
|
|
1325
1413
|
|
|
@@ -1341,7 +1429,7 @@ window.chatInteractionManager = function () {
|
|
|
1341
1429
|
}, '');
|
|
1342
1430
|
base64 = btoa(binaryString);
|
|
1343
1431
|
try {
|
|
1344
|
-
|
|
1432
|
+
_this13._conversationSubject.next(base64);
|
|
1345
1433
|
} catch (err) {
|
|
1346
1434
|
// Subject may have been completed already.
|
|
1347
1435
|
}
|
|
@@ -1352,27 +1440,27 @@ window.chatInteractionManager = function () {
|
|
|
1352
1440
|
})));
|
|
1353
1441
|
}
|
|
1354
1442
|
});
|
|
1355
|
-
|
|
1443
|
+
_this13.mediaRecorder.addEventListener('stop', function () {
|
|
1356
1444
|
stream.getTracks().forEach(function (track) {
|
|
1357
1445
|
return track.stop();
|
|
1358
1446
|
});
|
|
1359
1447
|
pendingChunk.then(function () {
|
|
1360
1448
|
try {
|
|
1361
|
-
|
|
1449
|
+
_this13._conversationSubject.complete();
|
|
1362
1450
|
} catch (err) {
|
|
1363
1451
|
// Already completed.
|
|
1364
1452
|
}
|
|
1365
1453
|
});
|
|
1366
1454
|
});
|
|
1367
|
-
var itemId =
|
|
1455
|
+
var itemId = _this13.getItemId();
|
|
1368
1456
|
var language = navigator.language || document.documentElement.lang || 'en-US';
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1457
|
+
_this13.connection.send("StartConversation", itemId, _this13._conversationSubject, mimeType, language);
|
|
1458
|
+
_this13.mediaRecorder.start(250);
|
|
1459
|
+
_this13.isRecording = true;
|
|
1372
1460
|
})["catch"](function (err) {
|
|
1373
1461
|
console.error('Microphone access denied:', err);
|
|
1374
|
-
|
|
1375
|
-
|
|
1462
|
+
_this13.isConversationMode = false;
|
|
1463
|
+
_this13.updateConversationButton();
|
|
1376
1464
|
});
|
|
1377
1465
|
},
|
|
1378
1466
|
stopConversationMode: function stopConversationMode() {
|
|
@@ -1476,12 +1564,12 @@ window.chatInteractionManager = function () {
|
|
|
1476
1564
|
return removedCount;
|
|
1477
1565
|
},
|
|
1478
1566
|
scrollToBottom: function scrollToBottom() {
|
|
1479
|
-
var
|
|
1567
|
+
var _this14 = this;
|
|
1480
1568
|
if (!this.autoScroll) {
|
|
1481
1569
|
return;
|
|
1482
1570
|
}
|
|
1483
1571
|
setTimeout(function () {
|
|
1484
|
-
|
|
1572
|
+
_this14.chatContainer.scrollTop = _this14.chatContainer.scrollHeight - _this14.chatContainer.clientHeight;
|
|
1485
1573
|
}, 50);
|
|
1486
1574
|
},
|
|
1487
1575
|
handleUserInput: function handleUserInput(event) {
|
|
@@ -1497,7 +1585,7 @@ window.chatInteractionManager = function () {
|
|
|
1497
1585
|
return document.querySelector('[data-chat-interaction-save-indicator]');
|
|
1498
1586
|
},
|
|
1499
1587
|
showSaveIndicator: function showSaveIndicator(text, className) {
|
|
1500
|
-
var
|
|
1588
|
+
var _this15 = this;
|
|
1501
1589
|
var indicator = this.getSaveIndicatorElement();
|
|
1502
1590
|
if (!indicator) {
|
|
1503
1591
|
return;
|
|
@@ -1513,7 +1601,7 @@ window.chatInteractionManager = function () {
|
|
|
1513
1601
|
}
|
|
1514
1602
|
this.saveIndicatorTimeout = setTimeout(function () {
|
|
1515
1603
|
indicator.textContent = '';
|
|
1516
|
-
|
|
1604
|
+
_this15.saveIndicatorTimeout = null;
|
|
1517
1605
|
}, 3000);
|
|
1518
1606
|
},
|
|
1519
1607
|
clearPendingSettingsSave: function clearPendingSettingsSave() {
|
|
@@ -1587,10 +1675,10 @@ window.chatInteractionManager = function () {
|
|
|
1587
1675
|
return false;
|
|
1588
1676
|
},
|
|
1589
1677
|
validateSettings: function validateSettings() {
|
|
1590
|
-
var
|
|
1678
|
+
var _this16 = this;
|
|
1591
1679
|
var isValid = true;
|
|
1592
1680
|
this.getSettingInputs().forEach(function (input) {
|
|
1593
|
-
isValid =
|
|
1681
|
+
isValid = _this16.validateSettingInput(input) && isValid;
|
|
1594
1682
|
});
|
|
1595
1683
|
return isValid;
|
|
1596
1684
|
},
|
|
@@ -1686,12 +1774,12 @@ window.chatInteractionManager = function () {
|
|
|
1686
1774
|
}
|
|
1687
1775
|
},
|
|
1688
1776
|
scheduleNotificationDismiss: function scheduleNotificationDismiss(notification) {
|
|
1689
|
-
var
|
|
1777
|
+
var _this17 = this;
|
|
1690
1778
|
if (!notification || !notification.type || !notification.autoDismissMs || notification.autoDismissMs <= 0) {
|
|
1691
1779
|
return;
|
|
1692
1780
|
}
|
|
1693
1781
|
this.notificationDismissTimers[notification.type] = setTimeout(function () {
|
|
1694
|
-
|
|
1782
|
+
_this17.removeNotification(notification.type);
|
|
1695
1783
|
}, notification.autoDismissMs);
|
|
1696
1784
|
},
|
|
1697
1785
|
clearNotificationDismiss: function clearNotificationDismiss(notificationType) {
|
|
@@ -1731,7 +1819,7 @@ window.chatInteractionManager = function () {
|
|
|
1731
1819
|
this.showPlaceholder();
|
|
1732
1820
|
},
|
|
1733
1821
|
initializeApp: function initializeApp() {
|
|
1734
|
-
var
|
|
1822
|
+
var _this18 = this;
|
|
1735
1823
|
this.inputElement = document.querySelector(config.inputElementSelector);
|
|
1736
1824
|
this.buttonElement = document.querySelector(config.sendButtonElementSelector);
|
|
1737
1825
|
this.chatContainer = document.querySelector(config.chatContainerElementSelector);
|
|
@@ -1743,59 +1831,59 @@ window.chatInteractionManager = function () {
|
|
|
1743
1831
|
|
|
1744
1832
|
// Pause auto-scroll when the user manually scrolls up during streaming.
|
|
1745
1833
|
this.chatContainer.addEventListener('scroll', function () {
|
|
1746
|
-
if (!
|
|
1834
|
+
if (!_this18.stream) {
|
|
1747
1835
|
return;
|
|
1748
1836
|
}
|
|
1749
1837
|
var threshold = 30;
|
|
1750
|
-
var atBottom =
|
|
1751
|
-
|
|
1838
|
+
var atBottom = _this18.chatContainer.scrollHeight - _this18.chatContainer.clientHeight - _this18.chatContainer.scrollTop <= threshold;
|
|
1839
|
+
_this18.autoScroll = atBottom;
|
|
1752
1840
|
});
|
|
1753
1841
|
this.inputElement.addEventListener('keyup', function (event) {
|
|
1754
|
-
if (
|
|
1842
|
+
if (_this18.stream != null) {
|
|
1755
1843
|
return;
|
|
1756
1844
|
}
|
|
1757
1845
|
if (event.key === "Enter" && !event.shiftKey) {
|
|
1758
|
-
|
|
1846
|
+
_this18.buttonElement.click();
|
|
1759
1847
|
}
|
|
1760
1848
|
});
|
|
1761
1849
|
this.inputElement.addEventListener('input', function (e) {
|
|
1762
|
-
|
|
1850
|
+
_this18.handleUserInput(e);
|
|
1763
1851
|
if (e.target.value.trim()) {
|
|
1764
|
-
|
|
1852
|
+
_this18.buttonElement.removeAttribute('disabled');
|
|
1765
1853
|
} else {
|
|
1766
|
-
|
|
1854
|
+
_this18.buttonElement.setAttribute('disabled', true);
|
|
1767
1855
|
}
|
|
1768
1856
|
});
|
|
1769
1857
|
this.inputElement.addEventListener('paste', function (e) {
|
|
1770
1858
|
// Use setTimeout to allow the paste to complete before checking the value
|
|
1771
1859
|
setTimeout(function () {
|
|
1772
|
-
|
|
1773
|
-
if (
|
|
1774
|
-
|
|
1860
|
+
_this18.prompt = _this18.inputElement.value;
|
|
1861
|
+
if (_this18.inputElement.value.trim()) {
|
|
1862
|
+
_this18.buttonElement.removeAttribute('disabled');
|
|
1775
1863
|
} else {
|
|
1776
|
-
|
|
1864
|
+
_this18.buttonElement.setAttribute('disabled', true);
|
|
1777
1865
|
}
|
|
1778
1866
|
}, 0);
|
|
1779
1867
|
});
|
|
1780
1868
|
this.buttonElement.addEventListener('click', function () {
|
|
1781
|
-
if (
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1869
|
+
if (_this18.stream != null) {
|
|
1870
|
+
_this18.stream.dispose();
|
|
1871
|
+
_this18.stream = null;
|
|
1872
|
+
_this18.streamingFinished();
|
|
1873
|
+
_this18.hideTypingIndicator();
|
|
1786
1874
|
|
|
1787
1875
|
// Clean up: remove empty assistant message or stop streaming animation.
|
|
1788
|
-
if (
|
|
1789
|
-
var lastMsg =
|
|
1876
|
+
if (_this18.messages.length > 0) {
|
|
1877
|
+
var lastMsg = _this18.messages[_this18.messages.length - 1];
|
|
1790
1878
|
if (lastMsg.role === 'assistant' && !lastMsg.content) {
|
|
1791
|
-
|
|
1879
|
+
_this18.messages.pop();
|
|
1792
1880
|
} else if (lastMsg.isStreaming) {
|
|
1793
1881
|
lastMsg.isStreaming = false;
|
|
1794
1882
|
}
|
|
1795
1883
|
}
|
|
1796
1884
|
return;
|
|
1797
1885
|
}
|
|
1798
|
-
|
|
1886
|
+
_this18.sendMessage();
|
|
1799
1887
|
});
|
|
1800
1888
|
var chatInteractionItems = document.getElementsByClassName('chat-interaction-history-item');
|
|
1801
1889
|
for (var i = 0; i < chatInteractionItems.length; i++) {
|
|
@@ -1806,11 +1894,12 @@ window.chatInteractionManager = function () {
|
|
|
1806
1894
|
console.error('An element with the class chat-interaction-history-item with no data-interaction-id set.');
|
|
1807
1895
|
return;
|
|
1808
1896
|
}
|
|
1809
|
-
|
|
1897
|
+
_this18.loadInteraction(itemId);
|
|
1810
1898
|
});
|
|
1811
1899
|
}
|
|
1812
|
-
|
|
1813
|
-
|
|
1900
|
+
var initialMessages = Array.isArray(config.messages) ? config.messages : [];
|
|
1901
|
+
for (var _i4 = 0; _i4 < initialMessages.length; _i4++) {
|
|
1902
|
+
this.addMessage(initialMessages[_i4]);
|
|
1814
1903
|
}
|
|
1815
1904
|
|
|
1816
1905
|
// Delegate click for code block copy buttons.
|
|
@@ -1837,20 +1926,20 @@ window.chatInteractionManager = function () {
|
|
|
1837
1926
|
}
|
|
1838
1927
|
document.addEventListener('input', function (event) {
|
|
1839
1928
|
if (event.target.matches('.setting-input[data-setting]')) {
|
|
1840
|
-
|
|
1841
|
-
|
|
1929
|
+
_this18.validateSettingInput(event.target);
|
|
1930
|
+
_this18.queueSettingsSave();
|
|
1842
1931
|
}
|
|
1843
1932
|
});
|
|
1844
1933
|
document.addEventListener('change', function (event) {
|
|
1845
1934
|
if (event.target.matches('.setting-input[data-setting], .capability-checkbox[data-save-group], .capability-checkbox[data-group], .group-toggle, .ci-agent-global-toggle')) {
|
|
1846
1935
|
if (event.target.matches('.setting-input[data-setting]')) {
|
|
1847
|
-
|
|
1936
|
+
_this18.validateSettingInput(event.target);
|
|
1848
1937
|
}
|
|
1849
|
-
|
|
1938
|
+
_this18.queueSettingsSave();
|
|
1850
1939
|
return;
|
|
1851
1940
|
}
|
|
1852
1941
|
if (event.target.closest('.prompt-template-parameters-input, .prompt-template-id-input')) {
|
|
1853
|
-
|
|
1942
|
+
_this18.queueSettingsSave();
|
|
1854
1943
|
}
|
|
1855
1944
|
});
|
|
1856
1945
|
document.addEventListener('click', function (event) {
|
|
@@ -1858,7 +1947,7 @@ window.chatInteractionManager = function () {
|
|
|
1858
1947
|
return;
|
|
1859
1948
|
}
|
|
1860
1949
|
setTimeout(function () {
|
|
1861
|
-
|
|
1950
|
+
_this18.queueSettingsSave();
|
|
1862
1951
|
}, 0);
|
|
1863
1952
|
});
|
|
1864
1953
|
|
|
@@ -1868,7 +1957,7 @@ window.chatInteractionManager = function () {
|
|
|
1868
1957
|
clearHistoryBtn.addEventListener('click', function () {
|
|
1869
1958
|
var itemId = clearHistoryBtn.getAttribute('data-interaction-id');
|
|
1870
1959
|
if (itemId) {
|
|
1871
|
-
|
|
1960
|
+
_this18.clearHistory(itemId);
|
|
1872
1961
|
}
|
|
1873
1962
|
});
|
|
1874
1963
|
}
|
|
@@ -1879,7 +1968,7 @@ window.chatInteractionManager = function () {
|
|
|
1879
1968
|
if (this.micButton) {
|
|
1880
1969
|
this.micButton.style.display = '';
|
|
1881
1970
|
this.micButton.addEventListener('click', function () {
|
|
1882
|
-
|
|
1971
|
+
_this18.toggleRecording();
|
|
1883
1972
|
});
|
|
1884
1973
|
}
|
|
1885
1974
|
}
|
|
@@ -1889,7 +1978,7 @@ window.chatInteractionManager = function () {
|
|
|
1889
1978
|
this.conversationButton = document.querySelector(config.conversationButtonElementSelector);
|
|
1890
1979
|
if (this.conversationButton) {
|
|
1891
1980
|
this.conversationButton.addEventListener('click', function () {
|
|
1892
|
-
|
|
1981
|
+
_this18.toggleConversationMode();
|
|
1893
1982
|
});
|
|
1894
1983
|
}
|
|
1895
1984
|
}
|
|
@@ -1938,7 +2027,7 @@ window.chatInteractionManager = function () {
|
|
|
1938
2027
|
}
|
|
1939
2028
|
},
|
|
1940
2029
|
debouncedSaveSettings: function debouncedSaveSettings() {
|
|
1941
|
-
var
|
|
2030
|
+
var _this19 = this;
|
|
1942
2031
|
// Clear any existing timeout to reset the debounce timer
|
|
1943
2032
|
this.clearPendingSettingsSave();
|
|
1944
2033
|
|
|
@@ -1949,11 +2038,11 @@ window.chatInteractionManager = function () {
|
|
|
1949
2038
|
|
|
1950
2039
|
// Set a new timeout to save after 850ms of no changes
|
|
1951
2040
|
this.saveSettingsTimeout = setTimeout(function () {
|
|
1952
|
-
if (
|
|
1953
|
-
|
|
1954
|
-
|
|
2041
|
+
if (_this19.settingsDirty) {
|
|
2042
|
+
_this19.saveSettings();
|
|
2043
|
+
_this19.settingsDirty = false;
|
|
1955
2044
|
}
|
|
1956
|
-
|
|
2045
|
+
_this19.saveSettingsTimeout = null;
|
|
1957
2046
|
}, 850);
|
|
1958
2047
|
},
|
|
1959
2048
|
getSelectedToolNames: function getSelectedToolNames() {
|
|
@@ -1969,7 +2058,7 @@ window.chatInteractionManager = function () {
|
|
|
1969
2058
|
return this.getSelectedGroupValues('agentNames', 'input[type="checkbox"][name$="].IsSelected"][name^="ChatInteraction.Agents["]:checked');
|
|
1970
2059
|
},
|
|
1971
2060
|
saveSettings: function saveSettings() {
|
|
1972
|
-
var
|
|
2061
|
+
var _this20 = this;
|
|
1973
2062
|
var itemId = this.getItemId();
|
|
1974
2063
|
if (!itemId) {
|
|
1975
2064
|
return Promise.resolve();
|
|
@@ -2014,7 +2103,7 @@ window.chatInteractionManager = function () {
|
|
|
2014
2103
|
}
|
|
2015
2104
|
return this.connection.invoke("SaveSettings", itemId, settings)["catch"](function (err) {
|
|
2016
2105
|
console.error('Error saving settings:', err);
|
|
2017
|
-
|
|
2106
|
+
_this20.showSaveIndicator('Save failed', 'text-danger');
|
|
2018
2107
|
});
|
|
2019
2108
|
},
|
|
2020
2109
|
flushPendingSave: function flushPendingSave() {
|
|
@@ -2040,13 +2129,48 @@ window.chatInteractionManager = function () {
|
|
|
2040
2129
|
this.setItemId(itemId);
|
|
2041
2130
|
this.isInteractionStarted = true;
|
|
2042
2131
|
},
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2132
|
+
clearCopiedMessageState: function clearCopiedMessageState() {
|
|
2133
|
+
if (this.copyResetTimeoutId) {
|
|
2134
|
+
window.clearTimeout(this.copyResetTimeoutId);
|
|
2135
|
+
this.copyResetTimeoutId = null;
|
|
2136
|
+
}
|
|
2137
|
+
if (this.activeCopyButton) {
|
|
2138
|
+
this.setCopyButtonState(this.activeCopyButton, false);
|
|
2139
|
+
this.activeCopyButton = null;
|
|
2140
|
+
}
|
|
2141
|
+
this.copiedMessageIndex = -1;
|
|
2142
|
+
},
|
|
2143
|
+
copyResponse: function copyResponse(message, index, event) {
|
|
2144
|
+
var _ref21,
|
|
2145
|
+
_message$copyContent,
|
|
2146
|
+
_event$target,
|
|
2147
|
+
_event$target$closest,
|
|
2148
|
+
_this21 = this;
|
|
2149
|
+
var text = message && _typeof(message) === 'object' ? (_ref21 = (_message$copyContent = message.copyContent) !== null && _message$copyContent !== void 0 ? _message$copyContent : message.content) !== null && _ref21 !== void 0 ? _ref21 : '' : message !== null && message !== void 0 ? message : '';
|
|
2150
|
+
var button = (event === null || event === void 0 ? void 0 : event.currentTarget) || (event === null || event === void 0 || (_event$target = event.target) === null || _event$target === void 0 || (_event$target$closest = _event$target.closest) === null || _event$target$closest === void 0 ? void 0 : _event$target$closest.call(_event$target, '[data-copy-message-index]')) || null;
|
|
2151
|
+
navigator.clipboard.writeText(text).then(function () {
|
|
2152
|
+
_this21.clearCopiedMessageState();
|
|
2153
|
+
_this21.copiedMessageIndex = typeof index === 'number' ? index : -1;
|
|
2154
|
+
_this21.activeCopyButton = button;
|
|
2155
|
+
if (button) {
|
|
2156
|
+
_this21.setCopyButtonState(button, true);
|
|
2157
|
+
} else {
|
|
2158
|
+
_this21.$nextTick(function () {
|
|
2159
|
+
return _this21.updateCopyButtons();
|
|
2160
|
+
});
|
|
2161
|
+
}
|
|
2162
|
+
_this21.copyResetTimeoutId = window.setTimeout(function () {
|
|
2163
|
+
_this21.clearCopiedMessageState();
|
|
2164
|
+
_this21.$nextTick(function () {
|
|
2165
|
+
return _this21.updateCopyButtons();
|
|
2166
|
+
});
|
|
2167
|
+
}, Number(config.copyResetDelayMs) || 2000);
|
|
2168
|
+
})["catch"](function (err) {
|
|
2169
|
+
return console.error('Failed to copy response:', err);
|
|
2170
|
+
});
|
|
2047
2171
|
},
|
|
2048
2172
|
startRecording: function startRecording() {
|
|
2049
|
-
var
|
|
2173
|
+
var _this22 = this;
|
|
2050
2174
|
if (this.isRecording || !this.connection) {
|
|
2051
2175
|
return;
|
|
2052
2176
|
}
|
|
@@ -2058,16 +2182,16 @@ window.chatInteractionManager = function () {
|
|
|
2058
2182
|
}
|
|
2059
2183
|
}).then(function (stream) {
|
|
2060
2184
|
var mimeType = MediaRecorder.isTypeSupported('audio/ogg;codecs=opus') ? 'audio/ogg;codecs=opus' : MediaRecorder.isTypeSupported('audio/webm;codecs=opus') ? 'audio/webm;codecs=opus' : 'audio/webm';
|
|
2061
|
-
|
|
2185
|
+
_this22.mediaRecorder = new MediaRecorder(stream, {
|
|
2062
2186
|
mimeType: mimeType,
|
|
2063
2187
|
audioBitsPerSecond: 128000
|
|
2064
2188
|
});
|
|
2065
|
-
|
|
2066
|
-
|
|
2189
|
+
_this22.preRecordingPrompt = _this22.prompt;
|
|
2190
|
+
_this22._audioInputSent = false;
|
|
2067
2191
|
var subject = new signalR.Subject();
|
|
2068
|
-
var itemId =
|
|
2192
|
+
var itemId = _this22.getItemId();
|
|
2069
2193
|
var pendingChunk = Promise.resolve();
|
|
2070
|
-
|
|
2194
|
+
_this22.mediaRecorder.addEventListener('dataavailable', function (e) {
|
|
2071
2195
|
if (e.data && e.data.size > 0) {
|
|
2072
2196
|
pendingChunk = pendingChunk.then(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4() {
|
|
2073
2197
|
var data, uint8Array, binaryString, base64;
|
|
@@ -2091,7 +2215,7 @@ window.chatInteractionManager = function () {
|
|
|
2091
2215
|
})));
|
|
2092
2216
|
}
|
|
2093
2217
|
});
|
|
2094
|
-
|
|
2218
|
+
_this22.mediaRecorder.addEventListener('stop', function () {
|
|
2095
2219
|
stream.getTracks().forEach(function (track) {
|
|
2096
2220
|
return track.stop();
|
|
2097
2221
|
});
|
|
@@ -2100,10 +2224,10 @@ window.chatInteractionManager = function () {
|
|
|
2100
2224
|
});
|
|
2101
2225
|
});
|
|
2102
2226
|
var language = navigator.language || document.documentElement.lang || 'en-US';
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2227
|
+
_this22.connection.send("SendAudioStream", itemId, subject, mimeType, language);
|
|
2228
|
+
_this22.mediaRecorder.start(250);
|
|
2229
|
+
_this22.isRecording = true;
|
|
2230
|
+
_this22.updateMicButton();
|
|
2107
2231
|
})["catch"](function (err) {
|
|
2108
2232
|
console.error('Microphone access denied:', err);
|
|
2109
2233
|
});
|
|
@@ -2154,21 +2278,28 @@ window.chatInteractionManager = function () {
|
|
|
2154
2278
|
this.inputElement.placeholder = '';
|
|
2155
2279
|
}
|
|
2156
2280
|
}
|
|
2281
|
+
},
|
|
2282
|
+
copiedMessageIndex: function copiedMessageIndex() {
|
|
2283
|
+
var _this23 = this;
|
|
2284
|
+
this.$nextTick(function () {
|
|
2285
|
+
return _this23.updateCopyButtons();
|
|
2286
|
+
});
|
|
2157
2287
|
}
|
|
2158
2288
|
},
|
|
2159
2289
|
mounted: function mounted() {
|
|
2160
|
-
var
|
|
2290
|
+
var _this24 = this;
|
|
2161
2291
|
_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee5() {
|
|
2162
2292
|
return _regenerator().w(function (_context5) {
|
|
2163
2293
|
while (1) switch (_context5.n) {
|
|
2164
2294
|
case 0:
|
|
2165
2295
|
_context5.n = 1;
|
|
2166
|
-
return
|
|
2296
|
+
return _this24.startConnection();
|
|
2167
2297
|
case 1:
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2298
|
+
_this24.initializeApp();
|
|
2299
|
+
_this24.$nextTick(function () {
|
|
2300
|
+
_this24.updateCopyButtons();
|
|
2301
|
+
refreshFontAwesomeIcons(_this24.$el);
|
|
2302
|
+
_this24.fontAwesomeObserver = observeFontAwesomeIcons(_this24.$el);
|
|
2172
2303
|
});
|
|
2173
2304
|
case 2:
|
|
2174
2305
|
return _context5.a(2);
|
|
@@ -2185,6 +2316,7 @@ window.chatInteractionManager = function () {
|
|
|
2185
2316
|
this.fontAwesomeObserver.disconnect();
|
|
2186
2317
|
this.fontAwesomeObserver = null;
|
|
2187
2318
|
}
|
|
2319
|
+
this.clearCopiedMessageState();
|
|
2188
2320
|
this.stopAudio(false);
|
|
2189
2321
|
if (this.stream) {
|
|
2190
2322
|
this.stream.dispose();
|
|
@@ -2198,8 +2330,73 @@ window.chatInteractionManager = function () {
|
|
|
2198
2330
|
}).mount(config.appElementSelector);
|
|
2199
2331
|
return app;
|
|
2200
2332
|
};
|
|
2333
|
+
var autoInitializeSelector = '[data-chat-interaction-config]';
|
|
2334
|
+
function parseJsonAttribute(element, attributeName, description) {
|
|
2335
|
+
var rawValue = element.getAttribute(attributeName);
|
|
2336
|
+
if (!rawValue) {
|
|
2337
|
+
return null;
|
|
2338
|
+
}
|
|
2339
|
+
try {
|
|
2340
|
+
return JSON.parse(rawValue);
|
|
2341
|
+
} catch (error) {
|
|
2342
|
+
console.error('Failed to parse ' + description + ' JSON.', error);
|
|
2343
|
+
return null;
|
|
2344
|
+
}
|
|
2345
|
+
}
|
|
2346
|
+
function initializeFromElement(element) {
|
|
2347
|
+
if (!element || element.dataset.chatInteractionInitialized === 'true') {
|
|
2348
|
+
return element ? element.__chatInteractionApp || null : null;
|
|
2349
|
+
}
|
|
2350
|
+
var config = parseJsonAttribute(element, 'data-chat-interaction-config', 'chat interaction config');
|
|
2351
|
+
if (!config) {
|
|
2352
|
+
return null;
|
|
2353
|
+
}
|
|
2354
|
+
var app = initialize(config);
|
|
2355
|
+
if (!app) {
|
|
2356
|
+
return null;
|
|
2357
|
+
}
|
|
2358
|
+
element.dataset.chatInteractionInitialized = 'true';
|
|
2359
|
+
element.__chatInteractionApp = app;
|
|
2360
|
+
return app;
|
|
2361
|
+
}
|
|
2362
|
+
function scanForAutoInitialization(root) {
|
|
2363
|
+
if (!root || typeof root.querySelectorAll !== 'function') {
|
|
2364
|
+
return;
|
|
2365
|
+
}
|
|
2366
|
+
if (typeof root.matches === 'function' && root.matches(autoInitializeSelector)) {
|
|
2367
|
+
initializeFromElement(root);
|
|
2368
|
+
}
|
|
2369
|
+
root.querySelectorAll(autoInitializeSelector).forEach(initializeFromElement);
|
|
2370
|
+
}
|
|
2371
|
+
function startAutoInitialization() {
|
|
2372
|
+
scanForAutoInitialization(document);
|
|
2373
|
+
if (typeof MutationObserver === 'undefined') {
|
|
2374
|
+
return;
|
|
2375
|
+
}
|
|
2376
|
+
var observer = new MutationObserver(function (mutations) {
|
|
2377
|
+
mutations.forEach(function (mutation) {
|
|
2378
|
+
mutation.addedNodes.forEach(function (node) {
|
|
2379
|
+
if (node && node.nodeType === 1) {
|
|
2380
|
+
scanForAutoInitialization(node);
|
|
2381
|
+
}
|
|
2382
|
+
});
|
|
2383
|
+
});
|
|
2384
|
+
});
|
|
2385
|
+
observer.observe(document.body, {
|
|
2386
|
+
childList: true,
|
|
2387
|
+
subtree: true
|
|
2388
|
+
});
|
|
2389
|
+
}
|
|
2390
|
+
if (document.readyState === 'loading') {
|
|
2391
|
+
document.addEventListener('DOMContentLoaded', startAutoInitialization, {
|
|
2392
|
+
once: true
|
|
2393
|
+
});
|
|
2394
|
+
} else {
|
|
2395
|
+
startAutoInitialization();
|
|
2396
|
+
}
|
|
2201
2397
|
return {
|
|
2202
|
-
initialize: initialize
|
|
2398
|
+
initialize: initialize,
|
|
2399
|
+
initializeFromElement: initializeFromElement
|
|
2203
2400
|
};
|
|
2204
2401
|
}();
|
|
2205
2402
|
window.chatInteractionDocumentManager = function () {
|
|
@@ -2726,9 +2923,73 @@ window.chatInteractionDocumentManager = function () {
|
|
|
2726
2923
|
renderUploadQueue();
|
|
2727
2924
|
showUploadStatus(null);
|
|
2728
2925
|
showUploadProgress(null);
|
|
2926
|
+
return fileInput[managerStateKey];
|
|
2927
|
+
}
|
|
2928
|
+
function parseJsonAttribute(element, attributeName, description) {
|
|
2929
|
+
var rawValue = element.getAttribute(attributeName);
|
|
2930
|
+
if (!rawValue) {
|
|
2931
|
+
return null;
|
|
2932
|
+
}
|
|
2933
|
+
try {
|
|
2934
|
+
return JSON.parse(rawValue);
|
|
2935
|
+
} catch (error) {
|
|
2936
|
+
console.error('Failed to parse ' + description + ' JSON.', error);
|
|
2937
|
+
return null;
|
|
2938
|
+
}
|
|
2939
|
+
}
|
|
2940
|
+
function initializeFromElement(element) {
|
|
2941
|
+
if (!element || element.dataset.chatInteractionDocumentManagerInitialized === 'true') {
|
|
2942
|
+
return element ? element[managerStateKey] || null : null;
|
|
2943
|
+
}
|
|
2944
|
+
var config = parseJsonAttribute(element, 'data-chat-interaction-document-manager-config', 'chat interaction document manager config');
|
|
2945
|
+
if (!config) {
|
|
2946
|
+
return null;
|
|
2947
|
+
}
|
|
2948
|
+
var state = initialize(config);
|
|
2949
|
+
if (!state) {
|
|
2950
|
+
return null;
|
|
2951
|
+
}
|
|
2952
|
+
element.dataset.chatInteractionDocumentManagerInitialized = 'true';
|
|
2953
|
+
return state;
|
|
2954
|
+
}
|
|
2955
|
+
function scanForAutoInitialization(root) {
|
|
2956
|
+
if (!root || typeof root.querySelectorAll !== 'function') {
|
|
2957
|
+
return;
|
|
2958
|
+
}
|
|
2959
|
+
if (typeof root.matches === 'function' && root.matches('[data-chat-interaction-document-manager-config]')) {
|
|
2960
|
+
initializeFromElement(root);
|
|
2961
|
+
}
|
|
2962
|
+
root.querySelectorAll('[data-chat-interaction-document-manager-config]').forEach(initializeFromElement);
|
|
2963
|
+
}
|
|
2964
|
+
function startAutoInitialization() {
|
|
2965
|
+
scanForAutoInitialization(document);
|
|
2966
|
+
if (typeof MutationObserver === 'undefined') {
|
|
2967
|
+
return;
|
|
2968
|
+
}
|
|
2969
|
+
var observer = new MutationObserver(function (mutations) {
|
|
2970
|
+
mutations.forEach(function (mutation) {
|
|
2971
|
+
mutation.addedNodes.forEach(function (node) {
|
|
2972
|
+
if (node && node.nodeType === 1) {
|
|
2973
|
+
scanForAutoInitialization(node);
|
|
2974
|
+
}
|
|
2975
|
+
});
|
|
2976
|
+
});
|
|
2977
|
+
});
|
|
2978
|
+
observer.observe(document.body, {
|
|
2979
|
+
childList: true,
|
|
2980
|
+
subtree: true
|
|
2981
|
+
});
|
|
2982
|
+
}
|
|
2983
|
+
if (document.readyState === 'loading') {
|
|
2984
|
+
document.addEventListener('DOMContentLoaded', startAutoInitialization, {
|
|
2985
|
+
once: true
|
|
2986
|
+
});
|
|
2987
|
+
} else {
|
|
2988
|
+
startAutoInitialization();
|
|
2729
2989
|
}
|
|
2730
2990
|
return {
|
|
2731
|
-
initialize: initialize
|
|
2991
|
+
initialize: initialize,
|
|
2992
|
+
initializeFromElement: initializeFromElement
|
|
2732
2993
|
};
|
|
2733
2994
|
}();
|
|
2734
2995
|
|