@sinequa/assistant 3.6.2 → 3.7.1
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 +137 -18
- 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 +189 -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 +361 -62
- package/esm2020/chat/chat.service.mjs +49 -3
- package/esm2020/chat/debug-message/debug-message.component.mjs +3 -3
- package/esm2020/chat/instance-manager.service.mjs +2 -2
- 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 +18 -4
- package/esm2020/chat/websocket-chat.service.mjs +191 -99
- package/fesm2015/sinequa-assistant-chat.mjs +660 -182
- package/fesm2015/sinequa-assistant-chat.mjs.map +1 -1
- package/fesm2020/sinequa-assistant-chat.mjs +649 -179
- 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';
|
|
@@ -66,7 +66,7 @@ class InstanceManagerService {
|
|
|
66
66
|
*/
|
|
67
67
|
getInstance(key) {
|
|
68
68
|
if (!this.checkInstance(key)) {
|
|
69
|
-
throw new Error(`No
|
|
69
|
+
throw new Error(`No assistant instance found for the given key : '${key}'`);
|
|
70
70
|
}
|
|
71
71
|
return this._serviceInstances.get(key);
|
|
72
72
|
}
|
|
@@ -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
|
});
|
|
@@ -241,11 +242,21 @@ const defaultValuesSchema = z.object({
|
|
|
241
242
|
systemPrompt: z.string(),
|
|
242
243
|
userPrompt: z.string()
|
|
243
244
|
});
|
|
245
|
+
// Define the Zod representation for the chatStarter object
|
|
246
|
+
const chatStarterSchema = z.object({
|
|
247
|
+
text: z.string()
|
|
248
|
+
});
|
|
249
|
+
// Define the Zod representation for the action object
|
|
250
|
+
const actionSchema = z.object({
|
|
251
|
+
forcedWorkflow: z.string(),
|
|
252
|
+
forcedWorkflowProperties: z.record(z.unknown()).optional() // forcedWorkflowProperties must be an object (Map equivalent)
|
|
253
|
+
});
|
|
244
254
|
// Define the Zod representation for the modeSettings object
|
|
245
255
|
const initializationSchema = z.object({
|
|
246
256
|
event: z.enum(['Query', 'Prompt']),
|
|
247
257
|
forcedWorkflow: z.string().optional(),
|
|
248
|
-
displayUserQuery: z.boolean().optional(),
|
|
258
|
+
displayUserQuery: z.boolean().optional(),
|
|
259
|
+
chatStarters: z.array(chatStarterSchema).optional(), // Optional for event 'Prompt'
|
|
249
260
|
}).refine(data => ((data.event === "Query") ? (!!data.forcedWorkflow && data.displayUserQuery !== undefined && data.displayUserQuery !== null) : true), {
|
|
250
261
|
message: "The 'forcedWorkflow' and 'displayUserQuery' properties must be provided when the initialization's event is 'Query'.",
|
|
251
262
|
});
|
|
@@ -253,7 +264,10 @@ const modeSettingsSchema = z.object({
|
|
|
253
264
|
enabledUserInput: z.boolean(),
|
|
254
265
|
displayUserPrompt: z.boolean(),
|
|
255
266
|
sendUserPrompt: z.boolean(),
|
|
256
|
-
initialization: initializationSchema
|
|
267
|
+
initialization: initializationSchema,
|
|
268
|
+
actions: z.record(actionSchema).optional()
|
|
269
|
+
}).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')); }, {
|
|
270
|
+
message: "Incompatible configuration for using chatStarters ('sendUserPrompt' and 'displayUserPrompt' must be false, 'initialization.event' must not be 'Query')",
|
|
257
271
|
});
|
|
258
272
|
// Define the Zod representation for the savedChatSettings object
|
|
259
273
|
const savedChatSettingsSchema = z.object({
|
|
@@ -293,7 +307,11 @@ class ChatService {
|
|
|
293
307
|
this.initConfig$ = new BehaviorSubject(false);
|
|
294
308
|
/** Global configuration of the chat. */
|
|
295
309
|
this.chatConfig$ = new BehaviorSubject(undefined);
|
|
296
|
-
/**
|
|
310
|
+
/**
|
|
311
|
+
* 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).
|
|
312
|
+
* This is used to prevent multiple fetches at the same time.
|
|
313
|
+
* 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.
|
|
314
|
+
*/
|
|
297
315
|
this.streaming$ = new BehaviorSubject(false);
|
|
298
316
|
/** List of saved chats. */
|
|
299
317
|
this.savedChats$ = new BehaviorSubject([]);
|
|
@@ -307,6 +325,8 @@ class ChatService {
|
|
|
307
325
|
this.chatUsageMetrics$ = new BehaviorSubject(undefined);
|
|
308
326
|
/** Emit the calculated chat's token consumption based on the chat usage metrics. */
|
|
309
327
|
this.chatTokenConsumption$ = new BehaviorSubject(undefined);
|
|
328
|
+
/** Emit true if "CancelTasks" is ongoing. */
|
|
329
|
+
this.stoppingGeneration$ = new BehaviorSubject(false);
|
|
310
330
|
this.userSettingsService = inject(UserSettingsWebService);
|
|
311
331
|
this.notificationsService = inject(NotificationsService);
|
|
312
332
|
this.auditService = inject(AuditWebService);
|
|
@@ -434,7 +454,7 @@ class ChatService {
|
|
|
434
454
|
}
|
|
435
455
|
}
|
|
436
456
|
catch (error) {
|
|
437
|
-
this.notificationsService.error(`Missing valid configuration for the assistant instance '${key}'
|
|
457
|
+
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
458
|
throw new Error(`Missing valid configuration for the assistant instance '${key}' . \n ${JSON.stringify(error.issues, null, 2)}`);
|
|
439
459
|
}
|
|
440
460
|
}
|
|
@@ -475,6 +495,7 @@ class ChatService {
|
|
|
475
495
|
const consumptionPercentage = Math.round((quota.tokenCount * 100 / quota.periodTokens) * 100) / 100;
|
|
476
496
|
this.userTokenConsumption$.next({ percentage: consumptionPercentage, nextResetDate });
|
|
477
497
|
if (quota.maxQuotaReached) {
|
|
498
|
+
this.generateAuditEvent('quota.exceeded', {});
|
|
478
499
|
const msg = `Sorry, you have exceeded the allowed quota. Please retry starting from ${nextResetDate}.`;
|
|
479
500
|
this.notificationsService.error(msg);
|
|
480
501
|
if (propagateError)
|
|
@@ -532,6 +553,45 @@ class ChatService {
|
|
|
532
553
|
};
|
|
533
554
|
this.auditService.notify(audit);
|
|
534
555
|
}
|
|
556
|
+
/**
|
|
557
|
+
* Traverse the array from the end and track the first 'assistant' message among the last group of "assistant" messages where display is true
|
|
558
|
+
* @param array The array of ChatMessage to traverse
|
|
559
|
+
* @returns The index of the first visible assistant message among the last group of "assistant" messages in the array
|
|
560
|
+
*/
|
|
561
|
+
firstVisibleAssistantMessageIndex(array) {
|
|
562
|
+
if (!array) {
|
|
563
|
+
return -1;
|
|
564
|
+
}
|
|
565
|
+
let index = array.length - 1;
|
|
566
|
+
let firstVisibleAssistantMessageIndex = -1;
|
|
567
|
+
while (index >= 0 && array[index].role === 'assistant') {
|
|
568
|
+
if (array[index].additionalProperties.display === true) {
|
|
569
|
+
firstVisibleAssistantMessageIndex = index;
|
|
570
|
+
}
|
|
571
|
+
index--;
|
|
572
|
+
}
|
|
573
|
+
return firstVisibleAssistantMessageIndex;
|
|
574
|
+
}
|
|
575
|
+
/**
|
|
576
|
+
* Traverse the array from the end and pick the last 'assistant' message among the last group of "assistant" messages where display is true
|
|
577
|
+
* @param array The array of ChatMessage to traverse
|
|
578
|
+
* @returns The index of the last visible assistant message among the last group of "assistant" messages in the array
|
|
579
|
+
*/
|
|
580
|
+
lastVisibleAssistantMessageIndex(array) {
|
|
581
|
+
if (!array) {
|
|
582
|
+
return -1;
|
|
583
|
+
}
|
|
584
|
+
let index = array.length - 1;
|
|
585
|
+
let lastVisibleAssistantMessageIndex = -1;
|
|
586
|
+
while (index >= 0 && array[index].role === 'assistant') {
|
|
587
|
+
if (array[index].additionalProperties.display === true) {
|
|
588
|
+
lastVisibleAssistantMessageIndex = index;
|
|
589
|
+
break;
|
|
590
|
+
}
|
|
591
|
+
index--;
|
|
592
|
+
}
|
|
593
|
+
return lastVisibleAssistantMessageIndex;
|
|
594
|
+
}
|
|
535
595
|
/**
|
|
536
596
|
* Format a date string in UTC to a local date string
|
|
537
597
|
* @param value Date string in UTC to format
|
|
@@ -562,10 +622,8 @@ class WebSocketChatService extends ChatService {
|
|
|
562
622
|
this._messageHandlers = new Map();
|
|
563
623
|
this._actionMap = new Map();
|
|
564
624
|
this._progress = undefined;
|
|
565
|
-
this._content = "";
|
|
566
625
|
this._attachments = [];
|
|
567
|
-
this.
|
|
568
|
-
this._debugMessages = undefined;
|
|
626
|
+
this._debugMessages = [];
|
|
569
627
|
this.signalRService = inject(SignalRWebService);
|
|
570
628
|
this.authenticationService = inject(AuthenticationService);
|
|
571
629
|
}
|
|
@@ -615,38 +673,38 @@ class WebSocketChatService extends ChatService {
|
|
|
615
673
|
}
|
|
616
674
|
}
|
|
617
675
|
listModels() {
|
|
618
|
-
const modelsSubject = new Subject();
|
|
676
|
+
const modelsSubject$ = new Subject();
|
|
619
677
|
this.connection.on('ListModels', (res) => {
|
|
620
678
|
var _a;
|
|
621
679
|
this.models = (_a = res.models) === null || _a === void 0 ? void 0 : _a.filter(model => !!model.enable);
|
|
622
|
-
modelsSubject
|
|
623
|
-
modelsSubject
|
|
680
|
+
modelsSubject$.next(this.models);
|
|
681
|
+
modelsSubject$.complete();
|
|
624
682
|
});
|
|
625
683
|
// Send the request to get the list of models
|
|
626
684
|
this.connection.invoke('ListModels', { debug: this.chatConfig$.value.defaultValues.debug })
|
|
627
685
|
.catch(error => {
|
|
628
686
|
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
|
|
687
|
+
modelsSubject$.error(new Error(error));
|
|
688
|
+
return Promise.resolve(); // Return a resolved promise to handle the error and prevent unhandled promise rejection when no further error handling exists downstream
|
|
631
689
|
});
|
|
632
|
-
return modelsSubject
|
|
690
|
+
return modelsSubject$.asObservable();
|
|
633
691
|
}
|
|
634
692
|
listFunctions() {
|
|
635
|
-
const functionsSubject = new Subject();
|
|
693
|
+
const functionsSubject$ = new Subject();
|
|
636
694
|
this.connection.on('ListFunctions', (res) => {
|
|
637
695
|
var _a;
|
|
638
696
|
this.functions = (_a = res.functions) === null || _a === void 0 ? void 0 : _a.filter(func => func.enabled);
|
|
639
|
-
functionsSubject
|
|
640
|
-
functionsSubject
|
|
697
|
+
functionsSubject$.next(this.functions);
|
|
698
|
+
functionsSubject$.complete();
|
|
641
699
|
});
|
|
642
700
|
// Send the request to get the list of functions
|
|
643
701
|
this.connection.invoke('ListFunctions', { debug: this.chatConfig$.value.defaultValues.debug })
|
|
644
702
|
.catch(error => {
|
|
645
703
|
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
|
|
704
|
+
functionsSubject$.error(new Error(error));
|
|
705
|
+
return Promise.resolve(); // Return a resolved promise to handle the error and prevent unhandled promise rejection when no further error handling exists downstream
|
|
648
706
|
});
|
|
649
|
-
return functionsSubject
|
|
707
|
+
return functionsSubject$.asObservable();
|
|
650
708
|
}
|
|
651
709
|
fetch(messages, query) {
|
|
652
710
|
var _a;
|
|
@@ -668,7 +726,8 @@ class WebSocketChatService extends ChatService {
|
|
|
668
726
|
data.instanceId = this.chatInstanceId;
|
|
669
727
|
data.savedChatId = this.savedChatId;
|
|
670
728
|
}
|
|
671
|
-
|
|
729
|
+
// Initialize the response with an empty assistant message
|
|
730
|
+
this._response = [{ role: "assistant", content: "", additionalProperties: { display: true } }]; // here display: true is needed in order to be able to show the progress
|
|
672
731
|
// Create a Subject to signal completion
|
|
673
732
|
const completion$ = new Subject();
|
|
674
733
|
// 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 +735,19 @@ class WebSocketChatService extends ChatService {
|
|
|
676
735
|
.from(this._messageHandlers.entries())
|
|
677
736
|
.filter(([eventName, eventHandler]) => !eventHandler.isGlobalHandler)
|
|
678
737
|
.map(([eventName, eventHandler]) => {
|
|
679
|
-
return fromEvent(this.connection, eventName).pipe(
|
|
680
|
-
|
|
738
|
+
return fromEvent(this.connection, eventName).pipe(mergeMap((event) => {
|
|
739
|
+
// Wrap the handler in a try-catch block to prevent the entire stream from failing if an error occurs in a single handler
|
|
740
|
+
try {
|
|
741
|
+
// Execute the handler and emit the result
|
|
742
|
+
// 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
|
|
743
|
+
return of(eventHandler.handler(event));
|
|
744
|
+
}
|
|
745
|
+
catch (error) {
|
|
746
|
+
console.error(`Error in event handler for ${eventName}:`, error);
|
|
747
|
+
// Use throwError to propagate the error downstream
|
|
748
|
+
return throwError(() => new Error(`Error in event handler for ${eventName}: ${error}`));
|
|
749
|
+
}
|
|
750
|
+
}));
|
|
681
751
|
});
|
|
682
752
|
// Then merge them into a single observable in order to simulate the streaming behavior
|
|
683
753
|
const combined$ = merge(...observables).pipe(map(() => {
|
|
@@ -694,37 +764,74 @@ class WebSocketChatService extends ChatService {
|
|
|
694
764
|
});
|
|
695
765
|
})
|
|
696
766
|
: undefined;
|
|
697
|
-
//
|
|
698
|
-
|
|
699
|
-
|
|
767
|
+
// Always update ONLY the first assistant message of the _response with the new $progress, $attachment and $debug
|
|
768
|
+
// Assuming that the first assistant message is always visible since the hub does not send hidden messages by design
|
|
769
|
+
// So even if the first assistant message is hidden (display: false), the _response[0] will and should contain :
|
|
770
|
+
// - $progress, $attachment and $debug
|
|
771
|
+
// - the content of the first visible assistant message in the workflow
|
|
772
|
+
// This is mandatory in order to match the behavior of consecutive messages and maintain consistency with the chatHistory
|
|
773
|
+
if (!!this._progress || this._attachments.length > 0 || this._debugMessages.length > 0) {
|
|
774
|
+
this._response[0].additionalProperties.$progress = this._progress;
|
|
775
|
+
this._response[0].additionalProperties.$attachment = this._attachments;
|
|
776
|
+
this._response[0].additionalProperties.$debug = this._debugMessages;
|
|
700
777
|
}
|
|
701
778
|
// Return the result
|
|
702
|
-
return { history: [...messages,
|
|
779
|
+
return { history: [...messages, ...this._response], executionTime: this._executionTime };
|
|
703
780
|
}), takeUntil(completion$));
|
|
704
781
|
// 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
782
|
return new Observable(observer => {
|
|
706
783
|
// Subscribe to combined stream
|
|
707
784
|
combined$.subscribe({
|
|
708
785
|
next: (value) => observer.next(value),
|
|
709
|
-
error: (err) => observer.error(err)
|
|
710
|
-
complete: () => observer.complete(),
|
|
786
|
+
error: (err) => observer.error(err)
|
|
711
787
|
});
|
|
712
788
|
// Invoke the Chat method and handle errors
|
|
713
789
|
this.connection.invoke('Chat', data)
|
|
790
|
+
.then(() => {
|
|
791
|
+
// If a valid assistant message with (display: true) was found, update it
|
|
792
|
+
// and it should always the case
|
|
793
|
+
const index = this.firstVisibleAssistantMessageIndex(this.chatHistory);
|
|
794
|
+
if (index !== -1) {
|
|
795
|
+
this.chatHistory[index].additionalProperties.$progress = this._progress;
|
|
796
|
+
this.chatHistory[index].additionalProperties.$attachment = this._attachments;
|
|
797
|
+
this.chatHistory[index].additionalProperties.$debug = this._debugMessages;
|
|
798
|
+
}
|
|
799
|
+
// Save/update the chat if savedChat enabled
|
|
800
|
+
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; })) {
|
|
801
|
+
const action = !this.savedChatId ? this.addSavedChat(this.chatHistory).pipe(tap(() => this.listSavedChat())) : this.updateSavedChat(this.savedChatId, undefined, this.chatHistory);
|
|
802
|
+
action.pipe(take(1)).subscribe({
|
|
803
|
+
next: () => { },
|
|
804
|
+
error: (error) => {
|
|
805
|
+
this.streaming$.next(false);
|
|
806
|
+
observer.error(error);
|
|
807
|
+
},
|
|
808
|
+
complete: () => {
|
|
809
|
+
this.streaming$.next(false);
|
|
810
|
+
observer.complete();
|
|
811
|
+
}
|
|
812
|
+
});
|
|
813
|
+
}
|
|
814
|
+
else {
|
|
815
|
+
this.streaming$.next(false);
|
|
816
|
+
observer.complete();
|
|
817
|
+
}
|
|
818
|
+
})
|
|
714
819
|
.catch(error => {
|
|
715
820
|
console.error('Error invoking Chat:', error);
|
|
821
|
+
this.streaming$.next(false);
|
|
716
822
|
// Emit the error to the newly created observable
|
|
717
823
|
observer.error(error);
|
|
718
824
|
// Return a resolved promise to handle the error and prevent unhandled promise rejection
|
|
719
825
|
return Promise.resolve();
|
|
720
826
|
})
|
|
721
827
|
.finally(() => {
|
|
722
|
-
|
|
828
|
+
// This block concerns ONLY the completion of the "Chat" method invocation.
|
|
829
|
+
// This means the completion of the combined$ stream.
|
|
830
|
+
// 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
|
|
831
|
+
this._response = []; // Clear the _response
|
|
723
832
|
this._actionMap.clear(); // Clear the _actionMap
|
|
724
|
-
this._content = ""; // Clear the _content
|
|
725
833
|
this._progress = undefined; // Clear the _progress
|
|
726
834
|
this._attachments = []; // Clear the _attachments
|
|
727
|
-
this._suggestedActions = []; // Clear the _suggestedActions
|
|
728
835
|
this._debugMessages = []; // Clear the _debugMessages
|
|
729
836
|
this._executionTime = ""; // Clear the _executionTime
|
|
730
837
|
completion$.next(); // Emit a signal to complete the observables
|
|
@@ -732,6 +839,34 @@ class WebSocketChatService extends ChatService {
|
|
|
732
839
|
});
|
|
733
840
|
});
|
|
734
841
|
}
|
|
842
|
+
stopGeneration() {
|
|
843
|
+
// Start stopping generation by invoking the CancelTasks method
|
|
844
|
+
this.stoppingGeneration$.next(true);
|
|
845
|
+
// Create a Subject to hold the result of the CancelTasks method
|
|
846
|
+
const stopGenerationSubject$ = new Subject();
|
|
847
|
+
this.connection.on('CancelTasks', (res) => {
|
|
848
|
+
var _a;
|
|
849
|
+
// When the generation is stopped before streaming any VISIBLE assistant message, this means that $progress, $attachment and $debug properties will be lost.
|
|
850
|
+
// However, the "ContextMessage" frames will be persisted in the chatHistory and the assistant may reference them in the next generation.
|
|
851
|
+
// This leads to the problem of referencing undisplayed attachments in the next generation.
|
|
852
|
+
// 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.
|
|
853
|
+
if (this._response.length === 1 && this._response[0].content === "") {
|
|
854
|
+
(_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 } });
|
|
855
|
+
}
|
|
856
|
+
stopGenerationSubject$.next(!!res); // Emit the result of the CancelTasks method
|
|
857
|
+
stopGenerationSubject$.complete(); // Complete the subject
|
|
858
|
+
this.stoppingGeneration$.next(false); // Complete stopping generation
|
|
859
|
+
});
|
|
860
|
+
// Invoke the CancelTasks method and handle errors
|
|
861
|
+
this.connection.invoke('CancelTasks')
|
|
862
|
+
.catch(error => {
|
|
863
|
+
console.error('Error invoking CancelTasks:', error);
|
|
864
|
+
stopGenerationSubject$.error(new Error(error));
|
|
865
|
+
this.stoppingGeneration$.next(false); // Complete stopping generation
|
|
866
|
+
return Promise.resolve(); // Return a resolved promise to handle the error and prevent unhandled promise rejection when no further error handling exists downstream
|
|
867
|
+
});
|
|
868
|
+
return stopGenerationSubject$.asObservable();
|
|
869
|
+
}
|
|
735
870
|
listSavedChat() {
|
|
736
871
|
if (!this.chatConfig$.value.savedChatSettings.enabled) {
|
|
737
872
|
return;
|
|
@@ -751,27 +886,27 @@ class WebSocketChatService extends ChatService {
|
|
|
751
886
|
});
|
|
752
887
|
}
|
|
753
888
|
getSavedChat(id) {
|
|
754
|
-
const savedChatSubject = new Subject();
|
|
889
|
+
const savedChatSubject$ = new Subject();
|
|
755
890
|
const data = {
|
|
756
891
|
instanceId: this.chatInstanceId,
|
|
757
892
|
savedChatId: id,
|
|
758
893
|
debug: this.chatConfig$.value.defaultValues.debug
|
|
759
894
|
};
|
|
760
895
|
this.connection.on('SavedChatGet', (res) => {
|
|
761
|
-
savedChatSubject
|
|
762
|
-
savedChatSubject
|
|
896
|
+
savedChatSubject$.next(res.savedChat);
|
|
897
|
+
savedChatSubject$.complete();
|
|
763
898
|
});
|
|
764
899
|
// Invoke the method SavedChatGet
|
|
765
900
|
this.connection.invoke('SavedChatGet', data)
|
|
766
901
|
.catch(error => {
|
|
767
902
|
console.error('Error invoking SavedChatGet:', error);
|
|
768
|
-
savedChatSubject
|
|
769
|
-
return Promise.resolve();
|
|
903
|
+
savedChatSubject$.error(new Error(error));
|
|
904
|
+
return Promise.resolve(); // Return a resolved promise to handle the error and prevent unhandled promise rejection when no further error handling exists downstream
|
|
770
905
|
});
|
|
771
|
-
return savedChatSubject
|
|
906
|
+
return savedChatSubject$.asObservable();
|
|
772
907
|
}
|
|
773
908
|
addSavedChat(messages) {
|
|
774
|
-
const addSavedChatSubject = new Subject();
|
|
909
|
+
const addSavedChatSubject$ = new Subject();
|
|
775
910
|
const data = {
|
|
776
911
|
instanceId: this.chatInstanceId,
|
|
777
912
|
savedChatId: this.chatId,
|
|
@@ -781,20 +916,20 @@ class WebSocketChatService extends ChatService {
|
|
|
781
916
|
this.connection.on('SavedChatAdd', (res) => {
|
|
782
917
|
this.setSavedChatId(res.savedChat.id); // Persist the savedChatId
|
|
783
918
|
this.generateAuditEvent('saved-chat.add', {}, res.savedChat.id); // Generate audit event
|
|
784
|
-
addSavedChatSubject
|
|
785
|
-
addSavedChatSubject
|
|
919
|
+
addSavedChatSubject$.next(res.savedChat);
|
|
920
|
+
addSavedChatSubject$.complete();
|
|
786
921
|
});
|
|
787
922
|
// Invoke the method SavedChatAdd
|
|
788
923
|
this.connection.invoke('SavedChatAdd', data)
|
|
789
924
|
.catch(error => {
|
|
790
925
|
console.error('Error invoking SavedChatAdd:', error);
|
|
791
|
-
addSavedChatSubject
|
|
792
|
-
return Promise.resolve();
|
|
926
|
+
addSavedChatSubject$.error(new Error(error));
|
|
927
|
+
return Promise.resolve(); // Return a resolved promise to handle the error and prevent unhandled promise rejection when no further error handling exists downstream
|
|
793
928
|
});
|
|
794
|
-
return addSavedChatSubject
|
|
929
|
+
return addSavedChatSubject$.asObservable();
|
|
795
930
|
}
|
|
796
931
|
updateSavedChat(id, name, messages) {
|
|
797
|
-
const updateSavedChatSubject = new Subject();
|
|
932
|
+
const updateSavedChatSubject$ = new Subject();
|
|
798
933
|
const data = {
|
|
799
934
|
instanceId: this.chatInstanceId,
|
|
800
935
|
savedChatId: id,
|
|
@@ -805,45 +940,64 @@ class WebSocketChatService extends ChatService {
|
|
|
805
940
|
if (messages)
|
|
806
941
|
data["history"] = messages;
|
|
807
942
|
this.connection.on('SavedChatUpdate', (res) => {
|
|
808
|
-
updateSavedChatSubject
|
|
809
|
-
updateSavedChatSubject
|
|
943
|
+
updateSavedChatSubject$.next(res.savedChat);
|
|
944
|
+
updateSavedChatSubject$.complete();
|
|
810
945
|
});
|
|
811
946
|
// Invoke the method SavedChatUpdate
|
|
812
947
|
this.connection.invoke('SavedChatUpdate', data)
|
|
813
948
|
.catch(error => {
|
|
814
949
|
console.error('Error invoking SavedChatUpdate:', error);
|
|
815
|
-
updateSavedChatSubject
|
|
816
|
-
return Promise.resolve();
|
|
950
|
+
updateSavedChatSubject$.error(new Error(error));
|
|
951
|
+
return Promise.resolve(); // Return a resolved promise to handle the error and prevent unhandled promise rejection when no further error handling exists downstream
|
|
817
952
|
});
|
|
818
|
-
return updateSavedChatSubject
|
|
953
|
+
return updateSavedChatSubject$.asObservable();
|
|
819
954
|
}
|
|
820
955
|
deleteSavedChat(ids) {
|
|
821
|
-
const deleteSavedChatSubject = new Subject();
|
|
956
|
+
const deleteSavedChatSubject$ = new Subject();
|
|
822
957
|
const data = {
|
|
823
958
|
instanceId: this.chatInstanceId,
|
|
824
959
|
SavedChatIds: ids,
|
|
825
960
|
debug: this.chatConfig$.value.defaultValues.debug
|
|
826
961
|
};
|
|
827
962
|
this.connection.on('SavedChatDelete', (res) => {
|
|
828
|
-
deleteSavedChatSubject
|
|
829
|
-
deleteSavedChatSubject
|
|
963
|
+
deleteSavedChatSubject$.next(res.deleteCount);
|
|
964
|
+
deleteSavedChatSubject$.complete();
|
|
830
965
|
});
|
|
831
966
|
// Invoke the method SavedChatDelete
|
|
832
967
|
this.connection.invoke('SavedChatDelete', data)
|
|
833
968
|
.catch(error => {
|
|
834
969
|
console.error('Error invoking SavedChatDelete:', error);
|
|
835
|
-
deleteSavedChatSubject
|
|
836
|
-
return Promise.resolve();
|
|
970
|
+
deleteSavedChatSubject$.error(new Error(error));
|
|
971
|
+
return Promise.resolve(); // Return a resolved promise to handle the error and prevent unhandled promise rejection when no further error handling exists downstream
|
|
837
972
|
});
|
|
838
|
-
return deleteSavedChatSubject
|
|
973
|
+
return deleteSavedChatSubject$.asObservable();
|
|
839
974
|
}
|
|
840
975
|
/**
|
|
841
976
|
* 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
|
|
977
|
+
* It is a placeholder for non-streaming scenarios, where you invoke a specific hub method, and the server responds with frame message(s)
|
|
843
978
|
*/
|
|
844
979
|
initMessageHandlers() {
|
|
845
|
-
this.addMessageHandler("
|
|
846
|
-
|
|
980
|
+
this.addMessageHandler("Error", {
|
|
981
|
+
handler: (error) => {
|
|
982
|
+
console.error(error);
|
|
983
|
+
this.notificationsService.error(error);
|
|
984
|
+
},
|
|
985
|
+
isGlobalHandler: true
|
|
986
|
+
});
|
|
987
|
+
this.addMessageHandler("Quota", {
|
|
988
|
+
handler: (message) => {
|
|
989
|
+
try {
|
|
990
|
+
this.updateQuota(message.quota);
|
|
991
|
+
}
|
|
992
|
+
catch (error) {
|
|
993
|
+
console.error(error);
|
|
994
|
+
}
|
|
995
|
+
},
|
|
996
|
+
isGlobalHandler: true
|
|
997
|
+
});
|
|
998
|
+
this.addMessageHandler("Debug", { handler: () => { },
|
|
999
|
+
isGlobalHandler: true
|
|
1000
|
+
});
|
|
847
1001
|
this.addMessageHandler("ActionStart", { handler: (action) => this._actionMap.set(action.guid, action),
|
|
848
1002
|
isGlobalHandler: false });
|
|
849
1003
|
this.addMessageHandler("ActionResult", {
|
|
@@ -859,36 +1013,50 @@ class WebSocketChatService extends ChatService {
|
|
|
859
1013
|
isGlobalHandler: false
|
|
860
1014
|
});
|
|
861
1015
|
this.addMessageHandler("Message", {
|
|
862
|
-
handler: (message) => this.
|
|
1016
|
+
handler: (message) => this._response.at(-1).content += message !== null && message !== void 0 ? message : "",
|
|
863
1017
|
isGlobalHandler: false
|
|
864
1018
|
});
|
|
865
1019
|
this.addMessageHandler("History", {
|
|
866
1020
|
handler: (history) => {
|
|
867
1021
|
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
|
|
1022
|
+
// 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)
|
|
1023
|
+
// This is mandatory to not lose the previous updates of the chatHistory when the assistant is streaming multiple message steps
|
|
1024
|
+
this.chatHistory = [...this.chatHistory, ...(history.history.slice(this.chatHistory.length))];
|
|
1025
|
+
// Emit the updated chat usage metrics
|
|
875
1026
|
if (!!((_a = this.chatHistory.at(-1)) === null || _a === void 0 ? void 0 : _a.additionalProperties.usageMetrics)) {
|
|
876
1027
|
this.updateChatUsageMetrics(this.chatHistory.at(-1).additionalProperties.usageMetrics);
|
|
877
1028
|
}
|
|
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
1029
|
this._executionTime = history.executionTime;
|
|
1030
|
+
},
|
|
1031
|
+
isGlobalHandler: false
|
|
1032
|
+
});
|
|
1033
|
+
this.addMessageHandler("SuggestedActions", {
|
|
1034
|
+
handler: (message) => {
|
|
1035
|
+
// Since after the "History" and "MessageBreak" that this event is caught,
|
|
1036
|
+
// $suggestedAction needs to be updated directly to the last visible "assistant" message in the _response and the chatHistory
|
|
1037
|
+
this._response.at(-1).additionalProperties.$suggestedAction = (this._response.at(-1).additionalProperties.$suggestedAction || []).concat(message.suggestedActions);
|
|
1038
|
+
const index = this.lastVisibleAssistantMessageIndex(this.chatHistory);
|
|
1039
|
+
if (index !== -1) {
|
|
1040
|
+
this.chatHistory[index].additionalProperties.$suggestedAction = (this.chatHistory[index].additionalProperties.$suggestedAction || []).concat(message.suggestedActions);
|
|
1041
|
+
}
|
|
1042
|
+
},
|
|
1043
|
+
isGlobalHandler: false
|
|
1044
|
+
});
|
|
1045
|
+
this.addMessageHandler("DebugDisplay", {
|
|
1046
|
+
handler: (message) => this._debugMessages = this._debugMessages.concat(message),
|
|
1047
|
+
isGlobalHandler: false
|
|
1048
|
+
});
|
|
1049
|
+
this.addMessageHandler("MessageBreak", {
|
|
1050
|
+
handler: () => {
|
|
1051
|
+
var _a, _b;
|
|
884
1052
|
// Generate audit event
|
|
885
1053
|
const details = {
|
|
886
1054
|
'duration': this._executionTime,
|
|
887
1055
|
'text': this.chatHistory.at(-1).content,
|
|
888
1056
|
'role': this.chatHistory.at(-1).role,
|
|
889
1057
|
'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,
|
|
1058
|
+
'generation-tokencount': (_a = this.chatHistory.at(-1).additionalProperties.usageMetrics) === null || _a === void 0 ? void 0 : _a.completionTokenCount,
|
|
1059
|
+
'prompt-tokencount': (_b = this.chatHistory.at(-1).additionalProperties.usageMetrics) === null || _b === void 0 ? void 0 : _b.promptTokenCount,
|
|
892
1060
|
'attachments': JSON.stringify(this._attachments.map(({ recordId, contextId, parts, type }) => ({
|
|
893
1061
|
recordId,
|
|
894
1062
|
contextId,
|
|
@@ -897,31 +1065,13 @@ class WebSocketChatService extends ChatService {
|
|
|
897
1065
|
})))
|
|
898
1066
|
};
|
|
899
1067
|
this.generateAuditEvent('message', details);
|
|
1068
|
+
// Push a new assistant message to the _response array ONLY if the content of the last message is not empty
|
|
1069
|
+
if (this._response.at(-1).content !== "") {
|
|
1070
|
+
this._response.push({ role: "assistant", content: "", additionalProperties: { display: true } });
|
|
1071
|
+
}
|
|
900
1072
|
},
|
|
901
1073
|
isGlobalHandler: false
|
|
902
1074
|
});
|
|
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
1075
|
}
|
|
926
1076
|
/**
|
|
927
1077
|
* Override and register the entire _messageHandlers map by merging the provided map with the default one
|
|
@@ -936,7 +1086,7 @@ class WebSocketChatService extends ChatService {
|
|
|
936
1086
|
});
|
|
937
1087
|
// Merge the new event handlers with the existing ones
|
|
938
1088
|
this._messageHandlers = new Map([...this._messageHandlers, ..._messageHandlers]);
|
|
939
|
-
// Register the global
|
|
1089
|
+
// Register the global handlers among the merged map
|
|
940
1090
|
this._messageHandlers.forEach((eventHandler, eventName) => {
|
|
941
1091
|
if (eventHandler.isGlobalHandler) {
|
|
942
1092
|
this.registerMessageHandler(eventName, eventHandler);
|
|
@@ -946,7 +1096,7 @@ class WebSocketChatService extends ChatService {
|
|
|
946
1096
|
/**
|
|
947
1097
|
* Add a listener for a specific event.
|
|
948
1098
|
* If a listener for this same event already exists, it will be overridden.
|
|
949
|
-
* If the listener has "
|
|
1099
|
+
* If the listener has "isGlobalHandler" set to true, it will be registered to the hub connection.
|
|
950
1100
|
* @param eventName Name of the event to register a listener for
|
|
951
1101
|
* @param eventHandler The handler to be called when the event is received
|
|
952
1102
|
*/
|
|
@@ -996,12 +1146,17 @@ class WebSocketChatService extends ChatService {
|
|
|
996
1146
|
*/
|
|
997
1147
|
buildConnection(options) {
|
|
998
1148
|
return new Promise((resolve, reject) => {
|
|
1149
|
+
var _a;
|
|
999
1150
|
if (!this.REQUEST_URL) {
|
|
1000
1151
|
reject(new Error("No endpoint provided to connect the websocket to"));
|
|
1001
1152
|
return;
|
|
1002
1153
|
}
|
|
1003
|
-
const logLevel = this.
|
|
1154
|
+
const logLevel = this._getLogLevel();
|
|
1004
1155
|
this.connection = this.signalRService.buildConnection(this.REQUEST_URL, Object.assign(Object.assign({}, this.defaultOptions), options), logLevel, true);
|
|
1156
|
+
const signalRServerTimeoutInMilliseconds = (_a = this.chatConfig$.value) === null || _a === void 0 ? void 0 : _a.connectionSettings.signalRServerTimeoutInMilliseconds;
|
|
1157
|
+
if (signalRServerTimeoutInMilliseconds) {
|
|
1158
|
+
this.connection.serverTimeoutInMilliseconds = signalRServerTimeoutInMilliseconds;
|
|
1159
|
+
}
|
|
1005
1160
|
resolve();
|
|
1006
1161
|
});
|
|
1007
1162
|
}
|
|
@@ -1019,7 +1174,7 @@ class WebSocketChatService extends ChatService {
|
|
|
1019
1174
|
stopConnection() {
|
|
1020
1175
|
return this.signalRService.stopConnection(this.connection);
|
|
1021
1176
|
}
|
|
1022
|
-
|
|
1177
|
+
_getTransports() {
|
|
1023
1178
|
var _a;
|
|
1024
1179
|
switch ((_a = this.chatConfig$.value) === null || _a === void 0 ? void 0 : _a.connectionSettings.signalRTransport) {
|
|
1025
1180
|
case "WebSockets":
|
|
@@ -1032,7 +1187,7 @@ class WebSocketChatService extends ChatService {
|
|
|
1032
1187
|
return HttpTransportType.None;
|
|
1033
1188
|
}
|
|
1034
1189
|
}
|
|
1035
|
-
|
|
1190
|
+
_getLogLevel() {
|
|
1036
1191
|
var _a;
|
|
1037
1192
|
switch ((_a = this.chatConfig$.value) === null || _a === void 0 ? void 0 : _a.connectionSettings.signalRLogLevel) {
|
|
1038
1193
|
case "Critical":
|
|
@@ -1067,7 +1222,7 @@ class WebSocketChatService extends ChatService {
|
|
|
1067
1222
|
// as far as we know, signalR only lets us tweak the request with this access token factory
|
|
1068
1223
|
// so we pass along the Sinequa CSRF token to pass the CSRF check..
|
|
1069
1224
|
return {
|
|
1070
|
-
transport: this.
|
|
1225
|
+
transport: this._getTransports(),
|
|
1071
1226
|
withCredentials: true,
|
|
1072
1227
|
headers,
|
|
1073
1228
|
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 +1464,10 @@ class ChatReferenceComponent {
|
|
|
1309
1464
|
}
|
|
1310
1465
|
}
|
|
1311
1466
|
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"] }] });
|
|
1467
|
+
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
1468
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ChatReferenceComponent, decorators: [{
|
|
1314
1469
|
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"] }]
|
|
1470
|
+
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
1471
|
}], propDecorators: { reference: [{
|
|
1317
1472
|
type: Input
|
|
1318
1473
|
}], attachment: [{
|
|
@@ -1378,6 +1533,7 @@ class ChatMessageComponent {
|
|
|
1378
1533
|
this.openDocument = new EventEmitter();
|
|
1379
1534
|
this.openPreview = new EventEmitter();
|
|
1380
1535
|
this.suggestAction = new EventEmitter();
|
|
1536
|
+
this.chatStarterClicked = new EventEmitter();
|
|
1381
1537
|
this.edit = new EventEmitter();
|
|
1382
1538
|
this.copy = new EventEmitter();
|
|
1383
1539
|
this.regenerate = new EventEmitter();
|
|
@@ -1455,7 +1611,7 @@ class ChatMessageComponent {
|
|
|
1455
1611
|
if (changes.streaming) {
|
|
1456
1612
|
this.collapseProgress = !this.streaming;
|
|
1457
1613
|
}
|
|
1458
|
-
if (
|
|
1614
|
+
if (((_a = this.message) === null || _a === void 0 ? void 0 : _a.role) === "assistant") {
|
|
1459
1615
|
this.references = [];
|
|
1460
1616
|
this.referenceMap.clear();
|
|
1461
1617
|
for (let m of this.conversation) {
|
|
@@ -1557,17 +1713,19 @@ class ChatMessageComponent {
|
|
|
1557
1713
|
}
|
|
1558
1714
|
}
|
|
1559
1715
|
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 });
|
|
1716
|
+
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
1717
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ChatMessageComponent, decorators: [{
|
|
1562
1718
|
type: Component,
|
|
1563
1719
|
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"] }]
|
|
1720
|
+
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
1721
|
}], ctorParameters: function () { return [{ type: i1$1.SearchService }, { type: i2$1.UIService }, { type: i3.PrincipalWebService }, { type: i0.ChangeDetectorRef }, { type: i0.ElementRef }]; }, propDecorators: { message: [{
|
|
1566
1722
|
type: Input
|
|
1567
1723
|
}], conversation: [{
|
|
1568
1724
|
type: Input
|
|
1569
1725
|
}], suggestedActions: [{
|
|
1570
1726
|
type: Input
|
|
1727
|
+
}], chatStarters: [{
|
|
1728
|
+
type: Input
|
|
1571
1729
|
}], assistantMessageIcon: [{
|
|
1572
1730
|
type: Input
|
|
1573
1731
|
}], userMessageIcon: [{
|
|
@@ -1596,6 +1754,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImpor
|
|
|
1596
1754
|
type: Output
|
|
1597
1755
|
}], suggestAction: [{
|
|
1598
1756
|
type: Output
|
|
1757
|
+
}], chatStarterClicked: [{
|
|
1758
|
+
type: Output
|
|
1599
1759
|
}], edit: [{
|
|
1600
1760
|
type: Output
|
|
1601
1761
|
}], copy: [{
|
|
@@ -1696,7 +1856,7 @@ class RestChatService extends ChatService {
|
|
|
1696
1856
|
}
|
|
1697
1857
|
// Request the Chat endpoint
|
|
1698
1858
|
return this.jsonMethodWebService.post(this.REQUEST_URL, data).pipe(tap((res) => this.updateQuota(res.quota, true)), map((res) => {
|
|
1699
|
-
var _a, _b;
|
|
1859
|
+
var _a, _b, _c, _d;
|
|
1700
1860
|
// Define $progress from the actions property of the response
|
|
1701
1861
|
let $progress;
|
|
1702
1862
|
if (((_a = res.actions) === null || _a === void 0 ? void 0 : _a.length) > 0) {
|
|
@@ -1740,9 +1900,9 @@ class RestChatService extends ChatService {
|
|
|
1740
1900
|
'text': response.content,
|
|
1741
1901
|
'role': response.role,
|
|
1742
1902
|
'rank': this.chatHistory.length - 1,
|
|
1743
|
-
'generation-tokencount': response.additionalProperties.usageMetrics.completionTokenCount,
|
|
1744
|
-
'prompt-tokencount': response.additionalProperties.usageMetrics.promptTokenCount,
|
|
1745
|
-
'attachments': (
|
|
1903
|
+
'generation-tokencount': (_b = response.additionalProperties.usageMetrics) === null || _b === void 0 ? void 0 : _b.completionTokenCount,
|
|
1904
|
+
'prompt-tokencount': (_c = response.additionalProperties.usageMetrics) === null || _c === void 0 ? void 0 : _c.promptTokenCount,
|
|
1905
|
+
'attachments': (_d = response.additionalProperties.$attachment) === null || _d === void 0 ? void 0 : _d.map(({ recordId, contextId, parts, type }) => ({
|
|
1746
1906
|
recordId,
|
|
1747
1907
|
contextId,
|
|
1748
1908
|
parts: parts.map(({ partId, text }) => ({ partId, text })),
|
|
@@ -1754,6 +1914,11 @@ class RestChatService extends ChatService {
|
|
|
1754
1914
|
return { history: [...messages, response], executionTime: res.executionTime };
|
|
1755
1915
|
}), finalize(() => this.streaming$.next(false)));
|
|
1756
1916
|
}
|
|
1917
|
+
stopGeneration() {
|
|
1918
|
+
const error = new Error('Not supported in REST');
|
|
1919
|
+
console.error(error);
|
|
1920
|
+
return throwError(() => error);
|
|
1921
|
+
}
|
|
1757
1922
|
listSavedChat() {
|
|
1758
1923
|
if (!this.chatConfig$.value.savedChatSettings.enabled) {
|
|
1759
1924
|
return;
|
|
@@ -1872,10 +2037,10 @@ class TokenProgressBarComponent {
|
|
|
1872
2037
|
}
|
|
1873
2038
|
}
|
|
1874
2039
|
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"] }] });
|
|
2040
|
+
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
2041
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: TokenProgressBarComponent, decorators: [{
|
|
1877
2042
|
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"] }]
|
|
2043
|
+
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
2044
|
}], propDecorators: { instanceId: [{
|
|
1880
2045
|
type: Input
|
|
1881
2046
|
}] } });
|
|
@@ -1904,10 +2069,10 @@ class DebugMessageComponent {
|
|
|
1904
2069
|
}
|
|
1905
2070
|
}
|
|
1906
2071
|
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.
|
|
2072
|
+
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
2073
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: DebugMessageComponent, decorators: [{
|
|
1909
2074
|
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.
|
|
2075
|
+
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
2076
|
}], ctorParameters: function () { return [{ type: i2$1.UIService }]; }, propDecorators: { data: [{
|
|
1912
2077
|
type: Input
|
|
1913
2078
|
}], level: [{
|
|
@@ -1935,6 +2100,8 @@ class ChatComponent extends AbstractFacet {
|
|
|
1935
2100
|
this.messageHandlers = new Map();
|
|
1936
2101
|
/** When the assistant answer a user question, automatically scroll down to the bottom of the discussion */
|
|
1937
2102
|
this.automaticScrollToLastResponse = false;
|
|
2103
|
+
/** When the assistant answer a user question, automatically focus to the chat input */
|
|
2104
|
+
this.focusAfterResponse = false;
|
|
1938
2105
|
/** Icon to use for the assistant messages */
|
|
1939
2106
|
this.assistantMessageIcon = 'sq-sinequa';
|
|
1940
2107
|
/** Event emitter triggered once the signalR connection is established */
|
|
@@ -1951,10 +2118,17 @@ class ChatComponent extends AbstractFacet {
|
|
|
1951
2118
|
this.openPreview = new EventEmitter();
|
|
1952
2119
|
/** Event emitter triggered when the user clicks on a suggested action */
|
|
1953
2120
|
this.suggestAction = new EventEmitter();
|
|
2121
|
+
/** Event emitter triggered when the user clicks on a chat starter */
|
|
2122
|
+
this.chatStarter = new EventEmitter();
|
|
1954
2123
|
this.messages$ = new BehaviorSubject(undefined);
|
|
1955
2124
|
this.question = '';
|
|
1956
2125
|
this._actions = [];
|
|
1957
|
-
this.
|
|
2126
|
+
this._resetChatAction = new Action({
|
|
2127
|
+
icon: 'fas fa-sync',
|
|
2128
|
+
title: "Reset assistant",
|
|
2129
|
+
action: () => this.newChat()
|
|
2130
|
+
});
|
|
2131
|
+
this._sub = new Subscription();
|
|
1958
2132
|
this.changes$ = new BehaviorSubject(undefined);
|
|
1959
2133
|
this.firstChangesHandled = false;
|
|
1960
2134
|
this.isAtBottom = true;
|
|
@@ -1972,16 +2146,14 @@ class ChatComponent extends AbstractFacet {
|
|
|
1972
2146
|
'Other'
|
|
1973
2147
|
];
|
|
1974
2148
|
this.issueType = '';
|
|
1975
|
-
this.
|
|
2149
|
+
this.reportType = 'dislike';
|
|
2150
|
+
this.showReport = false;
|
|
1976
2151
|
this.showDebugMessages = false;
|
|
1977
|
-
this.
|
|
1978
|
-
|
|
1979
|
-
title: 'Reset chat',
|
|
1980
|
-
action: () => this.newChat()
|
|
1981
|
-
}));
|
|
2152
|
+
this._reloadSubscription = undefined;
|
|
2153
|
+
this._actions.push(this._resetChatAction);
|
|
1982
2154
|
}
|
|
1983
2155
|
ngOnInit() {
|
|
1984
|
-
this.
|
|
2156
|
+
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
2157
|
if (this.chatService instanceof WebSocketChatService) {
|
|
1986
2158
|
this.connection.emit(this.chatService.connection);
|
|
1987
2159
|
}
|
|
@@ -2006,6 +2178,12 @@ class ChatComponent extends AbstractFacet {
|
|
|
2006
2178
|
throw error;
|
|
2007
2179
|
}
|
|
2008
2180
|
})).subscribe());
|
|
2181
|
+
this._sub.add(combineLatest([
|
|
2182
|
+
this.chatService.streaming$,
|
|
2183
|
+
this.chatService.stoppingGeneration$
|
|
2184
|
+
]).pipe(map(([streaming, stoppingGeneration]) => !!(streaming || stoppingGeneration))).subscribe((result) => {
|
|
2185
|
+
this._resetChatAction.disabled = result;
|
|
2186
|
+
}));
|
|
2009
2187
|
}
|
|
2010
2188
|
ngOnChanges(changes) {
|
|
2011
2189
|
this.changes$.next(changes);
|
|
@@ -2014,14 +2192,22 @@ class ChatComponent extends AbstractFacet {
|
|
|
2014
2192
|
}
|
|
2015
2193
|
}
|
|
2016
2194
|
ngOnDestroy() {
|
|
2017
|
-
var _a;
|
|
2018
|
-
this.
|
|
2019
|
-
(_a = this.
|
|
2195
|
+
var _a, _b;
|
|
2196
|
+
this._sub.unsubscribe();
|
|
2197
|
+
(_a = this._dataSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
|
|
2198
|
+
(_b = this._reloadSubscription) === null || _b === void 0 ? void 0 : _b.unsubscribe();
|
|
2199
|
+
if (this.chatService instanceof WebSocketChatService) {
|
|
2200
|
+
this.chatService.stopConnection();
|
|
2201
|
+
}
|
|
2020
2202
|
}
|
|
2021
2203
|
get isAdmin() {
|
|
2022
2204
|
var _a;
|
|
2023
2205
|
return ((_a = this.principalService.principal) === null || _a === void 0 ? void 0 : _a.isAdministrator) || false;
|
|
2024
2206
|
}
|
|
2207
|
+
get visibleMessagesCount() {
|
|
2208
|
+
var _a;
|
|
2209
|
+
return ((_a = this.messages$.value) === null || _a === void 0 ? void 0 : _a.filter(m => m.additionalProperties.display).length) || 0;
|
|
2210
|
+
}
|
|
2025
2211
|
/**
|
|
2026
2212
|
* Instantiate the chat service based on the provided @input protocol
|
|
2027
2213
|
* This chat service instance will then be stored in the instanceManagerService with provided @input instanceId as a key
|
|
@@ -2041,6 +2227,17 @@ class ChatComponent extends AbstractFacet {
|
|
|
2041
2227
|
this.instanceManagerService.storeInstance(this.instanceId, this.chatService);
|
|
2042
2228
|
}
|
|
2043
2229
|
get actions() { return this._actions; }
|
|
2230
|
+
/**
|
|
2231
|
+
* Handles the changes in the chat component.
|
|
2232
|
+
* If the chat service is a WebSocketChatService, it handles the override of the message handlers if they exist.
|
|
2233
|
+
* Initializes the chat with the provided chat messages if they exist, otherwise loads the default chat.
|
|
2234
|
+
* If the chat is initialized, the initialization event is "Query", the query changes, and the queryChangeShouldTriggerReload function is provided,
|
|
2235
|
+
* then the chat should be reloaded if the function returns true. Otherwise, the chat should be reloaded by default.
|
|
2236
|
+
* It takes into account the ongoing streaming process and the ongoing stopping process to trigger that conditionally define the logic
|
|
2237
|
+
* of the reload :
|
|
2238
|
+
* - If the chat is streaming, then stop the generation and wait for the fetch to complete before reloading the chat.
|
|
2239
|
+
* - If the chat is stopping the generation, then wait for the fetch to complete before reloading the chat.
|
|
2240
|
+
*/
|
|
2044
2241
|
_handleChanges() {
|
|
2045
2242
|
const changes = this.changes$.value;
|
|
2046
2243
|
// If the chat service is a WebSocketChatService, handle the override of the message handlers if exists
|
|
@@ -2075,11 +2272,70 @@ class ChatComponent extends AbstractFacet {
|
|
|
2075
2272
|
*/
|
|
2076
2273
|
if (this.firstChangesHandled && (changes === null || changes === void 0 ? void 0 : changes.query) && this.config.modeSettings.initialization.event === 'Query') {
|
|
2077
2274
|
if (this.queryChangeShouldTriggerReload ? this.queryChangeShouldTriggerReload(this._previousQuery, this.query) : true) {
|
|
2078
|
-
this.
|
|
2275
|
+
if (!!this.chatService.stoppingGeneration$.value) {
|
|
2276
|
+
if (!this._reloadSubscription) {
|
|
2277
|
+
// Create a subscription to wait for both streaming$ and stoppingGeneration$ to be false
|
|
2278
|
+
this._reloadSubscription = combineLatest([
|
|
2279
|
+
this.chatService.streaming$,
|
|
2280
|
+
this.chatService.stoppingGeneration$
|
|
2281
|
+
])
|
|
2282
|
+
.pipe(filter(([streaming, stopping]) => !streaming && !stopping), // Wait until both are false
|
|
2283
|
+
take(1) // Complete after the first match
|
|
2284
|
+
).subscribe(() => {
|
|
2285
|
+
// Execute the reload after the query change
|
|
2286
|
+
this._triggerReloadAfterQueryChange();
|
|
2287
|
+
// Update _previousQuery with the current query
|
|
2288
|
+
this._previousQuery = JSON.parse(JSON.stringify(this.query));
|
|
2289
|
+
// Clean up subscription and reset its value
|
|
2290
|
+
this._reloadSubscription = undefined;
|
|
2291
|
+
});
|
|
2292
|
+
}
|
|
2293
|
+
}
|
|
2294
|
+
else if (!!this.chatService.streaming$.value) {
|
|
2295
|
+
if (!this._reloadSubscription) {
|
|
2296
|
+
this._reloadSubscription = this.chatService.stopGeneration()
|
|
2297
|
+
.subscribe({
|
|
2298
|
+
next: () => { },
|
|
2299
|
+
error: () => {
|
|
2300
|
+
var _a;
|
|
2301
|
+
// Clean up subscription and reset its value
|
|
2302
|
+
(_a = this._reloadSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
|
|
2303
|
+
this._reloadSubscription = undefined;
|
|
2304
|
+
},
|
|
2305
|
+
complete: () => {
|
|
2306
|
+
// Wait for the ongoing fetch to complete, then trigger the reload
|
|
2307
|
+
this.chatService.streaming$.pipe(filter((streaming) => !streaming), take(1)).subscribe(() => {
|
|
2308
|
+
// Execute the reload after the query change
|
|
2309
|
+
this._triggerReloadAfterQueryChange();
|
|
2310
|
+
// Update _previousQuery with the current query
|
|
2311
|
+
this._previousQuery = JSON.parse(JSON.stringify(this.query));
|
|
2312
|
+
// Clean up subscription and reset its value
|
|
2313
|
+
this._reloadSubscription.unsubscribe();
|
|
2314
|
+
this._reloadSubscription = undefined;
|
|
2315
|
+
});
|
|
2316
|
+
}
|
|
2317
|
+
});
|
|
2318
|
+
}
|
|
2319
|
+
}
|
|
2320
|
+
else {
|
|
2321
|
+
// Execute the reload after the query change
|
|
2322
|
+
this._triggerReloadAfterQueryChange();
|
|
2323
|
+
// Update _previousQuery with the current query
|
|
2324
|
+
this._previousQuery = JSON.parse(JSON.stringify(this.query));
|
|
2325
|
+
}
|
|
2326
|
+
}
|
|
2327
|
+
else {
|
|
2328
|
+
// Update _previousQuery with the current query
|
|
2329
|
+
this._previousQuery = JSON.parse(JSON.stringify(this.query));
|
|
2079
2330
|
}
|
|
2080
|
-
this._previousQuery = JSON.parse(JSON.stringify(this.query)); // Update the previous query
|
|
2081
2331
|
}
|
|
2082
2332
|
}
|
|
2333
|
+
/**
|
|
2334
|
+
* Triggers a reload after the query change.
|
|
2335
|
+
* This method performs the necessary operations to reload the chat after a query change.
|
|
2336
|
+
* It sets the system and user messages, resets the savedChatId, generates a new chatId,
|
|
2337
|
+
* generates a new chat audit event, and handles the query mode.
|
|
2338
|
+
*/
|
|
2083
2339
|
_triggerReloadAfterQueryChange() {
|
|
2084
2340
|
const systemMsg = { role: 'system', content: this.config.defaultValues.systemPrompt, additionalProperties: { display: false } };
|
|
2085
2341
|
const userMsg = { role: 'user', content: ChatService.formatPrompt(this.config.defaultValues.userPrompt, { principal: this.principalService.principal }), additionalProperties: { display: this.config.modeSettings.displayUserPrompt } };
|
|
@@ -2088,26 +2344,49 @@ class ChatComponent extends AbstractFacet {
|
|
|
2088
2344
|
this.chatService.generateAuditEvent('new-chat', { 'configuration': JSON.stringify(this.chatService.chatConfig$.value) }); // Generate a new chat audit event
|
|
2089
2345
|
this._handleQueryMode(systemMsg, userMsg);
|
|
2090
2346
|
}
|
|
2347
|
+
/**
|
|
2348
|
+
* Adds a scroll listener to the message list element.
|
|
2349
|
+
* The listener is triggered when any of the following events occur:
|
|
2350
|
+
* - Loading state changes
|
|
2351
|
+
* - Messages change
|
|
2352
|
+
* - Streaming state changes
|
|
2353
|
+
* - Scroll event occurs on the message list element
|
|
2354
|
+
*
|
|
2355
|
+
* When the listener is triggered, it updates the `isAtBottom` property.
|
|
2356
|
+
*/
|
|
2091
2357
|
_addScrollListener() {
|
|
2092
|
-
this.
|
|
2358
|
+
this._sub.add(merge(this.loading$, this.messages$, this.chatService.streaming$, fromEvent(this.messageList.nativeElement, 'scroll')).subscribe(() => {
|
|
2093
2359
|
this.isAtBottom = this._toggleScrollButtonVisibility();
|
|
2094
2360
|
this.cdr.detectChanges();
|
|
2095
2361
|
}));
|
|
2096
2362
|
}
|
|
2363
|
+
/**
|
|
2364
|
+
* Get the model description based on the defaultValues service_id and model_id
|
|
2365
|
+
*/
|
|
2097
2366
|
updateModelDescription() {
|
|
2098
2367
|
this.modelDescription = this.chatService.getModel(this.config.defaultValues.service_id, this.config.defaultValues.model_id);
|
|
2099
2368
|
this.cdr.detectChanges();
|
|
2100
2369
|
}
|
|
2370
|
+
/**
|
|
2371
|
+
* Submits a question from the user.
|
|
2372
|
+
* If the user is editing a previous message, removes all subsequent messages from the chat history.
|
|
2373
|
+
* Triggers the fetch of the answer for the submitted question by calling _fetchAnswer().
|
|
2374
|
+
* Clears the input value in the UI.
|
|
2375
|
+
*/
|
|
2101
2376
|
submitQuestion() {
|
|
2102
2377
|
var _a;
|
|
2378
|
+
if (!!this.chatService.streaming$.value || !!this.chatService.stoppingGeneration$.value) {
|
|
2379
|
+
return;
|
|
2380
|
+
}
|
|
2103
2381
|
if (this.question.trim() && this.messages$.value && this.chatService.chatHistory) {
|
|
2104
2382
|
// When the user submits a question, if the user is editing a previous message, remove all subsequent messages from the chat history
|
|
2105
2383
|
if (this.messageToEdit !== undefined) {
|
|
2106
2384
|
// Update the messages in the UI
|
|
2107
2385
|
this.messages$.next(this.messages$.value.slice(0, this.messageToEdit));
|
|
2108
2386
|
// 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.
|
|
2387
|
+
this.chatService.chatHistory = this.chatService.chatHistory.slice(0, this.remappedMessageToEdit);
|
|
2110
2388
|
this.messageToEdit = undefined;
|
|
2389
|
+
this.remappedMessageToEdit = undefined;
|
|
2111
2390
|
}
|
|
2112
2391
|
// Remove the search warning message if exists
|
|
2113
2392
|
if (((_a = this.chatService.chatHistory.at(-1)) === null || _a === void 0 ? void 0 : _a.role) === 'search-warning') {
|
|
@@ -2120,6 +2399,13 @@ class ChatComponent extends AbstractFacet {
|
|
|
2120
2399
|
this.questionInput.nativeElement.style.height = `auto`;
|
|
2121
2400
|
}
|
|
2122
2401
|
}
|
|
2402
|
+
/**
|
|
2403
|
+
* Triggers the fetch of the answer for the given question and updates the conversation.
|
|
2404
|
+
* Generates an audit event for the user input.
|
|
2405
|
+
*
|
|
2406
|
+
* @param question - The question asked by the user.
|
|
2407
|
+
* @param conversation - The current conversation messages.
|
|
2408
|
+
*/
|
|
2123
2409
|
_fetchAnswer(question, conversation) {
|
|
2124
2410
|
var _a;
|
|
2125
2411
|
const userMsg = { role: 'user', content: question, additionalProperties: { display: true, isUserInput: true, additionalWorkflowProperties: this.config.additionalWorkflowProperties } };
|
|
@@ -2132,7 +2418,7 @@ class ChatComponent extends AbstractFacet {
|
|
|
2132
2418
|
* Depending on the connection's state :
|
|
2133
2419
|
* - If connected => given a list of messages, the chat endpoint is invoked for a continuation and updates the list of messages accordingly.
|
|
2134
2420
|
* - If any other state => a connection error message is displayed in the chat.
|
|
2135
|
-
* @param messages
|
|
2421
|
+
* @param messages The list of messages to invoke the chat endpoint with
|
|
2136
2422
|
*/
|
|
2137
2423
|
fetch(messages) {
|
|
2138
2424
|
var _a;
|
|
@@ -2140,8 +2426,8 @@ class ChatComponent extends AbstractFacet {
|
|
|
2140
2426
|
this.cdr.detectChanges();
|
|
2141
2427
|
if (this.isConnected) {
|
|
2142
2428
|
this.loading$.next(true);
|
|
2143
|
-
(_a = this.
|
|
2144
|
-
this.
|
|
2429
|
+
(_a = this._dataSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
|
|
2430
|
+
this._dataSubscription = this.chatService.fetch(messages, this.query)
|
|
2145
2431
|
.subscribe({
|
|
2146
2432
|
next: res => this.updateData(res.history),
|
|
2147
2433
|
error: () => {
|
|
@@ -2153,6 +2439,15 @@ class ChatComponent extends AbstractFacet {
|
|
|
2153
2439
|
this.terminateFetch();
|
|
2154
2440
|
},
|
|
2155
2441
|
complete: () => {
|
|
2442
|
+
var _a, _b, _c, _d, _e, _f;
|
|
2443
|
+
// Remove the last message if it's an empty message
|
|
2444
|
+
// This is due to the manner in which the chat service handles consecutive messages
|
|
2445
|
+
const lastMessage = (_a = this.messages$.value) === null || _a === void 0 ? void 0 : _a.at(-1);
|
|
2446
|
+
if ((lastMessage === null || lastMessage === void 0 ? void 0 : lastMessage.role) === 'assistant' && (lastMessage === null || lastMessage === void 0 ? void 0 : lastMessage.content) === ""
|
|
2447
|
+
&& !((_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)
|
|
2448
|
+
&& !((_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)) {
|
|
2449
|
+
this.messages$.next((_f = this.messages$.value) === null || _f === void 0 ? void 0 : _f.slice(0, -1));
|
|
2450
|
+
}
|
|
2156
2451
|
this.terminateFetch();
|
|
2157
2452
|
}
|
|
2158
2453
|
});
|
|
@@ -2176,10 +2471,21 @@ class ChatComponent extends AbstractFacet {
|
|
|
2176
2471
|
if (this.chatService instanceof WebSocketChatService) {
|
|
2177
2472
|
// A one-time listener for reconnected event
|
|
2178
2473
|
const onReconnectedHandler = () => {
|
|
2474
|
+
// Get the messages without the last one (the connection error message)
|
|
2179
2475
|
const messages = this.messages$.value.slice(0, -1);
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2476
|
+
// Find the last "user" message in the messages list
|
|
2477
|
+
let index = messages.length - 1;
|
|
2478
|
+
while (index >= 0 && messages[index].role !== 'user') {
|
|
2479
|
+
index--;
|
|
2480
|
+
}
|
|
2481
|
+
// If a user message is found (and it should always be the case), remove all subsequent messages from the chat history
|
|
2482
|
+
// Update the messages in the UI
|
|
2483
|
+
// and fetch the answer from the assistant
|
|
2484
|
+
if (index >= 0) {
|
|
2485
|
+
this.messages$.next(this.messages$.value.slice(0, index + 1));
|
|
2486
|
+
const remappedIndex = this._remapIndexInChatHistory(index);
|
|
2487
|
+
this.chatService.chatHistory = this.chatService.chatHistory.slice(0, remappedIndex + 1);
|
|
2488
|
+
this.fetch(this.chatService.chatHistory);
|
|
2183
2489
|
}
|
|
2184
2490
|
this.retrialAttempts = undefined; // Reset the number of retrial attempts
|
|
2185
2491
|
/**
|
|
@@ -2238,6 +2544,9 @@ class ChatComponent extends AbstractFacet {
|
|
|
2238
2544
|
this.scrollDown();
|
|
2239
2545
|
}
|
|
2240
2546
|
}
|
|
2547
|
+
/**
|
|
2548
|
+
* @returns true if the chat discussion is scrolled down to the bottom, false otherwise
|
|
2549
|
+
*/
|
|
2241
2550
|
_toggleScrollButtonVisibility() {
|
|
2242
2551
|
var _a, _b, _c, _d;
|
|
2243
2552
|
if ((_a = this.messageList) === null || _a === void 0 ? void 0 : _a.nativeElement) {
|
|
@@ -2245,6 +2554,9 @@ class ChatComponent extends AbstractFacet {
|
|
|
2245
2554
|
}
|
|
2246
2555
|
return true;
|
|
2247
2556
|
}
|
|
2557
|
+
/**
|
|
2558
|
+
* Scroll down to the bottom of the chat discussion
|
|
2559
|
+
*/
|
|
2248
2560
|
scrollDown() {
|
|
2249
2561
|
setTimeout(() => {
|
|
2250
2562
|
var _a;
|
|
@@ -2260,12 +2572,40 @@ class ChatComponent extends AbstractFacet {
|
|
|
2260
2572
|
* If the savedChat feature is enabled, the list of saved chats will be refreshed
|
|
2261
2573
|
*/
|
|
2262
2574
|
newChat() {
|
|
2575
|
+
if (!!this.chatService.streaming$.value || !!this.chatService.stoppingGeneration$.value) {
|
|
2576
|
+
return;
|
|
2577
|
+
}
|
|
2263
2578
|
this.chatService.setSavedChatId(undefined); // Reset the savedChatId
|
|
2264
2579
|
this.chatService.generateChatId(); // Generate a new chatId
|
|
2265
2580
|
this.chatService.listSavedChat(); // Refresh the list of saved chats
|
|
2266
2581
|
this.chatService.generateAuditEvent('new-chat', { 'configuration': JSON.stringify(this.chatService.chatConfig$.value) }); // Generate a new chat audit event
|
|
2267
2582
|
this.loadDefaultChat(); // Start a new chat
|
|
2268
2583
|
}
|
|
2584
|
+
/**
|
|
2585
|
+
* Attaches the specified document IDs to the assistant.
|
|
2586
|
+
* If the chat is streaming or stopping the generation, the operation is not allowed.
|
|
2587
|
+
* If no document IDs are provided, the operation is not allowed.
|
|
2588
|
+
* If the action for attaching a document is not defined at the application customization level, an error is logged.
|
|
2589
|
+
* @param ids - An array of document IDs to attach.
|
|
2590
|
+
*/
|
|
2591
|
+
attachToChat(ids) {
|
|
2592
|
+
var _a;
|
|
2593
|
+
if (!!this.chatService.streaming$.value || !!this.chatService.stoppingGeneration$.value) {
|
|
2594
|
+
return;
|
|
2595
|
+
}
|
|
2596
|
+
if (!ids || (ids === null || ids === void 0 ? void 0 : ids.length) < 1) {
|
|
2597
|
+
return;
|
|
2598
|
+
}
|
|
2599
|
+
const attachDocAction = (_a = this.config.modeSettings.actions) === null || _a === void 0 ? void 0 : _a["attachDocAction"];
|
|
2600
|
+
if (!attachDocAction) {
|
|
2601
|
+
console.error(`No action is defined for attaching a document to the assistant "${this.instanceId}"`);
|
|
2602
|
+
return;
|
|
2603
|
+
}
|
|
2604
|
+
const userMsg = { role: 'user', content: '', additionalProperties: { display: false, isUserInput: false, type: "Action", forcedWorkflow: attachDocAction.forcedWorkflow, forcedWorkflowProperties: Object.assign(Object.assign({}, (attachDocAction.forcedWorkflowProperties || {})), { ids }), additionalWorkflowProperties: this.config.additionalWorkflowProperties } };
|
|
2605
|
+
const messages = [...this.chatService.chatHistory, userMsg];
|
|
2606
|
+
this.messages$.next(messages);
|
|
2607
|
+
this.fetch(messages);
|
|
2608
|
+
}
|
|
2269
2609
|
/**
|
|
2270
2610
|
* Start the default chat with the defaultValues settings
|
|
2271
2611
|
* If the chat is meant to be initialized with event === "Query", the corresponding user query message will be added to the chat history
|
|
@@ -2326,7 +2666,7 @@ class ChatComponent extends AbstractFacet {
|
|
|
2326
2666
|
*/
|
|
2327
2667
|
openChat(messages, savedChatId) {
|
|
2328
2668
|
if (!messages || !Array.isArray(messages)) {
|
|
2329
|
-
console.error('Error occurs while trying to load the
|
|
2669
|
+
console.error('Error occurs while trying to load the discussion. Invalid messages received :', messages);
|
|
2330
2670
|
return;
|
|
2331
2671
|
}
|
|
2332
2672
|
if (savedChatId) {
|
|
@@ -2359,17 +2699,38 @@ class ChatComponent extends AbstractFacet {
|
|
|
2359
2699
|
this.question = '';
|
|
2360
2700
|
this.terminateFetch();
|
|
2361
2701
|
}
|
|
2702
|
+
/**
|
|
2703
|
+
* Fetch and Load the saved chat from the saved chat index.
|
|
2704
|
+
* If the saved chat is found, the chat discussion will be loaded with the provided messages and chatId
|
|
2705
|
+
*/
|
|
2362
2706
|
onLoadChat() {
|
|
2363
2707
|
this.loading$.next(true);
|
|
2364
|
-
this.
|
|
2708
|
+
this._sub.add(this.chatService.loadSavedChat$
|
|
2365
2709
|
.pipe(filter(savedChat => !!savedChat), switchMap(savedChat => this.chatService.getSavedChat(savedChat.id)), filter(savedChatHistory => !!savedChatHistory), tap(savedChatHistory => this.openChat(savedChatHistory.history, savedChatHistory.id))).subscribe());
|
|
2366
2710
|
}
|
|
2711
|
+
/**
|
|
2712
|
+
* Stop the generation of the current assistant's answer.
|
|
2713
|
+
* The fetch subscription will be terminated.
|
|
2714
|
+
*/
|
|
2715
|
+
stopGeneration() {
|
|
2716
|
+
this.chatService.stopGeneration().subscribe(() => this.terminateFetch());
|
|
2717
|
+
}
|
|
2718
|
+
/**
|
|
2719
|
+
* Terminate the fetch process by unsubscribing from the data subscription and updating the loading status to false.
|
|
2720
|
+
* Additionally, focus on the chat input if the focusAfterResponse flag is set to true.
|
|
2721
|
+
*/
|
|
2367
2722
|
terminateFetch() {
|
|
2368
2723
|
var _a;
|
|
2369
|
-
(_a = this.
|
|
2370
|
-
this.
|
|
2724
|
+
(_a = this._dataSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
|
|
2725
|
+
this._dataSubscription = undefined;
|
|
2371
2726
|
this.loading$.next(false);
|
|
2372
2727
|
this.cdr.detectChanges();
|
|
2728
|
+
if (this.focusAfterResponse) {
|
|
2729
|
+
setTimeout(() => {
|
|
2730
|
+
var _a;
|
|
2731
|
+
(_a = this.questionInput) === null || _a === void 0 ? void 0 : _a.nativeElement.focus();
|
|
2732
|
+
});
|
|
2733
|
+
}
|
|
2373
2734
|
}
|
|
2374
2735
|
/**
|
|
2375
2736
|
* Copy a previous user message of the chat history to the chat user input.
|
|
@@ -2380,15 +2741,18 @@ class ChatComponent extends AbstractFacet {
|
|
|
2380
2741
|
*/
|
|
2381
2742
|
editMessage(index) {
|
|
2382
2743
|
this.messageToEdit = index;
|
|
2383
|
-
this.
|
|
2384
|
-
this.chatService.
|
|
2744
|
+
this.remappedMessageToEdit = this._remapIndexInChatHistory(index);
|
|
2745
|
+
this.question = this.chatService.chatHistory[this._remapIndexInChatHistory(index)].content;
|
|
2746
|
+
this.chatService.generateAuditEvent('edit.click', { 'rank': this._remapIndexInChatHistory(index) });
|
|
2385
2747
|
}
|
|
2386
2748
|
/**
|
|
2387
2749
|
* Copy a previous assistant message of the chat history to the clipboard.
|
|
2388
2750
|
* @param index The index of the assistant's message to edit
|
|
2389
2751
|
*/
|
|
2390
2752
|
copyMessage(index) {
|
|
2391
|
-
|
|
2753
|
+
// Remap the index in the chat history
|
|
2754
|
+
const idx = this._remapIndexInChatHistory(index);
|
|
2755
|
+
this.chatService.generateAuditEvent('copy.click', { 'rank': idx });
|
|
2392
2756
|
}
|
|
2393
2757
|
/**
|
|
2394
2758
|
* Starting from the provided index, remove all subsequent messages from the chat history and the UI accordingly.
|
|
@@ -2396,14 +2760,50 @@ class ChatComponent extends AbstractFacet {
|
|
|
2396
2760
|
* @param index The index of the assistant's message to regenerate
|
|
2397
2761
|
*/
|
|
2398
2762
|
regenerateMessage(index) {
|
|
2399
|
-
//
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2763
|
+
// Update the messages in the UI by removing all subsequent 'assistant' messages starting from the provided index until the first previous 'user' message
|
|
2764
|
+
let i = index;
|
|
2765
|
+
while (i >= 0 && (this.messages$.value)[i].role !== 'user') {
|
|
2766
|
+
i--;
|
|
2767
|
+
}
|
|
2768
|
+
// It should always be the case that i > 0
|
|
2769
|
+
if (i >= 0) {
|
|
2770
|
+
this.messages$.next(this.messages$.value.slice(0, i + 1));
|
|
2771
|
+
// Remap the index of this found first previous 'user' message in the chat history
|
|
2772
|
+
const idx = this._remapIndexInChatHistory(i);
|
|
2773
|
+
// Define and Update the chat history based on which the assistant will generate a new answer
|
|
2774
|
+
this.chatService.chatHistory = this.chatService.chatHistory.slice(0, idx + 1);
|
|
2775
|
+
// Fetch the answer
|
|
2776
|
+
this.fetch(this.chatService.chatHistory);
|
|
2777
|
+
this.chatService.generateAuditEvent('regenerate.click', { 'rank': idx });
|
|
2778
|
+
}
|
|
2779
|
+
}
|
|
2780
|
+
/**
|
|
2781
|
+
* Remaps the index in the chat history.
|
|
2782
|
+
* The chat history is a list of messages where some messages can be hidden (display set to false).
|
|
2783
|
+
* The index provided as input is the index of the message in the chat history displayed in the UI.
|
|
2784
|
+
* This function should be removed once the backend is updated to add the ids of the messages in the chat history
|
|
2785
|
+
* @param index - The index to be remapped.
|
|
2786
|
+
*/
|
|
2787
|
+
_remapIndexInChatHistory(index) {
|
|
2788
|
+
// a copy of the chat history is created to avoid modifying the original chat history. Additionally, a rank is giving to each message.
|
|
2789
|
+
const history = this.chatService.chatHistory.slice().map((message, idx) => {
|
|
2790
|
+
return Object.assign(Object.assign({}, message), { additionalProperties: Object.assign(Object.assign({}, message.additionalProperties), { rank: idx }) });
|
|
2791
|
+
});
|
|
2792
|
+
// Count the number of hidden messages in messages$ before the provided index
|
|
2793
|
+
// This is mandatory to get the correct rank of the message in the chat history
|
|
2794
|
+
// Since some hidden messages (like 'system' messages) are not displayed in the UI but have been counted in the provided index
|
|
2795
|
+
const numberOfHiddenMessagesInMessages$BeforeIndex = this.messages$.value.slice(0, index).filter(message => !message.additionalProperties.display).length;
|
|
2796
|
+
// remove all messages that have display set to false
|
|
2797
|
+
// this is mandatory since at the point of time when the assistant answers a question,
|
|
2798
|
+
// 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
|
|
2799
|
+
const filteredHistory = history.filter(message => message.additionalProperties.display);
|
|
2800
|
+
// return the index of the message in the filtered history
|
|
2801
|
+
return filteredHistory[index - numberOfHiddenMessagesInMessages$BeforeIndex].additionalProperties.rank;
|
|
2406
2802
|
}
|
|
2803
|
+
/**
|
|
2804
|
+
* Handles the key up event for 'Backspace' and 'Enter' keys.
|
|
2805
|
+
* @param event - The keyboard event.
|
|
2806
|
+
*/
|
|
2407
2807
|
onKeyUp(event) {
|
|
2408
2808
|
switch (event.key) {
|
|
2409
2809
|
case 'Backspace':
|
|
@@ -2420,6 +2820,11 @@ class ChatComponent extends AbstractFacet {
|
|
|
2420
2820
|
break;
|
|
2421
2821
|
}
|
|
2422
2822
|
}
|
|
2823
|
+
/**
|
|
2824
|
+
* Calculates and adjusts the height of the question input element based on its content.
|
|
2825
|
+
* If the Enter key is pressed without the Shift key, it prevents the default behavior.
|
|
2826
|
+
* @param event The keyboard event
|
|
2827
|
+
*/
|
|
2423
2828
|
calculateHeight(event) {
|
|
2424
2829
|
if ((event === null || event === void 0 ? void 0 : event.key) === 'Enter' && !event.shiftKey) {
|
|
2425
2830
|
event === null || event === void 0 ? void 0 : event.preventDefault();
|
|
@@ -2433,43 +2838,59 @@ class ChatComponent extends AbstractFacet {
|
|
|
2433
2838
|
}
|
|
2434
2839
|
/**
|
|
2435
2840
|
* Send a "like" event on clicking on the thumb-up icon of an assistant's message
|
|
2841
|
+
* @param message The assistant message to like
|
|
2436
2842
|
* @param rank The rank of the message to like
|
|
2437
2843
|
*/
|
|
2438
|
-
onLike(rank) {
|
|
2439
|
-
|
|
2844
|
+
onLike(message, rank) {
|
|
2845
|
+
// Remap the index in the chat history
|
|
2846
|
+
const idx = this._remapIndexInChatHistory(rank);
|
|
2847
|
+
this.chatService.generateAuditEvent('thumb-up.click', { rank: idx });
|
|
2848
|
+
this.reportType = 'like';
|
|
2849
|
+
this.messageToReport = message;
|
|
2850
|
+
this.reportComment = undefined;
|
|
2851
|
+
this.reportRank = rank;
|
|
2852
|
+
this.showReport = true;
|
|
2440
2853
|
}
|
|
2441
2854
|
/**
|
|
2442
2855
|
* Send a "dislike" event on clicking on the thumb-down icon of an assistant's message.
|
|
2443
2856
|
* It also opens the issue reporting dialog.
|
|
2444
2857
|
* @param message The assistant message to dislike
|
|
2445
|
-
* @param
|
|
2858
|
+
* @param index The rank of the message to dislike
|
|
2446
2859
|
*/
|
|
2447
2860
|
onDislike(message, rank) {
|
|
2448
|
-
|
|
2449
|
-
|
|
2861
|
+
// Remap the index in the chat history
|
|
2862
|
+
const idx = this._remapIndexInChatHistory(rank);
|
|
2863
|
+
this.chatService.generateAuditEvent('thumb-down.click', { rank: idx });
|
|
2864
|
+
this.reportType = 'dislike';
|
|
2865
|
+
this.messageToReport = message;
|
|
2450
2866
|
this.issueType = '';
|
|
2451
|
-
this.
|
|
2452
|
-
this.
|
|
2453
|
-
this.
|
|
2867
|
+
this.reportComment = undefined;
|
|
2868
|
+
this.reportRank = rank;
|
|
2869
|
+
this.showReport = true;
|
|
2454
2870
|
}
|
|
2455
2871
|
/**
|
|
2456
2872
|
* Report an issue related to the assistant's message.
|
|
2457
2873
|
*/
|
|
2458
|
-
|
|
2874
|
+
sendReport() {
|
|
2459
2875
|
const details = {
|
|
2460
|
-
'
|
|
2461
|
-
'
|
|
2462
|
-
'
|
|
2463
|
-
'rank': this.issueRank,
|
|
2876
|
+
'comment': this.reportComment,
|
|
2877
|
+
'text': this.messageToReport.content,
|
|
2878
|
+
'rank': this.reportRank,
|
|
2464
2879
|
};
|
|
2465
|
-
this.
|
|
2466
|
-
|
|
2880
|
+
if (this.reportType === 'dislike') {
|
|
2881
|
+
details['report-type'] = this.issueType;
|
|
2882
|
+
this.chatService.generateAuditEvent('negative-report.send', details);
|
|
2883
|
+
}
|
|
2884
|
+
else {
|
|
2885
|
+
this.chatService.generateAuditEvent('positive-report.send', details);
|
|
2886
|
+
}
|
|
2887
|
+
this.showReport = false;
|
|
2467
2888
|
}
|
|
2468
2889
|
/**
|
|
2469
|
-
* Close the
|
|
2890
|
+
* Close the reporting dialog.
|
|
2470
2891
|
*/
|
|
2471
|
-
|
|
2472
|
-
this.
|
|
2892
|
+
ignoreReport() {
|
|
2893
|
+
this.showReport = false;
|
|
2473
2894
|
}
|
|
2474
2895
|
/**
|
|
2475
2896
|
* Handle the click on a reference's 'open preview'.
|
|
@@ -2514,27 +2935,69 @@ class ChatComponent extends AbstractFacet {
|
|
|
2514
2935
|
this.suggestAction.emit(action);
|
|
2515
2936
|
this.chatService.generateAuditEvent('suggestedAction.click', { 'text': action.content, 'suggestedAction-type': action.type });
|
|
2516
2937
|
}
|
|
2938
|
+
/**
|
|
2939
|
+
* Handle the click on a chat starter.
|
|
2940
|
+
* @param starter the chat starter.
|
|
2941
|
+
*/
|
|
2942
|
+
chatStarterClick(starter) {
|
|
2943
|
+
this.chatStarter.emit(starter);
|
|
2944
|
+
}
|
|
2945
|
+
/**
|
|
2946
|
+
* It looks for the debug messages available in the current group of "assistant" messages.
|
|
2947
|
+
* By design, the debug messages are only available in the first visible message among the group "assistant" messages.
|
|
2948
|
+
* @param index The rank of the message
|
|
2949
|
+
* @returns The debug messages available in the current group of "assistant" messages
|
|
2950
|
+
*/
|
|
2951
|
+
getDebugMessages(index) {
|
|
2952
|
+
// If it is not an assistant message, return
|
|
2953
|
+
if ((this.messages$.value)[index].role !== 'assistant') {
|
|
2954
|
+
return [];
|
|
2955
|
+
}
|
|
2956
|
+
// Get the array of messages up to the indicated index
|
|
2957
|
+
const array = this.messages$.value.slice(0, index + 1);
|
|
2958
|
+
// If it is an assistant message, look for the debug messages available in the current group of "assistant" messages
|
|
2959
|
+
// By design, the debug messages are only available in the first visible message among the group "assistant" messages.
|
|
2960
|
+
const idx = this.chatService.firstVisibleAssistantMessageIndex(array);
|
|
2961
|
+
if (idx > -1) {
|
|
2962
|
+
return (this.messages$.value)[idx].additionalProperties.$debug || [];
|
|
2963
|
+
}
|
|
2964
|
+
return [];
|
|
2965
|
+
}
|
|
2517
2966
|
/**
|
|
2518
2967
|
* Handle the click on the 'show log info' button of a message.
|
|
2519
|
-
* @param
|
|
2968
|
+
* @param index The rank of the message
|
|
2520
2969
|
*/
|
|
2521
|
-
showDebug(
|
|
2522
|
-
this.debugMessages =
|
|
2970
|
+
showDebug(index) {
|
|
2971
|
+
this.debugMessages = this.getDebugMessages(index);
|
|
2523
2972
|
this.showDebugMessages = true;
|
|
2524
2973
|
this.cdr.detectChanges();
|
|
2525
2974
|
}
|
|
2975
|
+
/**
|
|
2976
|
+
* Verify whether the current message is an assistant message and that all following messages are assistant ones
|
|
2977
|
+
* Used to keep the "View progress" opened even though the assistant is sending additional messages after the current one
|
|
2978
|
+
* @param messages the list of current messages
|
|
2979
|
+
* @param index the index of the current message
|
|
2980
|
+
* @returns if this messages and the following ones (if any) are the last ones
|
|
2981
|
+
*/
|
|
2982
|
+
isAssistantLastMessages(messages, index) {
|
|
2983
|
+
for (let i = index; i < messages.length; i++) {
|
|
2984
|
+
if (messages[i].role !== 'assistant')
|
|
2985
|
+
return false;
|
|
2986
|
+
}
|
|
2987
|
+
return true;
|
|
2988
|
+
}
|
|
2526
2989
|
}
|
|
2527
2990
|
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: [
|
|
2991
|
+
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
2992
|
RestChatService,
|
|
2530
2993
|
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 });
|
|
2994
|
+
], 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
2995
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ChatComponent, decorators: [{
|
|
2533
2996
|
type: Component,
|
|
2534
2997
|
args: [{ selector: 'sq-chat-v3', providers: [
|
|
2535
2998
|
RestChatService,
|
|
2536
2999
|
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"] }]
|
|
3000
|
+
], 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
3001
|
}], ctorParameters: function () { return []; }, propDecorators: { instanceId: [{
|
|
2539
3002
|
type: Input
|
|
2540
3003
|
}], query: [{
|
|
@@ -2547,6 +3010,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImpor
|
|
|
2547
3010
|
type: Input
|
|
2548
3011
|
}], automaticScrollToLastResponse: [{
|
|
2549
3012
|
type: Input
|
|
3013
|
+
}], focusAfterResponse: [{
|
|
3014
|
+
type: Input
|
|
2550
3015
|
}], chat: [{
|
|
2551
3016
|
type: Input
|
|
2552
3017
|
}], assistantMessageIcon: [{
|
|
@@ -2573,6 +3038,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImpor
|
|
|
2573
3038
|
type: Output
|
|
2574
3039
|
}], suggestAction: [{
|
|
2575
3040
|
type: Output
|
|
3041
|
+
}], chatStarter: [{
|
|
3042
|
+
type: Output
|
|
2576
3043
|
}], messageList: [{
|
|
2577
3044
|
type: ViewChild,
|
|
2578
3045
|
args: ['messageList']
|
|
@@ -2582,9 +3049,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImpor
|
|
|
2582
3049
|
}], loadingTpl: [{
|
|
2583
3050
|
type: ContentChild,
|
|
2584
3051
|
args: ['loadingTpl']
|
|
2585
|
-
}],
|
|
3052
|
+
}], reportTpl: [{
|
|
2586
3053
|
type: ContentChild,
|
|
2587
|
-
args: ['
|
|
3054
|
+
args: ['reportTpl']
|
|
2588
3055
|
}], tokenConsumptionTpl: [{
|
|
2589
3056
|
type: ContentChild,
|
|
2590
3057
|
args: ['tokenConsumptionTpl']
|
|
@@ -2622,6 +3089,9 @@ class SavedChatsComponent {
|
|
|
2622
3089
|
}));
|
|
2623
3090
|
}
|
|
2624
3091
|
onLoad(savedChat) {
|
|
3092
|
+
if (!!this.chatService.streaming$.value || !!this.chatService.stoppingGeneration$.value) {
|
|
3093
|
+
return;
|
|
3094
|
+
}
|
|
2625
3095
|
this.chatService.setSavedChatId(savedChat.id);
|
|
2626
3096
|
this.chatService.generateChatId(savedChat.id);
|
|
2627
3097
|
this.chatService.loadSavedChat$.next(savedChat);
|
|
@@ -2629,7 +3099,11 @@ class SavedChatsComponent {
|
|
|
2629
3099
|
this.chatService.listSavedChat();
|
|
2630
3100
|
this.load.emit(savedChat);
|
|
2631
3101
|
}
|
|
2632
|
-
onRename(savedChat) {
|
|
3102
|
+
onRename(event, savedChat) {
|
|
3103
|
+
event.stopPropagation();
|
|
3104
|
+
if (!!this.chatService.streaming$.value || !!this.chatService.stoppingGeneration$.value) {
|
|
3105
|
+
return;
|
|
3106
|
+
}
|
|
2633
3107
|
const model = {
|
|
2634
3108
|
title: 'Rename saved discussion',
|
|
2635
3109
|
message: `Please enter a new name for the discussion "${savedChat.title}".`,
|
|
@@ -2655,7 +3129,11 @@ class SavedChatsComponent {
|
|
|
2655
3129
|
}
|
|
2656
3130
|
});
|
|
2657
3131
|
}
|
|
2658
|
-
onDelete(savedChat) {
|
|
3132
|
+
onDelete(event, savedChat) {
|
|
3133
|
+
event.stopPropagation();
|
|
3134
|
+
if (!!this.chatService.streaming$.value || !!this.chatService.stoppingGeneration$.value) {
|
|
3135
|
+
return;
|
|
3136
|
+
}
|
|
2659
3137
|
this.modalService
|
|
2660
3138
|
.confirm({
|
|
2661
3139
|
title: "Delete saved discussion",
|
|
@@ -2732,10 +3210,10 @@ class SavedChatsComponent {
|
|
|
2732
3210
|
}
|
|
2733
3211
|
}
|
|
2734
3212
|
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\"
|
|
3213
|
+
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
3214
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: SavedChatsComponent, decorators: [{
|
|
2737
3215
|
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\"
|
|
3216
|
+
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
3217
|
}], propDecorators: { instanceId: [{
|
|
2740
3218
|
type: Input
|
|
2741
3219
|
}], load: [{
|