@sinequa/assistant 3.6.2 → 3.7.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/chat/chat-message/chat-message.component.d.ts +4 -2
- package/chat/chat.component.d.ts +56 -17
- package/chat/chat.service.d.ts +23 -1
- package/chat/rest-chat.service.d.ts +1 -0
- package/chat/saved-chats/saved-chats.component.d.ts +2 -2
- package/chat/styles/assistant.scss +5 -0
- package/chat/types.d.ts +128 -3
- package/chat/websocket-chat.service.d.ts +6 -6
- package/esm2020/chat/chat-message/chat-message.component.mjs +9 -4
- package/esm2020/chat/chat-reference/chat-reference.component.mjs +3 -3
- package/esm2020/chat/chat.component.mjs +262 -60
- package/esm2020/chat/chat.service.mjs +49 -3
- package/esm2020/chat/debug-message/debug-message.component.mjs +3 -3
- package/esm2020/chat/rest-chat.service.mjs +8 -3
- package/esm2020/chat/saved-chats/saved-chats.component.mjs +16 -5
- package/esm2020/chat/token-progress-bar/token-progress-bar.component.mjs +3 -3
- package/esm2020/chat/types.mjs +11 -3
- package/esm2020/chat/websocket-chat.service.mjs +191 -99
- package/fesm2015/sinequa-assistant-chat.mjs +552 -178
- package/fesm2015/sinequa-assistant-chat.mjs.map +1 -1
- package/fesm2020/sinequa-assistant-chat.mjs +542 -175
- package/fesm2020/sinequa-assistant-chat.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { Injectable, EventEmitter, inject, Component, Input, Output, ViewEncapsulation, ChangeDetectionStrategy, ChangeDetectorRef, ViewChild, ContentChild, Inject } from '@angular/core';
|
|
3
|
-
import { Subscription, filter, tap, switchMap, BehaviorSubject, forkJoin, map, catchError, throwError, shareReplay, Subject, fromEvent, merge, takeUntil, Observable, take, finalize } from 'rxjs';
|
|
3
|
+
import { Subscription, filter, tap, switchMap, BehaviorSubject, forkJoin, map, catchError, throwError, shareReplay, Subject, fromEvent, mergeMap, of, merge, takeUntil, Observable, take, finalize, combineLatest } from 'rxjs';
|
|
4
4
|
import * as i3 from '@sinequa/core/web-services';
|
|
5
5
|
import { PrincipalWebService, UserSettingsWebService, AuditWebService, SignalRWebService, JsonMethodPluginService } from '@sinequa/core/web-services';
|
|
6
6
|
import * as i1 from '@angular/common';
|
|
@@ -198,7 +198,8 @@ const connectionSettingsSchema = z.object({
|
|
|
198
198
|
restEndpoint: z.string().optional(),
|
|
199
199
|
websocketEndpoint: z.string().optional(),
|
|
200
200
|
signalRTransport: z.enum(["WebSockets", "ServerSentEvents", "LongPolling", "None"]),
|
|
201
|
-
signalRLogLevel: z.enum(["Critical", "Debug", "Error", "Information", "None", "Trace", "Warning"])
|
|
201
|
+
signalRLogLevel: z.enum(["Critical", "Debug", "Error", "Information", "None", "Trace", "Warning"]),
|
|
202
|
+
signalRServerTimeoutInMilliseconds: z.number().optional()
|
|
202
203
|
}).refine(data => (!!data.restEndpoint || !!data.websocketEndpoint), {
|
|
203
204
|
message: "Based on the provided input() protocol ('REST' or 'WEBSOCKET') to the Chat Component, either 'restEndpoint' or 'websocketEndpoint' property should be provided in the 'globalSettings' of the assistant instance.",
|
|
204
205
|
});
|
|
@@ -226,6 +227,10 @@ const uiSettingsSchema = z.object({
|
|
|
226
227
|
displaySystemPrompt: z.boolean(),
|
|
227
228
|
displayUserPrompt: z.boolean()
|
|
228
229
|
});
|
|
230
|
+
// Define the Zod representation for the chatStarter object
|
|
231
|
+
const chatStarterSchema = z.object({
|
|
232
|
+
text: z.string()
|
|
233
|
+
});
|
|
229
234
|
// Define the Zod representation for the defaultValues object
|
|
230
235
|
const defaultValuesSchema = z.object({
|
|
231
236
|
service_id: z.string(),
|
|
@@ -245,7 +250,8 @@ const defaultValuesSchema = z.object({
|
|
|
245
250
|
const initializationSchema = z.object({
|
|
246
251
|
event: z.enum(['Query', 'Prompt']),
|
|
247
252
|
forcedWorkflow: z.string().optional(),
|
|
248
|
-
displayUserQuery: z.boolean().optional(),
|
|
253
|
+
displayUserQuery: z.boolean().optional(),
|
|
254
|
+
chatStarters: z.array(chatStarterSchema).optional(), // Optional for event 'Prompt'
|
|
249
255
|
}).refine(data => ((data.event === "Query") ? (!!data.forcedWorkflow && data.displayUserQuery !== undefined && data.displayUserQuery !== null) : true), {
|
|
250
256
|
message: "The 'forcedWorkflow' and 'displayUserQuery' properties must be provided when the initialization's event is 'Query'.",
|
|
251
257
|
});
|
|
@@ -254,6 +260,8 @@ const modeSettingsSchema = z.object({
|
|
|
254
260
|
displayUserPrompt: z.boolean(),
|
|
255
261
|
sendUserPrompt: z.boolean(),
|
|
256
262
|
initialization: initializationSchema
|
|
263
|
+
}).refine(data => { var _a; return !(((_a = data.initialization.chatStarters) === null || _a === void 0 ? void 0 : _a.length) && (data.sendUserPrompt || data.displayUserPrompt || data.initialization.event === 'Query')); }, {
|
|
264
|
+
message: "Incompatible configuration for using chatStarters ('sendUserPrompt' and 'displayUserPrompt' must be false, 'initialization.event' must not be 'Query')",
|
|
257
265
|
});
|
|
258
266
|
// Define the Zod representation for the savedChatSettings object
|
|
259
267
|
const savedChatSettingsSchema = z.object({
|
|
@@ -293,7 +301,11 @@ class ChatService {
|
|
|
293
301
|
this.initConfig$ = new BehaviorSubject(false);
|
|
294
302
|
/** Global configuration of the chat. */
|
|
295
303
|
this.chatConfig$ = new BehaviorSubject(undefined);
|
|
296
|
-
/**
|
|
304
|
+
/**
|
|
305
|
+
* Emit true if the fetch of an assistant's response is ongoing (it includes Streaming status of the chat endpoint AND saving the discussion if save Chat is enabled).
|
|
306
|
+
* This is used to prevent multiple fetches at the same time.
|
|
307
|
+
* Typically, there is no problem chaining fetches, but when forcing a reload after query changes cases, it can't be allowed because it breaks the whole business logic.
|
|
308
|
+
*/
|
|
297
309
|
this.streaming$ = new BehaviorSubject(false);
|
|
298
310
|
/** List of saved chats. */
|
|
299
311
|
this.savedChats$ = new BehaviorSubject([]);
|
|
@@ -307,6 +319,8 @@ class ChatService {
|
|
|
307
319
|
this.chatUsageMetrics$ = new BehaviorSubject(undefined);
|
|
308
320
|
/** Emit the calculated chat's token consumption based on the chat usage metrics. */
|
|
309
321
|
this.chatTokenConsumption$ = new BehaviorSubject(undefined);
|
|
322
|
+
/** Emit true if "CancelTasks" is ongoing. */
|
|
323
|
+
this.stoppingGeneration$ = new BehaviorSubject(false);
|
|
310
324
|
this.userSettingsService = inject(UserSettingsWebService);
|
|
311
325
|
this.notificationsService = inject(NotificationsService);
|
|
312
326
|
this.auditService = inject(AuditWebService);
|
|
@@ -434,7 +448,7 @@ class ChatService {
|
|
|
434
448
|
}
|
|
435
449
|
}
|
|
436
450
|
catch (error) {
|
|
437
|
-
this.notificationsService.error(`Missing valid configuration for the assistant instance '${key}'
|
|
451
|
+
this.notificationsService.error(`Missing valid configuration for the assistant instance '${key}'. See the browser console messages for details on the missing or incorrect properties.`);
|
|
438
452
|
throw new Error(`Missing valid configuration for the assistant instance '${key}' . \n ${JSON.stringify(error.issues, null, 2)}`);
|
|
439
453
|
}
|
|
440
454
|
}
|
|
@@ -475,6 +489,7 @@ class ChatService {
|
|
|
475
489
|
const consumptionPercentage = Math.round((quota.tokenCount * 100 / quota.periodTokens) * 100) / 100;
|
|
476
490
|
this.userTokenConsumption$.next({ percentage: consumptionPercentage, nextResetDate });
|
|
477
491
|
if (quota.maxQuotaReached) {
|
|
492
|
+
this.generateAuditEvent('quota.exceeded', {});
|
|
478
493
|
const msg = `Sorry, you have exceeded the allowed quota. Please retry starting from ${nextResetDate}.`;
|
|
479
494
|
this.notificationsService.error(msg);
|
|
480
495
|
if (propagateError)
|
|
@@ -532,6 +547,45 @@ class ChatService {
|
|
|
532
547
|
};
|
|
533
548
|
this.auditService.notify(audit);
|
|
534
549
|
}
|
|
550
|
+
/**
|
|
551
|
+
* Traverse the array from the end and track the first 'assistant' message among the last group of "assistant" messages where display is true
|
|
552
|
+
* @param array The array of ChatMessage to traverse
|
|
553
|
+
* @returns The index of the first visible assistant message among the last group of "assistant" messages in the array
|
|
554
|
+
*/
|
|
555
|
+
firstVisibleAssistantMessageIndex(array) {
|
|
556
|
+
if (!array) {
|
|
557
|
+
return -1;
|
|
558
|
+
}
|
|
559
|
+
let index = array.length - 1;
|
|
560
|
+
let firstVisibleAssistantMessageIndex = -1;
|
|
561
|
+
while (index >= 0 && array[index].role === 'assistant') {
|
|
562
|
+
if (array[index].additionalProperties.display === true) {
|
|
563
|
+
firstVisibleAssistantMessageIndex = index;
|
|
564
|
+
}
|
|
565
|
+
index--;
|
|
566
|
+
}
|
|
567
|
+
return firstVisibleAssistantMessageIndex;
|
|
568
|
+
}
|
|
569
|
+
/**
|
|
570
|
+
* Traverse the array from the end and pick the last 'assistant' message among the last group of "assistant" messages where display is true
|
|
571
|
+
* @param array The array of ChatMessage to traverse
|
|
572
|
+
* @returns The index of the last visible assistant message among the last group of "assistant" messages in the array
|
|
573
|
+
*/
|
|
574
|
+
lastVisibleAssistantMessageIndex(array) {
|
|
575
|
+
if (!array) {
|
|
576
|
+
return -1;
|
|
577
|
+
}
|
|
578
|
+
let index = array.length - 1;
|
|
579
|
+
let lastVisibleAssistantMessageIndex = -1;
|
|
580
|
+
while (index >= 0 && array[index].role === 'assistant') {
|
|
581
|
+
if (array[index].additionalProperties.display === true) {
|
|
582
|
+
lastVisibleAssistantMessageIndex = index;
|
|
583
|
+
break;
|
|
584
|
+
}
|
|
585
|
+
index--;
|
|
586
|
+
}
|
|
587
|
+
return lastVisibleAssistantMessageIndex;
|
|
588
|
+
}
|
|
535
589
|
/**
|
|
536
590
|
* Format a date string in UTC to a local date string
|
|
537
591
|
* @param value Date string in UTC to format
|
|
@@ -562,10 +616,8 @@ class WebSocketChatService extends ChatService {
|
|
|
562
616
|
this._messageHandlers = new Map();
|
|
563
617
|
this._actionMap = new Map();
|
|
564
618
|
this._progress = undefined;
|
|
565
|
-
this._content = "";
|
|
566
619
|
this._attachments = [];
|
|
567
|
-
this.
|
|
568
|
-
this._debugMessages = undefined;
|
|
620
|
+
this._debugMessages = [];
|
|
569
621
|
this.signalRService = inject(SignalRWebService);
|
|
570
622
|
this.authenticationService = inject(AuthenticationService);
|
|
571
623
|
}
|
|
@@ -615,38 +667,38 @@ class WebSocketChatService extends ChatService {
|
|
|
615
667
|
}
|
|
616
668
|
}
|
|
617
669
|
listModels() {
|
|
618
|
-
const modelsSubject = new Subject();
|
|
670
|
+
const modelsSubject$ = new Subject();
|
|
619
671
|
this.connection.on('ListModels', (res) => {
|
|
620
672
|
var _a;
|
|
621
673
|
this.models = (_a = res.models) === null || _a === void 0 ? void 0 : _a.filter(model => !!model.enable);
|
|
622
|
-
modelsSubject
|
|
623
|
-
modelsSubject
|
|
674
|
+
modelsSubject$.next(this.models);
|
|
675
|
+
modelsSubject$.complete();
|
|
624
676
|
});
|
|
625
677
|
// Send the request to get the list of models
|
|
626
678
|
this.connection.invoke('ListModels', { debug: this.chatConfig$.value.defaultValues.debug })
|
|
627
679
|
.catch(error => {
|
|
628
680
|
console.error('Error invoking ListModels:', error);
|
|
629
|
-
modelsSubject
|
|
630
|
-
return Promise.resolve(); // Return a resolved promise to handle the error and prevent unhandled promise rejection
|
|
681
|
+
modelsSubject$.error(new Error(error));
|
|
682
|
+
return Promise.resolve(); // Return a resolved promise to handle the error and prevent unhandled promise rejection when no further error handling exists downstream
|
|
631
683
|
});
|
|
632
|
-
return modelsSubject
|
|
684
|
+
return modelsSubject$.asObservable();
|
|
633
685
|
}
|
|
634
686
|
listFunctions() {
|
|
635
|
-
const functionsSubject = new Subject();
|
|
687
|
+
const functionsSubject$ = new Subject();
|
|
636
688
|
this.connection.on('ListFunctions', (res) => {
|
|
637
689
|
var _a;
|
|
638
690
|
this.functions = (_a = res.functions) === null || _a === void 0 ? void 0 : _a.filter(func => func.enabled);
|
|
639
|
-
functionsSubject
|
|
640
|
-
functionsSubject
|
|
691
|
+
functionsSubject$.next(this.functions);
|
|
692
|
+
functionsSubject$.complete();
|
|
641
693
|
});
|
|
642
694
|
// Send the request to get the list of functions
|
|
643
695
|
this.connection.invoke('ListFunctions', { debug: this.chatConfig$.value.defaultValues.debug })
|
|
644
696
|
.catch(error => {
|
|
645
697
|
console.error('Error invoking ListFunctions:', error);
|
|
646
|
-
functionsSubject
|
|
647
|
-
return Promise.resolve(); // Return a resolved promise to handle the error and prevent unhandled promise rejection
|
|
698
|
+
functionsSubject$.error(new Error(error));
|
|
699
|
+
return Promise.resolve(); // Return a resolved promise to handle the error and prevent unhandled promise rejection when no further error handling exists downstream
|
|
648
700
|
});
|
|
649
|
-
return functionsSubject
|
|
701
|
+
return functionsSubject$.asObservable();
|
|
650
702
|
}
|
|
651
703
|
fetch(messages, query) {
|
|
652
704
|
var _a;
|
|
@@ -668,7 +720,8 @@ class WebSocketChatService extends ChatService {
|
|
|
668
720
|
data.instanceId = this.chatInstanceId;
|
|
669
721
|
data.savedChatId = this.savedChatId;
|
|
670
722
|
}
|
|
671
|
-
|
|
723
|
+
// Initialize the response with an empty assistant message
|
|
724
|
+
this._response = [{ role: "assistant", content: "", additionalProperties: { display: true } }]; // here display: true is needed in order to be able to show the progress
|
|
672
725
|
// Create a Subject to signal completion
|
|
673
726
|
const completion$ = new Subject();
|
|
674
727
|
// Create observables for each non-global handler in the _messageHandlers map (default and eventual custom ones) once it is triggered by the hub connection
|
|
@@ -676,8 +729,19 @@ class WebSocketChatService extends ChatService {
|
|
|
676
729
|
.from(this._messageHandlers.entries())
|
|
677
730
|
.filter(([eventName, eventHandler]) => !eventHandler.isGlobalHandler)
|
|
678
731
|
.map(([eventName, eventHandler]) => {
|
|
679
|
-
return fromEvent(this.connection, eventName).pipe(
|
|
680
|
-
|
|
732
|
+
return fromEvent(this.connection, eventName).pipe(mergeMap((event) => {
|
|
733
|
+
// Wrap the handler in a try-catch block to prevent the entire stream from failing if an error occurs in a single handler
|
|
734
|
+
try {
|
|
735
|
+
// Execute the handler and emit the result
|
|
736
|
+
// NB: here we could use [eventHandler.handler(event)] which behind the scenes mergeMap interprets this array as an observable sequence with one item, which it then emits
|
|
737
|
+
return of(eventHandler.handler(event));
|
|
738
|
+
}
|
|
739
|
+
catch (error) {
|
|
740
|
+
console.error(`Error in event handler for ${eventName}:`, error);
|
|
741
|
+
// Use throwError to propagate the error downstream
|
|
742
|
+
return throwError(() => new Error(`Error in event handler for ${eventName}: ${error}`));
|
|
743
|
+
}
|
|
744
|
+
}));
|
|
681
745
|
});
|
|
682
746
|
// Then merge them into a single observable in order to simulate the streaming behavior
|
|
683
747
|
const combined$ = merge(...observables).pipe(map(() => {
|
|
@@ -694,37 +758,74 @@ class WebSocketChatService extends ChatService {
|
|
|
694
758
|
});
|
|
695
759
|
})
|
|
696
760
|
: undefined;
|
|
697
|
-
//
|
|
698
|
-
|
|
699
|
-
|
|
761
|
+
// Always update ONLY the first assistant message of the _response with the new $progress, $attachment and $debug
|
|
762
|
+
// Assuming that the first assistant message is always visible since the hub does not send hidden messages by design
|
|
763
|
+
// So even if the first assistant message is hidden (display: false), the _response[0] will and should contain :
|
|
764
|
+
// - $progress, $attachment and $debug
|
|
765
|
+
// - the content of the first visible assistant message in the workflow
|
|
766
|
+
// This is mandatory in order to match the behavior of consecutive messages and maintain consistency with the chatHistory
|
|
767
|
+
if (!!this._progress || this._attachments.length > 0 || this._debugMessages.length > 0) {
|
|
768
|
+
this._response[0].additionalProperties.$progress = this._progress;
|
|
769
|
+
this._response[0].additionalProperties.$attachment = this._attachments;
|
|
770
|
+
this._response[0].additionalProperties.$debug = this._debugMessages;
|
|
700
771
|
}
|
|
701
772
|
// Return the result
|
|
702
|
-
return { history: [...messages,
|
|
773
|
+
return { history: [...messages, ...this._response], executionTime: this._executionTime };
|
|
703
774
|
}), takeUntil(completion$));
|
|
704
775
|
// return a new Observable that emits the result of the combined stream and handles the eventual errors of the invocation of the Chat method
|
|
705
776
|
return new Observable(observer => {
|
|
706
777
|
// Subscribe to combined stream
|
|
707
778
|
combined$.subscribe({
|
|
708
779
|
next: (value) => observer.next(value),
|
|
709
|
-
error: (err) => observer.error(err)
|
|
710
|
-
complete: () => observer.complete(),
|
|
780
|
+
error: (err) => observer.error(err)
|
|
711
781
|
});
|
|
712
782
|
// Invoke the Chat method and handle errors
|
|
713
783
|
this.connection.invoke('Chat', data)
|
|
784
|
+
.then(() => {
|
|
785
|
+
// If a valid assistant message with (display: true) was found, update it
|
|
786
|
+
// and it should always the case
|
|
787
|
+
const index = this.firstVisibleAssistantMessageIndex(this.chatHistory);
|
|
788
|
+
if (index !== -1) {
|
|
789
|
+
this.chatHistory[index].additionalProperties.$progress = this._progress;
|
|
790
|
+
this.chatHistory[index].additionalProperties.$attachment = this._attachments;
|
|
791
|
+
this.chatHistory[index].additionalProperties.$debug = this._debugMessages;
|
|
792
|
+
}
|
|
793
|
+
// Save/update the chat if savedChat enabled
|
|
794
|
+
if (this.chatConfig$.value.savedChatSettings.enabled && this.chatHistory.some((msg) => { var _a; return ((_a = msg.additionalProperties) === null || _a === void 0 ? void 0 : _a.isUserInput) === true; })) {
|
|
795
|
+
const action = !this.savedChatId ? this.addSavedChat(this.chatHistory).pipe(tap(() => this.listSavedChat())) : this.updateSavedChat(this.savedChatId, undefined, this.chatHistory);
|
|
796
|
+
action.pipe(take(1)).subscribe({
|
|
797
|
+
next: () => { },
|
|
798
|
+
error: (error) => {
|
|
799
|
+
this.streaming$.next(false);
|
|
800
|
+
observer.error(error);
|
|
801
|
+
},
|
|
802
|
+
complete: () => {
|
|
803
|
+
this.streaming$.next(false);
|
|
804
|
+
observer.complete();
|
|
805
|
+
}
|
|
806
|
+
});
|
|
807
|
+
}
|
|
808
|
+
else {
|
|
809
|
+
this.streaming$.next(false);
|
|
810
|
+
observer.complete();
|
|
811
|
+
}
|
|
812
|
+
})
|
|
714
813
|
.catch(error => {
|
|
715
814
|
console.error('Error invoking Chat:', error);
|
|
815
|
+
this.streaming$.next(false);
|
|
716
816
|
// Emit the error to the newly created observable
|
|
717
817
|
observer.error(error);
|
|
718
818
|
// Return a resolved promise to handle the error and prevent unhandled promise rejection
|
|
719
819
|
return Promise.resolve();
|
|
720
820
|
})
|
|
721
821
|
.finally(() => {
|
|
722
|
-
|
|
822
|
+
// This block concerns ONLY the completion of the "Chat" method invocation.
|
|
823
|
+
// This means the completion of the combined$ stream.
|
|
824
|
+
// It does not take into account the completion of the entire fetch method (the observable returned by fetch) and which depends on the completion of the save chat action if enabled
|
|
825
|
+
this._response = []; // Clear the _response
|
|
723
826
|
this._actionMap.clear(); // Clear the _actionMap
|
|
724
|
-
this._content = ""; // Clear the _content
|
|
725
827
|
this._progress = undefined; // Clear the _progress
|
|
726
828
|
this._attachments = []; // Clear the _attachments
|
|
727
|
-
this._suggestedActions = []; // Clear the _suggestedActions
|
|
728
829
|
this._debugMessages = []; // Clear the _debugMessages
|
|
729
830
|
this._executionTime = ""; // Clear the _executionTime
|
|
730
831
|
completion$.next(); // Emit a signal to complete the observables
|
|
@@ -732,6 +833,34 @@ class WebSocketChatService extends ChatService {
|
|
|
732
833
|
});
|
|
733
834
|
});
|
|
734
835
|
}
|
|
836
|
+
stopGeneration() {
|
|
837
|
+
// Start stopping generation by invoking the CancelTasks method
|
|
838
|
+
this.stoppingGeneration$.next(true);
|
|
839
|
+
// Create a Subject to hold the result of the CancelTasks method
|
|
840
|
+
const stopGenerationSubject$ = new Subject();
|
|
841
|
+
this.connection.on('CancelTasks', (res) => {
|
|
842
|
+
var _a;
|
|
843
|
+
// When the generation is stopped before streaming any VISIBLE assistant message, this means that $progress, $attachment and $debug properties will be lost.
|
|
844
|
+
// However, the "ContextMessage" frames will be persisted in the chatHistory and the assistant may reference them in the next generation.
|
|
845
|
+
// This leads to the problem of referencing undisplayed attachments in the next generation.
|
|
846
|
+
// To solve this problem, we need to persist $progress, $attachment and $debug properties by adding a new assistant message with empty content and these properties.
|
|
847
|
+
if (this._response.length === 1 && this._response[0].content === "") {
|
|
848
|
+
(_a = this.chatHistory) === null || _a === void 0 ? void 0 : _a.push({ role: "assistant", content: "", additionalProperties: { display: true, $progress: this._progress, $attachment: this._attachments, $debug: this._debugMessages } });
|
|
849
|
+
}
|
|
850
|
+
stopGenerationSubject$.next(!!res); // Emit the result of the CancelTasks method
|
|
851
|
+
stopGenerationSubject$.complete(); // Complete the subject
|
|
852
|
+
this.stoppingGeneration$.next(false); // Complete stopping generation
|
|
853
|
+
});
|
|
854
|
+
// Invoke the CancelTasks method and handle errors
|
|
855
|
+
this.connection.invoke('CancelTasks')
|
|
856
|
+
.catch(error => {
|
|
857
|
+
console.error('Error invoking CancelTasks:', error);
|
|
858
|
+
stopGenerationSubject$.error(new Error(error));
|
|
859
|
+
this.stoppingGeneration$.next(false); // Complete stopping generation
|
|
860
|
+
return Promise.resolve(); // Return a resolved promise to handle the error and prevent unhandled promise rejection when no further error handling exists downstream
|
|
861
|
+
});
|
|
862
|
+
return stopGenerationSubject$.asObservable();
|
|
863
|
+
}
|
|
735
864
|
listSavedChat() {
|
|
736
865
|
if (!this.chatConfig$.value.savedChatSettings.enabled) {
|
|
737
866
|
return;
|
|
@@ -751,27 +880,27 @@ class WebSocketChatService extends ChatService {
|
|
|
751
880
|
});
|
|
752
881
|
}
|
|
753
882
|
getSavedChat(id) {
|
|
754
|
-
const savedChatSubject = new Subject();
|
|
883
|
+
const savedChatSubject$ = new Subject();
|
|
755
884
|
const data = {
|
|
756
885
|
instanceId: this.chatInstanceId,
|
|
757
886
|
savedChatId: id,
|
|
758
887
|
debug: this.chatConfig$.value.defaultValues.debug
|
|
759
888
|
};
|
|
760
889
|
this.connection.on('SavedChatGet', (res) => {
|
|
761
|
-
savedChatSubject
|
|
762
|
-
savedChatSubject
|
|
890
|
+
savedChatSubject$.next(res.savedChat);
|
|
891
|
+
savedChatSubject$.complete();
|
|
763
892
|
});
|
|
764
893
|
// Invoke the method SavedChatGet
|
|
765
894
|
this.connection.invoke('SavedChatGet', data)
|
|
766
895
|
.catch(error => {
|
|
767
896
|
console.error('Error invoking SavedChatGet:', error);
|
|
768
|
-
savedChatSubject
|
|
769
|
-
return Promise.resolve();
|
|
897
|
+
savedChatSubject$.error(new Error(error));
|
|
898
|
+
return Promise.resolve(); // Return a resolved promise to handle the error and prevent unhandled promise rejection when no further error handling exists downstream
|
|
770
899
|
});
|
|
771
|
-
return savedChatSubject
|
|
900
|
+
return savedChatSubject$.asObservable();
|
|
772
901
|
}
|
|
773
902
|
addSavedChat(messages) {
|
|
774
|
-
const addSavedChatSubject = new Subject();
|
|
903
|
+
const addSavedChatSubject$ = new Subject();
|
|
775
904
|
const data = {
|
|
776
905
|
instanceId: this.chatInstanceId,
|
|
777
906
|
savedChatId: this.chatId,
|
|
@@ -781,20 +910,20 @@ class WebSocketChatService extends ChatService {
|
|
|
781
910
|
this.connection.on('SavedChatAdd', (res) => {
|
|
782
911
|
this.setSavedChatId(res.savedChat.id); // Persist the savedChatId
|
|
783
912
|
this.generateAuditEvent('saved-chat.add', {}, res.savedChat.id); // Generate audit event
|
|
784
|
-
addSavedChatSubject
|
|
785
|
-
addSavedChatSubject
|
|
913
|
+
addSavedChatSubject$.next(res.savedChat);
|
|
914
|
+
addSavedChatSubject$.complete();
|
|
786
915
|
});
|
|
787
916
|
// Invoke the method SavedChatAdd
|
|
788
917
|
this.connection.invoke('SavedChatAdd', data)
|
|
789
918
|
.catch(error => {
|
|
790
919
|
console.error('Error invoking SavedChatAdd:', error);
|
|
791
|
-
addSavedChatSubject
|
|
792
|
-
return Promise.resolve();
|
|
920
|
+
addSavedChatSubject$.error(new Error(error));
|
|
921
|
+
return Promise.resolve(); // Return a resolved promise to handle the error and prevent unhandled promise rejection when no further error handling exists downstream
|
|
793
922
|
});
|
|
794
|
-
return addSavedChatSubject
|
|
923
|
+
return addSavedChatSubject$.asObservable();
|
|
795
924
|
}
|
|
796
925
|
updateSavedChat(id, name, messages) {
|
|
797
|
-
const updateSavedChatSubject = new Subject();
|
|
926
|
+
const updateSavedChatSubject$ = new Subject();
|
|
798
927
|
const data = {
|
|
799
928
|
instanceId: this.chatInstanceId,
|
|
800
929
|
savedChatId: id,
|
|
@@ -805,45 +934,64 @@ class WebSocketChatService extends ChatService {
|
|
|
805
934
|
if (messages)
|
|
806
935
|
data["history"] = messages;
|
|
807
936
|
this.connection.on('SavedChatUpdate', (res) => {
|
|
808
|
-
updateSavedChatSubject
|
|
809
|
-
updateSavedChatSubject
|
|
937
|
+
updateSavedChatSubject$.next(res.savedChat);
|
|
938
|
+
updateSavedChatSubject$.complete();
|
|
810
939
|
});
|
|
811
940
|
// Invoke the method SavedChatUpdate
|
|
812
941
|
this.connection.invoke('SavedChatUpdate', data)
|
|
813
942
|
.catch(error => {
|
|
814
943
|
console.error('Error invoking SavedChatUpdate:', error);
|
|
815
|
-
updateSavedChatSubject
|
|
816
|
-
return Promise.resolve();
|
|
944
|
+
updateSavedChatSubject$.error(new Error(error));
|
|
945
|
+
return Promise.resolve(); // Return a resolved promise to handle the error and prevent unhandled promise rejection when no further error handling exists downstream
|
|
817
946
|
});
|
|
818
|
-
return updateSavedChatSubject
|
|
947
|
+
return updateSavedChatSubject$.asObservable();
|
|
819
948
|
}
|
|
820
949
|
deleteSavedChat(ids) {
|
|
821
|
-
const deleteSavedChatSubject = new Subject();
|
|
950
|
+
const deleteSavedChatSubject$ = new Subject();
|
|
822
951
|
const data = {
|
|
823
952
|
instanceId: this.chatInstanceId,
|
|
824
953
|
SavedChatIds: ids,
|
|
825
954
|
debug: this.chatConfig$.value.defaultValues.debug
|
|
826
955
|
};
|
|
827
956
|
this.connection.on('SavedChatDelete', (res) => {
|
|
828
|
-
deleteSavedChatSubject
|
|
829
|
-
deleteSavedChatSubject
|
|
957
|
+
deleteSavedChatSubject$.next(res.deleteCount);
|
|
958
|
+
deleteSavedChatSubject$.complete();
|
|
830
959
|
});
|
|
831
960
|
// Invoke the method SavedChatDelete
|
|
832
961
|
this.connection.invoke('SavedChatDelete', data)
|
|
833
962
|
.catch(error => {
|
|
834
963
|
console.error('Error invoking SavedChatDelete:', error);
|
|
835
|
-
deleteSavedChatSubject
|
|
836
|
-
return Promise.resolve();
|
|
964
|
+
deleteSavedChatSubject$.error(new Error(error));
|
|
965
|
+
return Promise.resolve(); // Return a resolved promise to handle the error and prevent unhandled promise rejection when no further error handling exists downstream
|
|
837
966
|
});
|
|
838
|
-
return deleteSavedChatSubject
|
|
967
|
+
return deleteSavedChatSubject$.asObservable();
|
|
839
968
|
}
|
|
840
969
|
/**
|
|
841
970
|
* Initialize out-of-the-box handlers
|
|
842
|
-
* It is a placeholder for non-streaming scenarios, where you invoke a specific hub method, and the server responds with
|
|
971
|
+
* It is a placeholder for non-streaming scenarios, where you invoke a specific hub method, and the server responds with frame message(s)
|
|
843
972
|
*/
|
|
844
973
|
initMessageHandlers() {
|
|
845
|
-
this.addMessageHandler("
|
|
846
|
-
|
|
974
|
+
this.addMessageHandler("Error", {
|
|
975
|
+
handler: (error) => {
|
|
976
|
+
console.error(error);
|
|
977
|
+
this.notificationsService.error(error);
|
|
978
|
+
},
|
|
979
|
+
isGlobalHandler: true
|
|
980
|
+
});
|
|
981
|
+
this.addMessageHandler("Quota", {
|
|
982
|
+
handler: (message) => {
|
|
983
|
+
try {
|
|
984
|
+
this.updateQuota(message.quota);
|
|
985
|
+
}
|
|
986
|
+
catch (error) {
|
|
987
|
+
console.error(error);
|
|
988
|
+
}
|
|
989
|
+
},
|
|
990
|
+
isGlobalHandler: true
|
|
991
|
+
});
|
|
992
|
+
this.addMessageHandler("Debug", { handler: () => { },
|
|
993
|
+
isGlobalHandler: true
|
|
994
|
+
});
|
|
847
995
|
this.addMessageHandler("ActionStart", { handler: (action) => this._actionMap.set(action.guid, action),
|
|
848
996
|
isGlobalHandler: false });
|
|
849
997
|
this.addMessageHandler("ActionResult", {
|
|
@@ -859,36 +1007,50 @@ class WebSocketChatService extends ChatService {
|
|
|
859
1007
|
isGlobalHandler: false
|
|
860
1008
|
});
|
|
861
1009
|
this.addMessageHandler("Message", {
|
|
862
|
-
handler: (message) => this.
|
|
1010
|
+
handler: (message) => this._response.at(-1).content += message !== null && message !== void 0 ? message : "",
|
|
863
1011
|
isGlobalHandler: false
|
|
864
1012
|
});
|
|
865
1013
|
this.addMessageHandler("History", {
|
|
866
1014
|
handler: (history) => {
|
|
867
1015
|
var _a;
|
|
868
|
-
|
|
869
|
-
//
|
|
870
|
-
this.chatHistory
|
|
871
|
-
|
|
872
|
-
this.chatHistory.at(-1).additionalProperties.$suggestedAction = this._suggestedActions;
|
|
873
|
-
this.chatHistory.at(-1).additionalProperties.$debug = this._debugMessages;
|
|
874
|
-
// Emit the updated chat usage metrics once the generation of the assistant response is completed
|
|
1016
|
+
// The ChatHistory is updated: it is the current copy concatenated with the new items ONLY (it can have multiple messages: the context messages + the response message)
|
|
1017
|
+
// This is mandatory to not lose the previous updates of the chatHistory when the assistant is streaming multiple message steps
|
|
1018
|
+
this.chatHistory = [...this.chatHistory, ...(history.history.slice(this.chatHistory.length))];
|
|
1019
|
+
// Emit the updated chat usage metrics
|
|
875
1020
|
if (!!((_a = this.chatHistory.at(-1)) === null || _a === void 0 ? void 0 : _a.additionalProperties.usageMetrics)) {
|
|
876
1021
|
this.updateChatUsageMetrics(this.chatHistory.at(-1).additionalProperties.usageMetrics);
|
|
877
1022
|
}
|
|
878
|
-
// Save/update the chat if savedChat enabled
|
|
879
|
-
if (this.chatConfig$.value.savedChatSettings.enabled && this.chatHistory.some((msg) => { var _a; return ((_a = msg.additionalProperties) === null || _a === void 0 ? void 0 : _a.isUserInput) === true; })) {
|
|
880
|
-
const action = !this.savedChatId ? this.addSavedChat(this.chatHistory) : this.updateSavedChat(this.savedChatId, undefined, this.chatHistory);
|
|
881
|
-
action.pipe(take(1)).subscribe();
|
|
882
|
-
}
|
|
883
1023
|
this._executionTime = history.executionTime;
|
|
1024
|
+
},
|
|
1025
|
+
isGlobalHandler: false
|
|
1026
|
+
});
|
|
1027
|
+
this.addMessageHandler("SuggestedActions", {
|
|
1028
|
+
handler: (message) => {
|
|
1029
|
+
// Since after the "History" and "MessageBreak" that this event is caught,
|
|
1030
|
+
// $suggestedAction needs to be updated directly to the last visible "assistant" message in the _response and the chatHistory
|
|
1031
|
+
this._response.at(-1).additionalProperties.$suggestedAction = (this._response.at(-1).additionalProperties.$suggestedAction || []).concat(message.suggestedActions);
|
|
1032
|
+
const index = this.lastVisibleAssistantMessageIndex(this.chatHistory);
|
|
1033
|
+
if (index !== -1) {
|
|
1034
|
+
this.chatHistory[index].additionalProperties.$suggestedAction = (this.chatHistory[index].additionalProperties.$suggestedAction || []).concat(message.suggestedActions);
|
|
1035
|
+
}
|
|
1036
|
+
},
|
|
1037
|
+
isGlobalHandler: false
|
|
1038
|
+
});
|
|
1039
|
+
this.addMessageHandler("DebugDisplay", {
|
|
1040
|
+
handler: (message) => this._debugMessages = this._debugMessages.concat(message),
|
|
1041
|
+
isGlobalHandler: false
|
|
1042
|
+
});
|
|
1043
|
+
this.addMessageHandler("MessageBreak", {
|
|
1044
|
+
handler: () => {
|
|
1045
|
+
var _a, _b;
|
|
884
1046
|
// Generate audit event
|
|
885
1047
|
const details = {
|
|
886
1048
|
'duration': this._executionTime,
|
|
887
1049
|
'text': this.chatHistory.at(-1).content,
|
|
888
1050
|
'role': this.chatHistory.at(-1).role,
|
|
889
1051
|
'rank': this.chatHistory.length - 1,
|
|
890
|
-
'generation-tokencount': this.chatHistory.at(-1).additionalProperties.usageMetrics.completionTokenCount,
|
|
891
|
-
'prompt-tokencount': this.chatHistory.at(-1).additionalProperties.usageMetrics.promptTokenCount,
|
|
1052
|
+
'generation-tokencount': (_a = this.chatHistory.at(-1).additionalProperties.usageMetrics) === null || _a === void 0 ? void 0 : _a.completionTokenCount,
|
|
1053
|
+
'prompt-tokencount': (_b = this.chatHistory.at(-1).additionalProperties.usageMetrics) === null || _b === void 0 ? void 0 : _b.promptTokenCount,
|
|
892
1054
|
'attachments': JSON.stringify(this._attachments.map(({ recordId, contextId, parts, type }) => ({
|
|
893
1055
|
recordId,
|
|
894
1056
|
contextId,
|
|
@@ -897,31 +1059,13 @@ class WebSocketChatService extends ChatService {
|
|
|
897
1059
|
})))
|
|
898
1060
|
};
|
|
899
1061
|
this.generateAuditEvent('message', details);
|
|
1062
|
+
// Push a new assistant message to the _response array ONLY if the content of the last message is not empty
|
|
1063
|
+
if (this._response.at(-1).content !== "") {
|
|
1064
|
+
this._response.push({ role: "assistant", content: "", additionalProperties: { display: true } });
|
|
1065
|
+
}
|
|
900
1066
|
},
|
|
901
1067
|
isGlobalHandler: false
|
|
902
1068
|
});
|
|
903
|
-
this.addMessageHandler("Error", {
|
|
904
|
-
handler: (error) => {
|
|
905
|
-
console.error(error);
|
|
906
|
-
this.notificationsService.error(error);
|
|
907
|
-
},
|
|
908
|
-
isGlobalHandler: true
|
|
909
|
-
});
|
|
910
|
-
this.addMessageHandler("Quota", {
|
|
911
|
-
handler: (message) => this.updateQuota(message.quota),
|
|
912
|
-
isGlobalHandler: true
|
|
913
|
-
});
|
|
914
|
-
this.addMessageHandler("SuggestedActions", {
|
|
915
|
-
handler: (message) => {
|
|
916
|
-
// Suggested actions are concatenated to the existing ones in case of multiple events "SuggestedActions"
|
|
917
|
-
this._suggestedActions = this._suggestedActions.concat(message.suggestedActions);
|
|
918
|
-
},
|
|
919
|
-
isGlobalHandler: false
|
|
920
|
-
});
|
|
921
|
-
this.addMessageHandler("DebugDisplay", {
|
|
922
|
-
handler: (message) => this._debugMessages = this._debugMessages ? this._debugMessages.concat(message) : [message],
|
|
923
|
-
isGlobalHandler: false
|
|
924
|
-
});
|
|
925
1069
|
}
|
|
926
1070
|
/**
|
|
927
1071
|
* Override and register the entire _messageHandlers map by merging the provided map with the default one
|
|
@@ -936,7 +1080,7 @@ class WebSocketChatService extends ChatService {
|
|
|
936
1080
|
});
|
|
937
1081
|
// Merge the new event handlers with the existing ones
|
|
938
1082
|
this._messageHandlers = new Map([...this._messageHandlers, ..._messageHandlers]);
|
|
939
|
-
// Register the global
|
|
1083
|
+
// Register the global handlers among the merged map
|
|
940
1084
|
this._messageHandlers.forEach((eventHandler, eventName) => {
|
|
941
1085
|
if (eventHandler.isGlobalHandler) {
|
|
942
1086
|
this.registerMessageHandler(eventName, eventHandler);
|
|
@@ -946,7 +1090,7 @@ class WebSocketChatService extends ChatService {
|
|
|
946
1090
|
/**
|
|
947
1091
|
* Add a listener for a specific event.
|
|
948
1092
|
* If a listener for this same event already exists, it will be overridden.
|
|
949
|
-
* If the listener has "
|
|
1093
|
+
* If the listener has "isGlobalHandler" set to true, it will be registered to the hub connection.
|
|
950
1094
|
* @param eventName Name of the event to register a listener for
|
|
951
1095
|
* @param eventHandler The handler to be called when the event is received
|
|
952
1096
|
*/
|
|
@@ -996,12 +1140,17 @@ class WebSocketChatService extends ChatService {
|
|
|
996
1140
|
*/
|
|
997
1141
|
buildConnection(options) {
|
|
998
1142
|
return new Promise((resolve, reject) => {
|
|
1143
|
+
var _a;
|
|
999
1144
|
if (!this.REQUEST_URL) {
|
|
1000
1145
|
reject(new Error("No endpoint provided to connect the websocket to"));
|
|
1001
1146
|
return;
|
|
1002
1147
|
}
|
|
1003
|
-
const logLevel = this.
|
|
1148
|
+
const logLevel = this._getLogLevel();
|
|
1004
1149
|
this.connection = this.signalRService.buildConnection(this.REQUEST_URL, Object.assign(Object.assign({}, this.defaultOptions), options), logLevel, true);
|
|
1150
|
+
const signalRServerTimeoutInMilliseconds = (_a = this.chatConfig$.value) === null || _a === void 0 ? void 0 : _a.connectionSettings.signalRServerTimeoutInMilliseconds;
|
|
1151
|
+
if (signalRServerTimeoutInMilliseconds) {
|
|
1152
|
+
this.connection.serverTimeoutInMilliseconds = signalRServerTimeoutInMilliseconds;
|
|
1153
|
+
}
|
|
1005
1154
|
resolve();
|
|
1006
1155
|
});
|
|
1007
1156
|
}
|
|
@@ -1019,7 +1168,7 @@ class WebSocketChatService extends ChatService {
|
|
|
1019
1168
|
stopConnection() {
|
|
1020
1169
|
return this.signalRService.stopConnection(this.connection);
|
|
1021
1170
|
}
|
|
1022
|
-
|
|
1171
|
+
_getTransports() {
|
|
1023
1172
|
var _a;
|
|
1024
1173
|
switch ((_a = this.chatConfig$.value) === null || _a === void 0 ? void 0 : _a.connectionSettings.signalRTransport) {
|
|
1025
1174
|
case "WebSockets":
|
|
@@ -1032,7 +1181,7 @@ class WebSocketChatService extends ChatService {
|
|
|
1032
1181
|
return HttpTransportType.None;
|
|
1033
1182
|
}
|
|
1034
1183
|
}
|
|
1035
|
-
|
|
1184
|
+
_getLogLevel() {
|
|
1036
1185
|
var _a;
|
|
1037
1186
|
switch ((_a = this.chatConfig$.value) === null || _a === void 0 ? void 0 : _a.connectionSettings.signalRLogLevel) {
|
|
1038
1187
|
case "Critical":
|
|
@@ -1067,7 +1216,7 @@ class WebSocketChatService extends ChatService {
|
|
|
1067
1216
|
// as far as we know, signalR only lets us tweak the request with this access token factory
|
|
1068
1217
|
// so we pass along the Sinequa CSRF token to pass the CSRF check..
|
|
1069
1218
|
return {
|
|
1070
|
-
transport: this.
|
|
1219
|
+
transport: this._getTransports(),
|
|
1071
1220
|
withCredentials: true,
|
|
1072
1221
|
headers,
|
|
1073
1222
|
accessTokenFactory: () => { var _a, _b; return ((_b = (_a = this.authenticationService.processedCredentials) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.csrfToken) || ""; }
|
|
@@ -1309,10 +1458,10 @@ class ChatReferenceComponent {
|
|
|
1309
1458
|
}
|
|
1310
1459
|
}
|
|
1311
1460
|
ChatReferenceComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ChatReferenceComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1312
|
-
ChatReferenceComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: ChatReferenceComponent, isStandalone: true, selector: "sq-chat-reference", inputs: { reference: "reference", attachment: "attachment", partId: "partId" }, outputs: { openDocument: "openDocument", openPreview: "openPreview" }, ngImport: i0, template: "<div [class.reference-tooltip]=\"!!partId\">\n <div class=\"reference-data\" [class.expanded]=\"attachment['$expanded'] || !!partId\" (click)=\"expandAttachment()\">\n <span class=\"reference me-1\">{{reference}}</span>\n <sq-format-icon [extension]=\"attachment.record.fileext\"></sq-format-icon>\n <a [id]=\"'attachment-'+attachment.recordId\">\n {{attachment.record.title}}\n </a>\n <i class=\"fas fa-eye\" (click)=\"$event.stopPropagation(); openPreview.emit(attachment)\" [sqTooltip]=\"!partId ? 'Preview document' : ''\"></i>\n <i class=\"fas fa-arrow-up-right-from-square\" *ngIf=\"attachment.record.url1 || attachment.record.originalUrl\"\n (click)=\"$event.stopPropagation(); openDocument.emit(attachment)\" [sqTooltip]=\"!partId ? 'Open document' : ''\">\n </i>\n </div>\n <div class=\"reference-passages\" *ngIf=\"!!partId || (attachment['$expanded']) && parts.length\">\n <div class=\"reference-passage\" *ngFor=\"let part of parts\">\n <span class=\"reference me-1\">{{reference}}.{{part.partId}}</span>\n <span [innerHTML]=\"part.text\"></span>\n </div>\n </div>\n</div>\n", styles: [".ast-primary{color:var(--ast-primary-color, #005DA7);background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover{background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover:hover{color:var(--ast-primary-color, #005DA7)}.ast-secondary{color:var(--ast-secondary-color, #FF732E);background-color:var(--ast-secondary-bg, #FFF8F1)}.ast-error{background-color:var(--ast-error-bg, rgba(249, 58, 55, .2))}.ast-error:hover{color:var(--ast-error-color, rgba(249, 58, 55, .7))}.ast-btn{border:0;text-align:left;padding-top:.5rem;padding-bottom:.5rem;display:flex;align-items:center}.dark{--ast-primary-bg: #0d0701;--ast-primary-color: #008cd1;--ast-secondary-bg: #00070e;--ast-secondary-color: #ffa258;--ast-input-bg: #070707;--ast-input-color: rgba(222, 218, 218, .75);--ast-muted-color: rgba(222, 218, 218, .75);--ast-saved-chat-hover-background: #262421;--ast-message-table-border-color: #333333;--ast-message-table-tr-bg: #070707;--ast-message-table-tr-border-color: #222222;--ast-reference-icon-color: white;--ast-reference-icon-active-color: black;--ast-reference-passages-color: white;--ast-reference-expanded-hover-bg: #262421;--ast-message-reference-color: black}:host ::ng-deep .reference,:host ::ng-deep .message-content .reference,:host ::ng-deep .attachment .reference{position:relative;bottom:var(--ast-reference-bottom, .3em);font-weight:var(--ast-reference-font-weight, bold);padding:var(--ast-reference-padding, 0 .2em);margin:var(--ast-reference-margin, 0 .1em);border-radius:var(--ast-reference-border-radius, .2em);background-color:var(--ast-reference-background-color, lightblue);color:var(--ast-reference-color, black)}:host ::ng-deep .reference,:host ::ng-deep .message-content .reference{font-size:var(--ast-reference-message-font-size, .7em)}:host ::ng-deep .attachment .reference{font-size:var(--ast-reference-attachment-font-size, 13px)}:host{display:block}:host.expanded,:host:hover{background-color:var(--ast-reference-expanded-hover-bg, white)}.reference-data{display:flex;flex-direction:row;align-items:baseline;padding:var(--ast-size-1, .25rem);cursor:pointer}.reference-data a{color:var(--ast-secondary-color, #FF732E);flex-grow:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-weight:var(--font-weight-bold, 500);cursor:pointer}.reference-data i{padding:var(--ast-size-1, .25rem);margin-left:var(--ast-size-1, .25rem);cursor:pointer;color:var(--ast-reference-icon-color, black)}.reference-data i.active{color:var(--ast-reference-icon-active-color, white);background-color:var(--ast-secondary-color, #FF732E)}.reference-data:not(.expanded) i{opacity:0}.reference-data:not(.expanded):hover i{opacity:1}.reference-passages{white-space:normal;font-style:italic;font-weight:400;padding:1rem 0;color:var(--ast-reference-passages-color, black)}.reference-passages .reference-passage{display:flex;align-items:baseline;padding-left:2.5rem;padding-right:1rem;word-wrap:break-word}.reference-passages .reference-passage+.reference-passage{padding-top:1rem}.reference-passages .reference-passage .reference{white-space:nowrap;margin-right:var(--ast-size-2, .5rem)}sq-format-icon{margin-left:var(--ast-size-1, .25rem);margin-right:var(--ast-size-2, .5rem);color:var(--ast-secondary-color, #FF732E)}.reference-tooltip{max-width:600px!important;box-shadow:0 .5rem 1rem #00000026;padding:.5rem;font-size:.875rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: UtilsModule }, { kind: "directive", type: i2$1.TooltipDirective, selector: "[sqTooltip]", inputs: ["sqTooltip", "sqTooltipData", "sqTooltipTemplate", "placement", "fallbackPlacements", "delay", "hoverableTooltip", "tooltipClass"] }, { kind: "component", type: FormatIconComponent, selector: "sq-format-icon", inputs: ["extension"] }] });
|
|
1461
|
+
ChatReferenceComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: ChatReferenceComponent, isStandalone: true, selector: "sq-chat-reference", inputs: { reference: "reference", attachment: "attachment", partId: "partId" }, outputs: { openDocument: "openDocument", openPreview: "openPreview" }, ngImport: i0, template: "<div [class.reference-tooltip]=\"!!partId\">\n <div class=\"reference-data\" [class.expanded]=\"attachment['$expanded'] || !!partId\" (click)=\"expandAttachment()\">\n <span class=\"reference me-1\">{{reference}}</span>\n <sq-format-icon [extension]=\"attachment.record.fileext\"></sq-format-icon>\n <a [id]=\"'attachment-'+attachment.recordId\">\n {{attachment.record.title}}\n </a>\n <i class=\"fas fa-eye\" (click)=\"$event.stopPropagation(); openPreview.emit(attachment)\" [sqTooltip]=\"!partId ? 'Preview document' : ''\"></i>\n <i class=\"fas fa-arrow-up-right-from-square\" *ngIf=\"attachment.record.url1 || attachment.record.originalUrl\"\n (click)=\"$event.stopPropagation(); openDocument.emit(attachment)\" [sqTooltip]=\"!partId ? 'Open document' : ''\">\n </i>\n </div>\n <div class=\"reference-passages\" *ngIf=\"!!partId || (attachment['$expanded']) && parts.length\">\n <div class=\"reference-passage\" *ngFor=\"let part of parts\">\n <span class=\"reference me-1\">{{reference}}.{{part.partId}}</span>\n <span class=\"w-100 pe-2\" [innerHTML]=\"part.text\"></span>\n </div>\n </div>\n</div>\n", styles: [".ast-primary{color:var(--ast-primary-color, #005DA7);background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover{background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover:hover{color:var(--ast-primary-color, #005DA7)}.ast-secondary{color:var(--ast-secondary-color, #FF732E);background-color:var(--ast-secondary-bg, #FFF8F1)}.ast-error{background-color:var(--ast-error-bg, rgba(249, 58, 55, .2));color:var(--ast-action-buttons-color, inherit)}.ast-error:hover{color:var(--ast-error-color, rgba(249, 58, 55, .7))}.ast-btn{border:0;text-align:left;padding-top:.5rem;padding-bottom:.5rem;display:flex;align-items:center}.dark{--ast-primary-bg: #0d0701;--ast-primary-color: #008cd1;--ast-secondary-bg: #00070e;--ast-secondary-color: #ffa258;--ast-input-bg: #070707;--ast-input-color: rgba(222, 218, 218, .75);--ast-muted-color: rgba(222, 218, 218, .75);--ast-saved-chat-hover-background: #262421;--ast-message-table-border-color: #333333;--ast-message-table-tr-bg: #070707;--ast-message-table-tr-border-color: #222222;--ast-reference-icon-color: white;--ast-reference-icon-active-color: black;--ast-reference-passages-color: white;--ast-reference-expanded-hover-bg: #262421;--ast-message-reference-color: black;--ast-action-buttons-color: white;--ast-action-buttons-hover-color: #6dbee6}:host ::ng-deep .reference,:host ::ng-deep .message-content .reference,:host ::ng-deep .attachment .reference{position:relative;bottom:var(--ast-reference-bottom, .3em);font-weight:var(--ast-reference-font-weight, bold);padding:var(--ast-reference-padding, 0 .2em);margin:var(--ast-reference-margin, 0 .1em);border-radius:var(--ast-reference-border-radius, .2em);background-color:var(--ast-reference-background-color, lightblue);color:var(--ast-reference-color, black)}:host ::ng-deep .reference,:host ::ng-deep .message-content .reference{font-size:var(--ast-reference-message-font-size, .7em)}:host ::ng-deep .attachment .reference{font-size:var(--ast-reference-attachment-font-size, 13px)}:host{display:block}:host.expanded,:host:hover{background-color:var(--ast-reference-expanded-hover-bg, white)}.reference-data{display:flex;flex-direction:row;align-items:baseline;padding:var(--ast-size-1, .25rem);cursor:pointer}.reference-data a{color:var(--ast-secondary-color, #FF732E);flex-grow:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-weight:var(--font-weight-bold, 500);cursor:pointer}.reference-data i{padding:var(--ast-size-1, .25rem);margin-left:var(--ast-size-1, .25rem);cursor:pointer;color:var(--ast-reference-icon-color, black)}.reference-data i.active{color:var(--ast-reference-icon-active-color, white);background-color:var(--ast-secondary-color, #FF732E)}.reference-data:not(.expanded) i{opacity:0}.reference-data:not(.expanded):hover i{opacity:1}.reference-passages{white-space:normal;font-style:italic;font-weight:400;padding:1rem 0;color:var(--ast-reference-passages-color, black)}.reference-passages .reference-passage{display:flex;align-items:baseline;padding-left:2.5rem;padding-right:1rem;word-wrap:break-word}.reference-passages .reference-passage+.reference-passage{padding-top:1rem}.reference-passages .reference-passage .reference{white-space:nowrap;margin-right:var(--ast-size-2, .5rem)}sq-format-icon{margin-left:var(--ast-size-1, .25rem);margin-right:var(--ast-size-2, .5rem);color:var(--ast-secondary-color, #FF732E)}.reference-tooltip{max-width:600px!important;box-shadow:0 .5rem 1rem #00000026;padding:.5rem;font-size:.875rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: UtilsModule }, { kind: "directive", type: i2$1.TooltipDirective, selector: "[sqTooltip]", inputs: ["sqTooltip", "sqTooltipData", "sqTooltipTemplate", "placement", "fallbackPlacements", "delay", "hoverableTooltip", "tooltipClass"] }, { kind: "component", type: FormatIconComponent, selector: "sq-format-icon", inputs: ["extension"] }] });
|
|
1313
1462
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ChatReferenceComponent, decorators: [{
|
|
1314
1463
|
type: Component,
|
|
1315
|
-
args: [{ selector: 'sq-chat-reference', standalone: true, imports: [CommonModule, UtilsModule, FormatIconComponent], template: "<div [class.reference-tooltip]=\"!!partId\">\n <div class=\"reference-data\" [class.expanded]=\"attachment['$expanded'] || !!partId\" (click)=\"expandAttachment()\">\n <span class=\"reference me-1\">{{reference}}</span>\n <sq-format-icon [extension]=\"attachment.record.fileext\"></sq-format-icon>\n <a [id]=\"'attachment-'+attachment.recordId\">\n {{attachment.record.title}}\n </a>\n <i class=\"fas fa-eye\" (click)=\"$event.stopPropagation(); openPreview.emit(attachment)\" [sqTooltip]=\"!partId ? 'Preview document' : ''\"></i>\n <i class=\"fas fa-arrow-up-right-from-square\" *ngIf=\"attachment.record.url1 || attachment.record.originalUrl\"\n (click)=\"$event.stopPropagation(); openDocument.emit(attachment)\" [sqTooltip]=\"!partId ? 'Open document' : ''\">\n </i>\n </div>\n <div class=\"reference-passages\" *ngIf=\"!!partId || (attachment['$expanded']) && parts.length\">\n <div class=\"reference-passage\" *ngFor=\"let part of parts\">\n <span class=\"reference me-1\">{{reference}}.{{part.partId}}</span>\n <span [innerHTML]=\"part.text\"></span>\n </div>\n </div>\n</div>\n", styles: [".ast-primary{color:var(--ast-primary-color, #005DA7);background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover{background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover:hover{color:var(--ast-primary-color, #005DA7)}.ast-secondary{color:var(--ast-secondary-color, #FF732E);background-color:var(--ast-secondary-bg, #FFF8F1)}.ast-error{background-color:var(--ast-error-bg, rgba(249, 58, 55, .2))}.ast-error:hover{color:var(--ast-error-color, rgba(249, 58, 55, .7))}.ast-btn{border:0;text-align:left;padding-top:.5rem;padding-bottom:.5rem;display:flex;align-items:center}.dark{--ast-primary-bg: #0d0701;--ast-primary-color: #008cd1;--ast-secondary-bg: #00070e;--ast-secondary-color: #ffa258;--ast-input-bg: #070707;--ast-input-color: rgba(222, 218, 218, .75);--ast-muted-color: rgba(222, 218, 218, .75);--ast-saved-chat-hover-background: #262421;--ast-message-table-border-color: #333333;--ast-message-table-tr-bg: #070707;--ast-message-table-tr-border-color: #222222;--ast-reference-icon-color: white;--ast-reference-icon-active-color: black;--ast-reference-passages-color: white;--ast-reference-expanded-hover-bg: #262421;--ast-message-reference-color: black}:host ::ng-deep .reference,:host ::ng-deep .message-content .reference,:host ::ng-deep .attachment .reference{position:relative;bottom:var(--ast-reference-bottom, .3em);font-weight:var(--ast-reference-font-weight, bold);padding:var(--ast-reference-padding, 0 .2em);margin:var(--ast-reference-margin, 0 .1em);border-radius:var(--ast-reference-border-radius, .2em);background-color:var(--ast-reference-background-color, lightblue);color:var(--ast-reference-color, black)}:host ::ng-deep .reference,:host ::ng-deep .message-content .reference{font-size:var(--ast-reference-message-font-size, .7em)}:host ::ng-deep .attachment .reference{font-size:var(--ast-reference-attachment-font-size, 13px)}:host{display:block}:host.expanded,:host:hover{background-color:var(--ast-reference-expanded-hover-bg, white)}.reference-data{display:flex;flex-direction:row;align-items:baseline;padding:var(--ast-size-1, .25rem);cursor:pointer}.reference-data a{color:var(--ast-secondary-color, #FF732E);flex-grow:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-weight:var(--font-weight-bold, 500);cursor:pointer}.reference-data i{padding:var(--ast-size-1, .25rem);margin-left:var(--ast-size-1, .25rem);cursor:pointer;color:var(--ast-reference-icon-color, black)}.reference-data i.active{color:var(--ast-reference-icon-active-color, white);background-color:var(--ast-secondary-color, #FF732E)}.reference-data:not(.expanded) i{opacity:0}.reference-data:not(.expanded):hover i{opacity:1}.reference-passages{white-space:normal;font-style:italic;font-weight:400;padding:1rem 0;color:var(--ast-reference-passages-color, black)}.reference-passages .reference-passage{display:flex;align-items:baseline;padding-left:2.5rem;padding-right:1rem;word-wrap:break-word}.reference-passages .reference-passage+.reference-passage{padding-top:1rem}.reference-passages .reference-passage .reference{white-space:nowrap;margin-right:var(--ast-size-2, .5rem)}sq-format-icon{margin-left:var(--ast-size-1, .25rem);margin-right:var(--ast-size-2, .5rem);color:var(--ast-secondary-color, #FF732E)}.reference-tooltip{max-width:600px!important;box-shadow:0 .5rem 1rem #00000026;padding:.5rem;font-size:.875rem}\n"] }]
|
|
1464
|
+
args: [{ selector: 'sq-chat-reference', standalone: true, imports: [CommonModule, UtilsModule, FormatIconComponent], template: "<div [class.reference-tooltip]=\"!!partId\">\n <div class=\"reference-data\" [class.expanded]=\"attachment['$expanded'] || !!partId\" (click)=\"expandAttachment()\">\n <span class=\"reference me-1\">{{reference}}</span>\n <sq-format-icon [extension]=\"attachment.record.fileext\"></sq-format-icon>\n <a [id]=\"'attachment-'+attachment.recordId\">\n {{attachment.record.title}}\n </a>\n <i class=\"fas fa-eye\" (click)=\"$event.stopPropagation(); openPreview.emit(attachment)\" [sqTooltip]=\"!partId ? 'Preview document' : ''\"></i>\n <i class=\"fas fa-arrow-up-right-from-square\" *ngIf=\"attachment.record.url1 || attachment.record.originalUrl\"\n (click)=\"$event.stopPropagation(); openDocument.emit(attachment)\" [sqTooltip]=\"!partId ? 'Open document' : ''\">\n </i>\n </div>\n <div class=\"reference-passages\" *ngIf=\"!!partId || (attachment['$expanded']) && parts.length\">\n <div class=\"reference-passage\" *ngFor=\"let part of parts\">\n <span class=\"reference me-1\">{{reference}}.{{part.partId}}</span>\n <span class=\"w-100 pe-2\" [innerHTML]=\"part.text\"></span>\n </div>\n </div>\n</div>\n", styles: [".ast-primary{color:var(--ast-primary-color, #005DA7);background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover{background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover:hover{color:var(--ast-primary-color, #005DA7)}.ast-secondary{color:var(--ast-secondary-color, #FF732E);background-color:var(--ast-secondary-bg, #FFF8F1)}.ast-error{background-color:var(--ast-error-bg, rgba(249, 58, 55, .2));color:var(--ast-action-buttons-color, inherit)}.ast-error:hover{color:var(--ast-error-color, rgba(249, 58, 55, .7))}.ast-btn{border:0;text-align:left;padding-top:.5rem;padding-bottom:.5rem;display:flex;align-items:center}.dark{--ast-primary-bg: #0d0701;--ast-primary-color: #008cd1;--ast-secondary-bg: #00070e;--ast-secondary-color: #ffa258;--ast-input-bg: #070707;--ast-input-color: rgba(222, 218, 218, .75);--ast-muted-color: rgba(222, 218, 218, .75);--ast-saved-chat-hover-background: #262421;--ast-message-table-border-color: #333333;--ast-message-table-tr-bg: #070707;--ast-message-table-tr-border-color: #222222;--ast-reference-icon-color: white;--ast-reference-icon-active-color: black;--ast-reference-passages-color: white;--ast-reference-expanded-hover-bg: #262421;--ast-message-reference-color: black;--ast-action-buttons-color: white;--ast-action-buttons-hover-color: #6dbee6}:host ::ng-deep .reference,:host ::ng-deep .message-content .reference,:host ::ng-deep .attachment .reference{position:relative;bottom:var(--ast-reference-bottom, .3em);font-weight:var(--ast-reference-font-weight, bold);padding:var(--ast-reference-padding, 0 .2em);margin:var(--ast-reference-margin, 0 .1em);border-radius:var(--ast-reference-border-radius, .2em);background-color:var(--ast-reference-background-color, lightblue);color:var(--ast-reference-color, black)}:host ::ng-deep .reference,:host ::ng-deep .message-content .reference{font-size:var(--ast-reference-message-font-size, .7em)}:host ::ng-deep .attachment .reference{font-size:var(--ast-reference-attachment-font-size, 13px)}:host{display:block}:host.expanded,:host:hover{background-color:var(--ast-reference-expanded-hover-bg, white)}.reference-data{display:flex;flex-direction:row;align-items:baseline;padding:var(--ast-size-1, .25rem);cursor:pointer}.reference-data a{color:var(--ast-secondary-color, #FF732E);flex-grow:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-weight:var(--font-weight-bold, 500);cursor:pointer}.reference-data i{padding:var(--ast-size-1, .25rem);margin-left:var(--ast-size-1, .25rem);cursor:pointer;color:var(--ast-reference-icon-color, black)}.reference-data i.active{color:var(--ast-reference-icon-active-color, white);background-color:var(--ast-secondary-color, #FF732E)}.reference-data:not(.expanded) i{opacity:0}.reference-data:not(.expanded):hover i{opacity:1}.reference-passages{white-space:normal;font-style:italic;font-weight:400;padding:1rem 0;color:var(--ast-reference-passages-color, black)}.reference-passages .reference-passage{display:flex;align-items:baseline;padding-left:2.5rem;padding-right:1rem;word-wrap:break-word}.reference-passages .reference-passage+.reference-passage{padding-top:1rem}.reference-passages .reference-passage .reference{white-space:nowrap;margin-right:var(--ast-size-2, .5rem)}sq-format-icon{margin-left:var(--ast-size-1, .25rem);margin-right:var(--ast-size-2, .5rem);color:var(--ast-secondary-color, #FF732E)}.reference-tooltip{max-width:600px!important;box-shadow:0 .5rem 1rem #00000026;padding:.5rem;font-size:.875rem}\n"] }]
|
|
1316
1465
|
}], propDecorators: { reference: [{
|
|
1317
1466
|
type: Input
|
|
1318
1467
|
}], attachment: [{
|
|
@@ -1378,6 +1527,7 @@ class ChatMessageComponent {
|
|
|
1378
1527
|
this.openDocument = new EventEmitter();
|
|
1379
1528
|
this.openPreview = new EventEmitter();
|
|
1380
1529
|
this.suggestAction = new EventEmitter();
|
|
1530
|
+
this.chatStarterClicked = new EventEmitter();
|
|
1381
1531
|
this.edit = new EventEmitter();
|
|
1382
1532
|
this.copy = new EventEmitter();
|
|
1383
1533
|
this.regenerate = new EventEmitter();
|
|
@@ -1455,7 +1605,7 @@ class ChatMessageComponent {
|
|
|
1455
1605
|
if (changes.streaming) {
|
|
1456
1606
|
this.collapseProgress = !this.streaming;
|
|
1457
1607
|
}
|
|
1458
|
-
if (
|
|
1608
|
+
if (((_a = this.message) === null || _a === void 0 ? void 0 : _a.role) === "assistant") {
|
|
1459
1609
|
this.references = [];
|
|
1460
1610
|
this.referenceMap.clear();
|
|
1461
1611
|
for (let m of this.conversation) {
|
|
@@ -1557,17 +1707,19 @@ class ChatMessageComponent {
|
|
|
1557
1707
|
}
|
|
1558
1708
|
}
|
|
1559
1709
|
ChatMessageComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ChatMessageComponent, deps: [{ token: i1$1.SearchService }, { token: i2$1.UIService }, { token: i3.PrincipalWebService }, { token: i0.ChangeDetectorRef }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
1560
|
-
ChatMessageComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: ChatMessageComponent, isStandalone: true, selector: "sq-chat-message", inputs: { message: "message", conversation: "conversation", suggestedActions: "suggestedActions", assistantMessageIcon: "assistantMessageIcon", userMessageIcon: "userMessageIcon", connectionErrorMessageIcon: "connectionErrorMessageIcon", searchWarningMessageIcon: "searchWarningMessageIcon", streaming: "streaming", canEdit: "canEdit", canRegenerate: "canRegenerate", canCopy: "canCopy", canDebug: "canDebug", canLike: "canLike", canDislike: "canDislike" }, outputs: { openDocument: "openDocument", openPreview: "openPreview", suggestAction: "suggestAction", edit: "edit", copy: "copy", regenerate: "regenerate", like: "like", dislike: "dislike", debug: "debug" }, usesOnChanges: true, ngImport: i0, template: "<!-- Message icon -->\n<span class=\"message-icon\" [title]=\"message?.role\">\n <i class=\"d-block\" [style.width.px]=\"iconSize\" *ngIf=\"!message\"></i>\n <ng-container [ngSwitch]=\"message?.role\">\n <!-- For 'assistant' -->\n <i *ngSwitchCase=\"'assistant'\" [ngClass]=\"assistantMessageIcon\" [style.--sq-size.px]=\"iconSize\"></i>\n <!-- For 'user' -->\n <ng-container *ngSwitchCase=\"'user'\">\n <i *ngIf=\"!!userMessageIcon; else initialsAvatar\" [ngClass]=\"userMessageIcon\" [style.--sq-size.px]=\"iconSize\"></i>\n <ng-template #initialsAvatar>\n <sq-initials-avatar [fullName]=\"name\"></sq-initials-avatar>\n </ng-template>\n </ng-container>\n <!-- For 'connection-error' -->\n <ng-container *ngSwitchCase=\"'connection-error'\">\n <i *ngIf=\"!!connectionErrorMessageIcon; else defaultErrorIcon\" [ngClass]=\"connectionErrorMessageIcon\" [style.--sq-size.px]=\"iconSize\"></i>\n <ng-template #defaultErrorIcon>\n <svg [style.--sq-size.px]=\"iconSize\" class=\"connection-error\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\">\n <path fill=\"currentColor\" d=\"M17.1 292c-12.9-22.3-12.9-49.7 0-72L105.4 67.1c12.9-22.3 36.6-36 62.4-36l176.6 0c25.7 0 49.5 13.7 62.4 36L494.9 220c12.9 22.3 12.9 49.7 0 72L406.6 444.9c-12.9 22.3-36.6 36-62.4 36l-176.6 0c-25.7 0-49.5-13.7-62.4-36L17.1 292zM256 128c-13.3 0-24 10.7-24 24l0 112c0 13.3 10.7 24 24 24s24-10.7 24-24l0-112c0-13.3-10.7-24-24-24zm32 224a32 32 0 1 0 -64 0 32 32 0 1 0 64 0z\"/>\n </svg>\n </ng-template>\n </ng-container>\n <!-- For 'search-warning' -->\n <ng-container *ngSwitchCase=\"'search-warning'\">\n <i *ngIf=\"!!searchWarningMessageIcon; else defaultWarningIcon\" [ngClass]=\"searchWarningMessageIcon\" [style.--sq-size.px]=\"iconSize\"></i>\n <ng-template #defaultWarningIcon>\n <svg [style.--sq-size.px]=\"iconSize\" class=\"search-warning\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 384 512\">\n <path fill=\"currentColor\" d=\"M272 384c9.6-31.9 29.5-59.1 49.2-86.2c0 0 0 0 0 0c5.2-7.1 10.4-14.2 15.4-21.4c19.8-28.5 31.4-63 31.4-100.3C368 78.8 289.2 0 192 0S16 78.8 16 176c0 37.3 11.6 71.9 31.4 100.3c5 7.2 10.2 14.3 15.4 21.4c0 0 0 0 0 0c19.8 27.1 39.7 54.4 49.2 86.2l160 0zM192 512c44.2 0 80-35.8 80-80l0-16-160 0 0 16c0 44.2 35.8 80 80 80zm0-448c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zM160 288a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z\"/>\n </svg>\n </ng-template>\n </ng-container>\n </ng-container>\n\n</span>\n\n<!-- Message body -->\n<div class=\"flex-grow-1\" style=\"min-width: 0;\" [ngClass]=\"'message-'+message.role\">\n\n <div *ngIf=\"message.additionalProperties.$progress as progress\" class=\"small ms-3 mb-2\">\n <a href=\"#\" (click)=\"collapseProgress = !collapseProgress; false\" class=\"text-muted\">\n View progress\n <i class=\"fas fa-chevron-{{collapseProgress? 'right' : 'down'}}\"></i>\n </a>\n <sq-collapse [collapsed]=\"collapseProgress\">\n <ng-template>\n <ul class=\"list-unstyled\">\n <li *ngFor=\"let step of progress\">\n <i class=\"fas fa-fw fa-check text-success\" *ngIf=\"step.done\"></i>\n <i class=\"fas fa-fw fa-spin fa-circle-notch\" *ngIf=\"!step.done\"></i>\n <span class=\"ms-2 fw-bold\">{{step.title}}</span>\n <span *ngIf=\"step.content\">: {{step.content}}</span>\n </li>\n </ul>\n </ng-template>\n </sq-collapse>\n </div>\n\n <div class=\"message-content\" *ngIf=\"message.content\">\n\n <div *ngIf=\"message?.role === 'assistant' && message.messageType === 'CHART'\">\n <sq-assistant-chart [rawChartData]=\"message.content\"></sq-assistant-chart>\n </div>\n\n <remark *ngIf=\"(message?.role === 'assistant' && message.messageType === 'MARKDOWN') || message?.role === 'connection-error' || message?.role === 'search-warning'\" [markdown]=\"message.content\" [processor]=\"processor\">\n\n <ng-template remarkTemplate=\"chat-reference\" let-ref>\n\n <a *ngIf=\"referenceMap.get(ref.refId) as attachment; else staticRefTpl\"\n class=\"reference\"\n [sqTooltip]=\"attachment\"\n [sqTooltipTemplate]=\"tooltipTpl\"\n [hoverableTooltip]=\"true\"\n >{{ref.refId}}\n </a>\n\n <ng-template #staticRefTpl>\n <span class=\"reference\">{{ref.refId}}</span>\n </ng-template>\n\n </ng-template>\n\n <ng-template remarkTemplate=\"streaming-placeholder\">\n <span class=\"placeholder-glow\" *ngIf=\"streaming\">\n <span class=\"placeholder ms-1\"></span>\n </span>\n </ng-template>\n\n <ng-template remarkTemplate=\"code\" let-node>\n <div class=\"card mb-2\">\n <div class=\"card-header d-flex justify-content-between align-items-center\">\n <span>{{node.lang}}</span>\n <button class=\"btn btn-light btn-sm\" (click)=\"copyCode(node.value)\"><i class=\"far fa-fw fa-clipboard\"></i> Copy code</button>\n </div>\n <pre class=\"language-{{node.lang}} my-0 rounded-0 rounded-bottom\"><code class=\"language-{{node.lang}}\">{{node.value}}</code></pre>\n </div>\n </ng-template>\n\n <ng-template remarkTemplate=\"link\" let-node>\n <a [href]=\"node.url\" target=\"_blank\" rel=\"noopener noreferrer\">{{getLinkText(node)}}</a>\n </ng-template>\n\n </remark>\n\n <p *ngIf=\"message?.role === 'user'\">{{message.content}}</p>\n\n <!-- List of reference, if any -->\n <div *ngIf=\"references?.length\" class=\"references\">\n <span class=\"references-title\">References</span> <i class=\"fas references-collapse\" [class.fa-chevron-down]=\"showReferences\" [class.fa-chevron-right]=\"!showReferences\" (click)=\"showReferences=!showReferences\"></i>\n <sq-collapse [collapsed]=\"!showReferences\">\n <ng-template>\n <ul>\n <ng-container *ngFor=\"let reference of references\">\n <li *ngIf=\"referenceMap.get(reference) as attachment\" class=\"text-truncate\">\n <sq-chat-reference\n [class.expanded]=\"attachment.$expanded\"\n [attachment]=\"attachment\"\n [reference]=\"reference\"\n (openPreview)=\"openAttachmentPreview($event)\"\n (openDocument)=\"openOriginalAttachment($event)\">\n </sq-chat-reference>\n </li>\n </ng-container>\n </ul>\n </ng-template>\n </sq-collapse>\n </div>\n\n </div>\n\n <!-- Edit / Regenerate floating actions -->\n <div class=\"sq-chat-message-actions\" *ngIf=\"message\">\n <button class=\"btn btn-sm\" *ngIf=\"canEdit\" sqTooltip=\"Edit message\" (click)=\"edit.emit(message)\">\n <i class=\"fas fa-edit\"></i>\n </button>\n <button class=\"btn btn-sm\" *ngIf=\"canCopy\" sqTooltip=\"Copy text\" (click)=\"copyMessage(message)\">\n <i class=\"far fa-clipboard\"></i>\n </button>\n <button class=\"btn btn-sm\" *ngIf=\"canRegenerate\" sqTooltip=\"Regenerate message\" (click)=\"regenerate.emit(message)\">\n <i class=\"fas fa-sync-alt\"></i>\n </button>\n <button class=\"btn btn-sm\" [class.bounce]=\"liked\" *ngIf=\"canLike\" sqTooltip=\"Like the answer\" (click)=\"like.emit(message); liked = true;\">\n <i class=\"far fa-thumbs-up\"></i>\n </button>\n <button class=\"btn btn-sm bounce\" [class.bounce]=\"disliked\" *ngIf=\"canDislike\" sqTooltip=\"Report an issue\" (click)=\"dislike.emit(message); disliked = true;\">\n <i class=\"far fa-thumbs-down\"></i>\n </button>\n <button class=\"btn btn-sm\" *ngIf=\"canDebug && !!message.additionalProperties.$debug && message.additionalProperties.$debug?.length > 0\" sqTooltip=\"Show Log Information\" (click)=\"debug.emit(message);\">\n <i class=\"far fa-list-alt\"></i>\n </button>\n </div>\n\n <!-- List of suggested actions, if any -->\n <div *ngIf=\"suggestedActions\" class=\"mt-2 message-suggestion\">\n <div class=\"suggested-action\" *ngFor=\"let suggestedAction of suggestedActions\" (click)=\"suggestAction.emit(suggestedAction)\">\n <div class=\"message-content\">\n <p><i class=\"fas fa-clipboard-question\"></i> {{suggestedAction.content}}</p>\n </div>\n </div>\n </div>\n\n <ng-template #tooltipTpl let-ref>\n <sq-chat-reference\n *ngIf=\"!hiddenTooltip\"\n class=\"expanded\"\n [attachment]=\"ref\"\n [reference]=\"ref.contextId\"\n [partId]=\"ref.$partId\"\n (openPreview)=\"openAttachmentPreview($event, ref.$partId)\"\n (openDocument)=\"openOriginalAttachment($event, ref.$partId)\">\n </sq-chat-reference>\n </ng-template>\n\n</div>\n", styles: [".ast-primary{color:var(--ast-primary-color, #005DA7);background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover{background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover:hover{color:var(--ast-primary-color, #005DA7)}.ast-secondary{color:var(--ast-secondary-color, #FF732E);background-color:var(--ast-secondary-bg, #FFF8F1)}.ast-error{background-color:var(--ast-error-bg, rgba(249, 58, 55, .2))}.ast-error:hover{color:var(--ast-error-color, rgba(249, 58, 55, .7))}.ast-btn{border:0;text-align:left;padding-top:.5rem;padding-bottom:.5rem;display:flex;align-items:center}.dark{--ast-primary-bg: #0d0701;--ast-primary-color: #008cd1;--ast-secondary-bg: #00070e;--ast-secondary-color: #ffa258;--ast-input-bg: #070707;--ast-input-color: rgba(222, 218, 218, .75);--ast-muted-color: rgba(222, 218, 218, .75);--ast-saved-chat-hover-background: #262421;--ast-message-table-border-color: #333333;--ast-message-table-tr-bg: #070707;--ast-message-table-tr-border-color: #222222;--ast-reference-icon-color: white;--ast-reference-icon-active-color: black;--ast-reference-passages-color: white;--ast-reference-expanded-hover-bg: #262421;--ast-message-reference-color: black}:host{display:flex}:host:not(:hover):not(.last-message) .sq-chat-message-actions{visibility:hidden}.message-content{padding:var(--ast-message-padding, var(--ast-size-3, .75rem));border-radius:var(--ast-message-border-radius, var(--ast-size-4, 1rem));display:inline-block;max-width:100%;overflow-wrap:break-word;word-wrap:break-word;word-break:break-word}.message-content .references{margin-top:var(--ast-size-5, 1.25rem)}.message-content .references ul{border-left:.2rem solid var(--ast-secondary-color, #FF732E);padding-left:var(--ast-size-5, 1.25rem);margin-top:var(--ast-size-2, .5rem)}.message-content .references .references-title{font-weight:var(--font-weight-bold, 500)}.message-content .references .references-collapse{cursor:pointer;margin-left:var(--ast-size-2, .5rem)}.message-content ::ng-deep p:last-child{margin-bottom:0}.message-content ::ng-deep .placeholder-glow .placeholder{animation-duration:.4s;width:12px;height:var(--ast-size-4, 1rem);vertical-align:text-bottom}.message-content ::ng-deep img{max-width:100%}.message-content ::ng-deep table{display:table;border:1px solid;border-color:var(--ast-message-table-border-color, #ccc);border-collapse:collapse;margin:0;padding:0;min-width:100%;overflow-x:auto;table-layout:fixed}.message-content ::ng-deep table tr{background-color:var(--ast-message-table-tr-bg, #f8f8f8);border:1px solid;border-color:var(--ast-message-table-tr-border-color, #ddd);padding:.35em}.message-content ::ng-deep table th,.message-content ::ng-deep table td{padding:.625em;text-align:center}.message-content ::ng-deep table th{font-size:.85em;letter-spacing:.1em;text-transform:uppercase}.message-content ::ng-deep .reference{color:var(--ast-message-reference-color, black)!important}.message-content ::ng-deep ul,.message-content ::ng-deep ol{display:flex;flex-direction:column;gap:.5rem;padding-right:2rem;margin-left:0;margin-right:0;padding-left:40px;unicode-bidi:-webkit-isolate;unicode-bidi:isolate;list-style:disc}.message-content ::ng-deep p:not(:first-child){margin-top:.5rem}.message-assistant .message-content{background:var(--ast-secondary-bg, #FFF8F1)}.message-connection-error .message-content{background:var(--ast-error-bg, rgba(249, 58, 55, .2))}.message-search-warning .message-content{background:var(--ast-warning-bg, #fff1b8)}.message-user .message-content{background:var(--ast-primary-bg, #f2f8fe);font-weight:var(--ast-user-font-weight, var(--font-weight-bold, 500))}.message-user .message-content p{white-space:pre-line}.message-suggestion .message-content{background:var(--ast-input-bg, #F8F8F8);font-weight:var(--ast-user-font-weight, var(--font-weight-bold, 500));transition:background-color .5s ease,color .5s ease}.message-suggestion .message-content:hover{background:var(--ast-primary-bg, #f2f8fe);color:var(--ast-primary-color, #005DA7)}.message-suggestion .message-content p{white-space:pre-line}.message-suggestion .suggested-action{cursor:pointer}.message-suggestion .suggested-action+.suggested-action{margin-top:var(--ast-size-2, .5rem)}.sq-chat-message-actions{position:absolute;bottom:calc(0rem - var(--ast-size-3, .75rem));display:flex;z-index:999}.sq-chat-message-actions button{font-size:.75rem}.sq-chat-message-actions button:hover{color:var(--ast-primary-color, #005DA7)}.message-icon{margin-top:var(--ast-size-3, .75rem);margin-right:var(--ast-size-4, 1rem)}.connection-error{height:var(--sq-size);width:var(--sq-size);color:var(--ast-error-color, rgba(249, 58, 55, .7))}.search-warning{height:var(--sq-size);width:var(--sq-size);color:var(--ast-warning-color, #fed86f)}.bounce{animation:bounce 2s ease}@keyframes bounce{10%{transform:translateY(0)}20%{transform:translateY(-15%)}30%{transform:translateY(0)}35%{transform:translateY(-7%)}37%{transform:translateY(0)}39%{transform:translateY(-3%)}40%{transform:translateY(0)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "ngmodule", type: UtilsModule }, { kind: "directive", type: i2$1.TooltipDirective, selector: "[sqTooltip]", inputs: ["sqTooltip", "sqTooltipData", "sqTooltipTemplate", "placement", "fallbackPlacements", "delay", "hoverableTooltip", "tooltipClass"] }, { kind: "ngmodule", type: CollapseModule }, { kind: "component", type: i5.Collapse, selector: "sq-collapse", inputs: ["collapsed"] }, { kind: "ngmodule", type: RemarkModule }, { kind: "component", type: i6.RemarkComponent, selector: "remark", inputs: ["markdown", "processor", "debug"] }, { kind: "directive", type: i6.RemarkTemplateDirective, selector: "[remarkTemplate]", inputs: ["remarkTemplate"] }, { kind: "component", type: InitialsAvatarComponent, selector: "sq-initials-avatar", inputs: ["fullName", "size"] }, { kind: "component", type: ChatReferenceComponent, selector: "sq-chat-reference", inputs: ["reference", "attachment", "partId"], outputs: ["openDocument", "openPreview"] }, { kind: "component", type: ChartComponent, selector: "sq-assistant-chart", inputs: ["rawChartData"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1710
|
+
ChatMessageComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: ChatMessageComponent, isStandalone: true, selector: "sq-chat-message", inputs: { message: "message", conversation: "conversation", suggestedActions: "suggestedActions", chatStarters: "chatStarters", assistantMessageIcon: "assistantMessageIcon", userMessageIcon: "userMessageIcon", connectionErrorMessageIcon: "connectionErrorMessageIcon", searchWarningMessageIcon: "searchWarningMessageIcon", streaming: "streaming", canEdit: "canEdit", canRegenerate: "canRegenerate", canCopy: "canCopy", canDebug: "canDebug", canLike: "canLike", canDislike: "canDislike" }, outputs: { openDocument: "openDocument", openPreview: "openPreview", suggestAction: "suggestAction", chatStarterClicked: "chatStarterClicked", edit: "edit", copy: "copy", regenerate: "regenerate", like: "like", dislike: "dislike", debug: "debug" }, usesOnChanges: true, ngImport: i0, template: "<!-- Message icon -->\n<span class=\"message-icon\" [title]=\"message?.role\">\n <i class=\"d-block\" [style.width.px]=\"iconSize\" *ngIf=\"!message\"></i>\n <ng-container [ngSwitch]=\"message?.role\">\n <!-- For 'assistant' -->\n <i *ngSwitchCase=\"'assistant'\" [ngClass]=\"assistantMessageIcon\" [style.--sq-size.px]=\"iconSize\"></i>\n <!-- For 'user' -->\n <ng-container *ngSwitchCase=\"'user'\">\n <i *ngIf=\"!!userMessageIcon; else initialsAvatar\" [ngClass]=\"userMessageIcon\" [style.--sq-size.px]=\"iconSize\"></i>\n <ng-template #initialsAvatar>\n <sq-initials-avatar [fullName]=\"name\"></sq-initials-avatar>\n </ng-template>\n </ng-container>\n <!-- For 'connection-error' -->\n <ng-container *ngSwitchCase=\"'connection-error'\">\n <i *ngIf=\"!!connectionErrorMessageIcon; else defaultErrorIcon\" [ngClass]=\"connectionErrorMessageIcon\" [style.--sq-size.px]=\"iconSize\"></i>\n <ng-template #defaultErrorIcon>\n <svg [style.--sq-size.px]=\"iconSize\" class=\"connection-error\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\">\n <path fill=\"currentColor\" d=\"M17.1 292c-12.9-22.3-12.9-49.7 0-72L105.4 67.1c12.9-22.3 36.6-36 62.4-36l176.6 0c25.7 0 49.5 13.7 62.4 36L494.9 220c12.9 22.3 12.9 49.7 0 72L406.6 444.9c-12.9 22.3-36.6 36-62.4 36l-176.6 0c-25.7 0-49.5-13.7-62.4-36L17.1 292zM256 128c-13.3 0-24 10.7-24 24l0 112c0 13.3 10.7 24 24 24s24-10.7 24-24l0-112c0-13.3-10.7-24-24-24zm32 224a32 32 0 1 0 -64 0 32 32 0 1 0 64 0z\"/>\n </svg>\n </ng-template>\n </ng-container>\n <!-- For 'search-warning' -->\n <ng-container *ngSwitchCase=\"'search-warning'\">\n <i *ngIf=\"!!searchWarningMessageIcon; else defaultWarningIcon\" [ngClass]=\"searchWarningMessageIcon\" [style.--sq-size.px]=\"iconSize\"></i>\n <ng-template #defaultWarningIcon>\n <svg [style.--sq-size.px]=\"iconSize\" class=\"search-warning\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 384 512\">\n <path fill=\"currentColor\" d=\"M272 384c9.6-31.9 29.5-59.1 49.2-86.2c0 0 0 0 0 0c5.2-7.1 10.4-14.2 15.4-21.4c19.8-28.5 31.4-63 31.4-100.3C368 78.8 289.2 0 192 0S16 78.8 16 176c0 37.3 11.6 71.9 31.4 100.3c5 7.2 10.2 14.3 15.4 21.4c0 0 0 0 0 0c19.8 27.1 39.7 54.4 49.2 86.2l160 0zM192 512c44.2 0 80-35.8 80-80l0-16-160 0 0 16c0 44.2 35.8 80 80 80zm0-448c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zM160 288a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z\"/>\n </svg>\n </ng-template>\n </ng-container>\n </ng-container>\n\n</span>\n\n<!-- Message body -->\n<div class=\"flex-grow-1\" style=\"min-width: 0;\" [ngClass]=\"'message-'+message.role\">\n\n <!-- Progress steps -->\n <div *ngIf=\"message.additionalProperties.$progress as progress\" class=\"small ms-3 mb-2\">\n <a href=\"#\" (click)=\"collapseProgress = !collapseProgress; false\" class=\"text-muted\">\n View progress\n <i class=\"fas fa-chevron-{{collapseProgress? 'right' : 'down'}}\"></i>\n </a>\n <sq-collapse [collapsed]=\"collapseProgress\">\n <ng-template>\n <ul class=\"list-unstyled\">\n <li *ngFor=\"let step of progress\">\n <i class=\"fas fa-fw fa-check text-success\" *ngIf=\"step.done\"></i>\n <i class=\"fas fa-spinner fa-pulse step-ongoing\" *ngIf=\"!step.done && streaming\"></i>\n <i class=\"fa-solid fa-ban step-error\" *ngIf=\"!step.done && !streaming\"></i>\n <span class=\"ms-2 fw-bold\">{{step.title}}</span>\n <span *ngIf=\"step.content\" [innerHTML]=\"': ' + step.content\"></span>\n </li>\n </ul>\n </ng-template>\n </sq-collapse>\n </div>\n\n <!-- Message content -->\n <div class=\"message-content\" *ngIf=\"message.content\">\n\n <div *ngIf=\"message?.role === 'assistant' && message.messageType === 'CHART'\">\n <sq-assistant-chart [rawChartData]=\"message.content\"></sq-assistant-chart>\n </div>\n\n <!-- This section is responsible for customizing the template nodes used in the application.\n Template nodes are predefined structures that serve as blueprints for creating/customizing dynamic content -->\n <remark *ngIf=\"(message?.role === 'assistant' && message.messageType === 'MARKDOWN') || message?.role === 'connection-error' || message?.role === 'search-warning'\" [markdown]=\"message.content\" [processor]=\"processor\">\n\n <ng-template remarkTemplate=\"chat-reference\" let-ref>\n\n <a *ngIf=\"referenceMap.get(ref.refId) as attachment; else staticRefTpl\"\n class=\"reference\"\n [sqTooltip]=\"attachment\"\n [sqTooltipTemplate]=\"tooltipTpl\"\n [hoverableTooltip]=\"true\"\n >{{ref.refId}}\n </a>\n\n <ng-template #staticRefTpl>\n <span class=\"reference\">{{ref.refId}}</span>\n </ng-template>\n\n </ng-template>\n\n <ng-template remarkTemplate=\"streaming-placeholder\">\n <span class=\"placeholder-glow\" *ngIf=\"streaming\">\n <span class=\"placeholder ms-1\"></span>\n </span>\n </ng-template>\n\n <ng-template remarkTemplate=\"code\" let-node>\n <div class=\"card mb-2\">\n <div class=\"card-header d-flex justify-content-between align-items-center\">\n <span>{{node.lang}}</span>\n <button class=\"btn btn-light btn-sm\" (click)=\"copyCode(node.value)\"><i class=\"far fa-fw fa-clipboard\"></i> Copy code</button>\n </div>\n <pre class=\"language-{{node.lang}} my-0 rounded-0 rounded-bottom\"><code class=\"language-{{node.lang}}\">{{node.value}}</code></pre>\n </div>\n </ng-template>\n\n <ng-template remarkTemplate=\"link\" let-node>\n <a [href]=\"node.url\" target=\"_blank\" rel=\"noopener noreferrer\">{{getLinkText(node)}}</a>\n </ng-template>\n\n </remark>\n\n <p *ngIf=\"message?.role === 'user'\">{{message.content}}</p>\n\n <!-- List of reference, if any -->\n <div *ngIf=\"references?.length\" class=\"references\">\n <span class=\"references-title\">References</span> <i class=\"fas references-collapse\" [class.fa-chevron-down]=\"showReferences\" [class.fa-chevron-right]=\"!showReferences\" (click)=\"showReferences=!showReferences\"></i>\n <sq-collapse [collapsed]=\"!showReferences\">\n <ng-template>\n <ul>\n <ng-container *ngFor=\"let reference of references\">\n <li *ngIf=\"referenceMap.get(reference) as attachment\" class=\"text-truncate\">\n <sq-chat-reference\n [class.expanded]=\"attachment.$expanded\"\n [attachment]=\"attachment\"\n [reference]=\"reference\"\n (openPreview)=\"openAttachmentPreview($event)\"\n (openDocument)=\"openOriginalAttachment($event)\">\n </sq-chat-reference>\n </li>\n </ng-container>\n </ul>\n </ng-template>\n </sq-collapse>\n </div>\n\n </div>\n\n <!-- Edit / Regenerate floating actions -->\n <div class=\"sq-chat-message-actions\" *ngIf=\"message\">\n <!-- Common action buttons for \"user\" & \"assistant\" message -->\n <button class=\"btn btn-sm\" *ngIf=\"canCopy\" sqTooltip=\"Copy text\" (click)=\"copyMessage(message)\">\n <i class=\"far fa-clipboard\"></i>\n </button>\n <!-- Action buttons for \"user\" message -->\n <button class=\"btn btn-sm\" *ngIf=\"canEdit\" sqTooltip=\"Edit message\" (click)=\"edit.emit(message)\">\n <i class=\"fas fa-edit\"></i>\n </button>\n <!-- Action buttons for \"assistant\" message -->\n <button class=\"btn btn-sm\" [class.bounce]=\"liked\" *ngIf=\"canLike\" sqTooltip=\"Like the answer\" (click)=\"like.emit(message); liked = true;\">\n <i class=\"far fa-thumbs-up\"></i>\n </button>\n <button class=\"btn btn-sm bounce\" [class.bounce]=\"disliked\" *ngIf=\"canDislike\" sqTooltip=\"Report an issue\" (click)=\"dislike.emit(message); disliked = true;\">\n <i class=\"far fa-thumbs-down\"></i>\n </button>\n <button class=\"btn btn-sm\" *ngIf=\"canRegenerate\" sqTooltip=\"Regenerate message\" (click)=\"regenerate.emit(message)\">\n <i class=\"fas fa-sync-alt\"></i>\n </button>\n <button class=\"btn btn-sm\" *ngIf=\"canDebug\" sqTooltip=\"Show Log Information\" (click)=\"debug.emit(message);\">\n <i class=\"far fa-list-alt\"></i>\n </button>\n </div>\n\n <!-- List of suggested actions, if any -->\n <div *ngIf=\"suggestedActions\" class=\"mt-2 message-suggestion\">\n <div class=\"suggested-action\" *ngFor=\"let suggestedAction of suggestedActions\" (click)=\"suggestAction.emit(suggestedAction)\">\n <div class=\"message-icon\" [style.width.px]=\"iconSize\"></div>\n <div class=\"message-content\">\n <p><i class=\"fas fa-clipboard-question\"></i> {{suggestedAction.content}}</p>\n </div>\n </div>\n </div>\n\n <ng-template #tooltipTpl let-ref>\n <sq-chat-reference\n *ngIf=\"!hiddenTooltip\"\n class=\"expanded\"\n [attachment]=\"ref\"\n [reference]=\"ref.contextId\"\n [partId]=\"ref.$partId\"\n (openPreview)=\"openAttachmentPreview($event, ref.$partId)\"\n (openDocument)=\"openOriginalAttachment($event, ref.$partId)\">\n </sq-chat-reference>\n </ng-template>\n\n</div>\n\n <!-- List of chat starters, if any -->\n <div *ngIf=\"chatStarters?.length\" class=\"mt-2 message-suggestion chat-starter\" [style.bottom.rem]=\"-(3.5*chatStarters!.length)\">\n <div class=\"suggested-action\" *ngFor=\"let chatStarter of chatStarters\" (click)=\"chatStarterClicked.emit(chatStarter)\">\n <div class=\"message-icon\" [style.width.px]=\"iconSize\"></div>\n <div class=\"message-content\">\n <p><i class=\"fas fa-clipboard-question\"></i> {{chatStarter.text}}</p>\n </div>\n </div>\n </div>\n", styles: [".ast-primary{color:var(--ast-primary-color, #005DA7);background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover{background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover:hover{color:var(--ast-primary-color, #005DA7)}.ast-secondary{color:var(--ast-secondary-color, #FF732E);background-color:var(--ast-secondary-bg, #FFF8F1)}.ast-error{background-color:var(--ast-error-bg, rgba(249, 58, 55, .2));color:var(--ast-action-buttons-color, inherit)}.ast-error:hover{color:var(--ast-error-color, rgba(249, 58, 55, .7))}.ast-btn{border:0;text-align:left;padding-top:.5rem;padding-bottom:.5rem;display:flex;align-items:center}.dark{--ast-primary-bg: #0d0701;--ast-primary-color: #008cd1;--ast-secondary-bg: #00070e;--ast-secondary-color: #ffa258;--ast-input-bg: #070707;--ast-input-color: rgba(222, 218, 218, .75);--ast-muted-color: rgba(222, 218, 218, .75);--ast-saved-chat-hover-background: #262421;--ast-message-table-border-color: #333333;--ast-message-table-tr-bg: #070707;--ast-message-table-tr-border-color: #222222;--ast-reference-icon-color: white;--ast-reference-icon-active-color: black;--ast-reference-passages-color: white;--ast-reference-expanded-hover-bg: #262421;--ast-message-reference-color: black;--ast-action-buttons-color: white;--ast-action-buttons-hover-color: #6dbee6}:host{display:flex}:host:not(:hover):not(.last-message) .sq-chat-message-actions{visibility:hidden}.message-content{padding:var(--ast-message-padding, var(--ast-size-3, .75rem));border-radius:var(--ast-message-border-radius, var(--ast-size-4, 1rem));display:inline-block;max-width:100%;overflow-wrap:break-word;word-wrap:break-word;word-break:break-word}.message-content .references{margin-top:var(--ast-size-5, 1.25rem)}.message-content .references ul{border-left:.2rem solid var(--ast-secondary-color, #FF732E);padding-left:var(--ast-size-5, 1.25rem);margin-top:var(--ast-size-2, .5rem)}.message-content .references .references-title{font-weight:var(--font-weight-bold, 500)}.message-content .references .references-collapse{cursor:pointer;margin-left:var(--ast-size-2, .5rem)}.message-content ::ng-deep p:last-child{margin-bottom:0}.message-content ::ng-deep .placeholder-glow .placeholder{animation-duration:.4s;width:12px;height:var(--ast-size-4, 1rem);vertical-align:text-bottom}.message-content ::ng-deep img{max-width:100%}.message-content ::ng-deep table{display:table;border:1px solid;border-color:var(--ast-message-table-border-color, #ccc);border-collapse:collapse;margin:0;padding:0;min-width:100%;overflow-x:auto;table-layout:fixed}.message-content ::ng-deep table tr{background-color:var(--ast-message-table-tr-bg, #f8f8f8);border:1px solid;border-color:var(--ast-message-table-tr-border-color, #ddd);padding:.35em}.message-content ::ng-deep table th,.message-content ::ng-deep table td{padding:.625em;text-align:center}.message-content ::ng-deep table th{font-size:.85em;letter-spacing:.1em;text-transform:uppercase}.message-content ::ng-deep .reference{color:var(--ast-message-reference-color, black)!important}.message-content ::ng-deep ul,.message-content ::ng-deep ol{display:flex;flex-direction:column;gap:.5rem;padding-right:2rem;margin-left:0;margin-right:0;padding-left:40px;unicode-bidi:-webkit-isolate;unicode-bidi:isolate;list-style:disc}.message-content ::ng-deep p:not(:first-child){margin-top:.5rem}.message-assistant .message-content{background:var(--ast-secondary-bg, #FFF8F1)}.message-connection-error .message-content{background:var(--ast-error-bg, rgba(249, 58, 55, .2))}.message-search-warning .message-content{background:var(--ast-warning-bg, #fff1b8);color:var(--ast-message-reference-color, inherit)}.message-user .message-content{background:var(--ast-primary-bg, #f2f8fe);font-weight:var(--ast-user-font-weight, var(--font-weight-bold, 500))}.message-user .message-content p{white-space:pre-line}.message-suggestion .message-content{background:var(--ast-input-bg, #F8F8F8);font-weight:var(--ast-user-font-weight, var(--font-weight-bold, 500));transition:background-color .5s ease,color .5s ease}.message-suggestion .message-content:hover{background:var(--ast-primary-bg, #f2f8fe);color:var(--ast-primary-color, #005DA7)}.message-suggestion .message-content p{white-space:pre-line}.message-suggestion .suggested-action{display:flex;cursor:pointer}.message-suggestion .suggested-action+.suggested-action{margin-top:var(--ast-size-2, .5rem)}.chat-starter{position:absolute}.sq-chat-message-actions{position:absolute;bottom:calc(0rem - var(--ast-size-3, .75rem));display:flex;z-index:999}.sq-chat-message-actions button{font-size:.75rem;color:var(--ast-action-buttons-color, #212529)}.sq-chat-message-actions button:hover{color:var(--ast-action-buttons-hover-color, var(--ast-primary-color, #005DA7))}.message-icon{margin-top:var(--ast-size-3, .75rem);margin-right:var(--ast-size-4, 1rem)}.connection-error{height:var(--sq-size);width:var(--sq-size);color:var(--ast-error-color, rgba(249, 58, 55, .7))}.search-warning{height:var(--sq-size);width:var(--sq-size);color:var(--ast-warning-color, #fed86f)}.step-success{color:var(--ast-primary-color, #005DA7)}.step-ongoing{color:var(--ast-secondary-color, #FF732E)}.step-error{color:var(--ast-error-color, rgba(249, 58, 55, .7))}.bounce{animation:bounce 2s ease}@keyframes bounce{10%{transform:translateY(0)}20%{transform:translateY(-15%)}30%{transform:translateY(0)}35%{transform:translateY(-7%)}37%{transform:translateY(0)}39%{transform:translateY(-3%)}40%{transform:translateY(0)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "ngmodule", type: UtilsModule }, { kind: "directive", type: i2$1.TooltipDirective, selector: "[sqTooltip]", inputs: ["sqTooltip", "sqTooltipData", "sqTooltipTemplate", "placement", "fallbackPlacements", "delay", "hoverableTooltip", "tooltipClass"] }, { kind: "ngmodule", type: CollapseModule }, { kind: "component", type: i5.Collapse, selector: "sq-collapse", inputs: ["collapsed"] }, { kind: "ngmodule", type: RemarkModule }, { kind: "component", type: i6.RemarkComponent, selector: "remark", inputs: ["markdown", "processor", "debug"] }, { kind: "directive", type: i6.RemarkTemplateDirective, selector: "[remarkTemplate]", inputs: ["remarkTemplate"] }, { kind: "component", type: InitialsAvatarComponent, selector: "sq-initials-avatar", inputs: ["fullName", "size"] }, { kind: "component", type: ChatReferenceComponent, selector: "sq-chat-reference", inputs: ["reference", "attachment", "partId"], outputs: ["openDocument", "openPreview"] }, { kind: "component", type: ChartComponent, selector: "sq-assistant-chart", inputs: ["rawChartData"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1561
1711
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ChatMessageComponent, decorators: [{
|
|
1562
1712
|
type: Component,
|
|
1563
1713
|
args: [{ selector: "sq-chat-message", changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [CommonModule, UtilsModule, CollapseModule, RemarkModule,
|
|
1564
|
-
InitialsAvatarComponent, ChatReferenceComponent, ChartComponent], template: "<!-- Message icon -->\n<span class=\"message-icon\" [title]=\"message?.role\">\n <i class=\"d-block\" [style.width.px]=\"iconSize\" *ngIf=\"!message\"></i>\n <ng-container [ngSwitch]=\"message?.role\">\n <!-- For 'assistant' -->\n <i *ngSwitchCase=\"'assistant'\" [ngClass]=\"assistantMessageIcon\" [style.--sq-size.px]=\"iconSize\"></i>\n <!-- For 'user' -->\n <ng-container *ngSwitchCase=\"'user'\">\n <i *ngIf=\"!!userMessageIcon; else initialsAvatar\" [ngClass]=\"userMessageIcon\" [style.--sq-size.px]=\"iconSize\"></i>\n <ng-template #initialsAvatar>\n <sq-initials-avatar [fullName]=\"name\"></sq-initials-avatar>\n </ng-template>\n </ng-container>\n <!-- For 'connection-error' -->\n <ng-container *ngSwitchCase=\"'connection-error'\">\n <i *ngIf=\"!!connectionErrorMessageIcon; else defaultErrorIcon\" [ngClass]=\"connectionErrorMessageIcon\" [style.--sq-size.px]=\"iconSize\"></i>\n <ng-template #defaultErrorIcon>\n <svg [style.--sq-size.px]=\"iconSize\" class=\"connection-error\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\">\n <path fill=\"currentColor\" d=\"M17.1 292c-12.9-22.3-12.9-49.7 0-72L105.4 67.1c12.9-22.3 36.6-36 62.4-36l176.6 0c25.7 0 49.5 13.7 62.4 36L494.9 220c12.9 22.3 12.9 49.7 0 72L406.6 444.9c-12.9 22.3-36.6 36-62.4 36l-176.6 0c-25.7 0-49.5-13.7-62.4-36L17.1 292zM256 128c-13.3 0-24 10.7-24 24l0 112c0 13.3 10.7 24 24 24s24-10.7 24-24l0-112c0-13.3-10.7-24-24-24zm32 224a32 32 0 1 0 -64 0 32 32 0 1 0 64 0z\"/>\n </svg>\n </ng-template>\n </ng-container>\n <!-- For 'search-warning' -->\n <ng-container *ngSwitchCase=\"'search-warning'\">\n <i *ngIf=\"!!searchWarningMessageIcon; else defaultWarningIcon\" [ngClass]=\"searchWarningMessageIcon\" [style.--sq-size.px]=\"iconSize\"></i>\n <ng-template #defaultWarningIcon>\n <svg [style.--sq-size.px]=\"iconSize\" class=\"search-warning\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 384 512\">\n <path fill=\"currentColor\" d=\"M272 384c9.6-31.9 29.5-59.1 49.2-86.2c0 0 0 0 0 0c5.2-7.1 10.4-14.2 15.4-21.4c19.8-28.5 31.4-63 31.4-100.3C368 78.8 289.2 0 192 0S16 78.8 16 176c0 37.3 11.6 71.9 31.4 100.3c5 7.2 10.2 14.3 15.4 21.4c0 0 0 0 0 0c19.8 27.1 39.7 54.4 49.2 86.2l160 0zM192 512c44.2 0 80-35.8 80-80l0-16-160 0 0 16c0 44.2 35.8 80 80 80zm0-448c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zM160 288a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z\"/>\n </svg>\n </ng-template>\n </ng-container>\n </ng-container>\n\n</span>\n\n<!-- Message body -->\n<div class=\"flex-grow-1\" style=\"min-width: 0;\" [ngClass]=\"'message-'+message.role\">\n\n <div *ngIf=\"message.additionalProperties.$progress as progress\" class=\"small ms-3 mb-2\">\n <a href=\"#\" (click)=\"collapseProgress = !collapseProgress; false\" class=\"text-muted\">\n View progress\n <i class=\"fas fa-chevron-{{collapseProgress? 'right' : 'down'}}\"></i>\n </a>\n <sq-collapse [collapsed]=\"collapseProgress\">\n <ng-template>\n <ul class=\"list-unstyled\">\n <li *ngFor=\"let step of progress\">\n <i class=\"fas fa-fw fa-check text-success\" *ngIf=\"step.done\"></i>\n <i class=\"fas fa-fw fa-spin fa-circle-notch\" *ngIf=\"!step.done\"></i>\n <span class=\"ms-2 fw-bold\">{{step.title}}</span>\n <span *ngIf=\"step.content\">: {{step.content}}</span>\n </li>\n </ul>\n </ng-template>\n </sq-collapse>\n </div>\n\n <div class=\"message-content\" *ngIf=\"message.content\">\n\n <div *ngIf=\"message?.role === 'assistant' && message.messageType === 'CHART'\">\n <sq-assistant-chart [rawChartData]=\"message.content\"></sq-assistant-chart>\n </div>\n\n <remark *ngIf=\"(message?.role === 'assistant' && message.messageType === 'MARKDOWN') || message?.role === 'connection-error' || message?.role === 'search-warning'\" [markdown]=\"message.content\" [processor]=\"processor\">\n\n <ng-template remarkTemplate=\"chat-reference\" let-ref>\n\n <a *ngIf=\"referenceMap.get(ref.refId) as attachment; else staticRefTpl\"\n class=\"reference\"\n [sqTooltip]=\"attachment\"\n [sqTooltipTemplate]=\"tooltipTpl\"\n [hoverableTooltip]=\"true\"\n >{{ref.refId}}\n </a>\n\n <ng-template #staticRefTpl>\n <span class=\"reference\">{{ref.refId}}</span>\n </ng-template>\n\n </ng-template>\n\n <ng-template remarkTemplate=\"streaming-placeholder\">\n <span class=\"placeholder-glow\" *ngIf=\"streaming\">\n <span class=\"placeholder ms-1\"></span>\n </span>\n </ng-template>\n\n <ng-template remarkTemplate=\"code\" let-node>\n <div class=\"card mb-2\">\n <div class=\"card-header d-flex justify-content-between align-items-center\">\n <span>{{node.lang}}</span>\n <button class=\"btn btn-light btn-sm\" (click)=\"copyCode(node.value)\"><i class=\"far fa-fw fa-clipboard\"></i> Copy code</button>\n </div>\n <pre class=\"language-{{node.lang}} my-0 rounded-0 rounded-bottom\"><code class=\"language-{{node.lang}}\">{{node.value}}</code></pre>\n </div>\n </ng-template>\n\n <ng-template remarkTemplate=\"link\" let-node>\n <a [href]=\"node.url\" target=\"_blank\" rel=\"noopener noreferrer\">{{getLinkText(node)}}</a>\n </ng-template>\n\n </remark>\n\n <p *ngIf=\"message?.role === 'user'\">{{message.content}}</p>\n\n <!-- List of reference, if any -->\n <div *ngIf=\"references?.length\" class=\"references\">\n <span class=\"references-title\">References</span> <i class=\"fas references-collapse\" [class.fa-chevron-down]=\"showReferences\" [class.fa-chevron-right]=\"!showReferences\" (click)=\"showReferences=!showReferences\"></i>\n <sq-collapse [collapsed]=\"!showReferences\">\n <ng-template>\n <ul>\n <ng-container *ngFor=\"let reference of references\">\n <li *ngIf=\"referenceMap.get(reference) as attachment\" class=\"text-truncate\">\n <sq-chat-reference\n [class.expanded]=\"attachment.$expanded\"\n [attachment]=\"attachment\"\n [reference]=\"reference\"\n (openPreview)=\"openAttachmentPreview($event)\"\n (openDocument)=\"openOriginalAttachment($event)\">\n </sq-chat-reference>\n </li>\n </ng-container>\n </ul>\n </ng-template>\n </sq-collapse>\n </div>\n\n </div>\n\n <!-- Edit / Regenerate floating actions -->\n <div class=\"sq-chat-message-actions\" *ngIf=\"message\">\n <button class=\"btn btn-sm\" *ngIf=\"canEdit\" sqTooltip=\"Edit message\" (click)=\"edit.emit(message)\">\n <i class=\"fas fa-edit\"></i>\n </button>\n <button class=\"btn btn-sm\" *ngIf=\"canCopy\" sqTooltip=\"Copy text\" (click)=\"copyMessage(message)\">\n <i class=\"far fa-clipboard\"></i>\n </button>\n <button class=\"btn btn-sm\" *ngIf=\"canRegenerate\" sqTooltip=\"Regenerate message\" (click)=\"regenerate.emit(message)\">\n <i class=\"fas fa-sync-alt\"></i>\n </button>\n <button class=\"btn btn-sm\" [class.bounce]=\"liked\" *ngIf=\"canLike\" sqTooltip=\"Like the answer\" (click)=\"like.emit(message); liked = true;\">\n <i class=\"far fa-thumbs-up\"></i>\n </button>\n <button class=\"btn btn-sm bounce\" [class.bounce]=\"disliked\" *ngIf=\"canDislike\" sqTooltip=\"Report an issue\" (click)=\"dislike.emit(message); disliked = true;\">\n <i class=\"far fa-thumbs-down\"></i>\n </button>\n <button class=\"btn btn-sm\" *ngIf=\"canDebug && !!message.additionalProperties.$debug && message.additionalProperties.$debug?.length > 0\" sqTooltip=\"Show Log Information\" (click)=\"debug.emit(message);\">\n <i class=\"far fa-list-alt\"></i>\n </button>\n </div>\n\n <!-- List of suggested actions, if any -->\n <div *ngIf=\"suggestedActions\" class=\"mt-2 message-suggestion\">\n <div class=\"suggested-action\" *ngFor=\"let suggestedAction of suggestedActions\" (click)=\"suggestAction.emit(suggestedAction)\">\n <div class=\"message-content\">\n <p><i class=\"fas fa-clipboard-question\"></i> {{suggestedAction.content}}</p>\n </div>\n </div>\n </div>\n\n <ng-template #tooltipTpl let-ref>\n <sq-chat-reference\n *ngIf=\"!hiddenTooltip\"\n class=\"expanded\"\n [attachment]=\"ref\"\n [reference]=\"ref.contextId\"\n [partId]=\"ref.$partId\"\n (openPreview)=\"openAttachmentPreview($event, ref.$partId)\"\n (openDocument)=\"openOriginalAttachment($event, ref.$partId)\">\n </sq-chat-reference>\n </ng-template>\n\n</div>\n", styles: [".ast-primary{color:var(--ast-primary-color, #005DA7);background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover{background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover:hover{color:var(--ast-primary-color, #005DA7)}.ast-secondary{color:var(--ast-secondary-color, #FF732E);background-color:var(--ast-secondary-bg, #FFF8F1)}.ast-error{background-color:var(--ast-error-bg, rgba(249, 58, 55, .2))}.ast-error:hover{color:var(--ast-error-color, rgba(249, 58, 55, .7))}.ast-btn{border:0;text-align:left;padding-top:.5rem;padding-bottom:.5rem;display:flex;align-items:center}.dark{--ast-primary-bg: #0d0701;--ast-primary-color: #008cd1;--ast-secondary-bg: #00070e;--ast-secondary-color: #ffa258;--ast-input-bg: #070707;--ast-input-color: rgba(222, 218, 218, .75);--ast-muted-color: rgba(222, 218, 218, .75);--ast-saved-chat-hover-background: #262421;--ast-message-table-border-color: #333333;--ast-message-table-tr-bg: #070707;--ast-message-table-tr-border-color: #222222;--ast-reference-icon-color: white;--ast-reference-icon-active-color: black;--ast-reference-passages-color: white;--ast-reference-expanded-hover-bg: #262421;--ast-message-reference-color: black}:host{display:flex}:host:not(:hover):not(.last-message) .sq-chat-message-actions{visibility:hidden}.message-content{padding:var(--ast-message-padding, var(--ast-size-3, .75rem));border-radius:var(--ast-message-border-radius, var(--ast-size-4, 1rem));display:inline-block;max-width:100%;overflow-wrap:break-word;word-wrap:break-word;word-break:break-word}.message-content .references{margin-top:var(--ast-size-5, 1.25rem)}.message-content .references ul{border-left:.2rem solid var(--ast-secondary-color, #FF732E);padding-left:var(--ast-size-5, 1.25rem);margin-top:var(--ast-size-2, .5rem)}.message-content .references .references-title{font-weight:var(--font-weight-bold, 500)}.message-content .references .references-collapse{cursor:pointer;margin-left:var(--ast-size-2, .5rem)}.message-content ::ng-deep p:last-child{margin-bottom:0}.message-content ::ng-deep .placeholder-glow .placeholder{animation-duration:.4s;width:12px;height:var(--ast-size-4, 1rem);vertical-align:text-bottom}.message-content ::ng-deep img{max-width:100%}.message-content ::ng-deep table{display:table;border:1px solid;border-color:var(--ast-message-table-border-color, #ccc);border-collapse:collapse;margin:0;padding:0;min-width:100%;overflow-x:auto;table-layout:fixed}.message-content ::ng-deep table tr{background-color:var(--ast-message-table-tr-bg, #f8f8f8);border:1px solid;border-color:var(--ast-message-table-tr-border-color, #ddd);padding:.35em}.message-content ::ng-deep table th,.message-content ::ng-deep table td{padding:.625em;text-align:center}.message-content ::ng-deep table th{font-size:.85em;letter-spacing:.1em;text-transform:uppercase}.message-content ::ng-deep .reference{color:var(--ast-message-reference-color, black)!important}.message-content ::ng-deep ul,.message-content ::ng-deep ol{display:flex;flex-direction:column;gap:.5rem;padding-right:2rem;margin-left:0;margin-right:0;padding-left:40px;unicode-bidi:-webkit-isolate;unicode-bidi:isolate;list-style:disc}.message-content ::ng-deep p:not(:first-child){margin-top:.5rem}.message-assistant .message-content{background:var(--ast-secondary-bg, #FFF8F1)}.message-connection-error .message-content{background:var(--ast-error-bg, rgba(249, 58, 55, .2))}.message-search-warning .message-content{background:var(--ast-warning-bg, #fff1b8)}.message-user .message-content{background:var(--ast-primary-bg, #f2f8fe);font-weight:var(--ast-user-font-weight, var(--font-weight-bold, 500))}.message-user .message-content p{white-space:pre-line}.message-suggestion .message-content{background:var(--ast-input-bg, #F8F8F8);font-weight:var(--ast-user-font-weight, var(--font-weight-bold, 500));transition:background-color .5s ease,color .5s ease}.message-suggestion .message-content:hover{background:var(--ast-primary-bg, #f2f8fe);color:var(--ast-primary-color, #005DA7)}.message-suggestion .message-content p{white-space:pre-line}.message-suggestion .suggested-action{cursor:pointer}.message-suggestion .suggested-action+.suggested-action{margin-top:var(--ast-size-2, .5rem)}.sq-chat-message-actions{position:absolute;bottom:calc(0rem - var(--ast-size-3, .75rem));display:flex;z-index:999}.sq-chat-message-actions button{font-size:.75rem}.sq-chat-message-actions button:hover{color:var(--ast-primary-color, #005DA7)}.message-icon{margin-top:var(--ast-size-3, .75rem);margin-right:var(--ast-size-4, 1rem)}.connection-error{height:var(--sq-size);width:var(--sq-size);color:var(--ast-error-color, rgba(249, 58, 55, .7))}.search-warning{height:var(--sq-size);width:var(--sq-size);color:var(--ast-warning-color, #fed86f)}.bounce{animation:bounce 2s ease}@keyframes bounce{10%{transform:translateY(0)}20%{transform:translateY(-15%)}30%{transform:translateY(0)}35%{transform:translateY(-7%)}37%{transform:translateY(0)}39%{transform:translateY(-3%)}40%{transform:translateY(0)}}\n"] }]
|
|
1714
|
+
InitialsAvatarComponent, ChatReferenceComponent, ChartComponent], template: "<!-- Message icon -->\n<span class=\"message-icon\" [title]=\"message?.role\">\n <i class=\"d-block\" [style.width.px]=\"iconSize\" *ngIf=\"!message\"></i>\n <ng-container [ngSwitch]=\"message?.role\">\n <!-- For 'assistant' -->\n <i *ngSwitchCase=\"'assistant'\" [ngClass]=\"assistantMessageIcon\" [style.--sq-size.px]=\"iconSize\"></i>\n <!-- For 'user' -->\n <ng-container *ngSwitchCase=\"'user'\">\n <i *ngIf=\"!!userMessageIcon; else initialsAvatar\" [ngClass]=\"userMessageIcon\" [style.--sq-size.px]=\"iconSize\"></i>\n <ng-template #initialsAvatar>\n <sq-initials-avatar [fullName]=\"name\"></sq-initials-avatar>\n </ng-template>\n </ng-container>\n <!-- For 'connection-error' -->\n <ng-container *ngSwitchCase=\"'connection-error'\">\n <i *ngIf=\"!!connectionErrorMessageIcon; else defaultErrorIcon\" [ngClass]=\"connectionErrorMessageIcon\" [style.--sq-size.px]=\"iconSize\"></i>\n <ng-template #defaultErrorIcon>\n <svg [style.--sq-size.px]=\"iconSize\" class=\"connection-error\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\">\n <path fill=\"currentColor\" d=\"M17.1 292c-12.9-22.3-12.9-49.7 0-72L105.4 67.1c12.9-22.3 36.6-36 62.4-36l176.6 0c25.7 0 49.5 13.7 62.4 36L494.9 220c12.9 22.3 12.9 49.7 0 72L406.6 444.9c-12.9 22.3-36.6 36-62.4 36l-176.6 0c-25.7 0-49.5-13.7-62.4-36L17.1 292zM256 128c-13.3 0-24 10.7-24 24l0 112c0 13.3 10.7 24 24 24s24-10.7 24-24l0-112c0-13.3-10.7-24-24-24zm32 224a32 32 0 1 0 -64 0 32 32 0 1 0 64 0z\"/>\n </svg>\n </ng-template>\n </ng-container>\n <!-- For 'search-warning' -->\n <ng-container *ngSwitchCase=\"'search-warning'\">\n <i *ngIf=\"!!searchWarningMessageIcon; else defaultWarningIcon\" [ngClass]=\"searchWarningMessageIcon\" [style.--sq-size.px]=\"iconSize\"></i>\n <ng-template #defaultWarningIcon>\n <svg [style.--sq-size.px]=\"iconSize\" class=\"search-warning\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 384 512\">\n <path fill=\"currentColor\" d=\"M272 384c9.6-31.9 29.5-59.1 49.2-86.2c0 0 0 0 0 0c5.2-7.1 10.4-14.2 15.4-21.4c19.8-28.5 31.4-63 31.4-100.3C368 78.8 289.2 0 192 0S16 78.8 16 176c0 37.3 11.6 71.9 31.4 100.3c5 7.2 10.2 14.3 15.4 21.4c0 0 0 0 0 0c19.8 27.1 39.7 54.4 49.2 86.2l160 0zM192 512c44.2 0 80-35.8 80-80l0-16-160 0 0 16c0 44.2 35.8 80 80 80zm0-448c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zM160 288a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z\"/>\n </svg>\n </ng-template>\n </ng-container>\n </ng-container>\n\n</span>\n\n<!-- Message body -->\n<div class=\"flex-grow-1\" style=\"min-width: 0;\" [ngClass]=\"'message-'+message.role\">\n\n <!-- Progress steps -->\n <div *ngIf=\"message.additionalProperties.$progress as progress\" class=\"small ms-3 mb-2\">\n <a href=\"#\" (click)=\"collapseProgress = !collapseProgress; false\" class=\"text-muted\">\n View progress\n <i class=\"fas fa-chevron-{{collapseProgress? 'right' : 'down'}}\"></i>\n </a>\n <sq-collapse [collapsed]=\"collapseProgress\">\n <ng-template>\n <ul class=\"list-unstyled\">\n <li *ngFor=\"let step of progress\">\n <i class=\"fas fa-fw fa-check text-success\" *ngIf=\"step.done\"></i>\n <i class=\"fas fa-spinner fa-pulse step-ongoing\" *ngIf=\"!step.done && streaming\"></i>\n <i class=\"fa-solid fa-ban step-error\" *ngIf=\"!step.done && !streaming\"></i>\n <span class=\"ms-2 fw-bold\">{{step.title}}</span>\n <span *ngIf=\"step.content\" [innerHTML]=\"': ' + step.content\"></span>\n </li>\n </ul>\n </ng-template>\n </sq-collapse>\n </div>\n\n <!-- Message content -->\n <div class=\"message-content\" *ngIf=\"message.content\">\n\n <div *ngIf=\"message?.role === 'assistant' && message.messageType === 'CHART'\">\n <sq-assistant-chart [rawChartData]=\"message.content\"></sq-assistant-chart>\n </div>\n\n <!-- This section is responsible for customizing the template nodes used in the application.\n Template nodes are predefined structures that serve as blueprints for creating/customizing dynamic content -->\n <remark *ngIf=\"(message?.role === 'assistant' && message.messageType === 'MARKDOWN') || message?.role === 'connection-error' || message?.role === 'search-warning'\" [markdown]=\"message.content\" [processor]=\"processor\">\n\n <ng-template remarkTemplate=\"chat-reference\" let-ref>\n\n <a *ngIf=\"referenceMap.get(ref.refId) as attachment; else staticRefTpl\"\n class=\"reference\"\n [sqTooltip]=\"attachment\"\n [sqTooltipTemplate]=\"tooltipTpl\"\n [hoverableTooltip]=\"true\"\n >{{ref.refId}}\n </a>\n\n <ng-template #staticRefTpl>\n <span class=\"reference\">{{ref.refId}}</span>\n </ng-template>\n\n </ng-template>\n\n <ng-template remarkTemplate=\"streaming-placeholder\">\n <span class=\"placeholder-glow\" *ngIf=\"streaming\">\n <span class=\"placeholder ms-1\"></span>\n </span>\n </ng-template>\n\n <ng-template remarkTemplate=\"code\" let-node>\n <div class=\"card mb-2\">\n <div class=\"card-header d-flex justify-content-between align-items-center\">\n <span>{{node.lang}}</span>\n <button class=\"btn btn-light btn-sm\" (click)=\"copyCode(node.value)\"><i class=\"far fa-fw fa-clipboard\"></i> Copy code</button>\n </div>\n <pre class=\"language-{{node.lang}} my-0 rounded-0 rounded-bottom\"><code class=\"language-{{node.lang}}\">{{node.value}}</code></pre>\n </div>\n </ng-template>\n\n <ng-template remarkTemplate=\"link\" let-node>\n <a [href]=\"node.url\" target=\"_blank\" rel=\"noopener noreferrer\">{{getLinkText(node)}}</a>\n </ng-template>\n\n </remark>\n\n <p *ngIf=\"message?.role === 'user'\">{{message.content}}</p>\n\n <!-- List of reference, if any -->\n <div *ngIf=\"references?.length\" class=\"references\">\n <span class=\"references-title\">References</span> <i class=\"fas references-collapse\" [class.fa-chevron-down]=\"showReferences\" [class.fa-chevron-right]=\"!showReferences\" (click)=\"showReferences=!showReferences\"></i>\n <sq-collapse [collapsed]=\"!showReferences\">\n <ng-template>\n <ul>\n <ng-container *ngFor=\"let reference of references\">\n <li *ngIf=\"referenceMap.get(reference) as attachment\" class=\"text-truncate\">\n <sq-chat-reference\n [class.expanded]=\"attachment.$expanded\"\n [attachment]=\"attachment\"\n [reference]=\"reference\"\n (openPreview)=\"openAttachmentPreview($event)\"\n (openDocument)=\"openOriginalAttachment($event)\">\n </sq-chat-reference>\n </li>\n </ng-container>\n </ul>\n </ng-template>\n </sq-collapse>\n </div>\n\n </div>\n\n <!-- Edit / Regenerate floating actions -->\n <div class=\"sq-chat-message-actions\" *ngIf=\"message\">\n <!-- Common action buttons for \"user\" & \"assistant\" message -->\n <button class=\"btn btn-sm\" *ngIf=\"canCopy\" sqTooltip=\"Copy text\" (click)=\"copyMessage(message)\">\n <i class=\"far fa-clipboard\"></i>\n </button>\n <!-- Action buttons for \"user\" message -->\n <button class=\"btn btn-sm\" *ngIf=\"canEdit\" sqTooltip=\"Edit message\" (click)=\"edit.emit(message)\">\n <i class=\"fas fa-edit\"></i>\n </button>\n <!-- Action buttons for \"assistant\" message -->\n <button class=\"btn btn-sm\" [class.bounce]=\"liked\" *ngIf=\"canLike\" sqTooltip=\"Like the answer\" (click)=\"like.emit(message); liked = true;\">\n <i class=\"far fa-thumbs-up\"></i>\n </button>\n <button class=\"btn btn-sm bounce\" [class.bounce]=\"disliked\" *ngIf=\"canDislike\" sqTooltip=\"Report an issue\" (click)=\"dislike.emit(message); disliked = true;\">\n <i class=\"far fa-thumbs-down\"></i>\n </button>\n <button class=\"btn btn-sm\" *ngIf=\"canRegenerate\" sqTooltip=\"Regenerate message\" (click)=\"regenerate.emit(message)\">\n <i class=\"fas fa-sync-alt\"></i>\n </button>\n <button class=\"btn btn-sm\" *ngIf=\"canDebug\" sqTooltip=\"Show Log Information\" (click)=\"debug.emit(message);\">\n <i class=\"far fa-list-alt\"></i>\n </button>\n </div>\n\n <!-- List of suggested actions, if any -->\n <div *ngIf=\"suggestedActions\" class=\"mt-2 message-suggestion\">\n <div class=\"suggested-action\" *ngFor=\"let suggestedAction of suggestedActions\" (click)=\"suggestAction.emit(suggestedAction)\">\n <div class=\"message-icon\" [style.width.px]=\"iconSize\"></div>\n <div class=\"message-content\">\n <p><i class=\"fas fa-clipboard-question\"></i> {{suggestedAction.content}}</p>\n </div>\n </div>\n </div>\n\n <ng-template #tooltipTpl let-ref>\n <sq-chat-reference\n *ngIf=\"!hiddenTooltip\"\n class=\"expanded\"\n [attachment]=\"ref\"\n [reference]=\"ref.contextId\"\n [partId]=\"ref.$partId\"\n (openPreview)=\"openAttachmentPreview($event, ref.$partId)\"\n (openDocument)=\"openOriginalAttachment($event, ref.$partId)\">\n </sq-chat-reference>\n </ng-template>\n\n</div>\n\n <!-- List of chat starters, if any -->\n <div *ngIf=\"chatStarters?.length\" class=\"mt-2 message-suggestion chat-starter\" [style.bottom.rem]=\"-(3.5*chatStarters!.length)\">\n <div class=\"suggested-action\" *ngFor=\"let chatStarter of chatStarters\" (click)=\"chatStarterClicked.emit(chatStarter)\">\n <div class=\"message-icon\" [style.width.px]=\"iconSize\"></div>\n <div class=\"message-content\">\n <p><i class=\"fas fa-clipboard-question\"></i> {{chatStarter.text}}</p>\n </div>\n </div>\n </div>\n", styles: [".ast-primary{color:var(--ast-primary-color, #005DA7);background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover{background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover:hover{color:var(--ast-primary-color, #005DA7)}.ast-secondary{color:var(--ast-secondary-color, #FF732E);background-color:var(--ast-secondary-bg, #FFF8F1)}.ast-error{background-color:var(--ast-error-bg, rgba(249, 58, 55, .2));color:var(--ast-action-buttons-color, inherit)}.ast-error:hover{color:var(--ast-error-color, rgba(249, 58, 55, .7))}.ast-btn{border:0;text-align:left;padding-top:.5rem;padding-bottom:.5rem;display:flex;align-items:center}.dark{--ast-primary-bg: #0d0701;--ast-primary-color: #008cd1;--ast-secondary-bg: #00070e;--ast-secondary-color: #ffa258;--ast-input-bg: #070707;--ast-input-color: rgba(222, 218, 218, .75);--ast-muted-color: rgba(222, 218, 218, .75);--ast-saved-chat-hover-background: #262421;--ast-message-table-border-color: #333333;--ast-message-table-tr-bg: #070707;--ast-message-table-tr-border-color: #222222;--ast-reference-icon-color: white;--ast-reference-icon-active-color: black;--ast-reference-passages-color: white;--ast-reference-expanded-hover-bg: #262421;--ast-message-reference-color: black;--ast-action-buttons-color: white;--ast-action-buttons-hover-color: #6dbee6}:host{display:flex}:host:not(:hover):not(.last-message) .sq-chat-message-actions{visibility:hidden}.message-content{padding:var(--ast-message-padding, var(--ast-size-3, .75rem));border-radius:var(--ast-message-border-radius, var(--ast-size-4, 1rem));display:inline-block;max-width:100%;overflow-wrap:break-word;word-wrap:break-word;word-break:break-word}.message-content .references{margin-top:var(--ast-size-5, 1.25rem)}.message-content .references ul{border-left:.2rem solid var(--ast-secondary-color, #FF732E);padding-left:var(--ast-size-5, 1.25rem);margin-top:var(--ast-size-2, .5rem)}.message-content .references .references-title{font-weight:var(--font-weight-bold, 500)}.message-content .references .references-collapse{cursor:pointer;margin-left:var(--ast-size-2, .5rem)}.message-content ::ng-deep p:last-child{margin-bottom:0}.message-content ::ng-deep .placeholder-glow .placeholder{animation-duration:.4s;width:12px;height:var(--ast-size-4, 1rem);vertical-align:text-bottom}.message-content ::ng-deep img{max-width:100%}.message-content ::ng-deep table{display:table;border:1px solid;border-color:var(--ast-message-table-border-color, #ccc);border-collapse:collapse;margin:0;padding:0;min-width:100%;overflow-x:auto;table-layout:fixed}.message-content ::ng-deep table tr{background-color:var(--ast-message-table-tr-bg, #f8f8f8);border:1px solid;border-color:var(--ast-message-table-tr-border-color, #ddd);padding:.35em}.message-content ::ng-deep table th,.message-content ::ng-deep table td{padding:.625em;text-align:center}.message-content ::ng-deep table th{font-size:.85em;letter-spacing:.1em;text-transform:uppercase}.message-content ::ng-deep .reference{color:var(--ast-message-reference-color, black)!important}.message-content ::ng-deep ul,.message-content ::ng-deep ol{display:flex;flex-direction:column;gap:.5rem;padding-right:2rem;margin-left:0;margin-right:0;padding-left:40px;unicode-bidi:-webkit-isolate;unicode-bidi:isolate;list-style:disc}.message-content ::ng-deep p:not(:first-child){margin-top:.5rem}.message-assistant .message-content{background:var(--ast-secondary-bg, #FFF8F1)}.message-connection-error .message-content{background:var(--ast-error-bg, rgba(249, 58, 55, .2))}.message-search-warning .message-content{background:var(--ast-warning-bg, #fff1b8);color:var(--ast-message-reference-color, inherit)}.message-user .message-content{background:var(--ast-primary-bg, #f2f8fe);font-weight:var(--ast-user-font-weight, var(--font-weight-bold, 500))}.message-user .message-content p{white-space:pre-line}.message-suggestion .message-content{background:var(--ast-input-bg, #F8F8F8);font-weight:var(--ast-user-font-weight, var(--font-weight-bold, 500));transition:background-color .5s ease,color .5s ease}.message-suggestion .message-content:hover{background:var(--ast-primary-bg, #f2f8fe);color:var(--ast-primary-color, #005DA7)}.message-suggestion .message-content p{white-space:pre-line}.message-suggestion .suggested-action{display:flex;cursor:pointer}.message-suggestion .suggested-action+.suggested-action{margin-top:var(--ast-size-2, .5rem)}.chat-starter{position:absolute}.sq-chat-message-actions{position:absolute;bottom:calc(0rem - var(--ast-size-3, .75rem));display:flex;z-index:999}.sq-chat-message-actions button{font-size:.75rem;color:var(--ast-action-buttons-color, #212529)}.sq-chat-message-actions button:hover{color:var(--ast-action-buttons-hover-color, var(--ast-primary-color, #005DA7))}.message-icon{margin-top:var(--ast-size-3, .75rem);margin-right:var(--ast-size-4, 1rem)}.connection-error{height:var(--sq-size);width:var(--sq-size);color:var(--ast-error-color, rgba(249, 58, 55, .7))}.search-warning{height:var(--sq-size);width:var(--sq-size);color:var(--ast-warning-color, #fed86f)}.step-success{color:var(--ast-primary-color, #005DA7)}.step-ongoing{color:var(--ast-secondary-color, #FF732E)}.step-error{color:var(--ast-error-color, rgba(249, 58, 55, .7))}.bounce{animation:bounce 2s ease}@keyframes bounce{10%{transform:translateY(0)}20%{transform:translateY(-15%)}30%{transform:translateY(0)}35%{transform:translateY(-7%)}37%{transform:translateY(0)}39%{transform:translateY(-3%)}40%{transform:translateY(0)}}\n"] }]
|
|
1565
1715
|
}], ctorParameters: function () { return [{ type: i1$1.SearchService }, { type: i2$1.UIService }, { type: i3.PrincipalWebService }, { type: i0.ChangeDetectorRef }, { type: i0.ElementRef }]; }, propDecorators: { message: [{
|
|
1566
1716
|
type: Input
|
|
1567
1717
|
}], conversation: [{
|
|
1568
1718
|
type: Input
|
|
1569
1719
|
}], suggestedActions: [{
|
|
1570
1720
|
type: Input
|
|
1721
|
+
}], chatStarters: [{
|
|
1722
|
+
type: Input
|
|
1571
1723
|
}], assistantMessageIcon: [{
|
|
1572
1724
|
type: Input
|
|
1573
1725
|
}], userMessageIcon: [{
|
|
@@ -1596,6 +1748,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImpor
|
|
|
1596
1748
|
type: Output
|
|
1597
1749
|
}], suggestAction: [{
|
|
1598
1750
|
type: Output
|
|
1751
|
+
}], chatStarterClicked: [{
|
|
1752
|
+
type: Output
|
|
1599
1753
|
}], edit: [{
|
|
1600
1754
|
type: Output
|
|
1601
1755
|
}], copy: [{
|
|
@@ -1696,7 +1850,7 @@ class RestChatService extends ChatService {
|
|
|
1696
1850
|
}
|
|
1697
1851
|
// Request the Chat endpoint
|
|
1698
1852
|
return this.jsonMethodWebService.post(this.REQUEST_URL, data).pipe(tap((res) => this.updateQuota(res.quota, true)), map((res) => {
|
|
1699
|
-
var _a, _b;
|
|
1853
|
+
var _a, _b, _c, _d;
|
|
1700
1854
|
// Define $progress from the actions property of the response
|
|
1701
1855
|
let $progress;
|
|
1702
1856
|
if (((_a = res.actions) === null || _a === void 0 ? void 0 : _a.length) > 0) {
|
|
@@ -1740,9 +1894,9 @@ class RestChatService extends ChatService {
|
|
|
1740
1894
|
'text': response.content,
|
|
1741
1895
|
'role': response.role,
|
|
1742
1896
|
'rank': this.chatHistory.length - 1,
|
|
1743
|
-
'generation-tokencount': response.additionalProperties.usageMetrics.completionTokenCount,
|
|
1744
|
-
'prompt-tokencount': response.additionalProperties.usageMetrics.promptTokenCount,
|
|
1745
|
-
'attachments': (
|
|
1897
|
+
'generation-tokencount': (_b = response.additionalProperties.usageMetrics) === null || _b === void 0 ? void 0 : _b.completionTokenCount,
|
|
1898
|
+
'prompt-tokencount': (_c = response.additionalProperties.usageMetrics) === null || _c === void 0 ? void 0 : _c.promptTokenCount,
|
|
1899
|
+
'attachments': (_d = response.additionalProperties.$attachment) === null || _d === void 0 ? void 0 : _d.map(({ recordId, contextId, parts, type }) => ({
|
|
1746
1900
|
recordId,
|
|
1747
1901
|
contextId,
|
|
1748
1902
|
parts: parts.map(({ partId, text }) => ({ partId, text })),
|
|
@@ -1754,6 +1908,11 @@ class RestChatService extends ChatService {
|
|
|
1754
1908
|
return { history: [...messages, response], executionTime: res.executionTime };
|
|
1755
1909
|
}), finalize(() => this.streaming$.next(false)));
|
|
1756
1910
|
}
|
|
1911
|
+
stopGeneration() {
|
|
1912
|
+
const error = new Error('Not supported in REST');
|
|
1913
|
+
console.error(error);
|
|
1914
|
+
return throwError(() => error);
|
|
1915
|
+
}
|
|
1757
1916
|
listSavedChat() {
|
|
1758
1917
|
if (!this.chatConfig$.value.savedChatSettings.enabled) {
|
|
1759
1918
|
return;
|
|
@@ -1872,10 +2031,10 @@ class TokenProgressBarComponent {
|
|
|
1872
2031
|
}
|
|
1873
2032
|
}
|
|
1874
2033
|
TokenProgressBarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: TokenProgressBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1875
|
-
TokenProgressBarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: TokenProgressBarComponent, isStandalone: true, selector: "sq-token-progress-bar", inputs: { instanceId: "instanceId" }, ngImport: i0, template: "<div class=\"bars-container d-flex flex-row gap-2 p-2 me-4\" *ngIf=\"(config?.globalSettings?.displayUserQuotaConsumption && userPercentage !== undefined) || (config?.globalSettings?.displayChatTokensConsumption && chatPercentage !== undefined)\">\n <div *ngIf=\"(config?.globalSettings?.displayUserQuotaConsumption && userPercentage !== undefined)\" class=\"token-progress-bar\" [sqTooltip]=\"userTitle\"\n [style.background]=\"'radial-gradient(closest-side, var(--ast-primary-bg, #F8F8F8) 70%, transparent 75% 100%), conic-gradient(#FF854A ' + userPercentage + '%, #0040BF 0)'\">\n </div>\n <div *ngIf=\"(config?.globalSettings?.displayChatTokensConsumption && chatPercentage !== undefined)\" class=\"token-progress-bar\" [sqTooltip]=\"chatTitle\"\n [style.background]=\"'radial-gradient(closest-side, var(--ast-primary-bg, #F8F8F8) 70%, transparent 75% 100%), conic-gradient(#FF854A ' + chatPercentage + '%, #0040BF 0)'\">\n </div>\n</div>\n", styles: [".ast-primary{color:var(--ast-primary-color, #005DA7);background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover{background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover:hover{color:var(--ast-primary-color, #005DA7)}.ast-secondary{color:var(--ast-secondary-color, #FF732E);background-color:var(--ast-secondary-bg, #FFF8F1)}.ast-error{background-color:var(--ast-error-bg, rgba(249, 58, 55, .2))}.ast-error:hover{color:var(--ast-error-color, rgba(249, 58, 55, .7))}.ast-btn{border:0;text-align:left;padding-top:.5rem;padding-bottom:.5rem;display:flex;align-items:center}.dark{--ast-primary-bg: #0d0701;--ast-primary-color: #008cd1;--ast-secondary-bg: #00070e;--ast-secondary-color: #ffa258;--ast-input-bg: #070707;--ast-input-color: rgba(222, 218, 218, .75);--ast-muted-color: rgba(222, 218, 218, .75);--ast-saved-chat-hover-background: #262421;--ast-message-table-border-color: #333333;--ast-message-table-tr-bg: #070707;--ast-message-table-tr-border-color: #222222;--ast-reference-icon-color: white;--ast-reference-icon-active-color: black;--ast-reference-passages-color: white;--ast-reference-expanded-hover-bg: #262421;--ast-message-reference-color: black}.bars-container{background-color:var(--ast-primary-bg, #f2f8fe);border-bottom-left-radius:1rem;border-bottom-right-radius:1rem}.token-progress-bar{width:1.5rem;height:1.5rem;border-radius:50%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: UtilsModule }, { kind: "directive", type: i2$1.TooltipDirective, selector: "[sqTooltip]", inputs: ["sqTooltip", "sqTooltipData", "sqTooltipTemplate", "placement", "fallbackPlacements", "delay", "hoverableTooltip", "tooltipClass"] }] });
|
|
2034
|
+
TokenProgressBarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: TokenProgressBarComponent, isStandalone: true, selector: "sq-token-progress-bar", inputs: { instanceId: "instanceId" }, ngImport: i0, template: "<div class=\"bars-container d-flex flex-row gap-2 p-2 me-4\" *ngIf=\"(config?.globalSettings?.displayUserQuotaConsumption && userPercentage !== undefined) || (config?.globalSettings?.displayChatTokensConsumption && chatPercentage !== undefined)\">\n <div *ngIf=\"(config?.globalSettings?.displayUserQuotaConsumption && userPercentage !== undefined)\" class=\"token-progress-bar\" [sqTooltip]=\"userTitle\"\n [style.background]=\"'radial-gradient(closest-side, var(--ast-primary-bg, #F8F8F8) 70%, transparent 75% 100%), conic-gradient(#FF854A ' + userPercentage + '%, #0040BF 0)'\">\n </div>\n <div *ngIf=\"(config?.globalSettings?.displayChatTokensConsumption && chatPercentage !== undefined)\" class=\"token-progress-bar\" [sqTooltip]=\"chatTitle\"\n [style.background]=\"'radial-gradient(closest-side, var(--ast-primary-bg, #F8F8F8) 70%, transparent 75% 100%), conic-gradient(#FF854A ' + chatPercentage + '%, #0040BF 0)'\">\n </div>\n</div>\n", styles: [".ast-primary{color:var(--ast-primary-color, #005DA7);background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover{background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover:hover{color:var(--ast-primary-color, #005DA7)}.ast-secondary{color:var(--ast-secondary-color, #FF732E);background-color:var(--ast-secondary-bg, #FFF8F1)}.ast-error{background-color:var(--ast-error-bg, rgba(249, 58, 55, .2));color:var(--ast-action-buttons-color, inherit)}.ast-error:hover{color:var(--ast-error-color, rgba(249, 58, 55, .7))}.ast-btn{border:0;text-align:left;padding-top:.5rem;padding-bottom:.5rem;display:flex;align-items:center}.dark{--ast-primary-bg: #0d0701;--ast-primary-color: #008cd1;--ast-secondary-bg: #00070e;--ast-secondary-color: #ffa258;--ast-input-bg: #070707;--ast-input-color: rgba(222, 218, 218, .75);--ast-muted-color: rgba(222, 218, 218, .75);--ast-saved-chat-hover-background: #262421;--ast-message-table-border-color: #333333;--ast-message-table-tr-bg: #070707;--ast-message-table-tr-border-color: #222222;--ast-reference-icon-color: white;--ast-reference-icon-active-color: black;--ast-reference-passages-color: white;--ast-reference-expanded-hover-bg: #262421;--ast-message-reference-color: black;--ast-action-buttons-color: white;--ast-action-buttons-hover-color: #6dbee6}.bars-container{background-color:var(--ast-primary-bg, #f2f8fe);border-bottom-left-radius:1rem;border-bottom-right-radius:1rem}.token-progress-bar{width:1.5rem;height:1.5rem;border-radius:50%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: UtilsModule }, { kind: "directive", type: i2$1.TooltipDirective, selector: "[sqTooltip]", inputs: ["sqTooltip", "sqTooltipData", "sqTooltipTemplate", "placement", "fallbackPlacements", "delay", "hoverableTooltip", "tooltipClass"] }] });
|
|
1876
2035
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: TokenProgressBarComponent, decorators: [{
|
|
1877
2036
|
type: Component,
|
|
1878
|
-
args: [{ selector: 'sq-token-progress-bar', standalone: true, imports: [CommonModule, UtilsModule], template: "<div class=\"bars-container d-flex flex-row gap-2 p-2 me-4\" *ngIf=\"(config?.globalSettings?.displayUserQuotaConsumption && userPercentage !== undefined) || (config?.globalSettings?.displayChatTokensConsumption && chatPercentage !== undefined)\">\n <div *ngIf=\"(config?.globalSettings?.displayUserQuotaConsumption && userPercentage !== undefined)\" class=\"token-progress-bar\" [sqTooltip]=\"userTitle\"\n [style.background]=\"'radial-gradient(closest-side, var(--ast-primary-bg, #F8F8F8) 70%, transparent 75% 100%), conic-gradient(#FF854A ' + userPercentage + '%, #0040BF 0)'\">\n </div>\n <div *ngIf=\"(config?.globalSettings?.displayChatTokensConsumption && chatPercentage !== undefined)\" class=\"token-progress-bar\" [sqTooltip]=\"chatTitle\"\n [style.background]=\"'radial-gradient(closest-side, var(--ast-primary-bg, #F8F8F8) 70%, transparent 75% 100%), conic-gradient(#FF854A ' + chatPercentage + '%, #0040BF 0)'\">\n </div>\n</div>\n", styles: [".ast-primary{color:var(--ast-primary-color, #005DA7);background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover{background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover:hover{color:var(--ast-primary-color, #005DA7)}.ast-secondary{color:var(--ast-secondary-color, #FF732E);background-color:var(--ast-secondary-bg, #FFF8F1)}.ast-error{background-color:var(--ast-error-bg, rgba(249, 58, 55, .2))}.ast-error:hover{color:var(--ast-error-color, rgba(249, 58, 55, .7))}.ast-btn{border:0;text-align:left;padding-top:.5rem;padding-bottom:.5rem;display:flex;align-items:center}.dark{--ast-primary-bg: #0d0701;--ast-primary-color: #008cd1;--ast-secondary-bg: #00070e;--ast-secondary-color: #ffa258;--ast-input-bg: #070707;--ast-input-color: rgba(222, 218, 218, .75);--ast-muted-color: rgba(222, 218, 218, .75);--ast-saved-chat-hover-background: #262421;--ast-message-table-border-color: #333333;--ast-message-table-tr-bg: #070707;--ast-message-table-tr-border-color: #222222;--ast-reference-icon-color: white;--ast-reference-icon-active-color: black;--ast-reference-passages-color: white;--ast-reference-expanded-hover-bg: #262421;--ast-message-reference-color: black}.bars-container{background-color:var(--ast-primary-bg, #f2f8fe);border-bottom-left-radius:1rem;border-bottom-right-radius:1rem}.token-progress-bar{width:1.5rem;height:1.5rem;border-radius:50%}\n"] }]
|
|
2037
|
+
args: [{ selector: 'sq-token-progress-bar', standalone: true, imports: [CommonModule, UtilsModule], template: "<div class=\"bars-container d-flex flex-row gap-2 p-2 me-4\" *ngIf=\"(config?.globalSettings?.displayUserQuotaConsumption && userPercentage !== undefined) || (config?.globalSettings?.displayChatTokensConsumption && chatPercentage !== undefined)\">\n <div *ngIf=\"(config?.globalSettings?.displayUserQuotaConsumption && userPercentage !== undefined)\" class=\"token-progress-bar\" [sqTooltip]=\"userTitle\"\n [style.background]=\"'radial-gradient(closest-side, var(--ast-primary-bg, #F8F8F8) 70%, transparent 75% 100%), conic-gradient(#FF854A ' + userPercentage + '%, #0040BF 0)'\">\n </div>\n <div *ngIf=\"(config?.globalSettings?.displayChatTokensConsumption && chatPercentage !== undefined)\" class=\"token-progress-bar\" [sqTooltip]=\"chatTitle\"\n [style.background]=\"'radial-gradient(closest-side, var(--ast-primary-bg, #F8F8F8) 70%, transparent 75% 100%), conic-gradient(#FF854A ' + chatPercentage + '%, #0040BF 0)'\">\n </div>\n</div>\n", styles: [".ast-primary{color:var(--ast-primary-color, #005DA7);background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover{background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover:hover{color:var(--ast-primary-color, #005DA7)}.ast-secondary{color:var(--ast-secondary-color, #FF732E);background-color:var(--ast-secondary-bg, #FFF8F1)}.ast-error{background-color:var(--ast-error-bg, rgba(249, 58, 55, .2));color:var(--ast-action-buttons-color, inherit)}.ast-error:hover{color:var(--ast-error-color, rgba(249, 58, 55, .7))}.ast-btn{border:0;text-align:left;padding-top:.5rem;padding-bottom:.5rem;display:flex;align-items:center}.dark{--ast-primary-bg: #0d0701;--ast-primary-color: #008cd1;--ast-secondary-bg: #00070e;--ast-secondary-color: #ffa258;--ast-input-bg: #070707;--ast-input-color: rgba(222, 218, 218, .75);--ast-muted-color: rgba(222, 218, 218, .75);--ast-saved-chat-hover-background: #262421;--ast-message-table-border-color: #333333;--ast-message-table-tr-bg: #070707;--ast-message-table-tr-border-color: #222222;--ast-reference-icon-color: white;--ast-reference-icon-active-color: black;--ast-reference-passages-color: white;--ast-reference-expanded-hover-bg: #262421;--ast-message-reference-color: black;--ast-action-buttons-color: white;--ast-action-buttons-hover-color: #6dbee6}.bars-container{background-color:var(--ast-primary-bg, #f2f8fe);border-bottom-left-radius:1rem;border-bottom-right-radius:1rem}.token-progress-bar{width:1.5rem;height:1.5rem;border-radius:50%}\n"] }]
|
|
1879
2038
|
}], propDecorators: { instanceId: [{
|
|
1880
2039
|
type: Input
|
|
1881
2040
|
}] } });
|
|
@@ -1904,10 +2063,10 @@ class DebugMessageComponent {
|
|
|
1904
2063
|
}
|
|
1905
2064
|
}
|
|
1906
2065
|
DebugMessageComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: DebugMessageComponent, deps: [{ token: i2$1.UIService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1907
|
-
DebugMessageComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: DebugMessageComponent, isStandalone: true, selector: "sq-debug-message", inputs: { data: "data", level: "level", parentColor: "parentColor" }, ngImport: i0, template: "<div *ngIf=\"data\" class=\"table-root\">\n <ng-container *ngFor=\"let item of data; let i = index\">\n <div *ngIf=\"item.type === 'KV'\" [ngClass]=\"getRowClass(item, i)\" class=\"table-row kv-object\">\n <div class=\"kv-key\">{{ item.data.key }}</div>\n <div class=\"kv-value\">\n <ng-container *ngIf=\"isObject(item.data.value); else normalValue\">\n <div class=\"card mb-2\">\n <div class=\"card-header\">\n <button class=\"btn btn-light btn-sm\" (click)=\"copyToClipboard(item.data.value)\"><i class=\"far fa-fw fa-clipboard\"></i> Copy code</button>\n </div>\n <pre class=\"language-json my-0 rounded-0 rounded-bottom\"><code class=\"language-json\">{{ item.data.value | json }}</code></pre>\n </div>\n </ng-container>\n <ng-template #normalValue>{{ item.data.value }}</ng-template>\n </div>\n </div>\n <div *ngIf=\"item.type === 'LIST'\" [ngClass]=\"getRowClass(item, i)\" class=\"table-row list-object\">\n <div class=\"list-name\" [class.
|
|
2066
|
+
DebugMessageComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: DebugMessageComponent, isStandalone: true, selector: "sq-debug-message", inputs: { data: "data", level: "level", parentColor: "parentColor" }, ngImport: i0, template: "<div *ngIf=\"data\" class=\"table-root\">\n <ng-container *ngFor=\"let item of data; let i = index\">\n <div *ngIf=\"item.type === 'KV'\" [ngClass]=\"getRowClass(item, i)\" class=\"table-row kv-object\">\n <div class=\"kv-key\">{{ item.data.key }}</div>\n <div class=\"kv-value\">\n <ng-container *ngIf=\"isObject(item.data.value); else normalValue\">\n <div class=\"card mb-2\">\n <div class=\"card-header\">\n <button class=\"btn btn-light btn-sm\" (click)=\"copyToClipboard(item.data.value)\"><i class=\"far fa-fw fa-clipboard\"></i> Copy code</button>\n </div>\n <pre class=\"language-json my-0 rounded-0 rounded-bottom\"><code class=\"language-json\">{{ item.data.value | json }}</code></pre>\n </div>\n </ng-container>\n <ng-template #normalValue><div class=\"data-value\">{{ item.data.value }}</div></ng-template>\n </div>\n </div>\n <div *ngIf=\"item.type === 'LIST'\" [ngClass]=\"getRowClass(item, i)\" class=\"table-row list-object\">\n <div class=\"list-name w-100\" [class.fw-bold]=\"level === 0\" (click)=\"item.expanded=!item.expanded\">\n <i class=\"fas\" [class.fa-chevron-up]=\"item.expanded\" [class.fa-chevron-down]=\"!item.expanded\"></i>\n {{ item.name }}\n </div>\n <div class=\"list-items w-100\" *ngIf=\"item.expanded\">\n <sq-debug-message [data]=\"item.items\" [level]=\"level + 1\" [parentColor]=\"getRowClass(item, i)\"></sq-debug-message>\n </div>\n </div>\n </ng-container>\n</div>\n", styles: [".table-root{display:flex;flex-direction:column;border:1px solid #ccc;width:100%;border-spacing:0}.table-row{display:flex;width:100%}.list-name{width:15%;cursor:pointer}.list-items{width:85%}.kv-key,.kv-value,.list-name{padding:8px;border:1px solid #ccc;box-sizing:border-box;word-wrap:break-word}.kv-key{width:20%}.kv-value{width:80%}.kv-value .data-value{white-space:pre-line}.kv-object,.list-object{display:flex;flex:1}.list-object{flex-direction:column}.row-even{background-color:#fff}.row-odd{background-color:#f2f8fe}.row-error{background-color:#f08080}.table-row:not(:last-child){border-bottom:1px solid #ccc}.kv-key:last-child,.kv-value:last-child,.list-name:last-child{border-right:none}\n"], dependencies: [{ kind: "component", type: DebugMessageComponent, selector: "sq-debug-message", inputs: ["data", "level", "parentColor"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i1.JsonPipe, name: "json" }] });
|
|
1908
2067
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: DebugMessageComponent, decorators: [{
|
|
1909
2068
|
type: Component,
|
|
1910
|
-
args: [{ selector: "sq-debug-message", standalone: true, imports: [CommonModule], template: "<div *ngIf=\"data\" class=\"table-root\">\n <ng-container *ngFor=\"let item of data; let i = index\">\n <div *ngIf=\"item.type === 'KV'\" [ngClass]=\"getRowClass(item, i)\" class=\"table-row kv-object\">\n <div class=\"kv-key\">{{ item.data.key }}</div>\n <div class=\"kv-value\">\n <ng-container *ngIf=\"isObject(item.data.value); else normalValue\">\n <div class=\"card mb-2\">\n <div class=\"card-header\">\n <button class=\"btn btn-light btn-sm\" (click)=\"copyToClipboard(item.data.value)\"><i class=\"far fa-fw fa-clipboard\"></i> Copy code</button>\n </div>\n <pre class=\"language-json my-0 rounded-0 rounded-bottom\"><code class=\"language-json\">{{ item.data.value | json }}</code></pre>\n </div>\n </ng-container>\n <ng-template #normalValue>{{ item.data.value }}</ng-template>\n </div>\n </div>\n <div *ngIf=\"item.type === 'LIST'\" [ngClass]=\"getRowClass(item, i)\" class=\"table-row list-object\">\n <div class=\"list-name\" [class.
|
|
2069
|
+
args: [{ selector: "sq-debug-message", standalone: true, imports: [CommonModule], template: "<div *ngIf=\"data\" class=\"table-root\">\n <ng-container *ngFor=\"let item of data; let i = index\">\n <div *ngIf=\"item.type === 'KV'\" [ngClass]=\"getRowClass(item, i)\" class=\"table-row kv-object\">\n <div class=\"kv-key\">{{ item.data.key }}</div>\n <div class=\"kv-value\">\n <ng-container *ngIf=\"isObject(item.data.value); else normalValue\">\n <div class=\"card mb-2\">\n <div class=\"card-header\">\n <button class=\"btn btn-light btn-sm\" (click)=\"copyToClipboard(item.data.value)\"><i class=\"far fa-fw fa-clipboard\"></i> Copy code</button>\n </div>\n <pre class=\"language-json my-0 rounded-0 rounded-bottom\"><code class=\"language-json\">{{ item.data.value | json }}</code></pre>\n </div>\n </ng-container>\n <ng-template #normalValue><div class=\"data-value\">{{ item.data.value }}</div></ng-template>\n </div>\n </div>\n <div *ngIf=\"item.type === 'LIST'\" [ngClass]=\"getRowClass(item, i)\" class=\"table-row list-object\">\n <div class=\"list-name w-100\" [class.fw-bold]=\"level === 0\" (click)=\"item.expanded=!item.expanded\">\n <i class=\"fas\" [class.fa-chevron-up]=\"item.expanded\" [class.fa-chevron-down]=\"!item.expanded\"></i>\n {{ item.name }}\n </div>\n <div class=\"list-items w-100\" *ngIf=\"item.expanded\">\n <sq-debug-message [data]=\"item.items\" [level]=\"level + 1\" [parentColor]=\"getRowClass(item, i)\"></sq-debug-message>\n </div>\n </div>\n </ng-container>\n</div>\n", styles: [".table-root{display:flex;flex-direction:column;border:1px solid #ccc;width:100%;border-spacing:0}.table-row{display:flex;width:100%}.list-name{width:15%;cursor:pointer}.list-items{width:85%}.kv-key,.kv-value,.list-name{padding:8px;border:1px solid #ccc;box-sizing:border-box;word-wrap:break-word}.kv-key{width:20%}.kv-value{width:80%}.kv-value .data-value{white-space:pre-line}.kv-object,.list-object{display:flex;flex:1}.list-object{flex-direction:column}.row-even{background-color:#fff}.row-odd{background-color:#f2f8fe}.row-error{background-color:#f08080}.table-row:not(:last-child){border-bottom:1px solid #ccc}.kv-key:last-child,.kv-value:last-child,.list-name:last-child{border-right:none}\n"] }]
|
|
1911
2070
|
}], ctorParameters: function () { return [{ type: i2$1.UIService }]; }, propDecorators: { data: [{
|
|
1912
2071
|
type: Input
|
|
1913
2072
|
}], level: [{
|
|
@@ -1935,6 +2094,8 @@ class ChatComponent extends AbstractFacet {
|
|
|
1935
2094
|
this.messageHandlers = new Map();
|
|
1936
2095
|
/** When the assistant answer a user question, automatically scroll down to the bottom of the discussion */
|
|
1937
2096
|
this.automaticScrollToLastResponse = false;
|
|
2097
|
+
/** When the assistant answer a user question, automatically focus to the chat input */
|
|
2098
|
+
this.focusAfterResponse = false;
|
|
1938
2099
|
/** Icon to use for the assistant messages */
|
|
1939
2100
|
this.assistantMessageIcon = 'sq-sinequa';
|
|
1940
2101
|
/** Event emitter triggered once the signalR connection is established */
|
|
@@ -1951,10 +2112,17 @@ class ChatComponent extends AbstractFacet {
|
|
|
1951
2112
|
this.openPreview = new EventEmitter();
|
|
1952
2113
|
/** Event emitter triggered when the user clicks on a suggested action */
|
|
1953
2114
|
this.suggestAction = new EventEmitter();
|
|
2115
|
+
/** Event emitter triggered when the user clicks on a chat starter */
|
|
2116
|
+
this.chatStarter = new EventEmitter();
|
|
1954
2117
|
this.messages$ = new BehaviorSubject(undefined);
|
|
1955
2118
|
this.question = '';
|
|
1956
2119
|
this._actions = [];
|
|
1957
|
-
this.
|
|
2120
|
+
this._resetChatAction = new Action({
|
|
2121
|
+
icon: 'fas fa-sync',
|
|
2122
|
+
title: "Reset chat",
|
|
2123
|
+
action: () => this.newChat()
|
|
2124
|
+
});
|
|
2125
|
+
this._sub = new Subscription();
|
|
1958
2126
|
this.changes$ = new BehaviorSubject(undefined);
|
|
1959
2127
|
this.firstChangesHandled = false;
|
|
1960
2128
|
this.isAtBottom = true;
|
|
@@ -1972,16 +2140,14 @@ class ChatComponent extends AbstractFacet {
|
|
|
1972
2140
|
'Other'
|
|
1973
2141
|
];
|
|
1974
2142
|
this.issueType = '';
|
|
1975
|
-
this.
|
|
2143
|
+
this.reportType = 'dislike';
|
|
2144
|
+
this.showReport = false;
|
|
1976
2145
|
this.showDebugMessages = false;
|
|
1977
|
-
this.
|
|
1978
|
-
|
|
1979
|
-
title: 'Reset chat',
|
|
1980
|
-
action: () => this.newChat()
|
|
1981
|
-
}));
|
|
2146
|
+
this._reloadSubscription = undefined;
|
|
2147
|
+
this._actions.push(this._resetChatAction);
|
|
1982
2148
|
}
|
|
1983
2149
|
ngOnInit() {
|
|
1984
|
-
this.
|
|
2150
|
+
this._sub.add(this.loginService.events.pipe(filter(e => e.type === 'login-complete'), tap(_ => this.instantiateChatService()), map(_ => this.chatService.initChatConfig()), switchMap(() => this.chatService.initConfig$), filter(initConfig => !!initConfig), switchMap(_ => this.chatService.init()), switchMap(_ => this.chatService.initProcess$), filter(success => !!success), tap(_ => {
|
|
1985
2151
|
if (this.chatService instanceof WebSocketChatService) {
|
|
1986
2152
|
this.connection.emit(this.chatService.connection);
|
|
1987
2153
|
}
|
|
@@ -2006,6 +2172,12 @@ class ChatComponent extends AbstractFacet {
|
|
|
2006
2172
|
throw error;
|
|
2007
2173
|
}
|
|
2008
2174
|
})).subscribe());
|
|
2175
|
+
this._sub.add(combineLatest([
|
|
2176
|
+
this.chatService.streaming$,
|
|
2177
|
+
this.chatService.stoppingGeneration$
|
|
2178
|
+
]).pipe(map(([streaming, stoppingGeneration]) => !!(streaming || stoppingGeneration))).subscribe((result) => {
|
|
2179
|
+
this._resetChatAction.disabled = result;
|
|
2180
|
+
}));
|
|
2009
2181
|
}
|
|
2010
2182
|
ngOnChanges(changes) {
|
|
2011
2183
|
this.changes$.next(changes);
|
|
@@ -2014,14 +2186,19 @@ class ChatComponent extends AbstractFacet {
|
|
|
2014
2186
|
}
|
|
2015
2187
|
}
|
|
2016
2188
|
ngOnDestroy() {
|
|
2017
|
-
var _a;
|
|
2018
|
-
this.
|
|
2019
|
-
(_a = this.
|
|
2189
|
+
var _a, _b;
|
|
2190
|
+
this._sub.unsubscribe();
|
|
2191
|
+
(_a = this._dataSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
|
|
2192
|
+
(_b = this._reloadSubscription) === null || _b === void 0 ? void 0 : _b.unsubscribe();
|
|
2020
2193
|
}
|
|
2021
2194
|
get isAdmin() {
|
|
2022
2195
|
var _a;
|
|
2023
2196
|
return ((_a = this.principalService.principal) === null || _a === void 0 ? void 0 : _a.isAdministrator) || false;
|
|
2024
2197
|
}
|
|
2198
|
+
get visibleMessagesCount() {
|
|
2199
|
+
var _a;
|
|
2200
|
+
return ((_a = this.messages$.value) === null || _a === void 0 ? void 0 : _a.filter(m => m.additionalProperties.display).length) || 0;
|
|
2201
|
+
}
|
|
2025
2202
|
/**
|
|
2026
2203
|
* Instantiate the chat service based on the provided @input protocol
|
|
2027
2204
|
* This chat service instance will then be stored in the instanceManagerService with provided @input instanceId as a key
|
|
@@ -2075,9 +2252,62 @@ class ChatComponent extends AbstractFacet {
|
|
|
2075
2252
|
*/
|
|
2076
2253
|
if (this.firstChangesHandled && (changes === null || changes === void 0 ? void 0 : changes.query) && this.config.modeSettings.initialization.event === 'Query') {
|
|
2077
2254
|
if (this.queryChangeShouldTriggerReload ? this.queryChangeShouldTriggerReload(this._previousQuery, this.query) : true) {
|
|
2078
|
-
this.
|
|
2255
|
+
if (!!this.chatService.stoppingGeneration$.value) {
|
|
2256
|
+
if (!this._reloadSubscription) {
|
|
2257
|
+
// Create a subscription to wait for both streaming$ and stoppingGeneration$ to be false
|
|
2258
|
+
this._reloadSubscription = combineLatest([
|
|
2259
|
+
this.chatService.streaming$,
|
|
2260
|
+
this.chatService.stoppingGeneration$
|
|
2261
|
+
])
|
|
2262
|
+
.pipe(filter(([streaming, stopping]) => !streaming && !stopping), // Wait until both are false
|
|
2263
|
+
take(1) // Complete after the first match
|
|
2264
|
+
).subscribe(() => {
|
|
2265
|
+
// Execute the reload after the query change
|
|
2266
|
+
this._triggerReloadAfterQueryChange();
|
|
2267
|
+
// Update _previousQuery with the current query
|
|
2268
|
+
this._previousQuery = JSON.parse(JSON.stringify(this.query));
|
|
2269
|
+
// Clean up subscription and reset its value
|
|
2270
|
+
this._reloadSubscription = undefined;
|
|
2271
|
+
});
|
|
2272
|
+
}
|
|
2273
|
+
}
|
|
2274
|
+
else if (!!this.chatService.streaming$.value) {
|
|
2275
|
+
if (!this._reloadSubscription) {
|
|
2276
|
+
this._reloadSubscription = this.chatService.stopGeneration()
|
|
2277
|
+
.subscribe({
|
|
2278
|
+
next: () => { },
|
|
2279
|
+
error: () => {
|
|
2280
|
+
var _a;
|
|
2281
|
+
// Clean up subscription and reset its value
|
|
2282
|
+
(_a = this._reloadSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
|
|
2283
|
+
this._reloadSubscription = undefined;
|
|
2284
|
+
},
|
|
2285
|
+
complete: () => {
|
|
2286
|
+
// Wait for the ongoing fetch to complete, then trigger the reload
|
|
2287
|
+
this.chatService.streaming$.pipe(filter((streaming) => !streaming), take(1)).subscribe(() => {
|
|
2288
|
+
// Execute the reload after the query change
|
|
2289
|
+
this._triggerReloadAfterQueryChange();
|
|
2290
|
+
// Update _previousQuery with the current query
|
|
2291
|
+
this._previousQuery = JSON.parse(JSON.stringify(this.query));
|
|
2292
|
+
// Clean up subscription and reset its value
|
|
2293
|
+
this._reloadSubscription.unsubscribe();
|
|
2294
|
+
this._reloadSubscription = undefined;
|
|
2295
|
+
});
|
|
2296
|
+
}
|
|
2297
|
+
});
|
|
2298
|
+
}
|
|
2299
|
+
}
|
|
2300
|
+
else {
|
|
2301
|
+
// Execute the reload after the query change
|
|
2302
|
+
this._triggerReloadAfterQueryChange();
|
|
2303
|
+
// Update _previousQuery with the current query
|
|
2304
|
+
this._previousQuery = JSON.parse(JSON.stringify(this.query));
|
|
2305
|
+
}
|
|
2306
|
+
}
|
|
2307
|
+
else {
|
|
2308
|
+
// Update _previousQuery with the current query
|
|
2309
|
+
this._previousQuery = JSON.parse(JSON.stringify(this.query));
|
|
2079
2310
|
}
|
|
2080
|
-
this._previousQuery = JSON.parse(JSON.stringify(this.query)); // Update the previous query
|
|
2081
2311
|
}
|
|
2082
2312
|
}
|
|
2083
2313
|
_triggerReloadAfterQueryChange() {
|
|
@@ -2089,7 +2319,7 @@ class ChatComponent extends AbstractFacet {
|
|
|
2089
2319
|
this._handleQueryMode(systemMsg, userMsg);
|
|
2090
2320
|
}
|
|
2091
2321
|
_addScrollListener() {
|
|
2092
|
-
this.
|
|
2322
|
+
this._sub.add(merge(this.loading$, this.messages$, this.chatService.streaming$, fromEvent(this.messageList.nativeElement, 'scroll')).subscribe(() => {
|
|
2093
2323
|
this.isAtBottom = this._toggleScrollButtonVisibility();
|
|
2094
2324
|
this.cdr.detectChanges();
|
|
2095
2325
|
}));
|
|
@@ -2100,14 +2330,18 @@ class ChatComponent extends AbstractFacet {
|
|
|
2100
2330
|
}
|
|
2101
2331
|
submitQuestion() {
|
|
2102
2332
|
var _a;
|
|
2333
|
+
if (this.chatService.streaming$.value) {
|
|
2334
|
+
return;
|
|
2335
|
+
}
|
|
2103
2336
|
if (this.question.trim() && this.messages$.value && this.chatService.chatHistory) {
|
|
2104
2337
|
// When the user submits a question, if the user is editing a previous message, remove all subsequent messages from the chat history
|
|
2105
2338
|
if (this.messageToEdit !== undefined) {
|
|
2106
2339
|
// Update the messages in the UI
|
|
2107
2340
|
this.messages$.next(this.messages$.value.slice(0, this.messageToEdit));
|
|
2108
2341
|
// Update the raw messages in the chat history which is the clean version used to make the next request
|
|
2109
|
-
this.chatService.chatHistory = this.chatService.chatHistory.slice(0, this.
|
|
2342
|
+
this.chatService.chatHistory = this.chatService.chatHistory.slice(0, this.remappedMessageToEdit);
|
|
2110
2343
|
this.messageToEdit = undefined;
|
|
2344
|
+
this.remappedMessageToEdit = undefined;
|
|
2111
2345
|
}
|
|
2112
2346
|
// Remove the search warning message if exists
|
|
2113
2347
|
if (((_a = this.chatService.chatHistory.at(-1)) === null || _a === void 0 ? void 0 : _a.role) === 'search-warning') {
|
|
@@ -2140,8 +2374,8 @@ class ChatComponent extends AbstractFacet {
|
|
|
2140
2374
|
this.cdr.detectChanges();
|
|
2141
2375
|
if (this.isConnected) {
|
|
2142
2376
|
this.loading$.next(true);
|
|
2143
|
-
(_a = this.
|
|
2144
|
-
this.
|
|
2377
|
+
(_a = this._dataSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
|
|
2378
|
+
this._dataSubscription = this.chatService.fetch(messages, this.query)
|
|
2145
2379
|
.subscribe({
|
|
2146
2380
|
next: res => this.updateData(res.history),
|
|
2147
2381
|
error: () => {
|
|
@@ -2153,6 +2387,15 @@ class ChatComponent extends AbstractFacet {
|
|
|
2153
2387
|
this.terminateFetch();
|
|
2154
2388
|
},
|
|
2155
2389
|
complete: () => {
|
|
2390
|
+
var _a, _b, _c, _d, _e, _f;
|
|
2391
|
+
// Remove the last message if it's an empty message
|
|
2392
|
+
// This is due to the manner in which the chat service handles consecutive messages
|
|
2393
|
+
const lastMessage = (_a = this.messages$.value) === null || _a === void 0 ? void 0 : _a.at(-1);
|
|
2394
|
+
if ((lastMessage === null || lastMessage === void 0 ? void 0 : lastMessage.role) === 'assistant' && (lastMessage === null || lastMessage === void 0 ? void 0 : lastMessage.content) === ""
|
|
2395
|
+
&& !((_b = lastMessage === null || lastMessage === void 0 ? void 0 : lastMessage.additionalProperties) === null || _b === void 0 ? void 0 : _b.$attachment) && !((_c = lastMessage === null || lastMessage === void 0 ? void 0 : lastMessage.additionalProperties) === null || _c === void 0 ? void 0 : _c.$progress)
|
|
2396
|
+
&& !((_d = lastMessage === null || lastMessage === void 0 ? void 0 : lastMessage.additionalProperties) === null || _d === void 0 ? void 0 : _d.$debug) && !((_e = lastMessage === null || lastMessage === void 0 ? void 0 : lastMessage.additionalProperties) === null || _e === void 0 ? void 0 : _e.$suggestedAction)) {
|
|
2397
|
+
this.messages$.next((_f = this.messages$.value) === null || _f === void 0 ? void 0 : _f.slice(0, -1));
|
|
2398
|
+
}
|
|
2156
2399
|
this.terminateFetch();
|
|
2157
2400
|
}
|
|
2158
2401
|
});
|
|
@@ -2176,10 +2419,21 @@ class ChatComponent extends AbstractFacet {
|
|
|
2176
2419
|
if (this.chatService instanceof WebSocketChatService) {
|
|
2177
2420
|
// A one-time listener for reconnected event
|
|
2178
2421
|
const onReconnectedHandler = () => {
|
|
2422
|
+
// Get the messages without the last one (the connection error message)
|
|
2179
2423
|
const messages = this.messages$.value.slice(0, -1);
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2424
|
+
// Find the last "user" message in the messages list
|
|
2425
|
+
let index = messages.length - 1;
|
|
2426
|
+
while (index >= 0 && messages[index].role !== 'user') {
|
|
2427
|
+
index--;
|
|
2428
|
+
}
|
|
2429
|
+
// If a user message is found (and it should always be the case), remove all subsequent messages from the chat history
|
|
2430
|
+
// Update the messages in the UI
|
|
2431
|
+
// and fetch the answer from the assistant
|
|
2432
|
+
if (index >= 0) {
|
|
2433
|
+
this.messages$.next(this.messages$.value.slice(0, index + 1));
|
|
2434
|
+
const remappedIndex = this._remapIndexInChatHistory(index);
|
|
2435
|
+
this.chatService.chatHistory = this.chatService.chatHistory.slice(0, remappedIndex + 1);
|
|
2436
|
+
this.fetch(this.chatService.chatHistory);
|
|
2183
2437
|
}
|
|
2184
2438
|
this.retrialAttempts = undefined; // Reset the number of retrial attempts
|
|
2185
2439
|
/**
|
|
@@ -2260,6 +2514,9 @@ class ChatComponent extends AbstractFacet {
|
|
|
2260
2514
|
* If the savedChat feature is enabled, the list of saved chats will be refreshed
|
|
2261
2515
|
*/
|
|
2262
2516
|
newChat() {
|
|
2517
|
+
if (!!this.chatService.streaming$.value || !!this.chatService.stoppingGeneration$.value) {
|
|
2518
|
+
return;
|
|
2519
|
+
}
|
|
2263
2520
|
this.chatService.setSavedChatId(undefined); // Reset the savedChatId
|
|
2264
2521
|
this.chatService.generateChatId(); // Generate a new chatId
|
|
2265
2522
|
this.chatService.listSavedChat(); // Refresh the list of saved chats
|
|
@@ -2361,15 +2618,24 @@ class ChatComponent extends AbstractFacet {
|
|
|
2361
2618
|
}
|
|
2362
2619
|
onLoadChat() {
|
|
2363
2620
|
this.loading$.next(true);
|
|
2364
|
-
this.
|
|
2621
|
+
this._sub.add(this.chatService.loadSavedChat$
|
|
2365
2622
|
.pipe(filter(savedChat => !!savedChat), switchMap(savedChat => this.chatService.getSavedChat(savedChat.id)), filter(savedChatHistory => !!savedChatHistory), tap(savedChatHistory => this.openChat(savedChatHistory.history, savedChatHistory.id))).subscribe());
|
|
2366
2623
|
}
|
|
2624
|
+
stopGeneration() {
|
|
2625
|
+
this.chatService.stopGeneration().subscribe(() => this.terminateFetch());
|
|
2626
|
+
}
|
|
2367
2627
|
terminateFetch() {
|
|
2368
2628
|
var _a;
|
|
2369
|
-
(_a = this.
|
|
2370
|
-
this.
|
|
2629
|
+
(_a = this._dataSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
|
|
2630
|
+
this._dataSubscription = undefined;
|
|
2371
2631
|
this.loading$.next(false);
|
|
2372
2632
|
this.cdr.detectChanges();
|
|
2633
|
+
if (this.focusAfterResponse) {
|
|
2634
|
+
setTimeout(() => {
|
|
2635
|
+
var _a;
|
|
2636
|
+
(_a = this.questionInput) === null || _a === void 0 ? void 0 : _a.nativeElement.focus();
|
|
2637
|
+
});
|
|
2638
|
+
}
|
|
2373
2639
|
}
|
|
2374
2640
|
/**
|
|
2375
2641
|
* Copy a previous user message of the chat history to the chat user input.
|
|
@@ -2380,15 +2646,18 @@ class ChatComponent extends AbstractFacet {
|
|
|
2380
2646
|
*/
|
|
2381
2647
|
editMessage(index) {
|
|
2382
2648
|
this.messageToEdit = index;
|
|
2383
|
-
this.
|
|
2384
|
-
this.chatService.
|
|
2649
|
+
this.remappedMessageToEdit = this._remapIndexInChatHistory(index);
|
|
2650
|
+
this.question = this.chatService.chatHistory[this._remapIndexInChatHistory(index)].content;
|
|
2651
|
+
this.chatService.generateAuditEvent('edit.click', { 'rank': this._remapIndexInChatHistory(index) });
|
|
2385
2652
|
}
|
|
2386
2653
|
/**
|
|
2387
2654
|
* Copy a previous assistant message of the chat history to the clipboard.
|
|
2388
2655
|
* @param index The index of the assistant's message to edit
|
|
2389
2656
|
*/
|
|
2390
2657
|
copyMessage(index) {
|
|
2391
|
-
|
|
2658
|
+
// Remap the index in the chat history
|
|
2659
|
+
const idx = this._remapIndexInChatHistory(index);
|
|
2660
|
+
this.chatService.generateAuditEvent('copy.click', { 'rank': idx });
|
|
2392
2661
|
}
|
|
2393
2662
|
/**
|
|
2394
2663
|
* Starting from the provided index, remove all subsequent messages from the chat history and the UI accordingly.
|
|
@@ -2396,13 +2665,45 @@ class ChatComponent extends AbstractFacet {
|
|
|
2396
2665
|
* @param index The index of the assistant's message to regenerate
|
|
2397
2666
|
*/
|
|
2398
2667
|
regenerateMessage(index) {
|
|
2399
|
-
//
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2668
|
+
// Update the messages in the UI by removing all subsequent 'assistant' messages starting from the provided index until the first previous 'user' message
|
|
2669
|
+
let i = index;
|
|
2670
|
+
while (i >= 0 && (this.messages$.value)[i].role !== 'user') {
|
|
2671
|
+
i--;
|
|
2672
|
+
}
|
|
2673
|
+
// It should always be the case that i > 0
|
|
2674
|
+
if (i >= 0) {
|
|
2675
|
+
this.messages$.next(this.messages$.value.slice(0, i + 1));
|
|
2676
|
+
// Remap the index of this found first previous 'user' message in the chat history
|
|
2677
|
+
const idx = this._remapIndexInChatHistory(i);
|
|
2678
|
+
// Define and Update the chat history based on which the assistant will generate a new answer
|
|
2679
|
+
this.chatService.chatHistory = this.chatService.chatHistory.slice(0, idx + 1);
|
|
2680
|
+
// Fetch the answer
|
|
2681
|
+
this.fetch(this.chatService.chatHistory);
|
|
2682
|
+
this.chatService.generateAuditEvent('regenerate.click', { 'rank': idx });
|
|
2683
|
+
}
|
|
2684
|
+
}
|
|
2685
|
+
/**
|
|
2686
|
+
* Remaps the index in the chat history.
|
|
2687
|
+
* The chat history is a list of messages where some messages can be hidden (display set to false).
|
|
2688
|
+
* The index provided as input is the index of the message in the chat history displayed in the UI.
|
|
2689
|
+
* This function should be removed once the backend is updated to add the ids of the messages in the chat history
|
|
2690
|
+
* @param index - The index to be remapped.
|
|
2691
|
+
*/
|
|
2692
|
+
_remapIndexInChatHistory(index) {
|
|
2693
|
+
// a copy of the chat history is created to avoid modifying the original chat history. Additionally, a rank is giving to each message.
|
|
2694
|
+
const history = this.chatService.chatHistory.slice().map((message, idx) => {
|
|
2695
|
+
return Object.assign(Object.assign({}, message), { additionalProperties: Object.assign(Object.assign({}, message.additionalProperties), { rank: idx }) });
|
|
2696
|
+
});
|
|
2697
|
+
// Count the number of hidden messages in messages$ before the provided index
|
|
2698
|
+
// This is mandatory to get the correct rank of the message in the chat history
|
|
2699
|
+
// Since some hidden messages (like 'system' messages) are not displayed in the UI but have been counted in the provided index
|
|
2700
|
+
const numberOfHiddenMessagesInMessages$BeforeIndex = this.messages$.value.slice(0, index).filter(message => !message.additionalProperties.display).length;
|
|
2701
|
+
// remove all messages that have display set to false
|
|
2702
|
+
// this is mandatory since at the point of time when the assistant answers a question,
|
|
2703
|
+
// it might have some hidden messages (for example contextMessages) that are available in the chat history but don't figure in messages$ unless a new question is asked
|
|
2704
|
+
const filteredHistory = history.filter(message => message.additionalProperties.display);
|
|
2705
|
+
// return the index of the message in the filtered history
|
|
2706
|
+
return filteredHistory[index - numberOfHiddenMessagesInMessages$BeforeIndex].additionalProperties.rank;
|
|
2406
2707
|
}
|
|
2407
2708
|
onKeyUp(event) {
|
|
2408
2709
|
switch (event.key) {
|
|
@@ -2433,43 +2734,59 @@ class ChatComponent extends AbstractFacet {
|
|
|
2433
2734
|
}
|
|
2434
2735
|
/**
|
|
2435
2736
|
* Send a "like" event on clicking on the thumb-up icon of an assistant's message
|
|
2737
|
+
* @param message The assistant message to like
|
|
2436
2738
|
* @param rank The rank of the message to like
|
|
2437
2739
|
*/
|
|
2438
|
-
onLike(rank) {
|
|
2439
|
-
|
|
2740
|
+
onLike(message, rank) {
|
|
2741
|
+
// Remap the index in the chat history
|
|
2742
|
+
const idx = this._remapIndexInChatHistory(rank);
|
|
2743
|
+
this.chatService.generateAuditEvent('thumb-up.click', { rank: idx });
|
|
2744
|
+
this.reportType = 'like';
|
|
2745
|
+
this.messageToReport = message;
|
|
2746
|
+
this.reportComment = undefined;
|
|
2747
|
+
this.reportRank = rank;
|
|
2748
|
+
this.showReport = true;
|
|
2440
2749
|
}
|
|
2441
2750
|
/**
|
|
2442
2751
|
* Send a "dislike" event on clicking on the thumb-down icon of an assistant's message.
|
|
2443
2752
|
* It also opens the issue reporting dialog.
|
|
2444
2753
|
* @param message The assistant message to dislike
|
|
2445
|
-
* @param
|
|
2754
|
+
* @param index The rank of the message to dislike
|
|
2446
2755
|
*/
|
|
2447
2756
|
onDislike(message, rank) {
|
|
2448
|
-
|
|
2449
|
-
|
|
2757
|
+
// Remap the index in the chat history
|
|
2758
|
+
const idx = this._remapIndexInChatHistory(rank);
|
|
2759
|
+
this.chatService.generateAuditEvent('thumb-down.click', { rank: idx });
|
|
2760
|
+
this.reportType = 'dislike';
|
|
2761
|
+
this.messageToReport = message;
|
|
2450
2762
|
this.issueType = '';
|
|
2451
|
-
this.
|
|
2452
|
-
this.
|
|
2453
|
-
this.
|
|
2763
|
+
this.reportComment = undefined;
|
|
2764
|
+
this.reportRank = rank;
|
|
2765
|
+
this.showReport = true;
|
|
2454
2766
|
}
|
|
2455
2767
|
/**
|
|
2456
2768
|
* Report an issue related to the assistant's message.
|
|
2457
2769
|
*/
|
|
2458
|
-
|
|
2770
|
+
sendReport() {
|
|
2459
2771
|
const details = {
|
|
2460
|
-
'
|
|
2461
|
-
'
|
|
2462
|
-
'
|
|
2463
|
-
'rank': this.issueRank,
|
|
2772
|
+
'comment': this.reportComment,
|
|
2773
|
+
'text': this.messageToReport.content,
|
|
2774
|
+
'rank': this.reportRank,
|
|
2464
2775
|
};
|
|
2465
|
-
this.
|
|
2466
|
-
|
|
2776
|
+
if (this.reportType === 'dislike') {
|
|
2777
|
+
details['report-type'] = this.issueType;
|
|
2778
|
+
this.chatService.generateAuditEvent('negative-report.send', details);
|
|
2779
|
+
}
|
|
2780
|
+
else {
|
|
2781
|
+
this.chatService.generateAuditEvent('positive-report.send', details);
|
|
2782
|
+
}
|
|
2783
|
+
this.showReport = false;
|
|
2467
2784
|
}
|
|
2468
2785
|
/**
|
|
2469
|
-
* Close the
|
|
2786
|
+
* Close the reporting dialog.
|
|
2470
2787
|
*/
|
|
2471
|
-
|
|
2472
|
-
this.
|
|
2788
|
+
ignoreReport() {
|
|
2789
|
+
this.showReport = false;
|
|
2473
2790
|
}
|
|
2474
2791
|
/**
|
|
2475
2792
|
* Handle the click on a reference's 'open preview'.
|
|
@@ -2514,27 +2831,69 @@ class ChatComponent extends AbstractFacet {
|
|
|
2514
2831
|
this.suggestAction.emit(action);
|
|
2515
2832
|
this.chatService.generateAuditEvent('suggestedAction.click', { 'text': action.content, 'suggestedAction-type': action.type });
|
|
2516
2833
|
}
|
|
2834
|
+
/**
|
|
2835
|
+
* Handle the click on a chat starter.
|
|
2836
|
+
* @param starter the chat starter.
|
|
2837
|
+
*/
|
|
2838
|
+
chatStarterClick(starter) {
|
|
2839
|
+
this.chatStarter.emit(starter);
|
|
2840
|
+
}
|
|
2841
|
+
/**
|
|
2842
|
+
* It looks for the debug messages available in the current group of "assistant" messages.
|
|
2843
|
+
* By design, the debug messages are only available in the first visible message among the group "assistant" messages.
|
|
2844
|
+
* @param index The rank of the message
|
|
2845
|
+
* @returns The debug messages available in the current group of "assistant" messages
|
|
2846
|
+
*/
|
|
2847
|
+
getDebugMessages(index) {
|
|
2848
|
+
// If it is not an assistant message, return
|
|
2849
|
+
if ((this.messages$.value)[index].role !== 'assistant') {
|
|
2850
|
+
return [];
|
|
2851
|
+
}
|
|
2852
|
+
// Get the array of messages up to the indicated index
|
|
2853
|
+
const array = this.messages$.value.slice(0, index + 1);
|
|
2854
|
+
// If it is an assistant message, look for the debug messages available in the current group of "assistant" messages
|
|
2855
|
+
// By design, the debug messages are only available in the first visible message among the group "assistant" messages.
|
|
2856
|
+
const idx = this.chatService.firstVisibleAssistantMessageIndex(array);
|
|
2857
|
+
if (idx > -1) {
|
|
2858
|
+
return (this.messages$.value)[idx].additionalProperties.$debug || [];
|
|
2859
|
+
}
|
|
2860
|
+
return [];
|
|
2861
|
+
}
|
|
2517
2862
|
/**
|
|
2518
2863
|
* Handle the click on the 'show log info' button of a message.
|
|
2519
|
-
* @param
|
|
2864
|
+
* @param index The rank of the message
|
|
2520
2865
|
*/
|
|
2521
|
-
showDebug(
|
|
2522
|
-
this.debugMessages =
|
|
2866
|
+
showDebug(index) {
|
|
2867
|
+
this.debugMessages = this.getDebugMessages(index);
|
|
2523
2868
|
this.showDebugMessages = true;
|
|
2524
2869
|
this.cdr.detectChanges();
|
|
2525
2870
|
}
|
|
2871
|
+
/**
|
|
2872
|
+
* Verify whether the current message is an assistant message and that all following messages are assistant ones
|
|
2873
|
+
* Used to keep the "View progress" opened even though the assistant is sending additional messages after the current one
|
|
2874
|
+
* @param messages the list of current messages
|
|
2875
|
+
* @param index the index of the current message
|
|
2876
|
+
* @returns if this messages and the following ones (if any) are the last ones
|
|
2877
|
+
*/
|
|
2878
|
+
isAssistantLastMessages(messages, index) {
|
|
2879
|
+
for (let i = index; i < messages.length; i++) {
|
|
2880
|
+
if (messages[i].role !== 'assistant')
|
|
2881
|
+
return false;
|
|
2882
|
+
}
|
|
2883
|
+
return true;
|
|
2884
|
+
}
|
|
2526
2885
|
}
|
|
2527
2886
|
ChatComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ChatComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2528
|
-
ChatComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: ChatComponent, isStandalone: true, selector: "sq-chat-v3", inputs: { instanceId: "instanceId", query: "query", queryChangeShouldTriggerReload: "queryChangeShouldTriggerReload", protocol: "protocol", messageHandlers: "messageHandlers", automaticScrollToLastResponse: "automaticScrollToLastResponse", chat: "chat", assistantMessageIcon: "assistantMessageIcon", userMessageIcon: "userMessageIcon", connectionErrorMessageIcon: "connectionErrorMessageIcon", searchWarningMessageIcon: "searchWarningMessageIcon" }, outputs: { connection: "connection", loading$: "loading", _config: "config", data: "data", openDocument: "openDocument", openPreview: "openPreview", suggestAction: "suggestAction" }, providers: [
|
|
2887
|
+
ChatComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: ChatComponent, isStandalone: true, selector: "sq-chat-v3", inputs: { instanceId: "instanceId", query: "query", queryChangeShouldTriggerReload: "queryChangeShouldTriggerReload", protocol: "protocol", messageHandlers: "messageHandlers", automaticScrollToLastResponse: "automaticScrollToLastResponse", focusAfterResponse: "focusAfterResponse", chat: "chat", assistantMessageIcon: "assistantMessageIcon", userMessageIcon: "userMessageIcon", connectionErrorMessageIcon: "connectionErrorMessageIcon", searchWarningMessageIcon: "searchWarningMessageIcon" }, outputs: { connection: "connection", loading$: "loading", _config: "config", data: "data", openDocument: "openDocument", openPreview: "openPreview", suggestAction: "suggestAction", chatStarter: "chatStarter" }, providers: [
|
|
2529
2888
|
RestChatService,
|
|
2530
2889
|
WebSocketChatService
|
|
2531
|
-
], queries: [{ propertyName: "loadingTpl", first: true, predicate: ["loadingTpl"], descendants: true }, { propertyName: "reportIssueTpl", first: true, predicate: ["reportIssueTpl"], descendants: true }, { propertyName: "tokenConsumptionTpl", first: true, predicate: ["tokenConsumptionTpl"], descendants: true }, { propertyName: "debugMessagesTpl", first: true, predicate: ["debugMessagesTpl"], descendants: true }], viewQueries: [{ propertyName: "messageList", first: true, predicate: ["messageList"], descendants: true }, { propertyName: "questionInput", first: true, predicate: ["questionInput"], descendants: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<ng-container *ngIf=\"!initializationError\">\n <div *ngIf=\"messages$ | async as messages; else loadingTpl || loadingTplDefault\" class=\"h-100 d-flex flex-column\">\n <!-- Token consumption -->\n <div class=\"ms-1\" *ngIf=\"config?.globalSettings?.displayUserQuotaConsumption || config?.globalSettings?.displayChatTokensConsumption\">\n <ng-container *ngTemplateOutlet=\"tokenConsumptionTpl || defaultTokenConsumptionTpl; context: { $implicit: instanceId }\"></ng-container>\n </div>\n\n <!-- Chat Messages -->\n <ul class=\"list-group list-group-flush overflow-auto flex-grow-1 pe-2 pb-2\" #messageList>\n <ng-container *ngFor=\"let message of messages; let index = index; let last = last\">\n <!-- Regular messages -->\n <li class=\"list-group-item\" [style.--bs-list-group-item-padding-y.rem]=\"'0.6'\" *ngIf=\"message.additionalProperties.display\"\n [class.opacity-50]=\"messageToEdit && messageToEdit < index + 1\">\n <sq-chat-message\n [class.sq-user-message]=\"message.role === 'user'\"\n [class.last-message]=\"last\"\n [message]=\"message\"\n [conversation]=\"messages\"\n [suggestedActions]=\"last ? message.additionalProperties.$suggestedAction : undefined\"\n [assistantMessageIcon]=\"assistantMessageIcon\"\n [userMessageIcon]=\"userMessageIcon\"\n [connectionErrorMessageIcon]=\"connectionErrorMessageIcon\"\n [searchWarningMessageIcon]=\"searchWarningMessageIcon\"\n [streaming]=\"last && (chatService.streaming$ | async)\"\n [canEdit]=\"(loading$ | async) === false && ((chatService.streaming$ | async) === false || !last) && messageToEdit === undefined && message.role === 'user'\"\n [canRegenerate]=\"(loading$ | async) === false && (chatService.streaming$ | async) === false && messageToEdit === undefined && message.role === 'assistant' && last\"\n [canCopy]=\"((chatService.streaming$ | async) === false || !last) && messageToEdit === undefined && message.role !== 'connection-error' && message.role !== 'search-warning'\"\n [canDebug]=\"((chatService.streaming$ | async) === false || !last) && message.role === 'assistant' && isAdmin && message.additionalProperties.$debug\"\n [canLike]=\"((chatService.streaming$ | async) === false || !last) && message.role === 'assistant'\"\n [canDislike]=\"((chatService.streaming$ | async) === false || !last) && message.role === 'assistant'\"\n (edit)=\"editMessage(index)\"\n (copy)=\"copyMessage(index)\"\n (regenerate)=\"regenerateMessage(index)\"\n (openDocument)=\"openOriginalAttachment($event)\"\n (openPreview)=\"openAttachmentPreview($event)\"\n (suggestAction)=\"suggestActionClick($event, index)\"\n (like)=\"onLike(index)\"\n (dislike)=\"onDislike($event, index)\"\n (debug)=\"showDebug($event)\">\n </sq-chat-message>\n </li>\n </ng-container>\n <!-- Loading spinner -->\n <li class=\"list-group-item\" *ngIf=\"(loading$ | async) === true\">\n <ng-container *ngTemplateOutlet=\"loadingTpl || loadingTplDefault\"></ng-container>\n </li>\n </ul>\n\n <!-- Reporting an issue form -->\n <div class=\"issue-report bg-light pt-3 pb-2\" *ngIf=\"showReportIssue\">\n <ng-container *ngTemplateOutlet=\"reportIssueTpl || reportIssueTplDefault; context: { $implicit: messageRelatedIssue, rank: issueRank }\"></ng-container>\n </div>\n\n <!-- User text input -->\n <div class=\"user-input mt-auto\" *ngIf=\"!showReportIssue\">\n <div class=\"py-2\">\n <div [hidden]=\"!isConnected\">\n <ng-container *ngIf=\"enabledUserInput\" [ngTemplateOutlet]=\"inputTpl\"></ng-container>\n </div>\n <!-- Retry button -->\n <button [hidden]=\"isConnected\" class=\"btn mb-4 ast-error ast-btn sq-retry\" (click)=\"retryFetch()\">\n <span>Try again</span>\n <span *ngIf=\"retrialAttempts\" class=\"ms-2 attempts\">{{ retrialAttempts }}</span>\n </button>\n <div class=\"text-end small text-muted px-3\" *ngIf=\"!!config?.globalSettings?.disclaimer\">\n {{ config?.globalSettings?.disclaimer }}\n </div>\n </div>\n </div>\n\n <!-- Floating scroll button -->\n <div *ngIf=\"!isAtBottom && !showReportIssue\" class=\"sq-floating-scroll\" [ngClass]=\"enabledUserInput ? 'sq-floating-scroll--when-user-input' : 'sq-floating-scroll--without-user-input'\">\n <button class=\"btn shadow\" (click)=\"scrollDown()\">\n <i class=\"fas fa-angle-double-down\"></i>\n </button>\n </div>\n </div>\n</ng-container>\n\n<!-- NG TEMPLATES-->\n\n<ng-template #loadingTplDefault>\n <div class=\"spinner-grow text-primary d-block mx-auto my-5\" role=\"status\">\n <span class=\"visually-hidden\">Loading...</span>\n </div>\n</ng-template>\n\n<ng-template #inputTpl>\n <div class=\"px-3 py-1\">\n <div class=\"ast-input-container\">\n <button disabled class=\"btn btn-light\">\n <i class=\"fas fa-search\"></i>\n </button>\n <textarea #questionInput rows=\"1\"\n type=\"text\" class=\"form-control\"\n placeholder=\"Ask something\" autofocus\n [(ngModel)]=\"question\"\n (keyup)=\"onKeyUp($event)\"\n (keydown)=\"calculateHeight($event)\"\n [disabled]=\"(loading$ | async) || (chatService.streaming$ | async)\">\n </textarea>\n <button\n *ngIf=\"!(chatService.streaming$ | async) && !(loading$ | async)\"\n type=\"button\"\n class=\"btn btn-light ms-2\"\n title=\"Send message\"\n (click)=\"submitQuestion()\">\n <i class=\"fas fa-paper-plane\"></i>\n </button>\n <!--<button\n *ngIf=\"(chatService.streaming$ | async)\"\n type=\"button\"\n class=\"btn btn-light ms-2\"\n title=\"Stop generating\"\n (click)=\"terminateFetch()\">\n <i class=\"fas fa-stop\"></i>\n </button>-->\n <button\n *ngIf=\"messageToEdit\"\n type=\"button\"\n class=\"btn btn-light ms-2\"\n title=\"Cancel edition\"\n (click)=\"messageToEdit = undefined; question = ''\">\n <i class=\"fas fa-undo-alt\"></i>\n </button>\n </div>\n </div>\n</ng-template>\n\n<ng-template #reportIssueTplDefault let-message let-rank=\"rank\">\n <div class=\"px-3\">\n <h5>Issue type</h5>\n <select class=\"form-select mb-4\" [(ngModel)]=\"issueType\">\n <option [value]=\"''\">Choose an issue type</option>\n <option *ngFor=\"let type of (issueTypes ?? defaultIssueTypes)\">{{type}}</option>\n </select>\n <h5>Comment (optional)</h5>\n <textarea class=\"form-control\" [(ngModel)]=\"issueComment\" placeholder=\"What was unsatisfying about this response?\"></textarea>\n <div class=\"d-flex flex-row-reverse mt-2\">\n <button class=\"btn btn-primary\" [disabled]=\"!issueType\" (click)=\"sendIssue()\">Send</button>\n <button class=\"btn btn-light\" (click)=\"ignoreIssue()\">Cancel</button>\n </div>\n </div>\n</ng-template>\n\n<ng-template #defaultTokenConsumptionTpl let-instanceId>\n <sq-token-progress-bar\n [instanceId]=\"instanceId\">\n </sq-token-progress-bar>\n</ng-template>\n\n<div class=\"debug-messages\" [class.displayed]=\"showDebugMessages\">\n <button *ngIf=\"showDebugMessages\" class=\"btn btn-light shadow back-btn\" (click)=\"showDebugMessages=false\">\n <i class=\"fas fa-chevron-right\"></i>\n </button>\n <ng-container *ngTemplateOutlet=\"debugMessagesTpl || defaultDebugMessagesTpl; context: { $implicit: debugMessages }\">\n </ng-container>\n</div>\n\n<ng-template #defaultDebugMessagesTpl let-debugMessages>\n <sq-debug-message [data]=\"debugMessages\"></sq-debug-message>\n</ng-template>\n", styles: [".ast-primary{color:var(--ast-primary-color, #005DA7);background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover{background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover:hover{color:var(--ast-primary-color, #005DA7)}.ast-secondary{color:var(--ast-secondary-color, #FF732E);background-color:var(--ast-secondary-bg, #FFF8F1)}.ast-error{background-color:var(--ast-error-bg, rgba(249, 58, 55, .2))}.ast-error:hover{color:var(--ast-error-color, rgba(249, 58, 55, .7))}.ast-btn{border:0;text-align:left;padding-top:.5rem;padding-bottom:.5rem;display:flex;align-items:center}.dark{--ast-primary-bg: #0d0701;--ast-primary-color: #008cd1;--ast-secondary-bg: #00070e;--ast-secondary-color: #ffa258;--ast-input-bg: #070707;--ast-input-color: rgba(222, 218, 218, .75);--ast-muted-color: rgba(222, 218, 218, .75);--ast-saved-chat-hover-background: #262421;--ast-message-table-border-color: #333333;--ast-message-table-tr-bg: #070707;--ast-message-table-tr-border-color: #222222;--ast-reference-icon-color: white;--ast-reference-icon-active-color: black;--ast-reference-passages-color: white;--ast-reference-expanded-hover-bg: #262421;--ast-message-reference-color: black}:host ::ng-deep .reference,:host ::ng-deep .message-content .reference,:host ::ng-deep .attachment .reference{position:relative;bottom:var(--ast-reference-bottom, .3em);font-weight:var(--ast-reference-font-weight, bold);padding:var(--ast-reference-padding, 0 .2em);margin:var(--ast-reference-margin, 0 .1em);border-radius:var(--ast-reference-border-radius, .2em);background-color:var(--ast-reference-background-color, lightblue);color:var(--ast-reference-color, black)}:host ::ng-deep .reference,:host ::ng-deep .message-content .reference{font-size:var(--ast-reference-message-font-size, .7em)}:host ::ng-deep .attachment .reference{font-size:var(--ast-reference-attachment-font-size, 13px)}:host{font-size:.875rem}:host>div>.user-input>div:not(.progress),:host>div>.issue-report>div,:host>div>ul>li{width:var(--ast-chat-container-width, 100%);max-width:100%;margin-left:auto;margin-right:auto}:host>div>ul{padding-top:var(--ast-chat-padding-top, 0);padding-bottom:var(--ast-chat-padding-bottom, 0)}li.attachment>p{display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;-webkit-line-clamp:3}li.attachment.expanded>p{display:block}.progress{--bs-progress-height: 3px}.progress.disabled{--bs-progress-height: 20px;--bs-progress-bar-bg: var(--bs-danger)}.user-input{z-index:1}.user-input ul.list-group{max-height:30vh}.form-control:disabled{background-color:#ededed}a.disabled{cursor:default;opacity:.5}.no-max-height{max-height:initial!important}.sq-floating-scroll{position:absolute;right:50%;text-align:center}.sq-floating-scroll--when-user-input{bottom:75px}.sq-floating-scroll--without-user-input{bottom:15px}.sq-floating-scroll .btn{background-color:#fff}.sq-floating-scroll .btn:hover{background-color:#fff;opacity:.9}.ast-input-container{display:flex;align-items:end;background-color:var(--ast-input-bg, #F8F8F8);border-radius:var(--ast-size-3, .75rem)}.ast-input-container>i{padding-left:var(--ast-size-3, .75rem);color:var(--ast-muted-color, rgba(33, 37, 41, .75))}.ast-input-container textarea{padding-left:var(--ast-size-3, .75rem);padding-right:var(--ast-size-3, .75rem);resize:none}.ast-input-container textarea,.ast-input-container button,.ast-input-container button:hover{background-color:transparent;border:0}.ast-input-container button:hover{color:var(--ast-primary-color, #005DA7)}.ast-input-container button:not(:hover){color:var(--ast-muted-color, rgba(33, 37, 41, .75))}sq-chat-message.sq-user-message{float:var(--ast-user-message-float, none)}sq-token-progress-bar{z-index:10;position:absolute;top:0;right:0}.debug-messages{position:fixed;z-index:999999;right:-60%;top:0;width:60%;height:100%;transition:all .5s ease;background-color:var(--bs-body-bg);overflow:auto}.debug-messages .back-btn{position:fixed;right:0%;transition:all .5s ease}.debug-messages.displayed{right:0}.debug-messages.displayed .back-btn{right:60%}.debug-messages sq-debug-message:first-of-type{display:block;width:100%}.sq-retry{display:flex;margin:auto;font-weight:var(--font-weight-bold, 500)}.sq-retry .attempts{display:flex;border-radius:100%;background:white;height:20px;width:20px;place-content:center;align-items:center}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ChatMessageComponent, selector: "sq-chat-message", inputs: ["message", "conversation", "suggestedActions", "assistantMessageIcon", "userMessageIcon", "connectionErrorMessageIcon", "searchWarningMessageIcon", "streaming", "canEdit", "canRegenerate", "canCopy", "canDebug", "canLike", "canDislike"], outputs: ["openDocument", "openPreview", "suggestAction", "edit", "copy", "regenerate", "like", "dislike", "debug"] }, { kind: "component", type: TokenProgressBarComponent, selector: "sq-token-progress-bar", inputs: ["instanceId"] }, { kind: "component", type: DebugMessageComponent, selector: "sq-debug-message", inputs: ["data", "level", "parentColor"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2890
|
+
], queries: [{ propertyName: "loadingTpl", first: true, predicate: ["loadingTpl"], descendants: true }, { propertyName: "reportTpl", first: true, predicate: ["reportTpl"], descendants: true }, { propertyName: "tokenConsumptionTpl", first: true, predicate: ["tokenConsumptionTpl"], descendants: true }, { propertyName: "debugMessagesTpl", first: true, predicate: ["debugMessagesTpl"], descendants: true }], viewQueries: [{ propertyName: "messageList", first: true, predicate: ["messageList"], descendants: true }, { propertyName: "questionInput", first: true, predicate: ["questionInput"], descendants: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<ng-container *ngIf=\"!initializationError\">\n <div *ngIf=\"messages$ | async as messages; else loadingTpl || loadingTplDefault\" class=\"h-100 d-flex flex-column\">\n <!-- Token consumption -->\n <div class=\"ms-1\" *ngIf=\"config?.globalSettings?.displayUserQuotaConsumption || config?.globalSettings?.displayChatTokensConsumption\">\n <ng-container *ngTemplateOutlet=\"tokenConsumptionTpl || defaultTokenConsumptionTpl; context: { $implicit: instanceId }\"></ng-container>\n </div>\n\n <!-- Chat Messages -->\n <ul class=\"list-group list-group-flush overflow-auto flex-grow-1 pe-2 pb-2\" #messageList>\n <ng-container *ngFor=\"let message of messages; let index = index; let last = last\">\n <!-- Regular messages -->\n <li class=\"list-group-item\"\n *ngIf=\"message.additionalProperties.display\"\n [style.--bs-list-group-item-padding-y.rem]=\"'0.6'\"\n [class.opacity-50]=\"messageToEdit && messageToEdit < index + 1\">\n <sq-chat-message\n [class.sq-user-message]=\"message.role === 'user'\"\n [class.last-message]=\"last\"\n [message]=\"message\"\n [conversation]=\"messages\"\n [suggestedActions]=\"last ? message.additionalProperties.$suggestedAction : undefined\"\n [chatStarters]=\"visibleMessagesCount === 1 ? config.modeSettings.initialization.chatStarters : undefined\"\n [assistantMessageIcon]=\"assistantMessageIcon\"\n [userMessageIcon]=\"userMessageIcon\"\n [connectionErrorMessageIcon]=\"connectionErrorMessageIcon\"\n [searchWarningMessageIcon]=\"searchWarningMessageIcon\"\n [streaming]=\"(chatService.streaming$ | async) && (last || isAssistantLastMessages(messages, index))\"\n [canEdit]=\"(loading$ | async) === false && ((chatService.streaming$ | async) === false || !last) && messageToEdit === undefined && message.role === 'user'\"\n [canCopy]=\"((chatService.streaming$ | async) === false || !last) && messageToEdit === undefined && message.role !== 'connection-error' && message.role !== 'search-warning'\"\n [canLike]=\"((chatService.streaming$ | async) === false || !last) && message.role === 'assistant'\"\n [canDislike]=\"((chatService.streaming$ | async) === false || !last) && message.role === 'assistant'\"\n [canDebug]=\"(((chatService.streaming$ | async) === false && last) || (!last && messages[index+1].role !== 'assistant')) && message.role === 'assistant' && isAdmin && (getDebugMessages(index).length > 0) && config?.defaultValues.debug\"\n [canRegenerate]=\"(loading$ | async) === false && (((chatService.streaming$ | async) === false && last) || (!last && messages[index+1].role !== 'assistant')) && message.role === 'assistant' && messageToEdit === undefined\"\n (edit)=\"editMessage(index)\"\n (copy)=\"copyMessage(index)\"\n (regenerate)=\"regenerateMessage(index)\"\n (openDocument)=\"openOriginalAttachment($event)\"\n (openPreview)=\"openAttachmentPreview($event)\"\n (suggestAction)=\"suggestActionClick($event, index)\"\n (chatStarterClicked)=\"chatStarterClick($event)\"\n (like)=\"onLike($event, index)\"\n (dislike)=\"onDislike($event, index)\"\n (debug)=\"showDebug(index)\">\n </sq-chat-message>\n </li>\n </ng-container>\n <!-- Loading spinner -->\n <li class=\"list-group-item\" *ngIf=\"(loading$ | async) === true\">\n <ng-container *ngTemplateOutlet=\"loadingTpl || loadingTplDefault\"></ng-container>\n </li>\n </ul>\n\n <!-- Reporting a feedback form -->\n <div class=\"issue-report bg-light pt-3 pb-2\" *ngIf=\"showReport\">\n <ng-container *ngTemplateOutlet=\"reportTpl || reportTplDefault; context: { $implicit: messageToReport, rank: reportRank, type: reportType }\"></ng-container>\n </div>\n\n <!-- User text input -->\n <div class=\"user-input mt-auto\" *ngIf=\"!showReport\">\n <div class=\"py-2\">\n <div [hidden]=\"!isConnected\">\n <ng-container *ngIf=\"enabledUserInput\" [ngTemplateOutlet]=\"inputTpl\"></ng-container>\n </div>\n <!-- Retry button -->\n <button [hidden]=\"isConnected\" class=\"btn mb-4 ast-error ast-btn sq-retry\" (click)=\"retryFetch()\">\n <span>Try again</span>\n <span *ngIf=\"retrialAttempts\" class=\"ms-2 attempts\">{{ retrialAttempts }}</span>\n </button>\n <div class=\"text-end small text-muted px-3\" *ngIf=\"!!config?.globalSettings?.disclaimer\">\n {{ config?.globalSettings?.disclaimer }}\n </div>\n </div>\n </div>\n\n <!-- Floating scroll button -->\n <div *ngIf=\"!isAtBottom && !showReport\" class=\"sq-floating-scroll\" [ngClass]=\"enabledUserInput ? 'sq-floating-scroll--when-user-input' : 'sq-floating-scroll--without-user-input'\">\n <button class=\"btn shadow\" (click)=\"scrollDown()\">\n <i class=\"fas fa-angle-double-down\"></i>\n </button>\n </div>\n </div>\n</ng-container>\n\n<!-- NG TEMPLATES-->\n\n<ng-template #loadingTplDefault>\n <div class=\"spinner-grow text-primary d-block mx-auto my-5\" role=\"status\">\n <span class=\"visually-hidden\">Loading...</span>\n </div>\n</ng-template>\n\n<ng-template #inputTpl>\n <div class=\"px-3 py-1\">\n <div class=\"ast-input-container\">\n <button disabled class=\"btn btn-light\">\n <i class=\"fas fa-search\"></i>\n </button>\n <textarea #questionInput rows=\"1\"\n type=\"text\" class=\"form-control\"\n placeholder=\"Ask something\" autofocus\n [(ngModel)]=\"question\"\n (keyup)=\"onKeyUp($event)\"\n (keydown)=\"calculateHeight($event)\"\n [disabled]=\"(loading$ | async) || (chatService.streaming$ | async) || (chatService.stoppingGeneration$ | async)\">\n </textarea>\n <button\n *ngIf=\"!(chatService.streaming$ | async) && !(loading$ | async) && !(chatService.stoppingGeneration$ | async)\"\n type=\"button\"\n class=\"btn btn-light ms-2\"\n sqTooltip=\"Send message\"\n (click)=\"submitQuestion()\">\n <i class=\"fas fa-paper-plane\"></i>\n </button>\n <button\n *ngIf=\"messageToEdit\"\n type=\"button\"\n class=\"btn btn-light ms-2\"\n sqTooltip=\"Cancel edition\"\n (click)=\"messageToEdit = undefined; question = ''\">\n <i class=\"fas fa-undo-alt\"></i>\n </button>\n <span *ngIf=\"(chatService.streaming$ | async) && !(chatService.stoppingGeneration$ | async)\" class=\"processing ms-2\">\n Generating <i class=\"ms-1 fas fa-spinner fa-pulse\"></i>\n </span>\n <span *ngIf=\"(chatService.stoppingGeneration$ | async)\" class=\"processing ms-2\">\n Stopping <i class=\"ms-1 fas fa-spinner fa-pulse\"></i>\n </span>\n <button\n *ngIf=\"(chatService.streaming$ | async) && !(chatService.stoppingGeneration$ | async)\"\n type=\"button\"\n class=\"btn btn-light ms-2\"\n sqTooltip=\"Stop generating\"\n (click)=\"stopGeneration()\">\n <i class=\"fas fa-stop\"></i>\n </button>\n </div>\n </div>\n</ng-template>\n\n<ng-template #reportTplDefault let-message let-rank=\"rank\" let-type=\"type\">\n <div class=\"px-3\">\n <ng-container *ngIf=\"type === 'dislike'\">\n <h5>Issue type</h5>\n <select class=\"form-select mb-4\" [(ngModel)]=\"issueType\">\n <option [value]=\"''\">Choose an issue type</option>\n <option *ngFor=\"let type of (issueTypes ?? defaultIssueTypes)\">{{type}}</option>\n </select>\n <h5>What was unsatisfying about this response? (optional)</h5>\n </ng-container>\n <ng-container *ngIf=\"type === 'like'\">\n <h5>Why did you like this answer? (optional)</h5>\n </ng-container>\n <textarea class=\"form-control\" [(ngModel)]=\"reportComment\" placeholder=\"Write your comment\"></textarea>\n <div class=\"d-flex flex-row-reverse mt-2\">\n <button class=\"btn btn-primary\" [disabled]=\"type === 'dislike' && !issueType\" (click)=\"sendReport()\">Send</button>\n <button class=\"btn btn-light\" (click)=\"ignoreReport()\">Cancel</button>\n </div>\n </div>\n</ng-template>\n\n<ng-template #defaultTokenConsumptionTpl let-instanceId>\n <sq-token-progress-bar\n [instanceId]=\"instanceId\">\n </sq-token-progress-bar>\n</ng-template>\n\n<div class=\"debug-messages\" [class.displayed]=\"showDebugMessages\">\n <button *ngIf=\"showDebugMessages\" class=\"btn btn-light shadow back-btn\" (click)=\"showDebugMessages=false\">\n <i class=\"fas fa-chevron-right\"></i>\n </button>\n <ng-container *ngTemplateOutlet=\"debugMessagesTpl || defaultDebugMessagesTpl; context: { $implicit: debugMessages }\">\n </ng-container>\n</div>\n\n<ng-template #defaultDebugMessagesTpl let-debugMessages>\n <sq-debug-message [data]=\"debugMessages\"></sq-debug-message>\n</ng-template>\n", styles: [".ast-primary{color:var(--ast-primary-color, #005DA7);background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover{background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover:hover{color:var(--ast-primary-color, #005DA7)}.ast-secondary{color:var(--ast-secondary-color, #FF732E);background-color:var(--ast-secondary-bg, #FFF8F1)}.ast-error{background-color:var(--ast-error-bg, rgba(249, 58, 55, .2));color:var(--ast-action-buttons-color, inherit)}.ast-error:hover{color:var(--ast-error-color, rgba(249, 58, 55, .7))}.ast-btn{border:0;text-align:left;padding-top:.5rem;padding-bottom:.5rem;display:flex;align-items:center}.dark{--ast-primary-bg: #0d0701;--ast-primary-color: #008cd1;--ast-secondary-bg: #00070e;--ast-secondary-color: #ffa258;--ast-input-bg: #070707;--ast-input-color: rgba(222, 218, 218, .75);--ast-muted-color: rgba(222, 218, 218, .75);--ast-saved-chat-hover-background: #262421;--ast-message-table-border-color: #333333;--ast-message-table-tr-bg: #070707;--ast-message-table-tr-border-color: #222222;--ast-reference-icon-color: white;--ast-reference-icon-active-color: black;--ast-reference-passages-color: white;--ast-reference-expanded-hover-bg: #262421;--ast-message-reference-color: black;--ast-action-buttons-color: white;--ast-action-buttons-hover-color: #6dbee6}:host ::ng-deep .reference,:host ::ng-deep .message-content .reference,:host ::ng-deep .attachment .reference{position:relative;bottom:var(--ast-reference-bottom, .3em);font-weight:var(--ast-reference-font-weight, bold);padding:var(--ast-reference-padding, 0 .2em);margin:var(--ast-reference-margin, 0 .1em);border-radius:var(--ast-reference-border-radius, .2em);background-color:var(--ast-reference-background-color, lightblue);color:var(--ast-reference-color, black)}:host ::ng-deep .reference,:host ::ng-deep .message-content .reference{font-size:var(--ast-reference-message-font-size, .7em)}:host ::ng-deep .attachment .reference{font-size:var(--ast-reference-attachment-font-size, 13px)}:host{font-size:.875rem}:host>div>.user-input>div:not(.progress),:host>div>.issue-report>div,:host>div>ul>li{width:var(--ast-chat-container-width, 100%);max-width:100%;margin-left:auto;margin-right:auto}:host>div>ul{padding-top:var(--ast-chat-padding-top, 0);padding-bottom:var(--ast-chat-padding-bottom, 0)}li.attachment>p{display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;-webkit-line-clamp:3}li.attachment.expanded>p{display:block}.progress{--bs-progress-height: 3px}.progress.disabled{--bs-progress-height: 20px;--bs-progress-bar-bg: var(--bs-danger)}.user-input{z-index:1}.user-input ul.list-group{max-height:30vh}.form-control:disabled{background-color:#ededed}a.disabled{cursor:default;opacity:.5}.no-max-height{max-height:initial!important}.sq-floating-scroll{position:absolute;right:50%;text-align:center}.sq-floating-scroll--when-user-input{bottom:75px}.sq-floating-scroll--without-user-input{bottom:15px}.sq-floating-scroll .btn{background-color:#fff}.sq-floating-scroll .btn:hover{background-color:#fff;opacity:.9}.ast-input-container{display:flex;align-items:center;background-color:var(--ast-input-bg, #F8F8F8);border-radius:var(--ast-size-3, .75rem)}.ast-input-container>i{padding-left:var(--ast-size-3, .75rem);color:var(--ast-muted-color, rgba(33, 37, 41, .75))}.ast-input-container textarea{padding-left:var(--ast-size-3, .75rem);padding-right:var(--ast-size-3, .75rem);resize:none}.ast-input-container textarea,.ast-input-container button,.ast-input-container button:hover{background-color:transparent;border:0}.ast-input-container button:hover{color:var(--ast-primary-color, #005DA7)}.ast-input-container button:not(:hover){color:var(--ast-muted-color, rgba(33, 37, 41, .75))}.ast-input-container .processing{display:flex;align-items:center;color:var(--ast-secondary-color, #FF732E)}sq-chat-message.sq-user-message{float:var(--ast-user-message-float, none)}sq-token-progress-bar{z-index:10;position:absolute;top:0;right:0}.debug-messages{position:fixed;z-index:999999;right:-60%;top:0;width:60%;height:100%;transition:all .5s ease;background-color:var(--bs-body-bg);overflow:auto}.debug-messages .back-btn{position:fixed;right:0%;transition:all .5s ease}.debug-messages.displayed{right:0}.debug-messages.displayed .back-btn{right:60%}.debug-messages sq-debug-message:first-of-type{display:block;width:100%}.sq-retry{display:flex;margin:auto;font-weight:var(--font-weight-bold, 500)}.sq-retry .attempts{display:flex;border-radius:100%;background:white;height:20px;width:20px;place-content:center;align-items:center}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ChatMessageComponent, selector: "sq-chat-message", inputs: ["message", "conversation", "suggestedActions", "chatStarters", "assistantMessageIcon", "userMessageIcon", "connectionErrorMessageIcon", "searchWarningMessageIcon", "streaming", "canEdit", "canRegenerate", "canCopy", "canDebug", "canLike", "canDislike"], outputs: ["openDocument", "openPreview", "suggestAction", "chatStarterClicked", "edit", "copy", "regenerate", "like", "dislike", "debug"] }, { kind: "component", type: TokenProgressBarComponent, selector: "sq-token-progress-bar", inputs: ["instanceId"] }, { kind: "component", type: DebugMessageComponent, selector: "sq-debug-message", inputs: ["data", "level", "parentColor"] }, { kind: "ngmodule", type: UtilsModule }, { kind: "directive", type: i2$1.TooltipDirective, selector: "[sqTooltip]", inputs: ["sqTooltip", "sqTooltipData", "sqTooltipTemplate", "placement", "fallbackPlacements", "delay", "hoverableTooltip", "tooltipClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2532
2891
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ChatComponent, decorators: [{
|
|
2533
2892
|
type: Component,
|
|
2534
2893
|
args: [{ selector: 'sq-chat-v3', providers: [
|
|
2535
2894
|
RestChatService,
|
|
2536
2895
|
WebSocketChatService
|
|
2537
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [CommonModule, FormsModule, ChatMessageComponent, TokenProgressBarComponent, DebugMessageComponent], template: "<ng-container *ngIf=\"!initializationError\">\n <div *ngIf=\"messages$ | async as messages; else loadingTpl || loadingTplDefault\" class=\"h-100 d-flex flex-column\">\n <!-- Token consumption -->\n <div class=\"ms-1\" *ngIf=\"config?.globalSettings?.displayUserQuotaConsumption || config?.globalSettings?.displayChatTokensConsumption\">\n <ng-container *ngTemplateOutlet=\"tokenConsumptionTpl || defaultTokenConsumptionTpl; context: { $implicit: instanceId }\"></ng-container>\n </div>\n\n <!-- Chat Messages -->\n <ul class=\"list-group list-group-flush overflow-auto flex-grow-1 pe-2 pb-2\" #messageList>\n <ng-container *ngFor=\"let message of messages; let index = index; let last = last\">\n <!-- Regular messages -->\n <li class=\"list-group-item\" [style.--bs-list-group-item-padding-y.rem]=\"'0.6'\" *ngIf=\"message.additionalProperties.display\"\n [class.opacity-50]=\"messageToEdit && messageToEdit < index + 1\">\n <sq-chat-message\n [class.sq-user-message]=\"message.role === 'user'\"\n [class.last-message]=\"last\"\n [message]=\"message\"\n [conversation]=\"messages\"\n [suggestedActions]=\"last ? message.additionalProperties.$suggestedAction : undefined\"\n [assistantMessageIcon]=\"assistantMessageIcon\"\n [userMessageIcon]=\"userMessageIcon\"\n [connectionErrorMessageIcon]=\"connectionErrorMessageIcon\"\n [searchWarningMessageIcon]=\"searchWarningMessageIcon\"\n [streaming]=\"last && (chatService.streaming$ | async)\"\n [canEdit]=\"(loading$ | async) === false && ((chatService.streaming$ | async) === false || !last) && messageToEdit === undefined && message.role === 'user'\"\n [canRegenerate]=\"(loading$ | async) === false && (chatService.streaming$ | async) === false && messageToEdit === undefined && message.role === 'assistant' && last\"\n [canCopy]=\"((chatService.streaming$ | async) === false || !last) && messageToEdit === undefined && message.role !== 'connection-error' && message.role !== 'search-warning'\"\n [canDebug]=\"((chatService.streaming$ | async) === false || !last) && message.role === 'assistant' && isAdmin && message.additionalProperties.$debug\"\n [canLike]=\"((chatService.streaming$ | async) === false || !last) && message.role === 'assistant'\"\n [canDislike]=\"((chatService.streaming$ | async) === false || !last) && message.role === 'assistant'\"\n (edit)=\"editMessage(index)\"\n (copy)=\"copyMessage(index)\"\n (regenerate)=\"regenerateMessage(index)\"\n (openDocument)=\"openOriginalAttachment($event)\"\n (openPreview)=\"openAttachmentPreview($event)\"\n (suggestAction)=\"suggestActionClick($event, index)\"\n (like)=\"onLike(index)\"\n (dislike)=\"onDislike($event, index)\"\n (debug)=\"showDebug($event)\">\n </sq-chat-message>\n </li>\n </ng-container>\n <!-- Loading spinner -->\n <li class=\"list-group-item\" *ngIf=\"(loading$ | async) === true\">\n <ng-container *ngTemplateOutlet=\"loadingTpl || loadingTplDefault\"></ng-container>\n </li>\n </ul>\n\n <!-- Reporting an issue form -->\n <div class=\"issue-report bg-light pt-3 pb-2\" *ngIf=\"showReportIssue\">\n <ng-container *ngTemplateOutlet=\"reportIssueTpl || reportIssueTplDefault; context: { $implicit: messageRelatedIssue, rank: issueRank }\"></ng-container>\n </div>\n\n <!-- User text input -->\n <div class=\"user-input mt-auto\" *ngIf=\"!showReportIssue\">\n <div class=\"py-2\">\n <div [hidden]=\"!isConnected\">\n <ng-container *ngIf=\"enabledUserInput\" [ngTemplateOutlet]=\"inputTpl\"></ng-container>\n </div>\n <!-- Retry button -->\n <button [hidden]=\"isConnected\" class=\"btn mb-4 ast-error ast-btn sq-retry\" (click)=\"retryFetch()\">\n <span>Try again</span>\n <span *ngIf=\"retrialAttempts\" class=\"ms-2 attempts\">{{ retrialAttempts }}</span>\n </button>\n <div class=\"text-end small text-muted px-3\" *ngIf=\"!!config?.globalSettings?.disclaimer\">\n {{ config?.globalSettings?.disclaimer }}\n </div>\n </div>\n </div>\n\n <!-- Floating scroll button -->\n <div *ngIf=\"!isAtBottom && !showReportIssue\" class=\"sq-floating-scroll\" [ngClass]=\"enabledUserInput ? 'sq-floating-scroll--when-user-input' : 'sq-floating-scroll--without-user-input'\">\n <button class=\"btn shadow\" (click)=\"scrollDown()\">\n <i class=\"fas fa-angle-double-down\"></i>\n </button>\n </div>\n </div>\n</ng-container>\n\n<!-- NG TEMPLATES-->\n\n<ng-template #loadingTplDefault>\n <div class=\"spinner-grow text-primary d-block mx-auto my-5\" role=\"status\">\n <span class=\"visually-hidden\">Loading...</span>\n </div>\n</ng-template>\n\n<ng-template #inputTpl>\n <div class=\"px-3 py-1\">\n <div class=\"ast-input-container\">\n <button disabled class=\"btn btn-light\">\n <i class=\"fas fa-search\"></i>\n </button>\n <textarea #questionInput rows=\"1\"\n type=\"text\" class=\"form-control\"\n placeholder=\"Ask something\" autofocus\n [(ngModel)]=\"question\"\n (keyup)=\"onKeyUp($event)\"\n (keydown)=\"calculateHeight($event)\"\n [disabled]=\"(loading$ | async) || (chatService.streaming$ | async)\">\n </textarea>\n <button\n *ngIf=\"!(chatService.streaming$ | async) && !(loading$ | async)\"\n type=\"button\"\n class=\"btn btn-light ms-2\"\n title=\"Send message\"\n (click)=\"submitQuestion()\">\n <i class=\"fas fa-paper-plane\"></i>\n </button>\n <!--<button\n *ngIf=\"(chatService.streaming$ | async)\"\n type=\"button\"\n class=\"btn btn-light ms-2\"\n title=\"Stop generating\"\n (click)=\"terminateFetch()\">\n <i class=\"fas fa-stop\"></i>\n </button>-->\n <button\n *ngIf=\"messageToEdit\"\n type=\"button\"\n class=\"btn btn-light ms-2\"\n title=\"Cancel edition\"\n (click)=\"messageToEdit = undefined; question = ''\">\n <i class=\"fas fa-undo-alt\"></i>\n </button>\n </div>\n </div>\n</ng-template>\n\n<ng-template #reportIssueTplDefault let-message let-rank=\"rank\">\n <div class=\"px-3\">\n <h5>Issue type</h5>\n <select class=\"form-select mb-4\" [(ngModel)]=\"issueType\">\n <option [value]=\"''\">Choose an issue type</option>\n <option *ngFor=\"let type of (issueTypes ?? defaultIssueTypes)\">{{type}}</option>\n </select>\n <h5>Comment (optional)</h5>\n <textarea class=\"form-control\" [(ngModel)]=\"issueComment\" placeholder=\"What was unsatisfying about this response?\"></textarea>\n <div class=\"d-flex flex-row-reverse mt-2\">\n <button class=\"btn btn-primary\" [disabled]=\"!issueType\" (click)=\"sendIssue()\">Send</button>\n <button class=\"btn btn-light\" (click)=\"ignoreIssue()\">Cancel</button>\n </div>\n </div>\n</ng-template>\n\n<ng-template #defaultTokenConsumptionTpl let-instanceId>\n <sq-token-progress-bar\n [instanceId]=\"instanceId\">\n </sq-token-progress-bar>\n</ng-template>\n\n<div class=\"debug-messages\" [class.displayed]=\"showDebugMessages\">\n <button *ngIf=\"showDebugMessages\" class=\"btn btn-light shadow back-btn\" (click)=\"showDebugMessages=false\">\n <i class=\"fas fa-chevron-right\"></i>\n </button>\n <ng-container *ngTemplateOutlet=\"debugMessagesTpl || defaultDebugMessagesTpl; context: { $implicit: debugMessages }\">\n </ng-container>\n</div>\n\n<ng-template #defaultDebugMessagesTpl let-debugMessages>\n <sq-debug-message [data]=\"debugMessages\"></sq-debug-message>\n</ng-template>\n", styles: [".ast-primary{color:var(--ast-primary-color, #005DA7);background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover{background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover:hover{color:var(--ast-primary-color, #005DA7)}.ast-secondary{color:var(--ast-secondary-color, #FF732E);background-color:var(--ast-secondary-bg, #FFF8F1)}.ast-error{background-color:var(--ast-error-bg, rgba(249, 58, 55, .2))}.ast-error:hover{color:var(--ast-error-color, rgba(249, 58, 55, .7))}.ast-btn{border:0;text-align:left;padding-top:.5rem;padding-bottom:.5rem;display:flex;align-items:center}.dark{--ast-primary-bg: #0d0701;--ast-primary-color: #008cd1;--ast-secondary-bg: #00070e;--ast-secondary-color: #ffa258;--ast-input-bg: #070707;--ast-input-color: rgba(222, 218, 218, .75);--ast-muted-color: rgba(222, 218, 218, .75);--ast-saved-chat-hover-background: #262421;--ast-message-table-border-color: #333333;--ast-message-table-tr-bg: #070707;--ast-message-table-tr-border-color: #222222;--ast-reference-icon-color: white;--ast-reference-icon-active-color: black;--ast-reference-passages-color: white;--ast-reference-expanded-hover-bg: #262421;--ast-message-reference-color: black}:host ::ng-deep .reference,:host ::ng-deep .message-content .reference,:host ::ng-deep .attachment .reference{position:relative;bottom:var(--ast-reference-bottom, .3em);font-weight:var(--ast-reference-font-weight, bold);padding:var(--ast-reference-padding, 0 .2em);margin:var(--ast-reference-margin, 0 .1em);border-radius:var(--ast-reference-border-radius, .2em);background-color:var(--ast-reference-background-color, lightblue);color:var(--ast-reference-color, black)}:host ::ng-deep .reference,:host ::ng-deep .message-content .reference{font-size:var(--ast-reference-message-font-size, .7em)}:host ::ng-deep .attachment .reference{font-size:var(--ast-reference-attachment-font-size, 13px)}:host{font-size:.875rem}:host>div>.user-input>div:not(.progress),:host>div>.issue-report>div,:host>div>ul>li{width:var(--ast-chat-container-width, 100%);max-width:100%;margin-left:auto;margin-right:auto}:host>div>ul{padding-top:var(--ast-chat-padding-top, 0);padding-bottom:var(--ast-chat-padding-bottom, 0)}li.attachment>p{display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;-webkit-line-clamp:3}li.attachment.expanded>p{display:block}.progress{--bs-progress-height: 3px}.progress.disabled{--bs-progress-height: 20px;--bs-progress-bar-bg: var(--bs-danger)}.user-input{z-index:1}.user-input ul.list-group{max-height:30vh}.form-control:disabled{background-color:#ededed}a.disabled{cursor:default;opacity:.5}.no-max-height{max-height:initial!important}.sq-floating-scroll{position:absolute;right:50%;text-align:center}.sq-floating-scroll--when-user-input{bottom:75px}.sq-floating-scroll--without-user-input{bottom:15px}.sq-floating-scroll .btn{background-color:#fff}.sq-floating-scroll .btn:hover{background-color:#fff;opacity:.9}.ast-input-container{display:flex;align-items:end;background-color:var(--ast-input-bg, #F8F8F8);border-radius:var(--ast-size-3, .75rem)}.ast-input-container>i{padding-left:var(--ast-size-3, .75rem);color:var(--ast-muted-color, rgba(33, 37, 41, .75))}.ast-input-container textarea{padding-left:var(--ast-size-3, .75rem);padding-right:var(--ast-size-3, .75rem);resize:none}.ast-input-container textarea,.ast-input-container button,.ast-input-container button:hover{background-color:transparent;border:0}.ast-input-container button:hover{color:var(--ast-primary-color, #005DA7)}.ast-input-container button:not(:hover){color:var(--ast-muted-color, rgba(33, 37, 41, .75))}sq-chat-message.sq-user-message{float:var(--ast-user-message-float, none)}sq-token-progress-bar{z-index:10;position:absolute;top:0;right:0}.debug-messages{position:fixed;z-index:999999;right:-60%;top:0;width:60%;height:100%;transition:all .5s ease;background-color:var(--bs-body-bg);overflow:auto}.debug-messages .back-btn{position:fixed;right:0%;transition:all .5s ease}.debug-messages.displayed{right:0}.debug-messages.displayed .back-btn{right:60%}.debug-messages sq-debug-message:first-of-type{display:block;width:100%}.sq-retry{display:flex;margin:auto;font-weight:var(--font-weight-bold, 500)}.sq-retry .attempts{display:flex;border-radius:100%;background:white;height:20px;width:20px;place-content:center;align-items:center}\n"] }]
|
|
2896
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [CommonModule, FormsModule, ChatMessageComponent, TokenProgressBarComponent, DebugMessageComponent, UtilsModule], template: "<ng-container *ngIf=\"!initializationError\">\n <div *ngIf=\"messages$ | async as messages; else loadingTpl || loadingTplDefault\" class=\"h-100 d-flex flex-column\">\n <!-- Token consumption -->\n <div class=\"ms-1\" *ngIf=\"config?.globalSettings?.displayUserQuotaConsumption || config?.globalSettings?.displayChatTokensConsumption\">\n <ng-container *ngTemplateOutlet=\"tokenConsumptionTpl || defaultTokenConsumptionTpl; context: { $implicit: instanceId }\"></ng-container>\n </div>\n\n <!-- Chat Messages -->\n <ul class=\"list-group list-group-flush overflow-auto flex-grow-1 pe-2 pb-2\" #messageList>\n <ng-container *ngFor=\"let message of messages; let index = index; let last = last\">\n <!-- Regular messages -->\n <li class=\"list-group-item\"\n *ngIf=\"message.additionalProperties.display\"\n [style.--bs-list-group-item-padding-y.rem]=\"'0.6'\"\n [class.opacity-50]=\"messageToEdit && messageToEdit < index + 1\">\n <sq-chat-message\n [class.sq-user-message]=\"message.role === 'user'\"\n [class.last-message]=\"last\"\n [message]=\"message\"\n [conversation]=\"messages\"\n [suggestedActions]=\"last ? message.additionalProperties.$suggestedAction : undefined\"\n [chatStarters]=\"visibleMessagesCount === 1 ? config.modeSettings.initialization.chatStarters : undefined\"\n [assistantMessageIcon]=\"assistantMessageIcon\"\n [userMessageIcon]=\"userMessageIcon\"\n [connectionErrorMessageIcon]=\"connectionErrorMessageIcon\"\n [searchWarningMessageIcon]=\"searchWarningMessageIcon\"\n [streaming]=\"(chatService.streaming$ | async) && (last || isAssistantLastMessages(messages, index))\"\n [canEdit]=\"(loading$ | async) === false && ((chatService.streaming$ | async) === false || !last) && messageToEdit === undefined && message.role === 'user'\"\n [canCopy]=\"((chatService.streaming$ | async) === false || !last) && messageToEdit === undefined && message.role !== 'connection-error' && message.role !== 'search-warning'\"\n [canLike]=\"((chatService.streaming$ | async) === false || !last) && message.role === 'assistant'\"\n [canDislike]=\"((chatService.streaming$ | async) === false || !last) && message.role === 'assistant'\"\n [canDebug]=\"(((chatService.streaming$ | async) === false && last) || (!last && messages[index+1].role !== 'assistant')) && message.role === 'assistant' && isAdmin && (getDebugMessages(index).length > 0) && config?.defaultValues.debug\"\n [canRegenerate]=\"(loading$ | async) === false && (((chatService.streaming$ | async) === false && last) || (!last && messages[index+1].role !== 'assistant')) && message.role === 'assistant' && messageToEdit === undefined\"\n (edit)=\"editMessage(index)\"\n (copy)=\"copyMessage(index)\"\n (regenerate)=\"regenerateMessage(index)\"\n (openDocument)=\"openOriginalAttachment($event)\"\n (openPreview)=\"openAttachmentPreview($event)\"\n (suggestAction)=\"suggestActionClick($event, index)\"\n (chatStarterClicked)=\"chatStarterClick($event)\"\n (like)=\"onLike($event, index)\"\n (dislike)=\"onDislike($event, index)\"\n (debug)=\"showDebug(index)\">\n </sq-chat-message>\n </li>\n </ng-container>\n <!-- Loading spinner -->\n <li class=\"list-group-item\" *ngIf=\"(loading$ | async) === true\">\n <ng-container *ngTemplateOutlet=\"loadingTpl || loadingTplDefault\"></ng-container>\n </li>\n </ul>\n\n <!-- Reporting a feedback form -->\n <div class=\"issue-report bg-light pt-3 pb-2\" *ngIf=\"showReport\">\n <ng-container *ngTemplateOutlet=\"reportTpl || reportTplDefault; context: { $implicit: messageToReport, rank: reportRank, type: reportType }\"></ng-container>\n </div>\n\n <!-- User text input -->\n <div class=\"user-input mt-auto\" *ngIf=\"!showReport\">\n <div class=\"py-2\">\n <div [hidden]=\"!isConnected\">\n <ng-container *ngIf=\"enabledUserInput\" [ngTemplateOutlet]=\"inputTpl\"></ng-container>\n </div>\n <!-- Retry button -->\n <button [hidden]=\"isConnected\" class=\"btn mb-4 ast-error ast-btn sq-retry\" (click)=\"retryFetch()\">\n <span>Try again</span>\n <span *ngIf=\"retrialAttempts\" class=\"ms-2 attempts\">{{ retrialAttempts }}</span>\n </button>\n <div class=\"text-end small text-muted px-3\" *ngIf=\"!!config?.globalSettings?.disclaimer\">\n {{ config?.globalSettings?.disclaimer }}\n </div>\n </div>\n </div>\n\n <!-- Floating scroll button -->\n <div *ngIf=\"!isAtBottom && !showReport\" class=\"sq-floating-scroll\" [ngClass]=\"enabledUserInput ? 'sq-floating-scroll--when-user-input' : 'sq-floating-scroll--without-user-input'\">\n <button class=\"btn shadow\" (click)=\"scrollDown()\">\n <i class=\"fas fa-angle-double-down\"></i>\n </button>\n </div>\n </div>\n</ng-container>\n\n<!-- NG TEMPLATES-->\n\n<ng-template #loadingTplDefault>\n <div class=\"spinner-grow text-primary d-block mx-auto my-5\" role=\"status\">\n <span class=\"visually-hidden\">Loading...</span>\n </div>\n</ng-template>\n\n<ng-template #inputTpl>\n <div class=\"px-3 py-1\">\n <div class=\"ast-input-container\">\n <button disabled class=\"btn btn-light\">\n <i class=\"fas fa-search\"></i>\n </button>\n <textarea #questionInput rows=\"1\"\n type=\"text\" class=\"form-control\"\n placeholder=\"Ask something\" autofocus\n [(ngModel)]=\"question\"\n (keyup)=\"onKeyUp($event)\"\n (keydown)=\"calculateHeight($event)\"\n [disabled]=\"(loading$ | async) || (chatService.streaming$ | async) || (chatService.stoppingGeneration$ | async)\">\n </textarea>\n <button\n *ngIf=\"!(chatService.streaming$ | async) && !(loading$ | async) && !(chatService.stoppingGeneration$ | async)\"\n type=\"button\"\n class=\"btn btn-light ms-2\"\n sqTooltip=\"Send message\"\n (click)=\"submitQuestion()\">\n <i class=\"fas fa-paper-plane\"></i>\n </button>\n <button\n *ngIf=\"messageToEdit\"\n type=\"button\"\n class=\"btn btn-light ms-2\"\n sqTooltip=\"Cancel edition\"\n (click)=\"messageToEdit = undefined; question = ''\">\n <i class=\"fas fa-undo-alt\"></i>\n </button>\n <span *ngIf=\"(chatService.streaming$ | async) && !(chatService.stoppingGeneration$ | async)\" class=\"processing ms-2\">\n Generating <i class=\"ms-1 fas fa-spinner fa-pulse\"></i>\n </span>\n <span *ngIf=\"(chatService.stoppingGeneration$ | async)\" class=\"processing ms-2\">\n Stopping <i class=\"ms-1 fas fa-spinner fa-pulse\"></i>\n </span>\n <button\n *ngIf=\"(chatService.streaming$ | async) && !(chatService.stoppingGeneration$ | async)\"\n type=\"button\"\n class=\"btn btn-light ms-2\"\n sqTooltip=\"Stop generating\"\n (click)=\"stopGeneration()\">\n <i class=\"fas fa-stop\"></i>\n </button>\n </div>\n </div>\n</ng-template>\n\n<ng-template #reportTplDefault let-message let-rank=\"rank\" let-type=\"type\">\n <div class=\"px-3\">\n <ng-container *ngIf=\"type === 'dislike'\">\n <h5>Issue type</h5>\n <select class=\"form-select mb-4\" [(ngModel)]=\"issueType\">\n <option [value]=\"''\">Choose an issue type</option>\n <option *ngFor=\"let type of (issueTypes ?? defaultIssueTypes)\">{{type}}</option>\n </select>\n <h5>What was unsatisfying about this response? (optional)</h5>\n </ng-container>\n <ng-container *ngIf=\"type === 'like'\">\n <h5>Why did you like this answer? (optional)</h5>\n </ng-container>\n <textarea class=\"form-control\" [(ngModel)]=\"reportComment\" placeholder=\"Write your comment\"></textarea>\n <div class=\"d-flex flex-row-reverse mt-2\">\n <button class=\"btn btn-primary\" [disabled]=\"type === 'dislike' && !issueType\" (click)=\"sendReport()\">Send</button>\n <button class=\"btn btn-light\" (click)=\"ignoreReport()\">Cancel</button>\n </div>\n </div>\n</ng-template>\n\n<ng-template #defaultTokenConsumptionTpl let-instanceId>\n <sq-token-progress-bar\n [instanceId]=\"instanceId\">\n </sq-token-progress-bar>\n</ng-template>\n\n<div class=\"debug-messages\" [class.displayed]=\"showDebugMessages\">\n <button *ngIf=\"showDebugMessages\" class=\"btn btn-light shadow back-btn\" (click)=\"showDebugMessages=false\">\n <i class=\"fas fa-chevron-right\"></i>\n </button>\n <ng-container *ngTemplateOutlet=\"debugMessagesTpl || defaultDebugMessagesTpl; context: { $implicit: debugMessages }\">\n </ng-container>\n</div>\n\n<ng-template #defaultDebugMessagesTpl let-debugMessages>\n <sq-debug-message [data]=\"debugMessages\"></sq-debug-message>\n</ng-template>\n", styles: [".ast-primary{color:var(--ast-primary-color, #005DA7);background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover{background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover:hover{color:var(--ast-primary-color, #005DA7)}.ast-secondary{color:var(--ast-secondary-color, #FF732E);background-color:var(--ast-secondary-bg, #FFF8F1)}.ast-error{background-color:var(--ast-error-bg, rgba(249, 58, 55, .2));color:var(--ast-action-buttons-color, inherit)}.ast-error:hover{color:var(--ast-error-color, rgba(249, 58, 55, .7))}.ast-btn{border:0;text-align:left;padding-top:.5rem;padding-bottom:.5rem;display:flex;align-items:center}.dark{--ast-primary-bg: #0d0701;--ast-primary-color: #008cd1;--ast-secondary-bg: #00070e;--ast-secondary-color: #ffa258;--ast-input-bg: #070707;--ast-input-color: rgba(222, 218, 218, .75);--ast-muted-color: rgba(222, 218, 218, .75);--ast-saved-chat-hover-background: #262421;--ast-message-table-border-color: #333333;--ast-message-table-tr-bg: #070707;--ast-message-table-tr-border-color: #222222;--ast-reference-icon-color: white;--ast-reference-icon-active-color: black;--ast-reference-passages-color: white;--ast-reference-expanded-hover-bg: #262421;--ast-message-reference-color: black;--ast-action-buttons-color: white;--ast-action-buttons-hover-color: #6dbee6}:host ::ng-deep .reference,:host ::ng-deep .message-content .reference,:host ::ng-deep .attachment .reference{position:relative;bottom:var(--ast-reference-bottom, .3em);font-weight:var(--ast-reference-font-weight, bold);padding:var(--ast-reference-padding, 0 .2em);margin:var(--ast-reference-margin, 0 .1em);border-radius:var(--ast-reference-border-radius, .2em);background-color:var(--ast-reference-background-color, lightblue);color:var(--ast-reference-color, black)}:host ::ng-deep .reference,:host ::ng-deep .message-content .reference{font-size:var(--ast-reference-message-font-size, .7em)}:host ::ng-deep .attachment .reference{font-size:var(--ast-reference-attachment-font-size, 13px)}:host{font-size:.875rem}:host>div>.user-input>div:not(.progress),:host>div>.issue-report>div,:host>div>ul>li{width:var(--ast-chat-container-width, 100%);max-width:100%;margin-left:auto;margin-right:auto}:host>div>ul{padding-top:var(--ast-chat-padding-top, 0);padding-bottom:var(--ast-chat-padding-bottom, 0)}li.attachment>p{display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;-webkit-line-clamp:3}li.attachment.expanded>p{display:block}.progress{--bs-progress-height: 3px}.progress.disabled{--bs-progress-height: 20px;--bs-progress-bar-bg: var(--bs-danger)}.user-input{z-index:1}.user-input ul.list-group{max-height:30vh}.form-control:disabled{background-color:#ededed}a.disabled{cursor:default;opacity:.5}.no-max-height{max-height:initial!important}.sq-floating-scroll{position:absolute;right:50%;text-align:center}.sq-floating-scroll--when-user-input{bottom:75px}.sq-floating-scroll--without-user-input{bottom:15px}.sq-floating-scroll .btn{background-color:#fff}.sq-floating-scroll .btn:hover{background-color:#fff;opacity:.9}.ast-input-container{display:flex;align-items:center;background-color:var(--ast-input-bg, #F8F8F8);border-radius:var(--ast-size-3, .75rem)}.ast-input-container>i{padding-left:var(--ast-size-3, .75rem);color:var(--ast-muted-color, rgba(33, 37, 41, .75))}.ast-input-container textarea{padding-left:var(--ast-size-3, .75rem);padding-right:var(--ast-size-3, .75rem);resize:none}.ast-input-container textarea,.ast-input-container button,.ast-input-container button:hover{background-color:transparent;border:0}.ast-input-container button:hover{color:var(--ast-primary-color, #005DA7)}.ast-input-container button:not(:hover){color:var(--ast-muted-color, rgba(33, 37, 41, .75))}.ast-input-container .processing{display:flex;align-items:center;color:var(--ast-secondary-color, #FF732E)}sq-chat-message.sq-user-message{float:var(--ast-user-message-float, none)}sq-token-progress-bar{z-index:10;position:absolute;top:0;right:0}.debug-messages{position:fixed;z-index:999999;right:-60%;top:0;width:60%;height:100%;transition:all .5s ease;background-color:var(--bs-body-bg);overflow:auto}.debug-messages .back-btn{position:fixed;right:0%;transition:all .5s ease}.debug-messages.displayed{right:0}.debug-messages.displayed .back-btn{right:60%}.debug-messages sq-debug-message:first-of-type{display:block;width:100%}.sq-retry{display:flex;margin:auto;font-weight:var(--font-weight-bold, 500)}.sq-retry .attempts{display:flex;border-radius:100%;background:white;height:20px;width:20px;place-content:center;align-items:center}\n"] }]
|
|
2538
2897
|
}], ctorParameters: function () { return []; }, propDecorators: { instanceId: [{
|
|
2539
2898
|
type: Input
|
|
2540
2899
|
}], query: [{
|
|
@@ -2547,6 +2906,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImpor
|
|
|
2547
2906
|
type: Input
|
|
2548
2907
|
}], automaticScrollToLastResponse: [{
|
|
2549
2908
|
type: Input
|
|
2909
|
+
}], focusAfterResponse: [{
|
|
2910
|
+
type: Input
|
|
2550
2911
|
}], chat: [{
|
|
2551
2912
|
type: Input
|
|
2552
2913
|
}], assistantMessageIcon: [{
|
|
@@ -2573,6 +2934,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImpor
|
|
|
2573
2934
|
type: Output
|
|
2574
2935
|
}], suggestAction: [{
|
|
2575
2936
|
type: Output
|
|
2937
|
+
}], chatStarter: [{
|
|
2938
|
+
type: Output
|
|
2576
2939
|
}], messageList: [{
|
|
2577
2940
|
type: ViewChild,
|
|
2578
2941
|
args: ['messageList']
|
|
@@ -2582,9 +2945,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImpor
|
|
|
2582
2945
|
}], loadingTpl: [{
|
|
2583
2946
|
type: ContentChild,
|
|
2584
2947
|
args: ['loadingTpl']
|
|
2585
|
-
}],
|
|
2948
|
+
}], reportTpl: [{
|
|
2586
2949
|
type: ContentChild,
|
|
2587
|
-
args: ['
|
|
2950
|
+
args: ['reportTpl']
|
|
2588
2951
|
}], tokenConsumptionTpl: [{
|
|
2589
2952
|
type: ContentChild,
|
|
2590
2953
|
args: ['tokenConsumptionTpl']
|
|
@@ -2622,6 +2985,9 @@ class SavedChatsComponent {
|
|
|
2622
2985
|
}));
|
|
2623
2986
|
}
|
|
2624
2987
|
onLoad(savedChat) {
|
|
2988
|
+
if (!!this.chatService.streaming$.value || !!this.chatService.stoppingGeneration$.value) {
|
|
2989
|
+
return;
|
|
2990
|
+
}
|
|
2625
2991
|
this.chatService.setSavedChatId(savedChat.id);
|
|
2626
2992
|
this.chatService.generateChatId(savedChat.id);
|
|
2627
2993
|
this.chatService.loadSavedChat$.next(savedChat);
|
|
@@ -2629,7 +2995,11 @@ class SavedChatsComponent {
|
|
|
2629
2995
|
this.chatService.listSavedChat();
|
|
2630
2996
|
this.load.emit(savedChat);
|
|
2631
2997
|
}
|
|
2632
|
-
onRename(savedChat) {
|
|
2998
|
+
onRename(event, savedChat) {
|
|
2999
|
+
event.stopPropagation();
|
|
3000
|
+
if (!!this.chatService.streaming$.value || !!this.chatService.stoppingGeneration$.value) {
|
|
3001
|
+
return;
|
|
3002
|
+
}
|
|
2633
3003
|
const model = {
|
|
2634
3004
|
title: 'Rename saved discussion',
|
|
2635
3005
|
message: `Please enter a new name for the discussion "${savedChat.title}".`,
|
|
@@ -2655,7 +3025,11 @@ class SavedChatsComponent {
|
|
|
2655
3025
|
}
|
|
2656
3026
|
});
|
|
2657
3027
|
}
|
|
2658
|
-
onDelete(savedChat) {
|
|
3028
|
+
onDelete(event, savedChat) {
|
|
3029
|
+
event.stopPropagation();
|
|
3030
|
+
if (!!this.chatService.streaming$.value || !!this.chatService.stoppingGeneration$.value) {
|
|
3031
|
+
return;
|
|
3032
|
+
}
|
|
2659
3033
|
this.modalService
|
|
2660
3034
|
.confirm({
|
|
2661
3035
|
title: "Delete saved discussion",
|
|
@@ -2732,10 +3106,10 @@ class SavedChatsComponent {
|
|
|
2732
3106
|
}
|
|
2733
3107
|
}
|
|
2734
3108
|
SavedChatsComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: SavedChatsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2735
|
-
SavedChatsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: SavedChatsComponent, isStandalone: true, selector: "sq-saved-chats-v3", inputs: { instanceId: "instanceId" }, outputs: { load: "load", delete: "delete" }, ngImport: i0, template: "<ng-container *ngIf=\"(chatService.chatConfig$ | async)?.savedChatSettings.display\">\n <div *ngFor=\"let group of (groupedSavedChats$ | async)\" class=\"saved-chats\">\n <div class=\"saved-chat-date\">{{group.key}}</div>\n <div *ngFor=\"let savedChat of group.value\"
|
|
3109
|
+
SavedChatsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: SavedChatsComponent, isStandalone: true, selector: "sq-saved-chats-v3", inputs: { instanceId: "instanceId" }, outputs: { load: "load", delete: "delete" }, ngImport: i0, template: "<ng-container *ngIf=\"(chatService.chatConfig$ | async)?.savedChatSettings.display\">\n <div *ngFor=\"let group of (groupedSavedChats$ | async)\" class=\"saved-chats\">\n <div class=\"saved-chat-date\">{{group.key}}</div>\n <div *ngFor=\"let savedChat of group.value\"\n (click)=\"onLoad(savedChat)\"\n class=\"saved-chat p-2\"\n [class.forbidden]=\"(chatService.streaming$ | async) || (chatService.stoppingGeneration$ | async)\"\n [class.active]=\"chatService.savedChatId === savedChat.id\">\n <span class=\"title me-1\">{{savedChat.title}}</span>\n <i class=\"saved-chat-actions fas fa-pen mx-1\" [sqTooltip]=\"'Rename'\"\n (click)=\"onRename($event, savedChat)\"></i>\n <i class=\"saved-chat-actions fas fa-trash ms-1\" [sqTooltip]=\"'Delete'\"\n (click)=\"onDelete($event, savedChat)\"></i>\n </div>\n </div>\n</ng-container>\n", styles: [".ast-primary{color:var(--ast-primary-color, #005DA7);background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover{background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover:hover{color:var(--ast-primary-color, #005DA7)}.ast-secondary{color:var(--ast-secondary-color, #FF732E);background-color:var(--ast-secondary-bg, #FFF8F1)}.ast-error{background-color:var(--ast-error-bg, rgba(249, 58, 55, .2));color:var(--ast-action-buttons-color, inherit)}.ast-error:hover{color:var(--ast-error-color, rgba(249, 58, 55, .7))}.ast-btn{border:0;text-align:left;padding-top:.5rem;padding-bottom:.5rem;display:flex;align-items:center}.dark{--ast-primary-bg: #0d0701;--ast-primary-color: #008cd1;--ast-secondary-bg: #00070e;--ast-secondary-color: #ffa258;--ast-input-bg: #070707;--ast-input-color: rgba(222, 218, 218, .75);--ast-muted-color: rgba(222, 218, 218, .75);--ast-saved-chat-hover-background: #262421;--ast-message-table-border-color: #333333;--ast-message-table-tr-bg: #070707;--ast-message-table-tr-border-color: #222222;--ast-reference-icon-color: white;--ast-reference-icon-active-color: black;--ast-reference-passages-color: white;--ast-reference-expanded-hover-bg: #262421;--ast-message-reference-color: black;--ast-action-buttons-color: white;--ast-action-buttons-hover-color: #6dbee6}.saved-chats .saved-chat-date{font-weight:500;color:#a9a9a9;margin-top:.5rem}.saved-chats .saved-chat{display:flex;align-items:center;cursor:pointer;margin-left:.25rem}.saved-chats .saved-chat span{flex-grow:1;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.saved-chats .saved-chat .saved-chat-actions{display:none}.saved-chats .saved-chat:hover,.saved-chats .saved-chat.active{color:var(--ast-secondary-color, #FF732E);background-color:var(--ast-saved-chat-hover-background, #FFF8F1)}.saved-chats .saved-chat:hover .saved-chat-actions{display:block}.saved-chats .saved-chat.forbidden{cursor:not-allowed}.saved-chats .title{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: ModalModule }, { kind: "ngmodule", type: UtilsModule }, { kind: "directive", type: i2$1.TooltipDirective, selector: "[sqTooltip]", inputs: ["sqTooltip", "sqTooltipData", "sqTooltipTemplate", "placement", "fallbackPlacements", "delay", "hoverableTooltip", "tooltipClass"] }] });
|
|
2736
3110
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: SavedChatsComponent, decorators: [{
|
|
2737
3111
|
type: Component,
|
|
2738
|
-
args: [{ selector: 'sq-saved-chats-v3', standalone: true, imports: [CommonModule, ModalModule, UtilsModule], template: "<ng-container *ngIf=\"(chatService.chatConfig$ | async)?.savedChatSettings.display\">\n <div *ngFor=\"let group of (groupedSavedChats$ | async)\" class=\"saved-chats\">\n <div class=\"saved-chat-date\">{{group.key}}</div>\n <div *ngFor=\"let savedChat of group.value\"
|
|
3112
|
+
args: [{ selector: 'sq-saved-chats-v3', standalone: true, imports: [CommonModule, ModalModule, UtilsModule], template: "<ng-container *ngIf=\"(chatService.chatConfig$ | async)?.savedChatSettings.display\">\n <div *ngFor=\"let group of (groupedSavedChats$ | async)\" class=\"saved-chats\">\n <div class=\"saved-chat-date\">{{group.key}}</div>\n <div *ngFor=\"let savedChat of group.value\"\n (click)=\"onLoad(savedChat)\"\n class=\"saved-chat p-2\"\n [class.forbidden]=\"(chatService.streaming$ | async) || (chatService.stoppingGeneration$ | async)\"\n [class.active]=\"chatService.savedChatId === savedChat.id\">\n <span class=\"title me-1\">{{savedChat.title}}</span>\n <i class=\"saved-chat-actions fas fa-pen mx-1\" [sqTooltip]=\"'Rename'\"\n (click)=\"onRename($event, savedChat)\"></i>\n <i class=\"saved-chat-actions fas fa-trash ms-1\" [sqTooltip]=\"'Delete'\"\n (click)=\"onDelete($event, savedChat)\"></i>\n </div>\n </div>\n</ng-container>\n", styles: [".ast-primary{color:var(--ast-primary-color, #005DA7);background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover{background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover:hover{color:var(--ast-primary-color, #005DA7)}.ast-secondary{color:var(--ast-secondary-color, #FF732E);background-color:var(--ast-secondary-bg, #FFF8F1)}.ast-error{background-color:var(--ast-error-bg, rgba(249, 58, 55, .2));color:var(--ast-action-buttons-color, inherit)}.ast-error:hover{color:var(--ast-error-color, rgba(249, 58, 55, .7))}.ast-btn{border:0;text-align:left;padding-top:.5rem;padding-bottom:.5rem;display:flex;align-items:center}.dark{--ast-primary-bg: #0d0701;--ast-primary-color: #008cd1;--ast-secondary-bg: #00070e;--ast-secondary-color: #ffa258;--ast-input-bg: #070707;--ast-input-color: rgba(222, 218, 218, .75);--ast-muted-color: rgba(222, 218, 218, .75);--ast-saved-chat-hover-background: #262421;--ast-message-table-border-color: #333333;--ast-message-table-tr-bg: #070707;--ast-message-table-tr-border-color: #222222;--ast-reference-icon-color: white;--ast-reference-icon-active-color: black;--ast-reference-passages-color: white;--ast-reference-expanded-hover-bg: #262421;--ast-message-reference-color: black;--ast-action-buttons-color: white;--ast-action-buttons-hover-color: #6dbee6}.saved-chats .saved-chat-date{font-weight:500;color:#a9a9a9;margin-top:.5rem}.saved-chats .saved-chat{display:flex;align-items:center;cursor:pointer;margin-left:.25rem}.saved-chats .saved-chat span{flex-grow:1;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.saved-chats .saved-chat .saved-chat-actions{display:none}.saved-chats .saved-chat:hover,.saved-chats .saved-chat.active{color:var(--ast-secondary-color, #FF732E);background-color:var(--ast-saved-chat-hover-background, #FFF8F1)}.saved-chats .saved-chat:hover .saved-chat-actions{display:block}.saved-chats .saved-chat.forbidden{cursor:not-allowed}.saved-chats .title{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n"] }]
|
|
2739
3113
|
}], propDecorators: { instanceId: [{
|
|
2740
3114
|
type: Input
|
|
2741
3115
|
}], load: [{
|