@sinequa/assistant 3.9.5 → 3.9.6-rc2
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 +17 -25
- package/chat/chat-message/i18n/de.json +11 -0
- package/chat/chat-reference/chat-reference.component.d.ts +18 -8
- package/chat/chat-reference/i18n/de.json +4 -0
- package/chat/chat-settings-v3/i18n/de.json +14 -0
- package/chat/chat.component.d.ts +2 -1
- package/chat/debug-message/debug-message-details/debug-message-details.component.d.ts +2 -3
- package/chat/debug-message/i18n/de.json +3 -0
- package/chat/dialogs/i18n/de.json +19 -0
- package/chat/directives/copy-to-clipboard.directive.d.ts +8 -0
- package/chat/documents-upload/document-list/document-list.component.d.ts +4 -9
- package/chat/documents-upload/document-overview/document-overview.component.d.ts +3 -17
- package/chat/documents-upload/document-upload/document-upload.component.d.ts +3 -8
- package/chat/documents-upload/documents-upload.service.d.ts +7 -16
- package/chat/documents-upload/i18n/de.json +24 -0
- package/chat/i18n/de.json +42 -0
- package/chat/markdown-it-plugins/code-block.plugin.d.ts +2 -0
- package/chat/markdown-it-plugins/image-reference.plugin.d.ts +3 -0
- package/chat/markdown-it-plugins/link.plugin.d.ts +5 -0
- package/chat/markdown-it-plugins/page-reference.plugin.d.ts +3 -0
- package/chat/markdown-it-plugins/reference.plugin.d.ts +7 -0
- package/chat/public-api.d.ts +2 -1
- package/chat/references/i18n/de.json +6 -0
- package/chat/references/references.component.d.ts +43 -0
- package/chat/saved-chats/i18n/de.json +5 -0
- package/chat/services/app.service.d.ts +2 -1
- package/chat/services/custom-elements.service.d.ts +13 -0
- package/chat/smart-renderer/smart-renderer.d.ts +23 -0
- package/chat/token-progress-bar/i18n/de.json +4 -0
- package/chat/tooltip/tooltip.directive.d.ts +2 -2
- package/chat/types.d.ts +8 -42
- package/esm2022/chat/chat-message/chat-message.component.mjs +33 -135
- package/esm2022/chat/chat-reference/chat-reference.component.mjs +60 -26
- package/esm2022/chat/chat-settings-v3/chat-settings-v3.component.mjs +1 -1
- package/esm2022/chat/chat.component.mjs +48 -12
- package/esm2022/chat/chat.service.mjs +3 -2
- package/esm2022/chat/debug-message/debug-message-details/debug-message-details.component.mjs +2 -2
- package/esm2022/chat/debug-message/debug-message.service.mjs +4 -7
- package/esm2022/chat/directives/copy-to-clipboard.directive.mjs +68 -0
- package/esm2022/chat/documents-upload/document-list/document-list.component.mjs +21 -22
- package/esm2022/chat/documents-upload/document-overview/document-overview.component.mjs +8 -31
- package/esm2022/chat/documents-upload/document-upload/document-upload.component.mjs +12 -14
- package/esm2022/chat/documents-upload/documents-upload.service.mjs +25 -44
- package/esm2022/chat/markdown-it-plugins/code-block.plugin.mjs +14 -0
- package/esm2022/chat/markdown-it-plugins/image-reference.plugin.mjs +58 -0
- package/esm2022/chat/markdown-it-plugins/link.plugin.mjs +15 -0
- package/esm2022/chat/markdown-it-plugins/page-reference.plugin.mjs +60 -0
- package/esm2022/chat/markdown-it-plugins/reference.plugin.mjs +68 -0
- package/esm2022/chat/public-api.mjs +3 -2
- package/esm2022/chat/references/references.component.mjs +290 -0
- package/esm2022/chat/saved-chats/saved-chats.component.mjs +4 -3
- package/esm2022/chat/saved-chats/saved-chats.service.mjs +9 -12
- package/esm2022/chat/services/app.service.mjs +8 -2
- package/esm2022/chat/services/assistant-configuration.service.mjs +9 -18
- package/esm2022/chat/services/assistant-metadata.service.mjs +3 -3
- package/esm2022/chat/services/assistant-tokens-tracking.service.mjs +3 -6
- package/esm2022/chat/services/custom-elements.service.mjs +43 -0
- package/esm2022/chat/smart-renderer/smart-renderer.mjs +103 -0
- package/esm2022/chat/tooltip/tooltip.directive.mjs +9 -9
- package/esm2022/chat/types.mjs +2 -5
- package/fesm2022/sinequa-assistant-chat.mjs +908 -497
- package/fesm2022/sinequa-assistant-chat.mjs.map +1 -1
- package/package.json +4 -6
- package/chat/prompt.component.d.ts +0 -25
- package/chat/unified-plugins/embedded-image-reference.plugin.d.ts +0 -3
- package/chat/unified-plugins/embedded-page-reference.plugin.d.ts +0 -3
- package/esm2022/chat/prompt.component.mjs +0 -88
- package/esm2022/chat/unified-plugins/embedded-image-reference.plugin.mjs +0 -56
- package/esm2022/chat/unified-plugins/embedded-page-reference.plugin.mjs +0 -57
|
@@ -1,34 +1,31 @@
|
|
|
1
1
|
import * as i1 from '@angular/common';
|
|
2
2
|
import { CommonModule, NgTemplateOutlet } from '@angular/common';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
|
-
import { Injectable, EventEmitter, inject, Component, Input, Output, ViewEncapsulation, ChangeDetectionStrategy, Directive,
|
|
4
|
+
import { Injectable, EventEmitter, inject, Component, Input, Output, ViewEncapsulation, ChangeDetectionStrategy, Directive, HostListener, input, output, viewChild, signal, computed, Pipe, effect, LOCALE_ID, InjectionToken, ElementRef, createComponent, ChangeDetectorRef, ViewChild, ContentChild, Injector } from '@angular/core';
|
|
5
5
|
import * as i2 from '@angular/forms';
|
|
6
|
-
import { FormsModule
|
|
6
|
+
import { FormsModule } from '@angular/forms';
|
|
7
7
|
import { Subscription, of, tap, switchMap, filter, delay, from, throwError, Subject, fromEvent, merge, Observable, BehaviorSubject, defer, take as take$1, forkJoin, map as map$1, catchError as catchError$1, finalize as finalize$1, combineLatest, EMPTY, interval, startWith, takeWhile } from 'rxjs';
|
|
8
8
|
import { provideTranslocoScope, TranslocoPipe, TranslocoService } from '@jsverse/transloco';
|
|
9
|
-
import { isAuthenticated, sha512, patchUserSettings, get, post, globalConfig, getToken,
|
|
9
|
+
import { fetchApp, isAuthenticated, sha512, patchUserSettings, get, post, globalConfig, getToken, fetchUserSettings, fetchPrincipal, guid, Audit, setGlobalConfig } from '@sinequa/atomic';
|
|
10
10
|
import { HubConnectionBuilder, LogLevel, HttpTransportType, HubConnectionState } from '@microsoft/signalr';
|
|
11
|
-
import * as i4 from 'ngx-remark';
|
|
12
|
-
import { RemarkModule } from 'ngx-remark';
|
|
13
|
-
import 'prismjs-components-importer/esm';
|
|
14
|
-
import 'prismjs/plugins/autoloader/prism-autoloader';
|
|
15
|
-
import remarkGfm from 'remark-gfm';
|
|
16
|
-
import remarkParse from 'remark-parse';
|
|
17
|
-
import { unified } from 'unified';
|
|
18
|
-
import { visit, CONTINUE, EXIT } from 'unist-util-visit';
|
|
19
11
|
import { Chart, registerables } from 'chart.js';
|
|
20
12
|
import { ComponentPortal } from '@angular/cdk/portal';
|
|
21
13
|
import { trigger, transition, style, animate } from '@angular/animations';
|
|
22
14
|
import * as i1$1 from '@angular/cdk/overlay';
|
|
23
15
|
import SafeColor from 'safecolor';
|
|
16
|
+
import markdownit from 'markdown-it';
|
|
17
|
+
import * as Prism from 'prismjs';
|
|
18
|
+
import 'prismjs-components-importer/esm';
|
|
19
|
+
import 'prismjs/plugins/autoloader/prism-autoloader';
|
|
20
|
+
import * as i1$2 from '@angular/platform-browser';
|
|
24
21
|
import { Clipboard } from '@angular/cdk/clipboard';
|
|
25
22
|
import { toDate, parseISO, isToday, isYesterday, isThisWeek, differenceInDays, endOfYesterday, isThisMonth, differenceInMonths, isThisQuarter, isThisYear, differenceInYears, format } from 'date-fns';
|
|
26
23
|
import { tap as tap$1, catchError, map, mergeMap, takeUntil, take, switchMap as switchMap$1, finalize } from 'rxjs/operators';
|
|
27
24
|
import { z } from 'zod';
|
|
28
|
-
import * as Prism$1 from 'prismjs';
|
|
29
25
|
import * as i2$1 from '@flowjs/ngx-flow';
|
|
30
26
|
import { NgxFlowModule } from '@flowjs/ngx-flow';
|
|
31
27
|
import { HttpClient, HttpHeaders, HttpEventType } from '@angular/common/http';
|
|
28
|
+
import { createCustomElement } from '@angular/elements';
|
|
32
29
|
|
|
33
30
|
/**
|
|
34
31
|
* A service to create and manage instances of ChatService dynamically based on the provided component references and the implementation type (http or websocket)
|
|
@@ -76,7 +73,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
|
|
|
76
73
|
|
|
77
74
|
class AppService {
|
|
78
75
|
constructor() {
|
|
79
|
-
this.app =
|
|
76
|
+
this.app = undefined;
|
|
77
|
+
}
|
|
78
|
+
async init() {
|
|
79
|
+
if (!this.app) {
|
|
80
|
+
this.app = await fetchApp();
|
|
81
|
+
}
|
|
80
82
|
}
|
|
81
83
|
get appName() {
|
|
82
84
|
return this?.app?.name || "";
|
|
@@ -498,7 +500,7 @@ class TooltipDirective {
|
|
|
498
500
|
*/
|
|
499
501
|
this.hoverableTooltip = false;
|
|
500
502
|
/**
|
|
501
|
-
* Applies the "has-tooltip" class to its host when displayed
|
|
503
|
+
* Applies the "has-tooltip" class to its host when displayed (Angular 20 host directive syntax)
|
|
502
504
|
*/
|
|
503
505
|
this.hasTooltip = false;
|
|
504
506
|
}
|
|
@@ -610,13 +612,16 @@ class TooltipDirective {
|
|
|
610
612
|
return Array.from(this.fallbackPlacements).map(p => this.position(p));
|
|
611
613
|
}
|
|
612
614
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TooltipDirective, deps: [{ token: i1$1.Overlay }, { token: i1$1.OverlayPositionBuilder }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
613
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: TooltipDirective, isStandalone: true, selector: "[sqTooltip]", inputs: { value: ["sqTooltip", "value"], data: ["sqTooltipData", "data"], template: ["sqTooltipTemplate", "template"], placement: "placement", fallbackPlacements: "fallbackPlacements", delay: "delay", hoverableTooltip: "hoverableTooltip", tooltipClass: "tooltipClass" }, host: { listeners: { "mouseenter": "show()", "mousedown": "mouseClick()", "mouseleave": "hide()" }
|
|
615
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: TooltipDirective, isStandalone: true, selector: "[sqTooltip]", inputs: { value: ["sqTooltip", "value"], data: ["sqTooltipData", "data"], template: ["sqTooltipTemplate", "template"], placement: "placement", fallbackPlacements: "fallbackPlacements", delay: "delay", hoverableTooltip: "hoverableTooltip", tooltipClass: "tooltipClass" }, host: { attributes: { "class.has-tooltip": "hasTooltip" }, listeners: { "mouseenter": "show()", "mousedown": "mouseClick()", "mouseleave": "hide()" } }, ngImport: i0 }); }
|
|
614
616
|
}
|
|
615
617
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TooltipDirective, decorators: [{
|
|
616
618
|
type: Directive,
|
|
617
619
|
args: [{
|
|
618
620
|
selector: "[sqTooltip]",
|
|
619
|
-
standalone: true
|
|
621
|
+
standalone: true,
|
|
622
|
+
host: {
|
|
623
|
+
'class.has-tooltip': 'hasTooltip'
|
|
624
|
+
}
|
|
620
625
|
}]
|
|
621
626
|
}], ctorParameters: () => [{ type: i1$1.Overlay }, { type: i1$1.OverlayPositionBuilder }, { type: i0.ElementRef }], propDecorators: { value: [{
|
|
622
627
|
type: Input,
|
|
@@ -637,9 +642,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
|
|
|
637
642
|
type: Input
|
|
638
643
|
}], tooltipClass: [{
|
|
639
644
|
type: Input
|
|
640
|
-
}], hasTooltip: [{
|
|
641
|
-
type: HostBinding,
|
|
642
|
-
args: ['class.has-tooltip']
|
|
643
645
|
}], show: [{
|
|
644
646
|
type: HostListener,
|
|
645
647
|
args: ["mouseenter"]
|
|
@@ -653,36 +655,71 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
|
|
|
653
655
|
|
|
654
656
|
class ChatReferenceComponent {
|
|
655
657
|
constructor() {
|
|
656
|
-
this.
|
|
657
|
-
this.
|
|
658
|
+
this.reference = input.required();
|
|
659
|
+
this.attachment = input.required();
|
|
660
|
+
this.partId = input(undefined);
|
|
661
|
+
this.referenceMap = input(undefined);
|
|
662
|
+
this.images = input([]);
|
|
663
|
+
this.pages = input([]);
|
|
664
|
+
this.openDocument = output();
|
|
665
|
+
this.openPreview = output();
|
|
666
|
+
this.modalTpl = viewChild("modal");
|
|
667
|
+
this.modalRef = signal({});
|
|
668
|
+
this.groupedImagesIds = computed(() => {
|
|
669
|
+
// Suppose images() returns an array like ['1.1.1', '1.1.2', '1.1.3']
|
|
670
|
+
const groups = {};
|
|
671
|
+
for (const id of this.images()) {
|
|
672
|
+
const parts = id.split(".").map(Number);
|
|
673
|
+
if (parts.length < 3)
|
|
674
|
+
continue;
|
|
675
|
+
const groupKey = parts[1].toString();
|
|
676
|
+
if (!groups[groupKey])
|
|
677
|
+
groups[groupKey] = [];
|
|
678
|
+
groups[groupKey].push(parts[2]);
|
|
679
|
+
}
|
|
680
|
+
return groups;
|
|
681
|
+
});
|
|
682
|
+
this.groupedPagesIds = computed(() => {
|
|
683
|
+
// Suppose images() returns an array like ['1.1', '1.2', '1.3']
|
|
684
|
+
const groups = {};
|
|
685
|
+
for (const id of this.pages()) {
|
|
686
|
+
const parts = id.split(".").map(Number);
|
|
687
|
+
const groupKey = parts[0].toString();
|
|
688
|
+
if (!groups[groupKey])
|
|
689
|
+
groups[groupKey] = [];
|
|
690
|
+
groups[groupKey].push(parts[1]);
|
|
691
|
+
}
|
|
692
|
+
return groups;
|
|
693
|
+
});
|
|
694
|
+
this.findImage = (arr, number) => arr.find((p) => p.imageNumber === number);
|
|
695
|
+
this.findPage = (arr, number) => arr.find((p) => p.pageNumber === number);
|
|
658
696
|
}
|
|
659
697
|
get parts() {
|
|
660
|
-
if (!this.attachment)
|
|
698
|
+
if (!this.attachment())
|
|
661
699
|
return [];
|
|
662
|
-
return this.attachment.parts.filter(part => (!this.partId || part.partId === this.partId) && !!part.text);
|
|
700
|
+
return this.attachment().parts.filter((part) => (!this.partId() || part.partId === this.partId()) && !!part.text);
|
|
663
701
|
}
|
|
664
702
|
expandAttachment() {
|
|
665
|
-
if (this.partId)
|
|
703
|
+
if (this.partId())
|
|
666
704
|
return;
|
|
667
|
-
this.attachment[
|
|
705
|
+
this.attachment()["$expanded"] = !this.attachment()["$expanded"];
|
|
706
|
+
}
|
|
707
|
+
modalClicked(ref) {
|
|
708
|
+
this.modalRef.set(ref);
|
|
709
|
+
this.modalTpl()?.nativeElement?.showModal();
|
|
668
710
|
}
|
|
669
711
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ChatReferenceComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
670
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
712
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: ChatReferenceComponent, isStandalone: true, selector: "sq-chat-reference", inputs: { reference: { classPropertyName: "reference", publicName: "reference", isSignal: true, isRequired: true, transformFunction: null }, attachment: { classPropertyName: "attachment", publicName: "attachment", isSignal: true, isRequired: true, transformFunction: null }, partId: { classPropertyName: "partId", publicName: "partId", isSignal: true, isRequired: false, transformFunction: null }, referenceMap: { classPropertyName: "referenceMap", publicName: "referenceMap", isSignal: true, isRequired: false, transformFunction: null }, images: { classPropertyName: "images", publicName: "images", isSignal: true, isRequired: false, transformFunction: null }, pages: { classPropertyName: "pages", publicName: "pages", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { openDocument: "openDocument", openPreview: "openPreview" }, providers: [provideTranslocoScope("chat-reference")], viewQueries: [{ propertyName: "modalTpl", first: true, predicate: ["modal"], descendants: true, isSignal: true }], ngImport: i0, template: "<div [class.reference-tooltip]=\"!!partId()\">\n <div\n class=\"reference-data\"\n [class.expanded]=\"attachment()['$expanded'] || !!partId()\"\n (click)=\"expandAttachment()\"\n >\n <span class=\"reference me-1\">{{ reference() }}</span>\n\n <sq-format-icon [extension]=\"attachment().record.fileext\"></sq-format-icon>\n\n <span class=\"title\" [id]=\"'attachment-' + attachment().recordId\">\n {{ attachment().record.title }}\n </span>\n\n <button\n type=\"button\"\n (click)=\"$event.stopPropagation(); openPreview.emit(attachment())\"\n [sqTooltip]=\"!partId() ? ('chatReference.previewDocument' | transloco) : ''\"\n class=\"bg-transparent border-0 p-0 m-0 cursor-pointer text-inherit leading-none inline-flex items-center justify-center\"\n >\n <i class=\"fas fa-eye\"></i>\n </button>\n\n\n @if (attachment().record.url1 || attachment().record.originalUrl) {\n <button\n type=\"button\"\n (click)=\"$event.stopPropagation(); openDocument.emit(attachment())\"\n [sqTooltip]=\"!partId() ? ('chatReference.openDocument' | transloco) : ''\"\n class=\"bg-transparent border-0 p-0 m-0 cursor-pointer text-inherit leading-none inline-flex items-center justify-center\"\n >\n <i class=\"fas fa-arrow-up-right-from-square\"></i>\n </button>\n }\n </div>\n\n @if (!!partId() || (attachment()['$expanded'] && parts.length)) {\n <div class=\"reference-passages\">\n @for (part of parts; track $index) {\n <div class=\"reference-passage\">\n <span class=\"reference me-1\">{{ reference() }}.{{ part.partId }}</span>\n <span class=\"w-100 pe-2\" [innerHTML]=\"part.text\"></span>\n </div>\n\n @for (imageId of groupedImagesIds()[part.partId]; track $index) { \n @let ref = part?.images?.[imageId - 1];\n @if (ref?.url) {\n <div\n class=\"gap-1 ms-2 my-2 items-start\"\n style=\"display: flex; align-items: start\"\n >\n <span class=\"reference\" style=\"flex-shrink: 0;\">\n {{ \"Img-\" + reference() + \".\" + part.partId + \".\" + imageId }}\n </span>\n\n <img\n [src]=\"ref.url\"\n [alt]=\"ref.description\"\n (click)=\"modalClicked(ref)\"\n />\n </div>\n }\n }\n }\n \n @for (pageId of groupedPagesIds()[reference()]; track $index) {\n @let ref = findPage(referenceMap()?.get(reference())?.pages, pageId);\n @if (ref?.url) {\n <div\n class=\"gap-1 ms-2 my-2 items-start\"\n style=\"display: flex; align-items: start\"\n >\n <span class=\"reference\" style=\"flex-shrink: 0;\">{{ \"Page-\" + reference() + \".\" + pageId }}</span>\n\n <img\n [src]=\"ref.url\"\n [alt]=\"ref.description\"\n (click)=\"modalClicked(ref)\"\n />\n </div>\n }\n }\n </div>\n }\n</div>\n\n<dialog #modal>\n <button class=\"close\" (click)=\"modalTpl()?.nativeElement?.close()\">\n <i class=\"fas fa-xmark\"></i>\n </button>\n\n <img [src]=\"modalRef().url\" [alt]=\"modalRef().description\" />\n</dialog>\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-uploaded-doc-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;--ast-report-bg: #070707}: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 span.title{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}.w-100{width:100%}dialog ::backdrop{background-color:#000c}dialog img{max-width:90vw;max-height:90vh;object-fit:contain}dialog button.close{position:absolute;top:0;right:0;border:solid 1px black;background-color:#fff;color:#000;font-size:1rem;cursor:pointer}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: FormatIconComponent, selector: "sq-format-icon", inputs: ["extension"] }, { kind: "directive", type: TooltipDirective, selector: "[sqTooltip]", inputs: ["sqTooltip", "sqTooltipData", "sqTooltipTemplate", "placement", "fallbackPlacements", "delay", "hoverableTooltip", "tooltipClass"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] }); }
|
|
671
713
|
}
|
|
672
714
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ChatReferenceComponent, decorators: [{
|
|
673
715
|
type: Component,
|
|
674
|
-
args: [{ selector:
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
}],
|
|
680
|
-
|
|
681
|
-
}], openDocument: [{
|
|
682
|
-
type: Output
|
|
683
|
-
}], openPreview: [{
|
|
684
|
-
type: Output
|
|
685
|
-
}] } });
|
|
716
|
+
args: [{ selector: "sq-chat-reference", standalone: true, imports: [
|
|
717
|
+
CommonModule,
|
|
718
|
+
FormatIconComponent,
|
|
719
|
+
TooltipDirective,
|
|
720
|
+
TranslocoPipe,
|
|
721
|
+
], providers: [provideTranslocoScope("chat-reference")], template: "<div [class.reference-tooltip]=\"!!partId()\">\n <div\n class=\"reference-data\"\n [class.expanded]=\"attachment()['$expanded'] || !!partId()\"\n (click)=\"expandAttachment()\"\n >\n <span class=\"reference me-1\">{{ reference() }}</span>\n\n <sq-format-icon [extension]=\"attachment().record.fileext\"></sq-format-icon>\n\n <span class=\"title\" [id]=\"'attachment-' + attachment().recordId\">\n {{ attachment().record.title }}\n </span>\n\n <button\n type=\"button\"\n (click)=\"$event.stopPropagation(); openPreview.emit(attachment())\"\n [sqTooltip]=\"!partId() ? ('chatReference.previewDocument' | transloco) : ''\"\n class=\"bg-transparent border-0 p-0 m-0 cursor-pointer text-inherit leading-none inline-flex items-center justify-center\"\n >\n <i class=\"fas fa-eye\"></i>\n </button>\n\n\n @if (attachment().record.url1 || attachment().record.originalUrl) {\n <button\n type=\"button\"\n (click)=\"$event.stopPropagation(); openDocument.emit(attachment())\"\n [sqTooltip]=\"!partId() ? ('chatReference.openDocument' | transloco) : ''\"\n class=\"bg-transparent border-0 p-0 m-0 cursor-pointer text-inherit leading-none inline-flex items-center justify-center\"\n >\n <i class=\"fas fa-arrow-up-right-from-square\"></i>\n </button>\n }\n </div>\n\n @if (!!partId() || (attachment()['$expanded'] && parts.length)) {\n <div class=\"reference-passages\">\n @for (part of parts; track $index) {\n <div class=\"reference-passage\">\n <span class=\"reference me-1\">{{ reference() }}.{{ part.partId }}</span>\n <span class=\"w-100 pe-2\" [innerHTML]=\"part.text\"></span>\n </div>\n\n @for (imageId of groupedImagesIds()[part.partId]; track $index) { \n @let ref = part?.images?.[imageId - 1];\n @if (ref?.url) {\n <div\n class=\"gap-1 ms-2 my-2 items-start\"\n style=\"display: flex; align-items: start\"\n >\n <span class=\"reference\" style=\"flex-shrink: 0;\">\n {{ \"Img-\" + reference() + \".\" + part.partId + \".\" + imageId }}\n </span>\n\n <img\n [src]=\"ref.url\"\n [alt]=\"ref.description\"\n (click)=\"modalClicked(ref)\"\n />\n </div>\n }\n }\n }\n \n @for (pageId of groupedPagesIds()[reference()]; track $index) {\n @let ref = findPage(referenceMap()?.get(reference())?.pages, pageId);\n @if (ref?.url) {\n <div\n class=\"gap-1 ms-2 my-2 items-start\"\n style=\"display: flex; align-items: start\"\n >\n <span class=\"reference\" style=\"flex-shrink: 0;\">{{ \"Page-\" + reference() + \".\" + pageId }}</span>\n\n <img\n [src]=\"ref.url\"\n [alt]=\"ref.description\"\n (click)=\"modalClicked(ref)\"\n />\n </div>\n }\n }\n </div>\n }\n</div>\n\n<dialog #modal>\n <button class=\"close\" (click)=\"modalTpl()?.nativeElement?.close()\">\n <i class=\"fas fa-xmark\"></i>\n </button>\n\n <img [src]=\"modalRef().url\" [alt]=\"modalRef().description\" />\n</dialog>\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-uploaded-doc-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;--ast-report-bg: #070707}: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 span.title{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}.w-100{width:100%}dialog ::backdrop{background-color:#000c}dialog img{max-width:90vw;max-height:90vh;object-fit:contain}dialog button.close{position:absolute;top:0;right:0;border:solid 1px black;background-color:#fff;color:#000;font-size:1rem;cursor:pointer}\n"] }]
|
|
722
|
+
}] });
|
|
686
723
|
|
|
687
724
|
class InitialsAvatarComponent {
|
|
688
725
|
constructor() {
|
|
@@ -986,116 +1023,311 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
|
|
|
986
1023
|
`, 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-uploaded-doc-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;--ast-report-bg: #070707}: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:flex;flex-direction:column;gap:.5rem;padding:.5rem;background-color:#00f;box-shadow:0 .5rem 1rem #00000026;font-size:.875rem;background-color:var(--ast-reference-expanded-hover-bg, white)}sq-format-icon{color:var(--ast-secondary-color, #FF732E)}header{display:flex;flex-direction:row;align-items:baseline;gap:var(--ast-size-1, .25rem);cursor:pointer}header a{color:var(--ast-secondary-color, #FF732E);font-weight:var(--font-weight-bold, 500)}header i{padding:var(--ast-size-1, .25rem);margin-left:var(--ast-size-1, .25rem);cursor:pointer;color:var(--ast-reference-icon-color, black)}header i.active{color:var(--ast-reference-icon-active-color, white);background-color:var(--ast-secondary-color, #FF732E)}header p{flex-grow:1;flex-shrink:1;margin:0!important;overflow-x:hidden;text-overflow:ellipsis}img{max-width:30vw;max-height:30vh;object-fit:contain}dialog ::backdrop{background-color:#000c}dialog img{max-width:90vw;max-height:90vh;object-fit:contain}dialog button.close{position:absolute;top:0;right:0;border:solid 1px black;background-color:#fff;color:#000;font-size:1rem;cursor:pointer}\n"] }]
|
|
987
1024
|
}] });
|
|
988
1025
|
|
|
1026
|
+
function markdownItCodeBlockPlugin(md) {
|
|
1027
|
+
const defaultFenceRenderer = md.renderer.rules.fence;
|
|
1028
|
+
md.renderer.rules.fence = (tokens, idx, options, env, self) => {
|
|
1029
|
+
const token = tokens[idx];
|
|
1030
|
+
const info = token.info ? md.utils.unescapeAll(token.info).trim() : '';
|
|
1031
|
+
const langName = info.split(/(\s+)/g)[0];
|
|
1032
|
+
const defaultRendered = defaultFenceRenderer(tokens, idx, options, env, self);
|
|
1033
|
+
// We add a wrapper and a copy button.
|
|
1034
|
+
// The button will have an attribute `[copy-to-clipboard]` which can be handled by an Angular directive
|
|
1035
|
+
// to implement the copy functionality. The code to be copied is passed as an input.
|
|
1036
|
+
return `<code-block-reference langname="${langName}">${defaultRendered}</code-block-reference>`;
|
|
1037
|
+
};
|
|
1038
|
+
}
|
|
1039
|
+
|
|
989
1040
|
const EMBEDDED_IMAGE_NAME = "embedded-image-reference";
|
|
990
1041
|
const EMBEDDED_IMAGE_REGEX = /\[(Img-([0-9]+(?:\.[0-9]+){2}))\]/g;
|
|
991
|
-
function
|
|
992
|
-
|
|
993
|
-
const
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
}
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1042
|
+
function markdownItImageReferencePlugin(md) {
|
|
1043
|
+
md.core.ruler.after("inline", EMBEDDED_IMAGE_NAME, (state) => {
|
|
1044
|
+
const getEmbeddedImageReference = state?.env?.getEmbeddedImageReference;
|
|
1045
|
+
state.tokens.forEach((blockToken) => {
|
|
1046
|
+
if (blockToken.type !== "inline" || !blockToken.children)
|
|
1047
|
+
return;
|
|
1048
|
+
const newChildren = [];
|
|
1049
|
+
blockToken.children.forEach((token) => {
|
|
1050
|
+
if (token.type !== "text") {
|
|
1051
|
+
newChildren.push(token);
|
|
1052
|
+
return;
|
|
1053
|
+
}
|
|
1054
|
+
let lastIndex = 0;
|
|
1055
|
+
let match;
|
|
1056
|
+
const text = token.content;
|
|
1057
|
+
EMBEDDED_IMAGE_REGEX.lastIndex = 0; // Reset regex state
|
|
1058
|
+
while ((match = EMBEDDED_IMAGE_REGEX.exec(text)) !== null) {
|
|
1059
|
+
// Add leading text
|
|
1060
|
+
if (match.index > lastIndex) {
|
|
1061
|
+
const t = new state.Token("text", "", 0);
|
|
1062
|
+
t.content = text.slice(lastIndex, match.index);
|
|
1063
|
+
newChildren.push(t);
|
|
1064
|
+
}
|
|
1065
|
+
// Add embedded image reference token
|
|
1066
|
+
const refToken = new state.Token(EMBEDDED_IMAGE_NAME, "", 0);
|
|
1067
|
+
refToken.content = match[2]; // e.g., "1.2.3"
|
|
1068
|
+
refToken.meta = { full: match[1] }; // e.g., "Img-1.2.3"
|
|
1069
|
+
refToken.attrs = [];
|
|
1070
|
+
if (getEmbeddedImageReference) {
|
|
1071
|
+
const attachment = getEmbeddedImageReference(match[2]);
|
|
1072
|
+
if (attachment) {
|
|
1073
|
+
refToken.attrs.push(['attachment', btoa(encodeURIComponent(JSON.stringify(attachment)))]);
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
newChildren.push(refToken);
|
|
1077
|
+
lastIndex = match.index + match[0].length;
|
|
1078
|
+
}
|
|
1079
|
+
// Add trailing text
|
|
1080
|
+
if (lastIndex < text.length) {
|
|
1081
|
+
const t = new state.Token("text", "", 0);
|
|
1082
|
+
t.content = text.slice(lastIndex);
|
|
1083
|
+
newChildren.push(t);
|
|
1084
|
+
}
|
|
1085
|
+
});
|
|
1086
|
+
blockToken.children = newChildren;
|
|
1027
1087
|
});
|
|
1028
|
-
}
|
|
1029
|
-
|
|
1088
|
+
});
|
|
1089
|
+
// Optional: renderer for the custom token
|
|
1090
|
+
md.renderer.rules[EMBEDDED_IMAGE_NAME] = (tokens, idx) => {
|
|
1091
|
+
const imgId = tokens[idx].content;
|
|
1092
|
+
const attrs = tokens[idx].attrs || [];
|
|
1093
|
+
const attachment = attrs[0];
|
|
1094
|
+
return `<image-reference id="${imgId}" attachment="${attachment ? attachment[1] : ''}" class="embedded-image-ref">Img-${imgId}</image-reference>`;
|
|
1095
|
+
};
|
|
1030
1096
|
}
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1097
|
+
|
|
1098
|
+
/**
|
|
1099
|
+
* This plugin overrides the default link renderer to add `target="_blank"` and `rel="noopener noreferrer"` to all links.
|
|
1100
|
+
*/
|
|
1101
|
+
function markdownItLinkPlugin(md) {
|
|
1102
|
+
const defaultRender = md.renderer.rules.link_open || function (tokens, idx, options, env, self) {
|
|
1103
|
+
return self.renderToken(tokens, idx, options);
|
|
1104
|
+
};
|
|
1105
|
+
md.renderer.rules.link_open = function (tokens, idx, options, env, self) {
|
|
1106
|
+
tokens[idx].attrPush(['target', '_blank']);
|
|
1107
|
+
tokens[idx].attrPush(['rel', 'noopener noreferrer']);
|
|
1108
|
+
// pass token to default renderer.
|
|
1109
|
+
return defaultRender(tokens, idx, options, env, self);
|
|
1110
|
+
};
|
|
1042
1111
|
}
|
|
1043
1112
|
|
|
1044
1113
|
const EMBEDDED_PAGE_NAME = "embedded-page-reference";
|
|
1045
1114
|
const EMBEDDED_PAGE_REGEX = /\[(Page-(\d+\.\d+))\]/g;
|
|
1046
|
-
function
|
|
1047
|
-
|
|
1048
|
-
const
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1115
|
+
function markdownItPageReferencePlugin(md) {
|
|
1116
|
+
md.core.ruler.after("inline", "embedded-page-reference", (state) => {
|
|
1117
|
+
const getEmbeddedPageReference = state?.env?.getEmbeddedPageReference;
|
|
1118
|
+
state.tokens.forEach((blockToken) => {
|
|
1119
|
+
if (blockToken.type !== "inline" || !blockToken.children)
|
|
1120
|
+
return;
|
|
1121
|
+
const newChildren = [];
|
|
1122
|
+
blockToken.children.forEach((token) => {
|
|
1123
|
+
if (token.type !== "text") {
|
|
1124
|
+
newChildren.push(token);
|
|
1125
|
+
return;
|
|
1126
|
+
}
|
|
1127
|
+
let lastIndex = 0;
|
|
1128
|
+
let match;
|
|
1129
|
+
const text = token.content;
|
|
1130
|
+
EMBEDDED_PAGE_REGEX.lastIndex = 0; // Reset regex state
|
|
1131
|
+
while ((match = EMBEDDED_PAGE_REGEX.exec(text)) !== null) {
|
|
1132
|
+
// Add leading text
|
|
1133
|
+
if (match.index > lastIndex) {
|
|
1134
|
+
const t = new state.Token("text", "", 0);
|
|
1135
|
+
t.content = text.slice(lastIndex, match.index);
|
|
1136
|
+
newChildren.push(t);
|
|
1137
|
+
}
|
|
1138
|
+
// Add embedded page reference token
|
|
1139
|
+
const refToken = new state.Token(EMBEDDED_PAGE_NAME, "", 0);
|
|
1140
|
+
refToken.content = match[2]; // e.g., "1.2"
|
|
1141
|
+
refToken.meta = { full: match[1] }; // e.g., "Page-1.2"
|
|
1142
|
+
refToken.attrs = [];
|
|
1143
|
+
if (getEmbeddedPageReference) {
|
|
1144
|
+
const attachment = getEmbeddedPageReference(match[2]);
|
|
1145
|
+
if (attachment) {
|
|
1146
|
+
refToken.attrs.push(['attachment', btoa(encodeURIComponent(JSON.stringify(attachment)))]);
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
newChildren.push(refToken);
|
|
1150
|
+
lastIndex = match.index + match[0].length;
|
|
1151
|
+
}
|
|
1152
|
+
// Add trailing text
|
|
1153
|
+
if (lastIndex < text.length) {
|
|
1154
|
+
const t = new state.Token("text", "", 0);
|
|
1155
|
+
t.content = text.slice(lastIndex);
|
|
1156
|
+
newChildren.push(t);
|
|
1157
|
+
}
|
|
1158
|
+
});
|
|
1159
|
+
blockToken.children = newChildren;
|
|
1160
|
+
});
|
|
1056
1161
|
});
|
|
1057
|
-
|
|
1162
|
+
// Optional: renderer for the custom token
|
|
1163
|
+
md.renderer.rules[EMBEDDED_PAGE_NAME] = (tokens, idx) => {
|
|
1164
|
+
const page = tokens[idx].content;
|
|
1165
|
+
// const getEmbeddedPageReference = tokens[idx].meta?.getEmbeddedPageReference;
|
|
1166
|
+
// const attachment = getEmbeddedPageReference ? getEmbeddedPageReference(page) : null;
|
|
1167
|
+
const attrs = tokens[idx].attrs || [];
|
|
1168
|
+
const attachment = attrs[0];
|
|
1169
|
+
return `<page-reference id=${page} attachment=${attachment[1]} class="embedded-page-ref">Page-${page}</page-reference>`;
|
|
1170
|
+
};
|
|
1058
1171
|
}
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1172
|
+
|
|
1173
|
+
/**
|
|
1174
|
+
* A markdown-it plugin to convert [n] where n is a number into a <reference id="n">n</reference> HTML tag.
|
|
1175
|
+
*
|
|
1176
|
+
* For example, [123] will be converted to <reference id="123">123</reference>.
|
|
1177
|
+
*/
|
|
1178
|
+
function markdownItReferencePlugin(md) {
|
|
1179
|
+
function referenceifyNumber(state, silent) {
|
|
1180
|
+
const referencesMap = state.env.referencesMap || new Map();
|
|
1181
|
+
const rank = state.env.rank || null;
|
|
1182
|
+
const char = state.src.charCodeAt(state.pos);
|
|
1183
|
+
// Check if the current character is '['
|
|
1184
|
+
if (char !== 0x5B /* [ */) {
|
|
1185
|
+
return false;
|
|
1186
|
+
}
|
|
1187
|
+
const start = state.pos + 1;
|
|
1188
|
+
let end = -1;
|
|
1189
|
+
// Find the closing ']'
|
|
1190
|
+
for (let i = start; i < state.src.length; i++) {
|
|
1191
|
+
if (state.src.charCodeAt(i) === 0x5D /* ] */) {
|
|
1192
|
+
end = i;
|
|
1193
|
+
break;
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
if (end === -1 || end === start) {
|
|
1197
|
+
return false;
|
|
1198
|
+
}
|
|
1199
|
+
const content = state.src.slice(start, end);
|
|
1200
|
+
// Match if content is a number or number.number (optionally allow whitespace)
|
|
1201
|
+
if (!/^\s*\d+(?:\.\d+)?\s*$/.test(content.trim())) {
|
|
1202
|
+
return false;
|
|
1203
|
+
}
|
|
1204
|
+
if (!silent) {
|
|
1205
|
+
const n = content.trim();
|
|
1206
|
+
// Open <reference>
|
|
1207
|
+
const attachment = referencesMap.get(n) || n;
|
|
1208
|
+
if (attachment) {
|
|
1209
|
+
// add attachment if found in the references map from env (set in the component)
|
|
1210
|
+
state.env.references(n.split('.')[0]);
|
|
1211
|
+
const tokenOpen = state.push('reference_open', 'reference-component', 1);
|
|
1212
|
+
// base64 encode the attachment if needed
|
|
1213
|
+
if (typeof attachment === 'object') {
|
|
1214
|
+
tokenOpen.attrs = [
|
|
1215
|
+
['id', n],
|
|
1216
|
+
['rank', rank],
|
|
1217
|
+
['attachment', btoa(encodeURIComponent(JSON.stringify(attachment)))]
|
|
1218
|
+
];
|
|
1219
|
+
}
|
|
1220
|
+
// Text content
|
|
1221
|
+
const tokenText = state.push('text', '', 0);
|
|
1222
|
+
tokenText.content = n;
|
|
1223
|
+
// Close </reference>
|
|
1224
|
+
state.push('reference_close', 'reference-component', -1);
|
|
1225
|
+
}
|
|
1226
|
+
else {
|
|
1227
|
+
// If no attachment found, just create a span text node
|
|
1228
|
+
const token = state.push('reference_open', 'span', 1);
|
|
1229
|
+
token.attrs = [['class', 'reference']];
|
|
1230
|
+
const tokenText = state.push('text', '', 0);
|
|
1231
|
+
tokenText.content = n;
|
|
1232
|
+
state.push('reference_close', 'span', -1);
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
state.pos = end + 1;
|
|
1236
|
+
return true;
|
|
1237
|
+
}
|
|
1238
|
+
md.inline.ruler.after('text', 'referenceify_number', referenceifyNumber);
|
|
1073
1239
|
}
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
end: ref.index,
|
|
1083
|
-
});
|
|
1240
|
+
|
|
1241
|
+
const GROUPING_REGEX = /<!--[\s\S]*-->|<[a-z0-9]+(?: [\S]*){1,}\/>|<([a-z0-9]+)(?: [\S]*?)*>[\s\S]*?<\/\1>/gim;
|
|
1242
|
+
class SafeHtmlPipe {
|
|
1243
|
+
constructor(sanitizer) {
|
|
1244
|
+
this.sanitizer = sanitizer;
|
|
1245
|
+
}
|
|
1246
|
+
transform(html) {
|
|
1247
|
+
return this.sanitizer.bypassSecurityTrustHtml(html);
|
|
1084
1248
|
}
|
|
1085
|
-
|
|
1249
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SafeHtmlPipe, deps: [{ token: i1$2.DomSanitizer }], target: i0.ɵɵFactoryTarget.Pipe }); }
|
|
1250
|
+
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: SafeHtmlPipe, isStandalone: true, name: "safeHtml" }); }
|
|
1086
1251
|
}
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1252
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SafeHtmlPipe, decorators: [{
|
|
1253
|
+
type: Pipe,
|
|
1254
|
+
args: [{
|
|
1255
|
+
name: "safeHtml",
|
|
1256
|
+
standalone: true,
|
|
1257
|
+
}]
|
|
1258
|
+
}], ctorParameters: () => [{ type: i1$2.DomSanitizer }] });
|
|
1259
|
+
class SmartRendererComponent {
|
|
1260
|
+
constructor() {
|
|
1261
|
+
// Entire message content with the delta
|
|
1262
|
+
this.message = input("");
|
|
1263
|
+
this.context = input(null);
|
|
1264
|
+
this.safe = signal("");
|
|
1265
|
+
this.processing = signal("");
|
|
1266
|
+
// High order last slice index, ie. where next message() should be truncated
|
|
1267
|
+
// to avoid re-rendering the same content.
|
|
1268
|
+
this.lastSliceIndex = 0;
|
|
1269
|
+
// Local slice index to keep track of the current message's content
|
|
1270
|
+
this.localSliceIndex = 0;
|
|
1271
|
+
effect(() => this.messageUpdated(), { allowSignalWrites: true });
|
|
1272
|
+
}
|
|
1273
|
+
messageUpdated() {
|
|
1274
|
+
// render delta from last sliced message
|
|
1275
|
+
const html = markdownit({
|
|
1276
|
+
highlight: function (code, lang) {
|
|
1277
|
+
if (lang && Prism.languages[lang]) {
|
|
1278
|
+
try {
|
|
1279
|
+
const highlightedCode = Prism.highlight(code, Prism.languages[lang], lang);
|
|
1280
|
+
// By returning a string that starts with <pre>, we are telling markdown-it that we handled the wrapping.
|
|
1281
|
+
return `<pre class="language-${lang}"><code class="language-${lang}">${highlightedCode}</code></pre>`;
|
|
1282
|
+
}
|
|
1283
|
+
catch (__) {
|
|
1284
|
+
// if prism fails, fall back to no highlighting
|
|
1285
|
+
}
|
|
1286
|
+
}
|
|
1287
|
+
// if no lang, or prism fails, just escape the code for safety
|
|
1288
|
+
return `<pre class="language-code"><code class="language-code">${markdownit().utils.escapeHtml(code)}</code></pre>`;
|
|
1289
|
+
},
|
|
1290
|
+
})
|
|
1291
|
+
.use(markdownItReferencePlugin)
|
|
1292
|
+
.use(markdownItPageReferencePlugin)
|
|
1293
|
+
.use(markdownItImageReferencePlugin)
|
|
1294
|
+
.use(markdownItLinkPlugin)
|
|
1295
|
+
.use(markdownItCodeBlockPlugin)
|
|
1296
|
+
.render(this.message(), this.context())
|
|
1297
|
+
?.slice(this.lastSliceIndex);
|
|
1298
|
+
// split the html into blocks of first level tags
|
|
1299
|
+
const blocks = html.match(GROUPING_REGEX);
|
|
1300
|
+
// no blocks, nothing to process
|
|
1301
|
+
if (!blocks || blocks.length === 0)
|
|
1302
|
+
return;
|
|
1303
|
+
if (blocks.length > 2) {
|
|
1304
|
+
this.localSliceIndex = html.lastIndexOf(blocks.at(-2) || "");
|
|
1305
|
+
this.lastSliceIndex += this.localSliceIndex;
|
|
1306
|
+
this.safe.update((v) => v + html.slice(0, this.localSliceIndex));
|
|
1307
|
+
this.processing.set(html.slice(this.localSliceIndex));
|
|
1308
|
+
}
|
|
1309
|
+
else {
|
|
1310
|
+
this.processing.set(blocks.slice(0, 2).join(""));
|
|
1311
|
+
}
|
|
1097
1312
|
}
|
|
1313
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SmartRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1314
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "18.2.13", type: SmartRendererComponent, isStandalone: true, selector: "SmartRenderer", inputs: { message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: false, transformFunction: null }, context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
1315
|
+
<div [innerHTML]="safe() | safeHtml"></div>
|
|
1316
|
+
<div [innerHTML]="processing() | safeHtml"></div>
|
|
1317
|
+
`, isInline: true, dependencies: [{ kind: "pipe", type: SafeHtmlPipe, name: "safeHtml" }] }); }
|
|
1098
1318
|
}
|
|
1319
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SmartRendererComponent, decorators: [{
|
|
1320
|
+
type: Component,
|
|
1321
|
+
args: [{
|
|
1322
|
+
selector: "SmartRenderer",
|
|
1323
|
+
template: `
|
|
1324
|
+
<div [innerHTML]="safe() | safeHtml"></div>
|
|
1325
|
+
<div [innerHTML]="processing() | safeHtml"></div>
|
|
1326
|
+
`,
|
|
1327
|
+
imports: [SafeHtmlPipe],
|
|
1328
|
+
standalone: true,
|
|
1329
|
+
}]
|
|
1330
|
+
}], ctorParameters: () => [] });
|
|
1099
1331
|
|
|
1100
1332
|
class NotificationsService {
|
|
1101
1333
|
success(message, title) {
|
|
@@ -1182,12 +1414,14 @@ class ChatMessageComponent {
|
|
|
1182
1414
|
this.principalService = principalService;
|
|
1183
1415
|
this.cdr = cdr;
|
|
1184
1416
|
this.el = el;
|
|
1417
|
+
this.id = input();
|
|
1185
1418
|
this.canEdit = false;
|
|
1186
1419
|
this.canRegenerate = false;
|
|
1187
1420
|
this.canCopy = false;
|
|
1188
1421
|
this.canDebug = false;
|
|
1189
1422
|
this.canLike = false;
|
|
1190
1423
|
this.canDislike = false;
|
|
1424
|
+
this.collapseReferences = true;
|
|
1191
1425
|
this.openDocument = new EventEmitter();
|
|
1192
1426
|
this.openPreview = new EventEmitter();
|
|
1193
1427
|
this.suggestAction = new EventEmitter();
|
|
@@ -1197,89 +1431,22 @@ class ChatMessageComponent {
|
|
|
1197
1431
|
this.like = new EventEmitter();
|
|
1198
1432
|
this.dislike = new EventEmitter();
|
|
1199
1433
|
this.debug = new EventEmitter();
|
|
1200
|
-
|
|
1434
|
+
// signal based set of references to avoid duplicates
|
|
1435
|
+
this.refs = signal([]);
|
|
1436
|
+
this.references = computed(() => this.refs().slice().sort((a, b) => a - b).map((r) => "" + r));
|
|
1201
1437
|
this.referenceMap = new Map();
|
|
1202
1438
|
this.imageReferencesMap = new Map();
|
|
1203
1439
|
this.pageReferencesMap = new Map();
|
|
1204
|
-
this.showReferences = true;
|
|
1205
1440
|
this.iconSize = 24;
|
|
1206
1441
|
this.hiddenTooltip = false;
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
* form [1], [2.3], etc. with custom nodes of type "chat-reference".
|
|
1210
|
-
*/
|
|
1211
|
-
this.referencePlugin = (tree) => {
|
|
1212
|
-
const references = new Set();
|
|
1213
|
-
// Visit all text nodes
|
|
1214
|
-
visit(tree, "text", (node, index, parent) => {
|
|
1215
|
-
let text = node.value;
|
|
1216
|
-
text = this.reformatReferences(text);
|
|
1217
|
-
const matches = this.getReferenceMatches(text);
|
|
1218
|
-
// Quit if no references were found
|
|
1219
|
-
if (matches.length === 0) {
|
|
1220
|
-
return CONTINUE;
|
|
1221
|
-
}
|
|
1222
|
-
const nodes = [];
|
|
1223
|
-
for (const match of matches) {
|
|
1224
|
-
const refId = match[1].trim();
|
|
1225
|
-
const [ref] = refId.split(".");
|
|
1226
|
-
// We find a valid reference in the text
|
|
1227
|
-
if (!isNaN(+ref)) {
|
|
1228
|
-
references.add(+ref); // Add it to the set of used references
|
|
1229
|
-
// If needed, insert a text node before the reference
|
|
1230
|
-
const current = nodes.at(-1) ?? { end: 0 };
|
|
1231
|
-
if (match.index > current.end) {
|
|
1232
|
-
nodes.push({
|
|
1233
|
-
type: "text",
|
|
1234
|
-
value: text.substring(current.end, match.index),
|
|
1235
|
-
end: match.index,
|
|
1236
|
-
});
|
|
1237
|
-
}
|
|
1238
|
-
// Add a custom reference node
|
|
1239
|
-
nodes.push({
|
|
1240
|
-
type: "chat-reference",
|
|
1241
|
-
refId,
|
|
1242
|
-
end: match.index + match[0].length,
|
|
1243
|
-
});
|
|
1244
|
-
}
|
|
1245
|
-
}
|
|
1246
|
-
// Quit if no references were found
|
|
1247
|
-
if (nodes.length === 0) {
|
|
1248
|
-
return CONTINUE;
|
|
1249
|
-
}
|
|
1250
|
-
if (nodes.at(-1).end < text.length) {
|
|
1251
|
-
nodes.push({
|
|
1252
|
-
type: "text",
|
|
1253
|
-
value: text.substring(nodes.at(-1).end, text.length),
|
|
1254
|
-
end: text.length,
|
|
1255
|
-
});
|
|
1256
|
-
}
|
|
1257
|
-
// Delete the current text node from the parent and replace it with the new nodes
|
|
1258
|
-
parent.children.splice(index, 1, ...nodes);
|
|
1259
|
-
return index + nodes.length; // Visit the next node after the inserted ones
|
|
1260
|
-
});
|
|
1261
|
-
if (references.size > 0) {
|
|
1262
|
-
this.references = Array.from(references.values())
|
|
1263
|
-
.sort((a, b) => a - b)
|
|
1264
|
-
.map((r) => "" + r);
|
|
1265
|
-
this.cdr.detectChanges();
|
|
1266
|
-
}
|
|
1267
|
-
return tree;
|
|
1268
|
-
};
|
|
1269
|
-
this.placeholderPlugin = (tree) => {
|
|
1270
|
-
visit(tree, "text", (node, index, parent) => {
|
|
1271
|
-
parent.children.push({ type: "streaming-placeholder" });
|
|
1272
|
-
return EXIT;
|
|
1273
|
-
}, true);
|
|
1274
|
-
return tree;
|
|
1275
|
-
};
|
|
1442
|
+
// used by the template
|
|
1443
|
+
this.Array = Array;
|
|
1276
1444
|
}
|
|
1277
1445
|
ngOnChanges(changes) {
|
|
1278
1446
|
if (changes.streaming) {
|
|
1279
1447
|
this.collapseProgress = !this.streaming;
|
|
1280
1448
|
}
|
|
1281
1449
|
if (this.message?.role === "assistant") {
|
|
1282
|
-
this.references = [];
|
|
1283
1450
|
this.referenceMap.clear();
|
|
1284
1451
|
for (let m of this.conversation) {
|
|
1285
1452
|
if (m.additionalProperties.$attachment &&
|
|
@@ -1305,20 +1472,8 @@ class ChatMessageComponent {
|
|
|
1305
1472
|
}
|
|
1306
1473
|
this.processMessageType(m);
|
|
1307
1474
|
}
|
|
1308
|
-
this.processor = unified()
|
|
1309
|
-
.use(remarkParse)
|
|
1310
|
-
.use(remarkGfm)
|
|
1311
|
-
.use(() => this.referencePlugin)
|
|
1312
|
-
.use(() => embeddedImageReferencePlugin)
|
|
1313
|
-
.use(() => embeddedPageReferencePlugin);
|
|
1314
|
-
if (this.streaming) {
|
|
1315
|
-
this.processor = this.processor.use(() => this.placeholderPlugin);
|
|
1316
|
-
}
|
|
1317
1475
|
}
|
|
1318
1476
|
}
|
|
1319
|
-
ngAfterViewInit() {
|
|
1320
|
-
Prism?.highlightAllUnder?.(this.el.nativeElement);
|
|
1321
|
-
}
|
|
1322
1477
|
getEmbeddedImageReference(ref) {
|
|
1323
1478
|
const [doc, part, image] = ref.split(".");
|
|
1324
1479
|
const images = this.referenceMap.get(doc)?.parts?.[+part - 1]?.images;
|
|
@@ -1369,40 +1524,25 @@ class ChatMessageComponent {
|
|
|
1369
1524
|
message.messageType = "MARKDOWN";
|
|
1370
1525
|
}
|
|
1371
1526
|
}
|
|
1372
|
-
getLinkText(node) {
|
|
1373
|
-
if (node.text) {
|
|
1374
|
-
return node.text; // Return directly if text is provided in node.text ([Example link](https://example.com))
|
|
1375
|
-
}
|
|
1376
|
-
else if (node.children && node.children.length > 0) {
|
|
1377
|
-
// Recursively search for text content in child nodes
|
|
1378
|
-
for (const child of node.children) {
|
|
1379
|
-
if (child.type === "text" && child.value) {
|
|
1380
|
-
return child.value; // Return the value of the first text node found ([**Emphasized Link Text**](https://example.com))
|
|
1381
|
-
}
|
|
1382
|
-
else if (child.children && child.children.length > 0) {
|
|
1383
|
-
const textContent = this.getLinkText(child); // Recursively search child nodes ([](https://example.com))
|
|
1384
|
-
if (textContent) {
|
|
1385
|
-
return textContent; // Return text content if found
|
|
1386
|
-
}
|
|
1387
|
-
}
|
|
1388
|
-
}
|
|
1389
|
-
}
|
|
1390
|
-
return "link"; // Return empty string if no text content is found
|
|
1391
|
-
}
|
|
1392
|
-
/**
|
|
1393
|
-
* Reformat [ids: 12.2, 42.5] to [12.2][42.5]
|
|
1394
|
-
*/
|
|
1395
|
-
reformatReferences(content) {
|
|
1396
|
-
return content.replace(/\[(?:ids?:?\s*)?(?:documents?:?\s*)?(\s*(?:,?\s*\d+(?:\.\d+)?(?:\.part)?\s*)+)\]/g, (str, match) => `[${match
|
|
1397
|
-
.replace(/\.part/g, "")
|
|
1398
|
-
.split(",")
|
|
1399
|
-
.join("] [")}]`);
|
|
1400
|
-
}
|
|
1401
1527
|
/**
|
|
1402
|
-
*
|
|
1528
|
+
* Processes a reference string by validating and adding it to the set of references if applicable.
|
|
1529
|
+
*
|
|
1530
|
+
* - Ignores empty or falsy references.
|
|
1531
|
+
* - Ignores references that are not numeric.
|
|
1532
|
+
* - Ignores references that already exist in the set.
|
|
1533
|
+
* - Converts the reference to a number and adds it to the set of references.
|
|
1534
|
+
*
|
|
1535
|
+
* @param ref - The reference string to process.
|
|
1403
1536
|
*/
|
|
1404
|
-
|
|
1405
|
-
|
|
1537
|
+
processReferences(ref) {
|
|
1538
|
+
if (!ref)
|
|
1539
|
+
return;
|
|
1540
|
+
if (isNaN(+ref))
|
|
1541
|
+
return;
|
|
1542
|
+
const refNum = +ref;
|
|
1543
|
+
if (this.refs().includes(refNum))
|
|
1544
|
+
return;
|
|
1545
|
+
this.refs.update(arr => [...arr, refNum]);
|
|
1406
1546
|
}
|
|
1407
1547
|
_copyToClipboard(content) {
|
|
1408
1548
|
this.ui.copyToClipboard(content);
|
|
@@ -1421,9 +1561,6 @@ class ChatMessageComponent {
|
|
|
1421
1561
|
this._copyToClipboard(content);
|
|
1422
1562
|
this.copy.emit(message);
|
|
1423
1563
|
}
|
|
1424
|
-
copyCode(code) {
|
|
1425
|
-
this._copyToClipboard(code);
|
|
1426
|
-
}
|
|
1427
1564
|
openAttachmentPreview(attachment, partId) {
|
|
1428
1565
|
this.openPreview.emit({ reference: attachment, partId });
|
|
1429
1566
|
this.hideTooltip();
|
|
@@ -1439,22 +1576,22 @@ class ChatMessageComponent {
|
|
|
1439
1576
|
});
|
|
1440
1577
|
}
|
|
1441
1578
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ChatMessageComponent, deps: [{ token: UIService }, { token: PrincipalService }, { token: i0.ChangeDetectorRef }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1442
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", 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" }, providers: [provideTranslocoScope('chat-message')], 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\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\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\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</span>\n\n<!-- Message body -->\n<div class=\"flex-grow-1 position-relative relative\" 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 <details role=\"button\" class=\"select-none\" [open]=\"!collapseProgress\">\n <summary class=\"text-muted\">\n {{ 'chatMessage.viewProgress' | transloco }}\n </summary>\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 </details>\n </div>\n\n <!-- Message content -->\n <div class=\"message-content\" *ngIf=\"message.content\">\n\n <!-- Custom rendering for WPS, to be remove with https://sinequa.atlassian.net/browse/ES-23710 -->\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 !== 'CHART') || message?.role === 'connection-error' || message?.role === 'search-warning'\" [markdown]=\"message.content | messageContent\" [processor]=\"processor\">\n\n <!-- Chat reference (badge with file and part number) -->\n <ng-template remarkTemplate=\"chat-reference\" let-ref>\n @let attachment = referenceMap.get(ref.refId);\n @if (attachment) {\n <a\n class=\"reference\"\n role=\"button\"\n [sqTooltip]=\"attachment\"\n [sqTooltipTemplate]=\"tooltipTpl\"\n [hoverableTooltip]=\"true\"\n (click)=\"openAttachmentPreview(attachment, ref.refId)\"\n >\n {{ref.refId}}\n </a>\n }\n @else {\n <ng-template #staticRefTpl>\n <span class=\"reference\">{{ ref.refId }}</span>\n </ng-template>\n }\n </ng-template>\n\n <!-- Embedded reference image -->\n <ng-template remarkTemplate=\"embedded-image-reference\" let-ref>\n @let refObj = getEmbeddedImageReference(ref.value);\n @if (refObj && refObj.url) {\n <span\n [ngClass]=\"{ 'reference': true, 'has-bounding-box': ref.boundingBox }\"\n [sqTooltip]=\"{ obj: refObj, id: ref.value }\"\n [sqTooltipTemplate]=\"imageTooltipTpl\"\n [hoverableTooltip]=\"true\"\n >\n Img-{{ ref.value }}\n </span>\n }\n </ng-template>\n\n <!-- Embedded reference page -->\n <ng-template remarkTemplate=\"embedded-page-reference\" let-ref>\n @let refObj = getEmbeddedPageReference(ref.value);\n @if (refObj && refObj.url) {\n <span\n [ngClass]=\"{ 'reference': true, 'has-bounding-box': ref.boundingBox }\"\n [sqTooltip]=\"{ obj: refObj, id: ref.value }\"\n [sqTooltipTemplate]=\"pageTooltipTpl\"\n [hoverableTooltip]=\"true\"\n >\n Page-{{ ref.value }}\n </span>\n }\n </ng-template>\n\n <!-- Blinking cursor -->\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> {{ 'chatMessage.copyCode' | transloco }}</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 | messageContent }}</p>\n\n <!-- List of reference, if any -->\n @if (references?.length > 0 || imageReferencesMap?.size > 0 || pageReferencesMap?.size > 0) {\n <div class=\"references\">\n <details role=\"button\" class=\"select-none\" [open]=\"!showReferences\">\n <summary class=\"references-title\">{{ 'chatMessage.references' | transloco }}</summary>\n <ul>\n @for (reference of references; track $index) {\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 }\n @for (imageReference of imageReferencesMap.entries(); track $index) {\n <li style=\"list-style-type: none;\">\n <InlineImageReference\n [id]=\"imageReference[0]\"\n [ref]=\"imageReference[1]\"\n (openPreview)=\"openAttachmentPreview($event)\"\n (openDocument)=\"openOriginalAttachment($event, $event.$partId)\"\n (openModal)=\"hideTooltip()\"\n />\n </li>\n }\n @for (pageReference of pageReferencesMap.entries(); track $index) {\n <li style=\"list-style-type: none;\">\n <InlinePageReference\n [id]=\"pageReference[0]\"\n [ref]=\"pageReference[1]\"\n (openPreview)=\"openAttachmentPreview($event)\"\n (openDocument)=\"openOriginalAttachment($event, $event.$partId)\"\n (openModal)=\"hideTooltip()\"\n />\n </li>\n }\n </ul>\n </details>\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]=\"'chatMessage.copyText' | transloco\" (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]=\"'chatMessage.editMessage' | transloco\" (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]=\"message.additionalProperties.$liked\" *ngIf=\"canLike\" [sqTooltip]=\"'chatMessage.likeAnswer' | transloco\" (click)=\"like.emit()\">\n <i *ngIf=\"!message.additionalProperties.$liked\" class=\"far fa-thumbs-up \"></i>\n <i *ngIf=\"message.additionalProperties.$liked\" class=\"fas fa-thumbs-up\"></i>\n </button>\n <button class=\"btn btn-sm\" [class.bounce]=\"message.additionalProperties.$disliked\" *ngIf=\"canDislike\" [sqTooltip]=\"'chatMessage.reportIssue' | transloco\" (click)=\"dislike.emit()\">\n <i *ngIf=\"!message.additionalProperties.$disliked\" class=\"far fa-thumbs-down \"></i>\n <i *ngIf=\"message.additionalProperties.$disliked\" class=\"fas fa-thumbs-down\"></i>\n </button>\n <button class=\"btn btn-sm\" *ngIf=\"canRegenerate\" [sqTooltip]=\"'chatMessage.regenerateResponse' | transloco\" (click)=\"regenerate.emit(message)\">\n <i class=\"fas fa-sync-alt\"></i>\n </button>\n <button class=\"btn btn-sm\" *ngIf=\"canDebug\" [sqTooltip]=\"'chatMessage.showLogInformation' | transloco\" (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 #imageTooltipTpl let-ref>\n <InlineImageReference\n style=\"max-width: 30vw;\"\n [id]=\"ref.id\"\n [ref]=\"ref.obj\"\n (openPreview)=\"openAttachmentPreview($event)\"\n (openDocument)=\"openOriginalAttachment($event, $event.$partId)\"\n (openModal)=\"hideTooltip()\"\n />\n </ng-template>\n\n <ng-template #pageTooltipTpl let-ref>\n <InlinePageReference\n style=\"max-width: 30vw;\"\n [id]=\"ref.id\"\n [ref]=\"ref.obj\"\n (openPreview)=\"openAttachmentPreview($event)\"\n (openDocument)=\"openOriginalAttachment($event, $event.$partId)\"\n (openModal)=\"hideTooltip()\"\n />\n </ng-template>\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));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-uploaded-doc-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;--ast-report-bg: #070707}: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 ::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: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{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-5, 1.25rem));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: "directive", type: TooltipDirective, selector: "[sqTooltip]", inputs: ["sqTooltip", "sqTooltipData", "sqTooltipTemplate", "placement", "fallbackPlacements", "delay", "hoverableTooltip", "tooltipClass"] }, { kind: "ngmodule", type: RemarkModule }, { kind: "component", type: i4.RemarkComponent, selector: "remark", inputs: ["markdown", "processor", "debug"] }, { kind: "directive", type: i4.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"] }, { kind: "pipe", type: MessageContentPipe, name: "messageContent" }, { kind: "component", type: InlineImageReferenceComponent, selector: "InlineImageReference", inputs: ["id", "ref"], outputs: ["openPreview", "openDocument", "openModal"] }, { kind: "component", type: InlinePageReferenceComponent, selector: "InlinePageReference", inputs: ["id", "ref"], outputs: ["openPreview", "openDocument", "openModal"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1579
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: ChatMessageComponent, isStandalone: true, selector: "sq-chat-message", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, message: { classPropertyName: "message", publicName: "message", isSignal: false, isRequired: false, transformFunction: null }, conversation: { classPropertyName: "conversation", publicName: "conversation", isSignal: false, isRequired: false, transformFunction: null }, suggestedActions: { classPropertyName: "suggestedActions", publicName: "suggestedActions", isSignal: false, isRequired: false, transformFunction: null }, assistantMessageIcon: { classPropertyName: "assistantMessageIcon", publicName: "assistantMessageIcon", isSignal: false, isRequired: false, transformFunction: null }, userMessageIcon: { classPropertyName: "userMessageIcon", publicName: "userMessageIcon", isSignal: false, isRequired: false, transformFunction: null }, connectionErrorMessageIcon: { classPropertyName: "connectionErrorMessageIcon", publicName: "connectionErrorMessageIcon", isSignal: false, isRequired: false, transformFunction: null }, searchWarningMessageIcon: { classPropertyName: "searchWarningMessageIcon", publicName: "searchWarningMessageIcon", isSignal: false, isRequired: false, transformFunction: null }, streaming: { classPropertyName: "streaming", publicName: "streaming", isSignal: false, isRequired: false, transformFunction: null }, canEdit: { classPropertyName: "canEdit", publicName: "canEdit", isSignal: false, isRequired: false, transformFunction: null }, canRegenerate: { classPropertyName: "canRegenerate", publicName: "canRegenerate", isSignal: false, isRequired: false, transformFunction: null }, canCopy: { classPropertyName: "canCopy", publicName: "canCopy", isSignal: false, isRequired: false, transformFunction: null }, canDebug: { classPropertyName: "canDebug", publicName: "canDebug", isSignal: false, isRequired: false, transformFunction: null }, canLike: { classPropertyName: "canLike", publicName: "canLike", isSignal: false, isRequired: false, transformFunction: null }, canDislike: { classPropertyName: "canDislike", publicName: "canDislike", isSignal: false, isRequired: false, transformFunction: null }, collapseReferences: { classPropertyName: "collapseReferences", publicName: "collapseReferences", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { openDocument: "openDocument", openPreview: "openPreview", suggestAction: "suggestAction", edit: "edit", copy: "copy", regenerate: "regenerate", like: "like", dislike: "dislike", debug: "debug" }, providers: [provideTranslocoScope('chat-message')], 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\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\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\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</span>\n\n<!-- Message body -->\n<div class=\"flex-grow-1 position-relative relative\" 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 <details role=\"button\" class=\"select-none\" [open]=\"!collapseProgress\">\n <summary class=\"text-muted\">\n {{ 'chatMessage.viewProgress' | transloco }}\n </summary>\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 </details>\n </div>\n\n <!-- Message content -->\n <div class=\"message-content\" *ngIf=\"message.content\">\n\n <!-- Custom rendering for WPS, to be remove with https://sinequa.atlassian.net/browse/ES-23710 -->\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\n\n @if(message?.role === 'assistant' && message.messageType !== 'CHART') {\n <SmartRenderer\n [message]=\"message.content | messageContent\"\n [context]=\"{\n getEmbeddedPageReference: getEmbeddedPageReference.bind(this),\n getEmbeddedImageReference: getEmbeddedImageReference.bind(this),\n referencesMap: referenceMap,\n references: processReferences.bind(this),\n rank: id()\n }\">\n </SmartRenderer>\n }\n\n <p *ngIf=\"message?.role === 'user'\">{{ message.content | messageContent }}</p>\n\n <!-- List of reference, if any -->\n @let referencesArray = references();\n @if (referencesArray?.length > 0 || imageReferencesMap?.size > 0 || pageReferencesMap?.size > 0) {\n <div class=\"references\">\n <details role=\"button\" class=\"select-none\" [open]=\"!collapseReferences\">\n <summary class=\"references-title\">{{ 'chatMessage.references' | transloco }}</summary>\n <ul>\n @for (reference of referencesArray; track $index) {\n @let attachment = referenceMap.get(reference);\n <!-- Only display the reference when the key is a integer not a decimal -->\n @if(attachment) {\n <li class=\"text-truncate\">\n <sq-chat-reference\n [class.expanded]=\"attachment?.$expanded\"\n [attachment]=\"attachment\"\n [reference]=\"reference\"\n [referenceMap]=\"referenceMap\"\n [images]=\"Array.from(imageReferencesMap.keys())\"\n [pages]=\"Array.from(pageReferencesMap.keys())\"\n (openPreview)=\"openAttachmentPreview($event)\"\n (openDocument)=\"openOriginalAttachment($event)\">\n </sq-chat-reference>\n </li>\n }\n }\n </ul>\n </details>\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]=\"'chatMessage.copyText' | transloco\" (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]=\"'chatMessage.editMessage' | transloco\" (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]=\"message.additionalProperties.$liked\" *ngIf=\"canLike\" [sqTooltip]=\"'chatMessage.likeAnswer' | transloco\" (click)=\"like.emit()\">\n <i *ngIf=\"!message.additionalProperties.$liked\" class=\"far fa-thumbs-up \"></i>\n <i *ngIf=\"message.additionalProperties.$liked\" class=\"fas fa-thumbs-up\"></i>\n </button>\n <button class=\"btn btn-sm\" [class.bounce]=\"message.additionalProperties.$disliked\" *ngIf=\"canDislike\" [sqTooltip]=\"'chatMessage.reportIssue' | transloco\" (click)=\"dislike.emit()\">\n <i *ngIf=\"!message.additionalProperties.$disliked\" class=\"far fa-thumbs-down \"></i>\n <i *ngIf=\"message.additionalProperties.$disliked\" class=\"fas fa-thumbs-down\"></i>\n </button>\n <button class=\"btn btn-sm\" *ngIf=\"canRegenerate\" [sqTooltip]=\"'chatMessage.regenerateResponse' | transloco\" (click)=\"regenerate.emit(message)\">\n <i class=\"fas fa-sync-alt\"></i>\n </button>\n <button class=\"btn btn-sm\" *ngIf=\"canDebug\" [sqTooltip]=\"'chatMessage.showLogInformation' | transloco\" (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 #imageTooltipTpl let-ref>\n <InlineImageReference\n style=\"max-width: 30vw;\"\n [id]=\"ref.id\"\n [ref]=\"ref.obj\"\n (openPreview)=\"openAttachmentPreview($event)\"\n (openDocument)=\"openOriginalAttachment($event, $event.$partId)\"\n (openModal)=\"hideTooltip()\"\n />\n </ng-template>\n\n <ng-template #pageTooltipTpl let-ref>\n <InlinePageReference\n style=\"max-width: 30vw;\"\n [id]=\"ref.id\"\n [ref]=\"ref.obj\"\n (openPreview)=\"openAttachmentPreview($event)\"\n (openDocument)=\"openOriginalAttachment($event, $event.$partId)\"\n (openModal)=\"hideTooltip()\"\n />\n </ng-template>\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));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-uploaded-doc-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;--ast-report-bg: #070707}: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 ::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: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{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-5, 1.25rem));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: "directive", type: TooltipDirective, selector: "[sqTooltip]", inputs: ["sqTooltip", "sqTooltipData", "sqTooltipTemplate", "placement", "fallbackPlacements", "delay", "hoverableTooltip", "tooltipClass"] }, { kind: "component", type: InitialsAvatarComponent, selector: "sq-initials-avatar", inputs: ["fullName", "size"] }, { kind: "component", type: ChatReferenceComponent, selector: "sq-chat-reference", inputs: ["reference", "attachment", "partId", "referenceMap", "images", "pages"], outputs: ["openDocument", "openPreview"] }, { kind: "component", type: ChartComponent, selector: "sq-assistant-chart", inputs: ["rawChartData"] }, { kind: "pipe", type: MessageContentPipe, name: "messageContent" }, { kind: "component", type: InlineImageReferenceComponent, selector: "InlineImageReference", inputs: ["id", "ref"], outputs: ["openPreview", "openDocument", "openModal"] }, { kind: "component", type: InlinePageReferenceComponent, selector: "InlinePageReference", inputs: ["id", "ref"], outputs: ["openPreview", "openDocument", "openModal"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }, { kind: "component", type: SmartRendererComponent, selector: "SmartRenderer", inputs: ["message", "context"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1443
1580
|
}
|
|
1444
1581
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ChatMessageComponent, decorators: [{
|
|
1445
1582
|
type: Component,
|
|
1446
1583
|
args: [{ selector: "sq-chat-message", changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
|
|
1447
1584
|
CommonModule,
|
|
1448
1585
|
TooltipDirective,
|
|
1449
|
-
RemarkModule,
|
|
1450
1586
|
InitialsAvatarComponent,
|
|
1451
1587
|
ChatReferenceComponent,
|
|
1452
1588
|
ChartComponent,
|
|
1453
1589
|
MessageContentPipe,
|
|
1454
1590
|
InlineImageReferenceComponent,
|
|
1455
1591
|
InlinePageReferenceComponent,
|
|
1456
|
-
TranslocoPipe
|
|
1457
|
-
], providers: [provideTranslocoScope('chat-message')], 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\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\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\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</span>\n\n<!-- Message body -->\n<div class=\"flex-grow-1 position-relative relative\" 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 <details role=\"button\" class=\"select-none\" [open]=\"!collapseProgress\">\n <summary class=\"text-muted\">\n {{ 'chatMessage.viewProgress' | transloco }}\n </summary>\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 </details>\n </div>\n\n <!-- Message content -->\n <div class=\"message-content\" *ngIf=\"message.content\">\n\n <!-- Custom rendering for WPS, to be remove with https://sinequa.atlassian.net/browse/ES-23710 -->\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 !== 'CHART') || message?.role === 'connection-error' || message?.role === 'search-warning'\" [markdown]=\"message.content | messageContent\" [processor]=\"processor\">\n\n <!-- Chat reference (badge with file and part number) -->\n <ng-template remarkTemplate=\"chat-reference\" let-ref>\n @let attachment = referenceMap.get(ref.refId);\n @if (attachment) {\n <a\n class=\"reference\"\n role=\"button\"\n [sqTooltip]=\"attachment\"\n [sqTooltipTemplate]=\"tooltipTpl\"\n [hoverableTooltip]=\"true\"\n (click)=\"openAttachmentPreview(attachment, ref.refId)\"\n >\n {{ref.refId}}\n </a>\n }\n @else {\n <ng-template #staticRefTpl>\n <span class=\"reference\">{{ ref.refId }}</span>\n </ng-template>\n }\n </ng-template>\n\n <!-- Embedded reference image -->\n <ng-template remarkTemplate=\"embedded-image-reference\" let-ref>\n @let refObj = getEmbeddedImageReference(ref.value);\n @if (refObj && refObj.url) {\n <span\n [ngClass]=\"{ 'reference': true, 'has-bounding-box': ref.boundingBox }\"\n [sqTooltip]=\"{ obj: refObj, id: ref.value }\"\n [sqTooltipTemplate]=\"imageTooltipTpl\"\n [hoverableTooltip]=\"true\"\n >\n Img-{{ ref.value }}\n </span>\n }\n </ng-template>\n\n <!-- Embedded reference page -->\n <ng-template remarkTemplate=\"embedded-page-reference\" let-ref>\n @let refObj = getEmbeddedPageReference(ref.value);\n @if (refObj && refObj.url) {\n <span\n [ngClass]=\"{ 'reference': true, 'has-bounding-box': ref.boundingBox }\"\n [sqTooltip]=\"{ obj: refObj, id: ref.value }\"\n [sqTooltipTemplate]=\"pageTooltipTpl\"\n [hoverableTooltip]=\"true\"\n >\n Page-{{ ref.value }}\n </span>\n }\n </ng-template>\n\n <!-- Blinking cursor -->\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> {{ 'chatMessage.copyCode' | transloco }}</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 | messageContent }}</p>\n\n <!-- List of reference, if any -->\n @if (references?.length > 0 || imageReferencesMap?.size > 0 || pageReferencesMap?.size > 0) {\n <div class=\"references\">\n <details role=\"button\" class=\"select-none\" [open]=\"!showReferences\">\n <summary class=\"references-title\">{{ 'chatMessage.references' | transloco }}</summary>\n <ul>\n @for (reference of references; track $index) {\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 }\n @for (imageReference of imageReferencesMap.entries(); track $index) {\n <li style=\"list-style-type: none;\">\n <InlineImageReference\n [id]=\"imageReference[0]\"\n [ref]=\"imageReference[1]\"\n (openPreview)=\"openAttachmentPreview($event)\"\n (openDocument)=\"openOriginalAttachment($event, $event.$partId)\"\n (openModal)=\"hideTooltip()\"\n />\n </li>\n }\n @for (pageReference of pageReferencesMap.entries(); track $index) {\n <li style=\"list-style-type: none;\">\n <InlinePageReference\n [id]=\"pageReference[0]\"\n [ref]=\"pageReference[1]\"\n (openPreview)=\"openAttachmentPreview($event)\"\n (openDocument)=\"openOriginalAttachment($event, $event.$partId)\"\n (openModal)=\"hideTooltip()\"\n />\n </li>\n }\n </ul>\n </details>\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]=\"'chatMessage.copyText' | transloco\" (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]=\"'chatMessage.editMessage' | transloco\" (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]=\"message.additionalProperties.$liked\" *ngIf=\"canLike\" [sqTooltip]=\"'chatMessage.likeAnswer' | transloco\" (click)=\"like.emit()\">\n <i *ngIf=\"!message.additionalProperties.$liked\" class=\"far fa-thumbs-up \"></i>\n <i *ngIf=\"message.additionalProperties.$liked\" class=\"fas fa-thumbs-up\"></i>\n </button>\n <button class=\"btn btn-sm\" [class.bounce]=\"message.additionalProperties.$disliked\" *ngIf=\"canDislike\" [sqTooltip]=\"'chatMessage.reportIssue' | transloco\" (click)=\"dislike.emit()\">\n <i *ngIf=\"!message.additionalProperties.$disliked\" class=\"far fa-thumbs-down \"></i>\n <i *ngIf=\"message.additionalProperties.$disliked\" class=\"fas fa-thumbs-down\"></i>\n </button>\n <button class=\"btn btn-sm\" *ngIf=\"canRegenerate\" [sqTooltip]=\"'chatMessage.regenerateResponse' | transloco\" (click)=\"regenerate.emit(message)\">\n <i class=\"fas fa-sync-alt\"></i>\n </button>\n <button class=\"btn btn-sm\" *ngIf=\"canDebug\" [sqTooltip]=\"'chatMessage.showLogInformation' | transloco\" (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 #imageTooltipTpl let-ref>\n <InlineImageReference\n style=\"max-width: 30vw;\"\n [id]=\"ref.id\"\n [ref]=\"ref.obj\"\n (openPreview)=\"openAttachmentPreview($event)\"\n (openDocument)=\"openOriginalAttachment($event, $event.$partId)\"\n (openModal)=\"hideTooltip()\"\n />\n </ng-template>\n\n <ng-template #pageTooltipTpl let-ref>\n <InlinePageReference\n style=\"max-width: 30vw;\"\n [id]=\"ref.id\"\n [ref]=\"ref.obj\"\n (openPreview)=\"openAttachmentPreview($event)\"\n (openDocument)=\"openOriginalAttachment($event, $event.$partId)\"\n (openModal)=\"hideTooltip()\"\n />\n </ng-template>\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));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-uploaded-doc-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;--ast-report-bg: #070707}: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 ::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: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{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-5, 1.25rem));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"] }]
|
|
1592
|
+
TranslocoPipe,
|
|
1593
|
+
SmartRendererComponent
|
|
1594
|
+
], providers: [provideTranslocoScope('chat-message')], 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\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\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\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</span>\n\n<!-- Message body -->\n<div class=\"flex-grow-1 position-relative relative\" 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 <details role=\"button\" class=\"select-none\" [open]=\"!collapseProgress\">\n <summary class=\"text-muted\">\n {{ 'chatMessage.viewProgress' | transloco }}\n </summary>\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 </details>\n </div>\n\n <!-- Message content -->\n <div class=\"message-content\" *ngIf=\"message.content\">\n\n <!-- Custom rendering for WPS, to be remove with https://sinequa.atlassian.net/browse/ES-23710 -->\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\n\n @if(message?.role === 'assistant' && message.messageType !== 'CHART') {\n <SmartRenderer\n [message]=\"message.content | messageContent\"\n [context]=\"{\n getEmbeddedPageReference: getEmbeddedPageReference.bind(this),\n getEmbeddedImageReference: getEmbeddedImageReference.bind(this),\n referencesMap: referenceMap,\n references: processReferences.bind(this),\n rank: id()\n }\">\n </SmartRenderer>\n }\n\n <p *ngIf=\"message?.role === 'user'\">{{ message.content | messageContent }}</p>\n\n <!-- List of reference, if any -->\n @let referencesArray = references();\n @if (referencesArray?.length > 0 || imageReferencesMap?.size > 0 || pageReferencesMap?.size > 0) {\n <div class=\"references\">\n <details role=\"button\" class=\"select-none\" [open]=\"!collapseReferences\">\n <summary class=\"references-title\">{{ 'chatMessage.references' | transloco }}</summary>\n <ul>\n @for (reference of referencesArray; track $index) {\n @let attachment = referenceMap.get(reference);\n <!-- Only display the reference when the key is a integer not a decimal -->\n @if(attachment) {\n <li class=\"text-truncate\">\n <sq-chat-reference\n [class.expanded]=\"attachment?.$expanded\"\n [attachment]=\"attachment\"\n [reference]=\"reference\"\n [referenceMap]=\"referenceMap\"\n [images]=\"Array.from(imageReferencesMap.keys())\"\n [pages]=\"Array.from(pageReferencesMap.keys())\"\n (openPreview)=\"openAttachmentPreview($event)\"\n (openDocument)=\"openOriginalAttachment($event)\">\n </sq-chat-reference>\n </li>\n }\n }\n </ul>\n </details>\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]=\"'chatMessage.copyText' | transloco\" (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]=\"'chatMessage.editMessage' | transloco\" (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]=\"message.additionalProperties.$liked\" *ngIf=\"canLike\" [sqTooltip]=\"'chatMessage.likeAnswer' | transloco\" (click)=\"like.emit()\">\n <i *ngIf=\"!message.additionalProperties.$liked\" class=\"far fa-thumbs-up \"></i>\n <i *ngIf=\"message.additionalProperties.$liked\" class=\"fas fa-thumbs-up\"></i>\n </button>\n <button class=\"btn btn-sm\" [class.bounce]=\"message.additionalProperties.$disliked\" *ngIf=\"canDislike\" [sqTooltip]=\"'chatMessage.reportIssue' | transloco\" (click)=\"dislike.emit()\">\n <i *ngIf=\"!message.additionalProperties.$disliked\" class=\"far fa-thumbs-down \"></i>\n <i *ngIf=\"message.additionalProperties.$disliked\" class=\"fas fa-thumbs-down\"></i>\n </button>\n <button class=\"btn btn-sm\" *ngIf=\"canRegenerate\" [sqTooltip]=\"'chatMessage.regenerateResponse' | transloco\" (click)=\"regenerate.emit(message)\">\n <i class=\"fas fa-sync-alt\"></i>\n </button>\n <button class=\"btn btn-sm\" *ngIf=\"canDebug\" [sqTooltip]=\"'chatMessage.showLogInformation' | transloco\" (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 #imageTooltipTpl let-ref>\n <InlineImageReference\n style=\"max-width: 30vw;\"\n [id]=\"ref.id\"\n [ref]=\"ref.obj\"\n (openPreview)=\"openAttachmentPreview($event)\"\n (openDocument)=\"openOriginalAttachment($event, $event.$partId)\"\n (openModal)=\"hideTooltip()\"\n />\n </ng-template>\n\n <ng-template #pageTooltipTpl let-ref>\n <InlinePageReference\n style=\"max-width: 30vw;\"\n [id]=\"ref.id\"\n [ref]=\"ref.obj\"\n (openPreview)=\"openAttachmentPreview($event)\"\n (openDocument)=\"openOriginalAttachment($event, $event.$partId)\"\n (openModal)=\"hideTooltip()\"\n />\n </ng-template>\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));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-uploaded-doc-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;--ast-report-bg: #070707}: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 ::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: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{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-5, 1.25rem));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"] }]
|
|
1458
1595
|
}], ctorParameters: () => [{ type: UIService }, { type: PrincipalService }, { type: i0.ChangeDetectorRef }, { type: i0.ElementRef }], propDecorators: { message: [{
|
|
1459
1596
|
type: Input
|
|
1460
1597
|
}], conversation: [{
|
|
@@ -1483,6 +1620,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
|
|
|
1483
1620
|
type: Input
|
|
1484
1621
|
}], canDislike: [{
|
|
1485
1622
|
type: Input
|
|
1623
|
+
}], collapseReferences: [{
|
|
1624
|
+
type: Input
|
|
1486
1625
|
}], openDocument: [{
|
|
1487
1626
|
type: Output
|
|
1488
1627
|
}], openPreview: [{
|
|
@@ -1713,7 +1852,7 @@ class SavedChatsService {
|
|
|
1713
1852
|
acc[key] = String(value);
|
|
1714
1853
|
return acc;
|
|
1715
1854
|
}, {}));
|
|
1716
|
-
from(get(`plugin/${config.getRestUrl()}`, searchParams)).pipe(tap$1(res => {
|
|
1855
|
+
from(get(`api/v1/plugin/${config.getRestUrl()}`, searchParams)).pipe(tap$1(res => {
|
|
1717
1856
|
config.updateSavedChatsList(res.savedChats);
|
|
1718
1857
|
config.setSavedChatsErrorStatus(false);
|
|
1719
1858
|
}), catchError((error) => {
|
|
@@ -1740,7 +1879,7 @@ class SavedChatsService {
|
|
|
1740
1879
|
acc[key] = String(value);
|
|
1741
1880
|
return acc;
|
|
1742
1881
|
}, {}));
|
|
1743
|
-
return from(get(`plugin/${config.getRestUrl()}`, searchParams)).pipe(tap$1(res => {
|
|
1882
|
+
return from(get(`api/v1/plugin/${config.getRestUrl()}`, searchParams)).pipe(tap$1(res => {
|
|
1744
1883
|
config.generateAuditEvent('ast-saved-chat.load', { duration: res.executionTimeMilliseconds }, res.savedChat.id);
|
|
1745
1884
|
}), map(res => res.savedChat), catchError((error) => {
|
|
1746
1885
|
const errorMsg = 'Error occurred while calling the SavedChatGet API: ' + error.error?.errorMessage;
|
|
@@ -1762,7 +1901,7 @@ class SavedChatsService {
|
|
|
1762
1901
|
history: messages,
|
|
1763
1902
|
debug: config.getDebugFlag()
|
|
1764
1903
|
};
|
|
1765
|
-
return from(post(`plugin/${config.getRestUrl()}`, data)).pipe(tap$1(res => {
|
|
1904
|
+
return from(post(`api/v1/plugin/${config.getRestUrl()}`, data)).pipe(tap$1(res => {
|
|
1766
1905
|
config.generateAuditEvent('ast-saved-chat.add', { duration: res.executionTimeMilliseconds }, res.savedChat.id);
|
|
1767
1906
|
}), catchError((error) => {
|
|
1768
1907
|
const errorMsg = 'Error occurred while calling the SavedChatAdd API: ' + error.error?.errorMessage;
|
|
@@ -1787,7 +1926,7 @@ class SavedChatsService {
|
|
|
1787
1926
|
data["title"] = name;
|
|
1788
1927
|
if (messages)
|
|
1789
1928
|
data["history"] = messages;
|
|
1790
|
-
return from(post(`plugin/${config.getRestUrl()}`, data)).pipe(catchError((error) => {
|
|
1929
|
+
return from(post(`api/v1/plugin/${config.getRestUrl()}`, data)).pipe(catchError((error) => {
|
|
1791
1930
|
const errorMsg = 'Error occurred while calling the SavedChatUpdate API: ' + error.error?.errorMessage;
|
|
1792
1931
|
console.error('SavedChatsService: ' + errorMsg);
|
|
1793
1932
|
return throwError(() => error);
|
|
@@ -1806,7 +1945,7 @@ class SavedChatsService {
|
|
|
1806
1945
|
chatIds: ids,
|
|
1807
1946
|
debug: config.getDebugFlag()
|
|
1808
1947
|
};
|
|
1809
|
-
return from(post(`plugin/${config.getRestUrl()}`, data)).pipe(catchError((error) => {
|
|
1948
|
+
return from(post(`api/v1/plugin/${config.getRestUrl()}`, data)).pipe(catchError((error) => {
|
|
1810
1949
|
return throwError(() => error);
|
|
1811
1950
|
}));
|
|
1812
1951
|
}
|
|
@@ -1827,20 +1966,17 @@ class SavedChatsService {
|
|
|
1827
1966
|
acc[key] = String(value);
|
|
1828
1967
|
return acc;
|
|
1829
1968
|
}, {}));
|
|
1830
|
-
return from(get(`plugin/${config.getRestUrl()}`, searchParams)).pipe(map(res => res.exists), catchError((error) => {
|
|
1969
|
+
return from(get(`api/v1/plugin/${config.getRestUrl()}`, searchParams)).pipe(map(res => res.exists), catchError((error) => {
|
|
1831
1970
|
const errorMsg = 'Error occurred while calling the SavedChatExist API: ' + error.error?.errorMessage;
|
|
1832
1971
|
console.error('SavedChatsService: ' + errorMsg);
|
|
1833
1972
|
return throwError(() => error);
|
|
1834
1973
|
}));
|
|
1835
1974
|
}
|
|
1836
1975
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SavedChatsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1837
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SavedChatsService
|
|
1976
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SavedChatsService }); }
|
|
1838
1977
|
}
|
|
1839
1978
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SavedChatsService, decorators: [{
|
|
1840
|
-
type: Injectable
|
|
1841
|
-
args: [{
|
|
1842
|
-
providedIn: 'root'
|
|
1843
|
-
}]
|
|
1979
|
+
type: Injectable
|
|
1844
1980
|
}], ctorParameters: () => [] });
|
|
1845
1981
|
|
|
1846
1982
|
/** A token that is used to inject the transports allowed to use by hub connection.
|
|
@@ -2117,7 +2253,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
|
|
|
2117
2253
|
const connectionSettingsSchema = z
|
|
2118
2254
|
.object({
|
|
2119
2255
|
connectionErrorMessage: z.string(),
|
|
2120
|
-
restEndpoint: z.string().optional(),
|
|
2121
2256
|
websocketEndpoint: z.string().optional(),
|
|
2122
2257
|
signalRSkipNegotiation: z.boolean().optional(),
|
|
2123
2258
|
signalRTransport: z.enum([
|
|
@@ -2136,9 +2271,6 @@ const connectionSettingsSchema = z
|
|
|
2136
2271
|
"Warning",
|
|
2137
2272
|
]),
|
|
2138
2273
|
signalRServerTimeoutInMilliseconds: z.number().optional(),
|
|
2139
|
-
})
|
|
2140
|
-
.refine((data) => !!data.restEndpoint || !!data.websocketEndpoint, {
|
|
2141
|
-
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.",
|
|
2142
2274
|
});
|
|
2143
2275
|
// Define the Zod representation for the serviceSettings object
|
|
2144
2276
|
const serviceSettingsSchema = z.object({
|
|
@@ -2224,6 +2356,7 @@ const globalSettingsSchema = z.object({
|
|
|
2224
2356
|
genericChatErrorMessage: z.string().optional(),
|
|
2225
2357
|
displayUserQuotaConsumption: z.boolean().optional(),
|
|
2226
2358
|
displayChatTokensConsumption: z.boolean().optional(),
|
|
2359
|
+
collapseReferences: z.boolean().optional()
|
|
2227
2360
|
});
|
|
2228
2361
|
// Define the Zod representation for the auditSettings object
|
|
2229
2362
|
const auditSettingsSchema = z.object({
|
|
@@ -2272,10 +2405,8 @@ class AssistantConfigurationService {
|
|
|
2272
2405
|
async initChatConfig() {
|
|
2273
2406
|
this.ensureInitialized();
|
|
2274
2407
|
const context = this.context;
|
|
2275
|
-
//
|
|
2276
|
-
|
|
2277
|
-
const capp = await fetchApp();
|
|
2278
|
-
this.appService.app = capp;
|
|
2408
|
+
// Ensure the app service is initialized
|
|
2409
|
+
await this.appService.init();
|
|
2279
2410
|
const settings = await fetchUserSettings();
|
|
2280
2411
|
this.userSettingsService.userSettings = settings;
|
|
2281
2412
|
const key = context.getChatInstanceId();
|
|
@@ -2380,22 +2511,15 @@ class AssistantConfigurationService {
|
|
|
2380
2511
|
getRESTRequestsUrl() {
|
|
2381
2512
|
this.ensureInitialized();
|
|
2382
2513
|
const context = this.context;
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
}
|
|
2387
|
-
else {
|
|
2388
|
-
throw new Error(`The property 'restEndpoint' must be provided`);
|
|
2389
|
-
}
|
|
2514
|
+
// According tothe ticket ES-27809, this value is hardcoded and could not be changed
|
|
2515
|
+
const url = "SinequaAssistantREST";
|
|
2516
|
+
context.setRESTRequestsUrl(url);
|
|
2390
2517
|
}
|
|
2391
2518
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AssistantConfigurationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2392
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AssistantConfigurationService
|
|
2519
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AssistantConfigurationService }); }
|
|
2393
2520
|
}
|
|
2394
2521
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AssistantConfigurationService, decorators: [{
|
|
2395
|
-
type: Injectable
|
|
2396
|
-
args: [{
|
|
2397
|
-
providedIn: 'root'
|
|
2398
|
-
}]
|
|
2522
|
+
type: Injectable
|
|
2399
2523
|
}], ctorParameters: () => [] });
|
|
2400
2524
|
|
|
2401
2525
|
class AssistantMetadataService {
|
|
@@ -2419,7 +2543,7 @@ class AssistantMetadataService {
|
|
|
2419
2543
|
acc[key] = typeof value === 'string' ? value : JSON.stringify(value);
|
|
2420
2544
|
return acc;
|
|
2421
2545
|
}, {}));
|
|
2422
|
-
return from(get(`plugin/${context.getRestUrl()}`, searchParams))
|
|
2546
|
+
return from(get(`api/v1/plugin/${context.getRestUrl()}`, searchParams))
|
|
2423
2547
|
.pipe(map(res => res?.models), tap$1(models => context.setModels(models?.filter(model => !!model.enable))), catchError((error) => {
|
|
2424
2548
|
console.error('Error invoking listmodels:', error);
|
|
2425
2549
|
return throwError(() => error);
|
|
@@ -2437,7 +2561,7 @@ class AssistantMetadataService {
|
|
|
2437
2561
|
acc[key] = typeof value === 'string' ? value : JSON.stringify(value);
|
|
2438
2562
|
return acc;
|
|
2439
2563
|
}, {}));
|
|
2440
|
-
return from(get(`plugin/${context.getRestUrl()}`, searchParams))
|
|
2564
|
+
return from(get(`api/v1/plugin/${context.getRestUrl()}`, searchParams))
|
|
2441
2565
|
.pipe(map(res => res?.functions), tap$1((functions) => {
|
|
2442
2566
|
const enabledConfigFunctions = assistantConfig.defaultValues.functions;
|
|
2443
2567
|
context.setFunctions(functions?.filter(func => func.enabled && !!enabledConfigFunctions.find(fn => fn.name === func.functionName)));
|
|
@@ -2496,13 +2620,10 @@ class AssistantTokensTrackingService {
|
|
|
2496
2620
|
}
|
|
2497
2621
|
}
|
|
2498
2622
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AssistantTokensTrackingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2499
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AssistantTokensTrackingService
|
|
2623
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AssistantTokensTrackingService }); }
|
|
2500
2624
|
}
|
|
2501
2625
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AssistantTokensTrackingService, decorators: [{
|
|
2502
|
-
type: Injectable
|
|
2503
|
-
args: [{
|
|
2504
|
-
providedIn: 'root'
|
|
2505
|
-
}]
|
|
2626
|
+
type: Injectable
|
|
2506
2627
|
}], ctorParameters: () => [] });
|
|
2507
2628
|
|
|
2508
2629
|
class AssistantWsFramesService {
|
|
@@ -2915,20 +3036,17 @@ class DebugMessageService {
|
|
|
2915
3036
|
acc[key] = String(value);
|
|
2916
3037
|
return acc;
|
|
2917
3038
|
}, {}));
|
|
2918
|
-
return from(get(`plugin/${config.getRestUrl()}`, searchParams)).pipe(map(res => res?.debugMessages[0]?.content), catchError((error) => {
|
|
3039
|
+
return from(get(`api/v1/plugin/${config.getRestUrl()}`, searchParams)).pipe(map(res => res?.debugMessages[0]?.content), catchError((error) => {
|
|
2919
3040
|
const errorMsg = 'Error occurred while calling the debugMessageList API: ' + error.error?.errorMessage;
|
|
2920
3041
|
console.error('DebugMessageService: ' + errorMsg);
|
|
2921
3042
|
return throwError(() => error);
|
|
2922
3043
|
}));
|
|
2923
3044
|
}
|
|
2924
3045
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DebugMessageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2925
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DebugMessageService
|
|
3046
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DebugMessageService }); }
|
|
2926
3047
|
}
|
|
2927
3048
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DebugMessageService, decorators: [{
|
|
2928
|
-
type: Injectable
|
|
2929
|
-
args: [{
|
|
2930
|
-
providedIn: 'root'
|
|
2931
|
-
}]
|
|
3049
|
+
type: Injectable
|
|
2932
3050
|
}], ctorParameters: () => [] });
|
|
2933
3051
|
|
|
2934
3052
|
class ChatService {
|
|
@@ -3016,7 +3134,8 @@ class ChatService {
|
|
|
3016
3134
|
])),
|
|
3017
3135
|
// Map the results of parallel requests to a boolean indicating success
|
|
3018
3136
|
map$1(([models, functions]) => {
|
|
3019
|
-
const result = !!models && !!functions;
|
|
3137
|
+
const result = (models !== undefined && functions !== undefined && !!models && !!functions);
|
|
3138
|
+
this.models = models;
|
|
3020
3139
|
this.initProcess$.next(result);
|
|
3021
3140
|
return result;
|
|
3022
3141
|
}),
|
|
@@ -3524,7 +3643,7 @@ class DebugMessageDetailsComponent {
|
|
|
3524
3643
|
this.parentColor = ''; // Track the parent row color
|
|
3525
3644
|
}
|
|
3526
3645
|
ngAfterViewInit() {
|
|
3527
|
-
Prism
|
|
3646
|
+
Prism.highlightAll();
|
|
3528
3647
|
}
|
|
3529
3648
|
isObject(value) {
|
|
3530
3649
|
return value !== null && typeof value === 'object';
|
|
@@ -3727,6 +3846,13 @@ class ChatComponent {
|
|
|
3727
3846
|
throw error;
|
|
3728
3847
|
}
|
|
3729
3848
|
})).subscribe());
|
|
3849
|
+
// Example of listening to custom events from the web element and handling them in the Angular component
|
|
3850
|
+
addEventListener('onOpenPreview', (event) => {
|
|
3851
|
+
this.openPreview.emit(event.detail.reference);
|
|
3852
|
+
});
|
|
3853
|
+
addEventListener('onOpenDocument', (event) => {
|
|
3854
|
+
this.openDocument.emit(event.detail.reference.record);
|
|
3855
|
+
});
|
|
3730
3856
|
}
|
|
3731
3857
|
ngOnChanges(changes) {
|
|
3732
3858
|
this.changes$.next(changes);
|
|
@@ -3879,8 +4005,10 @@ class ChatComponent {
|
|
|
3879
4005
|
*/
|
|
3880
4006
|
_addScrollListener() {
|
|
3881
4007
|
this._sub.add(merge(this.loading$, this.messages$, this.chatService.streaming$, fromEvent(this.messageList.nativeElement, 'scroll')).subscribe(() => {
|
|
3882
|
-
|
|
3883
|
-
|
|
4008
|
+
setTimeout(() => {
|
|
4009
|
+
this.isAtBottom = this._toggleScrollButtonVisibility();
|
|
4010
|
+
this.cdr.detectChanges();
|
|
4011
|
+
});
|
|
3884
4012
|
}));
|
|
3885
4013
|
}
|
|
3886
4014
|
/**
|
|
@@ -3903,11 +4031,11 @@ class ChatComponent {
|
|
|
3903
4031
|
}
|
|
3904
4032
|
if (this.question.trim() && this.messages$.value && this.chatService.chatHistory) {
|
|
3905
4033
|
// When the user submits a question, if the user is editing a previous message, remove all subsequent messages from the chat history
|
|
3906
|
-
if (this.indexMessageToEdit !== undefined) {
|
|
4034
|
+
if (this.indexMessageToEdit !== undefined && this.rankMessageToEdit !== undefined) {
|
|
3907
4035
|
// Update the messages in the UI
|
|
3908
4036
|
this.messages$.next(this.messages$.value.slice(0, this.indexMessageToEdit));
|
|
3909
4037
|
// Update the raw messages in the chat history which is the clean version used to make the next request
|
|
3910
|
-
this.chatService.chatHistory = this.chatService.chatHistory.slice(0, this.rankMessageToEdit);
|
|
4038
|
+
this.chatService.chatHistory = this.chatService.chatHistory.slice(0, this.rankMessageToEdit - 1);
|
|
3911
4039
|
this.indexMessageToEdit = undefined;
|
|
3912
4040
|
this.rankMessageToEdit = undefined;
|
|
3913
4041
|
}
|
|
@@ -3936,6 +4064,7 @@ class ChatComponent {
|
|
|
3936
4064
|
const messages = [...conversation, userMsg];
|
|
3937
4065
|
this.messages$.next(messages); // Update the messages in the UI with the new user message
|
|
3938
4066
|
this.chatService.chatHistory = messages; // Update the chat history with the new user message
|
|
4067
|
+
this.scrollDown(); // Scroll down to the bottom of the chat to see the new user message and the incoming assistant answer
|
|
3939
4068
|
this.fetch(messages);
|
|
3940
4069
|
this.chatService.generateAuditEvent('ast-message.message', { ...this._defineMessageAuditDetails(userMsg), 'query': JSON.stringify(this.query), 'is-user-input': true, 'enabled-functions': this.config.defaultValues.functions?.filter(func => func.enabled).map(func => func.name), 'additional-workflow-properties': JSON.stringify(additionalWorkflowProperties) });
|
|
3941
4070
|
}
|
|
@@ -4146,11 +4275,20 @@ class ChatComponent {
|
|
|
4146
4275
|
* If the chat is meant to be initialized with event === "Query", the corresponding user query message will be added to the chat history
|
|
4147
4276
|
*/
|
|
4148
4277
|
loadDefaultChat() {
|
|
4278
|
+
const date = (new Date()).toLocaleString('en-US', { weekday: 'long', month: 'long', day: '2-digit', year: 'numeric' });
|
|
4149
4279
|
// Define the default system prompt and user prompt messages
|
|
4150
|
-
const systemMsg = {
|
|
4280
|
+
const systemMsg = {
|
|
4281
|
+
role: 'system',
|
|
4282
|
+
content: AssistantUtils.formatPrompt(this.transloco.translate(this.config.defaultValues.systemPrompt), { principal: this.principalService.principal, date }),
|
|
4283
|
+
additionalProperties: { display: false, messageId: guid() }
|
|
4284
|
+
};
|
|
4151
4285
|
// backward compatibility with old configuration files
|
|
4152
4286
|
const userPrompt = this.config.defaultValues.userPrompt.replace(/\{\{(.*?)\}\}/g, '[[$1]]');
|
|
4153
|
-
const userMsg = {
|
|
4287
|
+
const userMsg = {
|
|
4288
|
+
role: 'user',
|
|
4289
|
+
content: AssistantUtils.formatPrompt(this.transloco.translate(userPrompt), { principal: this.principalService.principal, date }),
|
|
4290
|
+
additionalProperties: { display: this.config.modeSettings.displayUserPrompt, messageId: guid() }
|
|
4291
|
+
};
|
|
4154
4292
|
if (this.config.modeSettings.initialization.event === 'Query') {
|
|
4155
4293
|
this._handleQueryMode(systemMsg, userMsg);
|
|
4156
4294
|
}
|
|
@@ -4531,11 +4669,16 @@ class ChatComponent {
|
|
|
4531
4669
|
/**
|
|
4532
4670
|
* Handle the click on a suggested action.
|
|
4533
4671
|
* @param action Suggested action.
|
|
4534
|
-
* @param index
|
|
4672
|
+
* @param index index of the message containing the suggested action.
|
|
4673
|
+
* @returns void
|
|
4535
4674
|
*/
|
|
4536
4675
|
suggestActionClick(action, index) {
|
|
4537
4676
|
this.suggestAction.emit(action);
|
|
4538
|
-
|
|
4677
|
+
const details = {
|
|
4678
|
+
'text': action.content,
|
|
4679
|
+
'suggestedAction-type': action.type
|
|
4680
|
+
};
|
|
4681
|
+
this.chatService.generateAuditEvent('ast-suggested-action.click', details);
|
|
4539
4682
|
}
|
|
4540
4683
|
/**
|
|
4541
4684
|
* It looks for the debug messages available in the current group of "assistant" messages.
|
|
@@ -4613,15 +4756,23 @@ class ChatComponent {
|
|
|
4613
4756
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ChatComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4614
4757
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: ChatComponent, isStandalone: true, selector: "sq-chat-v3", inputs: { instanceId: "instanceId", query: "query", queryChangeShouldTriggerReload: "queryChangeShouldTriggerReload", messageHandlers: "messageHandlers", automaticScrollToLastResponse: "automaticScrollToLastResponse", focusAfterResponse: "focusAfterResponse", chat: "chat", assistantMessageIcon: "assistantMessageIcon", userMessageIcon: "userMessageIcon", connectionErrorMessageIcon: "connectionErrorMessageIcon", searchWarningMessageIcon: "searchWarningMessageIcon", additionalWorkflowProperties: "additionalWorkflowProperties", appConfig: "appConfig" }, outputs: { connection: "connection", loading$: "loading", _config: "config", data: "data", openDocument: "openDocument", openPreview: "openPreview", suggestAction: "suggestAction" }, providers: [
|
|
4615
4758
|
ChatService,
|
|
4759
|
+
AssistantConfigurationService,
|
|
4760
|
+
AssistantTokensTrackingService,
|
|
4761
|
+
SavedChatsService,
|
|
4762
|
+
DebugMessageService,
|
|
4616
4763
|
provideTranslocoScope('chat')
|
|
4617
|
-
], 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 }], 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=\"d-flex flex-column list-unstyled gap-3 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 && !isEmptyAssistantMessage(message)\"\n [style.--bs-list-group-item-padding-y.rem]=\"'0.6'\"\n [class.opacity-50]=\"indexMessageToEdit && (indexMessageToEdit < (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]=\"(chatService.streaming$ | async) && (last || isAssistantLastMessages(messages, index))\"\n [canEdit]=\"(chatService.streaming$ | async) === false && indexMessageToEdit === undefined && message.role === 'user'\"\n [canCopy]=\"((chatService.streaming$ | async) === false || !last) && indexMessageToEdit === 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' && (getDebugMessages(message, index).length > 0) && ((isAdminOrDeletedAdmin || (chatService.userOverride$ | async)) && config?.defaultValues.debug)\"\n [canRegenerate]=\"(chatService.streaming$ | async) === false && (last || (!last && messages[index+1].role !== 'assistant')) && message.role === 'assistant' && indexMessageToEdit === undefined\"\n (edit)=\"editMessage(message, index)\"\n (copy)=\"copyMessage(message, index)\"\n (regenerate)=\"regenerateMessage(message, index)\"\n (openDocument)=\"openOriginalAttachment($event, message, index)\"\n (openPreview)=\"openAttachmentPreview($event, message, index)\"\n (suggestAction)=\"suggestActionClick($event, index)\"\n (like)=\"onLike(message, index)\"\n (dislike)=\"onDislike(message, index)\"\n (debug)=\"showDebug(message, index)\">\n </sq-chat-message>\n </li>\n </ng-container>\n <!-- Loading spinner -->\n <li *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 p-3 rounded-lg\" *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 @if (!showReport) {\n <div class=\"user-input mt-auto\">\n <div class=\"py-2\">\n <div [hidden]=\"!isConnected\">\n <ng-container *ngIf=\"enabledUserInput\" [ngTemplateOutlet]=\"inputTpl\"></ng-container>\n </div>\n <!-- Retry button -->\n <!-- hidden attribute is in conflict with a css rule display: flex -->\n @if(!isConnected){\n <button class=\"btn mb-4 ast-error ast-btn sq-retry\" (click)=\"retryFetch()\">\n <span>{{ 'chat.tryAgain' | transloco }}</span>\n <span *ngIf=\"retrialAttempts\" class=\"ms-2 attempts\">{{ retrialAttempts }}</span>\n </button>\n }\n <div class=\"text-end small text-muted px-3\" *ngIf=\"!!config?.globalSettings?.disclaimer\">\n {{ config?.globalSettings?.disclaimer | transloco }}\n </div>\n </div>\n </div>\n }\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()\" aria-label=\"Scroll down\">\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\">{{ 'chat.loading' | transloco }}</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\" aria-label=\"search\">\n <i class=\"fas fa-search\"></i>\n </button>\n <textarea #questionInput rows=\"1\"\n type=\"text\" class=\"form-control\"\n [placeholder]=\"'chat.askSomething' | transloco\" 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 <div id=\"chat-actions\" class=\"d-flex gap-2\">\n <button\n *ngIf=\"(chatService.streaming$ | async) === false && (loading$ | async) === false && (chatService.stoppingGeneration$ | async) === false\"\n type=\"button\"\n class=\"btn btn-light\"\n aria-label=\"Send message\"\n [sqTooltip]=\"'chat.sendMessage' | transloco\"\n (click)=\"submitQuestion()\">\n <i class=\"fas fa-paper-plane\"></i>\n </button>\n <button\n *ngIf=\"indexMessageToEdit\"\n aria-label=\"Cancel edition\"\n type=\"button\"\n class=\"btn btn-light\"\n [sqTooltip]=\"'chat.cancelEdition' | transloco\"\n (click)=\"indexMessageToEdit = undefined; question = ''\">\n <i class=\"fas fa-undo-alt\"></i>\n </button>\n <span *ngIf=\"(chatService.streaming$ | async) && (chatService.stoppingGeneration$ | async) === false\" class=\"processing\">\n {{ 'chat.generating' | transloco }}<i class=\"fas fa-spinner fa-pulse\"></i>\n </span>\n <span *ngIf=\"(chatService.stoppingGeneration$ | async)\" class=\"processing\">\n {{ 'chat.stopping' | transloco }}<i class=\"fas fa-spinner fa-pulse\"></i>\n </span>\n <button\n *ngIf=\"(chatService.streaming$ | async) && (chatService.stoppingGeneration$ | async) === false\"\n type=\"button\"\n class=\"btn btn-light\"\n aria-label=\"Stop generating\"\n [sqTooltip]=\"'chat.stopGeneration' | transloco\"\n (click)=\"stopGeneration()\">\n <i class=\"fas fa-stop\"></i>\n </button>\n </div>\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>{{ 'chat.issueType' | transloco }}</h5>\n <select class=\"form-select mb-4\" [(ngModel)]=\"issueType\">\n <option [value]=\"''\">{{ 'chat.chooseIssueType' | transloco }}</option>\n <option *ngFor=\"let type of (issueTypes ?? defaultIssueTypes)\" [value]=\"type\">{{ type | transloco }}</option>\n </select>\n <h5>{{ 'chat.askUnlikeReasons' | transloco }}</h5>\n </ng-container>\n <ng-container *ngIf=\"type === 'like'\">\n <h5>{{ 'chat.askLikeReasons' | transloco }}</h5>\n </ng-container>\n <textarea class=\"form-control border border-neutral-200\" [(ngModel)]=\"reportComment\" [placeholder]=\"'chat.writeComment' | transloco\"></textarea>\n <div class=\"d-flex flex-row-reverse gap-1 mt-2\">\n <button class=\"btn btn-primary\" [disabled]=\"type === 'dislike' && !issueType\" (click)=\"sendReport()\">{{ 'chat.send' | transloco }}</button>\n <button class=\"btn btn-light\" (click)=\"ignoreReport()\">{{ 'chat.doNotSend' | transloco }}</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\" aria-label=\"Hide debug messages\">\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-uploaded-doc-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;--ast-report-bg: #070707}: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);gap:.5rem}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%}.btn.sq-retry{display:flex;margin:auto;background:var(--ast-error-bg, rgba(249, 58, 55, .2));font-weight:var(--font-weight-bold, 500)}.btn.sq-retry .attempts{display:flex;border-radius:100%;background:#fff;height:20px;width:20px;place-content:center;align-items:center}.issue-report{background-color:var(--ast-report-bg, white)}.text-end{text-align:right}.small{font-size:.875em}.text-muted{--bs-text-opacity: 1;color:var(--bs-secondary-color)}.d-flex{display:flex}.flex-row-reverse{flex-direction:row-reverse}.flex-grow-1{flex-grow:1}.spinner-grow,.spinner-border{display:inline-block;width:var(--bs-spinner-width);height:var(--bs-spinner-height);vertical-align:var(--bs-spinner-vertical-align);border-radius:50%;animation:var(--bs-spinner-animation-speed) linear infinite var(--bs-spinner-animation-name)}.text-primary{--bs-text-opacity: 1;color:rgba(var(--bs-primary-rgb),var(--bs-text-opacity))}.d-block{display:block}.btn{--bs-border-radius: .25rem;--bs-btn-padding-x: .75rem;--bs-btn-padding-y: .375rem;--bs-btn-font-family: ;--bs-btn-font-size: 1rem;--bs-btn-font-weight: 400;--bs-btn-line-height: 1.5;--bs-btn-color: var(--bs-body-color);--bs-btn-bg: transparent;--bs-btn-border-width: var(--bs-border-width);--bs-btn-border-color: transparent;--bs-btn-border-radius: var(--bs-border-radius);--bs-btn-hover-border-color: transparent;--bs-btn-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);--bs-btn-disabled-opacity: .65;--bs-btn-focus-box-shadow: 0 0 0 .25rem rgba(var(--bs-btn-focus-shadow-rgb), .5);display:inline-block;padding:var(--bs-btn-padding-y) var(--bs-btn-padding-x);font-family:var(--bs-btn-font-family);font-size:var(--bs-btn-font-size);font-weight:var(--bs-btn-font-weight);line-height:var(--bs-btn-line-height);color:var(--bs-btn-color);text-align:center;text-decoration:none;vertical-align:middle;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none;border:var(--bs-btn-border-width) solid var(--bs-btn-border-color);border-radius:var(--bs-btn-border-radius);background-color:var(--bs-btn-bg);transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}.btn-primary{--bs-btn-color: #fff;--bs-btn-bg: #0d6efd;--bs-btn-border-color: #0d6efd;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #0b5ed7;--bs-btn-hover-border-color: #0a58ca;--bs-btn-focus-shadow-rgb: 49, 132, 253;--bs-btn-active-color: #fff;--bs-btn-active-bg: #0a58ca;--bs-btn-active-border-color: #0a53be;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color: #fff;--bs-btn-disabled-bg: #0d6efd;--bs-btn-disabled-border-color: #0d6efd}.btn-light{--bs-btn-color: #000;--bs-btn-bg: #f8f9fa;--bs-btn-border-color: #f8f9fa;--bs-btn-hover-color: #000;--bs-btn-hover-bg: #d3d4d5;--bs-btn-hover-border-color: #c6c7c8;--bs-btn-focus-shadow-rgb: 211, 212, 213;--bs-btn-active-color: #000;--bs-btn-active-bg: #c6c7c8;--bs-btn-active-border-color: #babbbc;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color: #000;--bs-btn-disabled-bg: #f8f9fa;--bs-btn-disabled-border-color: #f8f9fa}.form-control{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:var(--bs-body-color);-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--bs-body-bg);background-clip:padding-box;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}.form-control:disabled{background-color:var(--bs-body-bg)}.form-select{--bs-form-select-bg-img: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e\");display:block;width:100%;padding:.375rem 2.25rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:var(--bs-body-color);-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--bs-body-bg);background-image:var(--bs-form-select-bg-img),var(--bs-form-select-bg-icon, none);background-repeat:no-repeat;background-position:right .75rem center;background-size:16px 12px;border:var(--bs-border-width, 1px) solid var(--bs-border-color, oklch(92.2% 0 0));border-radius:var(--bs-border-radius);transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}\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"] }, { kind: "directive", type: TooltipDirective, selector: "[sqTooltip]", inputs: ["sqTooltip", "sqTooltipData", "sqTooltipTemplate", "placement", "fallbackPlacements", "delay", "hoverableTooltip", "tooltipClass"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
4764
|
+
], 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 }], 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=\"d-flex flex-column list-unstyled gap-3 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 && !isEmptyAssistantMessage(message)\"\n [style.--bs-list-group-item-padding-y.rem]=\"'0.6'\"\n [class.opacity-50]=\"indexMessageToEdit && (indexMessageToEdit < (index + 1))\">\n <sq-chat-message\n [id]=\"message.additionalProperties.messageId\"\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]=\"(chatService.streaming$ | async) && (last || isAssistantLastMessages(messages, index))\"\n [canEdit]=\"(chatService.streaming$ | async) === false && indexMessageToEdit === undefined && message.role === 'user'\"\n [canCopy]=\"((chatService.streaming$ | async) === false || !last) && indexMessageToEdit === 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' && (getDebugMessages(message, index).length > 0) && ((isAdminOrDeletedAdmin || (chatService.userOverride$ | async)) && config?.defaultValues.debug)\"\n [canRegenerate]=\"(chatService.streaming$ | async) === false && (last || (!last && messages[index+1].role !== 'assistant')) && message.role === 'assistant' && indexMessageToEdit === undefined\"\n [collapseReferences]=\"!!config?.globalSettings.collapseReferences\"\n (edit)=\"editMessage(message, index)\"\n (copy)=\"copyMessage(message, index)\"\n (regenerate)=\"regenerateMessage(message, index)\"\n (openDocument)=\"openOriginalAttachment($event, message, index)\"\n (openPreview)=\"openAttachmentPreview($event, message, index)\"\n (suggestAction)=\"suggestActionClick($event, index)\"\n (like)=\"onLike(message, index)\"\n (dislike)=\"onDislike(message, index)\"\n (debug)=\"showDebug(message, index)\">\n </sq-chat-message>\n </li>\n </ng-container>\n <!-- Loading spinner -->\n <li *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 p-3 rounded-lg\" *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 @if (!showReport) {\n <div class=\"user-input mt-auto\">\n <div class=\"py-2\">\n <div [hidden]=\"!isConnected\">\n <ng-container *ngIf=\"enabledUserInput\" [ngTemplateOutlet]=\"inputTpl\"></ng-container>\n </div>\n <!-- Retry button -->\n <!-- hidden attribute is in conflict with a css rule display: flex -->\n @if(!isConnected){\n <button class=\"btn mb-4 ast-error ast-btn sq-retry\" (click)=\"retryFetch()\">\n <span>{{ 'chat.tryAgain' | transloco }}</span>\n <span *ngIf=\"retrialAttempts\" class=\"ms-2 attempts\">{{ retrialAttempts }}</span>\n </button>\n }\n <div class=\"text-end small text-muted px-3\" *ngIf=\"!!config?.globalSettings?.disclaimer\">\n {{ config?.globalSettings?.disclaimer | transloco }}\n </div>\n </div>\n </div>\n }\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()\" aria-label=\"Scroll down\">\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\">{{ 'chat.loading' | transloco }}</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\" aria-label=\"search\">\n <i class=\"fas fa-search\"></i>\n </button>\n <textarea #questionInput rows=\"1\"\n type=\"text\" class=\"form-control\"\n [placeholder]=\"'chat.askSomething' | transloco\" 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 <div id=\"chat-actions\" class=\"d-flex gap-2\">\n <button\n *ngIf=\"(chatService.streaming$ | async) === false && (loading$ | async) === false && (chatService.stoppingGeneration$ | async) === false\"\n type=\"button\"\n class=\"btn btn-light\"\n aria-label=\"Send message\"\n [sqTooltip]=\"'chat.sendMessage' | transloco\"\n (click)=\"submitQuestion()\">\n <i class=\"fas fa-paper-plane\"></i>\n </button>\n <button\n *ngIf=\"indexMessageToEdit\"\n aria-label=\"Cancel edition\"\n type=\"button\"\n class=\"btn btn-light\"\n [sqTooltip]=\"'chat.cancelEdition' | transloco\"\n (click)=\"indexMessageToEdit = undefined; question = ''\">\n <i class=\"fas fa-undo-alt\"></i>\n </button>\n <span *ngIf=\"(chatService.streaming$ | async) && (chatService.stoppingGeneration$ | async) === false\" class=\"processing\">\n {{ 'chat.generating' | transloco }}<i class=\"fas fa-spinner fa-pulse\"></i>\n </span>\n <span *ngIf=\"(chatService.stoppingGeneration$ | async)\" class=\"processing\">\n {{ 'chat.stopping' | transloco }}<i class=\"fas fa-spinner fa-pulse\"></i>\n </span>\n <button\n *ngIf=\"(chatService.streaming$ | async) && (chatService.stoppingGeneration$ | async) === false\"\n type=\"button\"\n class=\"btn btn-light\"\n aria-label=\"Stop generating\"\n [sqTooltip]=\"'chat.stopGeneration' | transloco\"\n (click)=\"stopGeneration()\">\n <i class=\"fas fa-stop\"></i>\n </button>\n </div>\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>{{ 'chat.issueType' | transloco }}</h5>\n <select class=\"form-select mb-4\" [(ngModel)]=\"issueType\">\n <option [value]=\"''\">{{ 'chat.chooseIssueType' | transloco }}</option>\n <option *ngFor=\"let type of (issueTypes ?? defaultIssueTypes)\" [value]=\"type\">{{ type | transloco }}</option>\n </select>\n <h5>{{ 'chat.askUnlikeReasons' | transloco }}</h5>\n </ng-container>\n <ng-container *ngIf=\"type === 'like'\">\n <h5>{{ 'chat.askLikeReasons' | transloco }}</h5>\n </ng-container>\n <textarea class=\"form-control border border-neutral-200\" [(ngModel)]=\"reportComment\" [placeholder]=\"'chat.writeComment' | transloco\"></textarea>\n <div class=\"d-flex flex-row-reverse gap-1 mt-2\">\n <button class=\"btn btn-primary\" [disabled]=\"type === 'dislike' && !issueType\" (click)=\"sendReport()\">{{ 'chat.send' | transloco }}</button>\n <button class=\"btn btn-light\" (click)=\"ignoreReport()\">{{ 'chat.doNotSend' | transloco }}</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\" aria-label=\"Hide debug messages\">\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-uploaded-doc-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;--ast-report-bg: #070707}: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);gap:.5rem}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%}.btn.sq-retry{display:flex;margin:auto;background:var(--ast-error-bg, rgba(249, 58, 55, .2));font-weight:var(--font-weight-bold, 500)}.btn.sq-retry .attempts{display:flex;border-radius:100%;background:#fff;height:20px;width:20px;place-content:center;align-items:center}.issue-report{background-color:var(--ast-report-bg, white)}.text-end{text-align:right}.small{font-size:.875em}.text-muted{--bs-text-opacity: 1;color:var(--bs-secondary-color)}.d-flex{display:flex}.flex-row-reverse{flex-direction:row-reverse}.flex-grow-1{flex-grow:1}.spinner-grow,.spinner-border{display:inline-block;width:var(--bs-spinner-width);height:var(--bs-spinner-height);vertical-align:var(--bs-spinner-vertical-align);border-radius:50%;animation:var(--bs-spinner-animation-speed) linear infinite var(--bs-spinner-animation-name)}.text-primary{--bs-text-opacity: 1;color:rgba(var(--bs-primary-rgb),var(--bs-text-opacity))}.d-block{display:block}.btn{--bs-border-radius: .25rem;--bs-btn-padding-x: .75rem;--bs-btn-padding-y: .375rem;--bs-btn-font-family: ;--bs-btn-font-size: 1rem;--bs-btn-font-weight: 400;--bs-btn-line-height: 1.5;--bs-btn-color: var(--bs-body-color);--bs-btn-bg: transparent;--bs-btn-border-width: var(--bs-border-width);--bs-btn-border-color: transparent;--bs-btn-border-radius: var(--bs-border-radius);--bs-btn-hover-border-color: transparent;--bs-btn-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);--bs-btn-disabled-opacity: .65;--bs-btn-focus-box-shadow: 0 0 0 .25rem rgba(var(--bs-btn-focus-shadow-rgb), .5);display:inline-block;padding:var(--bs-btn-padding-y) var(--bs-btn-padding-x);font-family:var(--bs-btn-font-family);font-size:var(--bs-btn-font-size);font-weight:var(--bs-btn-font-weight);line-height:var(--bs-btn-line-height);color:var(--bs-btn-color);text-align:center;text-decoration:none;vertical-align:middle;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none;border:var(--bs-btn-border-width) solid var(--bs-btn-border-color);border-radius:var(--bs-btn-border-radius);background-color:var(--bs-btn-bg);transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}.btn-primary{--bs-btn-color: #fff;--bs-btn-bg: #0d6efd;--bs-btn-border-color: #0d6efd;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #0b5ed7;--bs-btn-hover-border-color: #0a58ca;--bs-btn-focus-shadow-rgb: 49, 132, 253;--bs-btn-active-color: #fff;--bs-btn-active-bg: #0a58ca;--bs-btn-active-border-color: #0a53be;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color: #fff;--bs-btn-disabled-bg: #0d6efd;--bs-btn-disabled-border-color: #0d6efd}.btn-light{--bs-btn-color: #000;--bs-btn-bg: #f8f9fa;--bs-btn-border-color: #f8f9fa;--bs-btn-hover-color: #000;--bs-btn-hover-bg: #d3d4d5;--bs-btn-hover-border-color: #c6c7c8;--bs-btn-focus-shadow-rgb: 211, 212, 213;--bs-btn-active-color: #000;--bs-btn-active-bg: #c6c7c8;--bs-btn-active-border-color: #babbbc;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color: #000;--bs-btn-disabled-bg: #f8f9fa;--bs-btn-disabled-border-color: #f8f9fa}.form-control{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:var(--bs-body-color);-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--bs-body-bg);background-clip:padding-box;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}.form-control:disabled{background-color:var(--bs-body-bg)}.form-select{--bs-form-select-bg-img: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e\");display:block;width:100%;padding:.375rem 2.25rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:var(--bs-body-color);-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--bs-body-bg);background-image:var(--bs-form-select-bg-img),var(--bs-form-select-bg-icon, none);background-repeat:no-repeat;background-position:right .75rem center;background-size:16px 12px;border:var(--bs-border-width, 1px) solid var(--bs-border-color, oklch(92.2% 0 0));border-radius:var(--bs-border-radius);transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}\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: ["id", "message", "conversation", "suggestedActions", "assistantMessageIcon", "userMessageIcon", "connectionErrorMessageIcon", "searchWarningMessageIcon", "streaming", "canEdit", "canRegenerate", "canCopy", "canDebug", "canLike", "canDislike", "collapseReferences"], 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"] }, { kind: "directive", type: TooltipDirective, selector: "[sqTooltip]", inputs: ["sqTooltip", "sqTooltipData", "sqTooltipTemplate", "placement", "fallbackPlacements", "delay", "hoverableTooltip", "tooltipClass"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
4618
4765
|
}
|
|
4619
4766
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ChatComponent, decorators: [{
|
|
4620
4767
|
type: Component,
|
|
4621
4768
|
args: [{ selector: 'sq-chat-v3', providers: [
|
|
4622
4769
|
ChatService,
|
|
4770
|
+
AssistantConfigurationService,
|
|
4771
|
+
AssistantTokensTrackingService,
|
|
4772
|
+
SavedChatsService,
|
|
4773
|
+
DebugMessageService,
|
|
4623
4774
|
provideTranslocoScope('chat')
|
|
4624
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [CommonModule, FormsModule, ChatMessageComponent, TokenProgressBarComponent, DebugMessageComponent, TooltipDirective, TranslocoPipe], 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=\"d-flex flex-column list-unstyled gap-3 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 && !isEmptyAssistantMessage(message)\"\n [style.--bs-list-group-item-padding-y.rem]=\"'0.6'\"\n [class.opacity-50]=\"indexMessageToEdit && (indexMessageToEdit < (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]=\"(chatService.streaming$ | async) && (last || isAssistantLastMessages(messages, index))\"\n [canEdit]=\"(chatService.streaming$ | async) === false && indexMessageToEdit === undefined && message.role === 'user'\"\n [canCopy]=\"((chatService.streaming$ | async) === false || !last) && indexMessageToEdit === 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' && (getDebugMessages(message, index).length > 0) && ((isAdminOrDeletedAdmin || (chatService.userOverride$ | async)) && config?.defaultValues.debug)\"\n [canRegenerate]=\"(chatService.streaming$ | async) === false && (last || (!last && messages[index+1].role !== 'assistant')) && message.role === 'assistant' && indexMessageToEdit === undefined\"\n (edit)=\"editMessage(message, index)\"\n (copy)=\"copyMessage(message, index)\"\n (regenerate)=\"regenerateMessage(message, index)\"\n (openDocument)=\"openOriginalAttachment($event, message, index)\"\n (openPreview)=\"openAttachmentPreview($event, message, index)\"\n (suggestAction)=\"suggestActionClick($event, index)\"\n (like)=\"onLike(message, index)\"\n (dislike)=\"onDislike(message, index)\"\n (debug)=\"showDebug(message, index)\">\n </sq-chat-message>\n </li>\n </ng-container>\n <!-- Loading spinner -->\n <li *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 p-3 rounded-lg\" *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 @if (!showReport) {\n <div class=\"user-input mt-auto\">\n <div class=\"py-2\">\n <div [hidden]=\"!isConnected\">\n <ng-container *ngIf=\"enabledUserInput\" [ngTemplateOutlet]=\"inputTpl\"></ng-container>\n </div>\n <!-- Retry button -->\n <!-- hidden attribute is in conflict with a css rule display: flex -->\n @if(!isConnected){\n <button class=\"btn mb-4 ast-error ast-btn sq-retry\" (click)=\"retryFetch()\">\n <span>{{ 'chat.tryAgain' | transloco }}</span>\n <span *ngIf=\"retrialAttempts\" class=\"ms-2 attempts\">{{ retrialAttempts }}</span>\n </button>\n }\n <div class=\"text-end small text-muted px-3\" *ngIf=\"!!config?.globalSettings?.disclaimer\">\n {{ config?.globalSettings?.disclaimer | transloco }}\n </div>\n </div>\n </div>\n }\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()\" aria-label=\"Scroll down\">\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\">{{ 'chat.loading' | transloco }}</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\" aria-label=\"search\">\n <i class=\"fas fa-search\"></i>\n </button>\n <textarea #questionInput rows=\"1\"\n type=\"text\" class=\"form-control\"\n [placeholder]=\"'chat.askSomething' | transloco\" 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 <div id=\"chat-actions\" class=\"d-flex gap-2\">\n <button\n *ngIf=\"(chatService.streaming$ | async) === false && (loading$ | async) === false && (chatService.stoppingGeneration$ | async) === false\"\n type=\"button\"\n class=\"btn btn-light\"\n aria-label=\"Send message\"\n [sqTooltip]=\"'chat.sendMessage' | transloco\"\n (click)=\"submitQuestion()\">\n <i class=\"fas fa-paper-plane\"></i>\n </button>\n <button\n *ngIf=\"indexMessageToEdit\"\n aria-label=\"Cancel edition\"\n type=\"button\"\n class=\"btn btn-light\"\n [sqTooltip]=\"'chat.cancelEdition' | transloco\"\n (click)=\"indexMessageToEdit = undefined; question = ''\">\n <i class=\"fas fa-undo-alt\"></i>\n </button>\n <span *ngIf=\"(chatService.streaming$ | async) && (chatService.stoppingGeneration$ | async) === false\" class=\"processing\">\n {{ 'chat.generating' | transloco }}<i class=\"fas fa-spinner fa-pulse\"></i>\n </span>\n <span *ngIf=\"(chatService.stoppingGeneration$ | async)\" class=\"processing\">\n {{ 'chat.stopping' | transloco }}<i class=\"fas fa-spinner fa-pulse\"></i>\n </span>\n <button\n *ngIf=\"(chatService.streaming$ | async) && (chatService.stoppingGeneration$ | async) === false\"\n type=\"button\"\n class=\"btn btn-light\"\n aria-label=\"Stop generating\"\n [sqTooltip]=\"'chat.stopGeneration' | transloco\"\n (click)=\"stopGeneration()\">\n <i class=\"fas fa-stop\"></i>\n </button>\n </div>\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>{{ 'chat.issueType' | transloco }}</h5>\n <select class=\"form-select mb-4\" [(ngModel)]=\"issueType\">\n <option [value]=\"''\">{{ 'chat.chooseIssueType' | transloco }}</option>\n <option *ngFor=\"let type of (issueTypes ?? defaultIssueTypes)\" [value]=\"type\">{{ type | transloco }}</option>\n </select>\n <h5>{{ 'chat.askUnlikeReasons' | transloco }}</h5>\n </ng-container>\n <ng-container *ngIf=\"type === 'like'\">\n <h5>{{ 'chat.askLikeReasons' | transloco }}</h5>\n </ng-container>\n <textarea class=\"form-control border border-neutral-200\" [(ngModel)]=\"reportComment\" [placeholder]=\"'chat.writeComment' | transloco\"></textarea>\n <div class=\"d-flex flex-row-reverse gap-1 mt-2\">\n <button class=\"btn btn-primary\" [disabled]=\"type === 'dislike' && !issueType\" (click)=\"sendReport()\">{{ 'chat.send' | transloco }}</button>\n <button class=\"btn btn-light\" (click)=\"ignoreReport()\">{{ 'chat.doNotSend' | transloco }}</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\" aria-label=\"Hide debug messages\">\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-uploaded-doc-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;--ast-report-bg: #070707}: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);gap:.5rem}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%}.btn.sq-retry{display:flex;margin:auto;background:var(--ast-error-bg, rgba(249, 58, 55, .2));font-weight:var(--font-weight-bold, 500)}.btn.sq-retry .attempts{display:flex;border-radius:100%;background:#fff;height:20px;width:20px;place-content:center;align-items:center}.issue-report{background-color:var(--ast-report-bg, white)}.text-end{text-align:right}.small{font-size:.875em}.text-muted{--bs-text-opacity: 1;color:var(--bs-secondary-color)}.d-flex{display:flex}.flex-row-reverse{flex-direction:row-reverse}.flex-grow-1{flex-grow:1}.spinner-grow,.spinner-border{display:inline-block;width:var(--bs-spinner-width);height:var(--bs-spinner-height);vertical-align:var(--bs-spinner-vertical-align);border-radius:50%;animation:var(--bs-spinner-animation-speed) linear infinite var(--bs-spinner-animation-name)}.text-primary{--bs-text-opacity: 1;color:rgba(var(--bs-primary-rgb),var(--bs-text-opacity))}.d-block{display:block}.btn{--bs-border-radius: .25rem;--bs-btn-padding-x: .75rem;--bs-btn-padding-y: .375rem;--bs-btn-font-family: ;--bs-btn-font-size: 1rem;--bs-btn-font-weight: 400;--bs-btn-line-height: 1.5;--bs-btn-color: var(--bs-body-color);--bs-btn-bg: transparent;--bs-btn-border-width: var(--bs-border-width);--bs-btn-border-color: transparent;--bs-btn-border-radius: var(--bs-border-radius);--bs-btn-hover-border-color: transparent;--bs-btn-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);--bs-btn-disabled-opacity: .65;--bs-btn-focus-box-shadow: 0 0 0 .25rem rgba(var(--bs-btn-focus-shadow-rgb), .5);display:inline-block;padding:var(--bs-btn-padding-y) var(--bs-btn-padding-x);font-family:var(--bs-btn-font-family);font-size:var(--bs-btn-font-size);font-weight:var(--bs-btn-font-weight);line-height:var(--bs-btn-line-height);color:var(--bs-btn-color);text-align:center;text-decoration:none;vertical-align:middle;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none;border:var(--bs-btn-border-width) solid var(--bs-btn-border-color);border-radius:var(--bs-btn-border-radius);background-color:var(--bs-btn-bg);transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}.btn-primary{--bs-btn-color: #fff;--bs-btn-bg: #0d6efd;--bs-btn-border-color: #0d6efd;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #0b5ed7;--bs-btn-hover-border-color: #0a58ca;--bs-btn-focus-shadow-rgb: 49, 132, 253;--bs-btn-active-color: #fff;--bs-btn-active-bg: #0a58ca;--bs-btn-active-border-color: #0a53be;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color: #fff;--bs-btn-disabled-bg: #0d6efd;--bs-btn-disabled-border-color: #0d6efd}.btn-light{--bs-btn-color: #000;--bs-btn-bg: #f8f9fa;--bs-btn-border-color: #f8f9fa;--bs-btn-hover-color: #000;--bs-btn-hover-bg: #d3d4d5;--bs-btn-hover-border-color: #c6c7c8;--bs-btn-focus-shadow-rgb: 211, 212, 213;--bs-btn-active-color: #000;--bs-btn-active-bg: #c6c7c8;--bs-btn-active-border-color: #babbbc;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color: #000;--bs-btn-disabled-bg: #f8f9fa;--bs-btn-disabled-border-color: #f8f9fa}.form-control{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:var(--bs-body-color);-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--bs-body-bg);background-clip:padding-box;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}.form-control:disabled{background-color:var(--bs-body-bg)}.form-select{--bs-form-select-bg-img: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e\");display:block;width:100%;padding:.375rem 2.25rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:var(--bs-body-color);-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--bs-body-bg);background-image:var(--bs-form-select-bg-img),var(--bs-form-select-bg-icon, none);background-repeat:no-repeat;background-position:right .75rem center;background-size:16px 12px;border:var(--bs-border-width, 1px) solid var(--bs-border-color, oklch(92.2% 0 0));border-radius:var(--bs-border-radius);transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}\n"] }]
|
|
4775
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [CommonModule, FormsModule, ChatMessageComponent, TokenProgressBarComponent, DebugMessageComponent, TooltipDirective, TranslocoPipe], 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=\"d-flex flex-column list-unstyled gap-3 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 && !isEmptyAssistantMessage(message)\"\n [style.--bs-list-group-item-padding-y.rem]=\"'0.6'\"\n [class.opacity-50]=\"indexMessageToEdit && (indexMessageToEdit < (index + 1))\">\n <sq-chat-message\n [id]=\"message.additionalProperties.messageId\"\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]=\"(chatService.streaming$ | async) && (last || isAssistantLastMessages(messages, index))\"\n [canEdit]=\"(chatService.streaming$ | async) === false && indexMessageToEdit === undefined && message.role === 'user'\"\n [canCopy]=\"((chatService.streaming$ | async) === false || !last) && indexMessageToEdit === 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' && (getDebugMessages(message, index).length > 0) && ((isAdminOrDeletedAdmin || (chatService.userOverride$ | async)) && config?.defaultValues.debug)\"\n [canRegenerate]=\"(chatService.streaming$ | async) === false && (last || (!last && messages[index+1].role !== 'assistant')) && message.role === 'assistant' && indexMessageToEdit === undefined\"\n [collapseReferences]=\"!!config?.globalSettings.collapseReferences\"\n (edit)=\"editMessage(message, index)\"\n (copy)=\"copyMessage(message, index)\"\n (regenerate)=\"regenerateMessage(message, index)\"\n (openDocument)=\"openOriginalAttachment($event, message, index)\"\n (openPreview)=\"openAttachmentPreview($event, message, index)\"\n (suggestAction)=\"suggestActionClick($event, index)\"\n (like)=\"onLike(message, index)\"\n (dislike)=\"onDislike(message, index)\"\n (debug)=\"showDebug(message, index)\">\n </sq-chat-message>\n </li>\n </ng-container>\n <!-- Loading spinner -->\n <li *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 p-3 rounded-lg\" *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 @if (!showReport) {\n <div class=\"user-input mt-auto\">\n <div class=\"py-2\">\n <div [hidden]=\"!isConnected\">\n <ng-container *ngIf=\"enabledUserInput\" [ngTemplateOutlet]=\"inputTpl\"></ng-container>\n </div>\n <!-- Retry button -->\n <!-- hidden attribute is in conflict with a css rule display: flex -->\n @if(!isConnected){\n <button class=\"btn mb-4 ast-error ast-btn sq-retry\" (click)=\"retryFetch()\">\n <span>{{ 'chat.tryAgain' | transloco }}</span>\n <span *ngIf=\"retrialAttempts\" class=\"ms-2 attempts\">{{ retrialAttempts }}</span>\n </button>\n }\n <div class=\"text-end small text-muted px-3\" *ngIf=\"!!config?.globalSettings?.disclaimer\">\n {{ config?.globalSettings?.disclaimer | transloco }}\n </div>\n </div>\n </div>\n }\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()\" aria-label=\"Scroll down\">\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\">{{ 'chat.loading' | transloco }}</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\" aria-label=\"search\">\n <i class=\"fas fa-search\"></i>\n </button>\n <textarea #questionInput rows=\"1\"\n type=\"text\" class=\"form-control\"\n [placeholder]=\"'chat.askSomething' | transloco\" 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 <div id=\"chat-actions\" class=\"d-flex gap-2\">\n <button\n *ngIf=\"(chatService.streaming$ | async) === false && (loading$ | async) === false && (chatService.stoppingGeneration$ | async) === false\"\n type=\"button\"\n class=\"btn btn-light\"\n aria-label=\"Send message\"\n [sqTooltip]=\"'chat.sendMessage' | transloco\"\n (click)=\"submitQuestion()\">\n <i class=\"fas fa-paper-plane\"></i>\n </button>\n <button\n *ngIf=\"indexMessageToEdit\"\n aria-label=\"Cancel edition\"\n type=\"button\"\n class=\"btn btn-light\"\n [sqTooltip]=\"'chat.cancelEdition' | transloco\"\n (click)=\"indexMessageToEdit = undefined; question = ''\">\n <i class=\"fas fa-undo-alt\"></i>\n </button>\n <span *ngIf=\"(chatService.streaming$ | async) && (chatService.stoppingGeneration$ | async) === false\" class=\"processing\">\n {{ 'chat.generating' | transloco }}<i class=\"fas fa-spinner fa-pulse\"></i>\n </span>\n <span *ngIf=\"(chatService.stoppingGeneration$ | async)\" class=\"processing\">\n {{ 'chat.stopping' | transloco }}<i class=\"fas fa-spinner fa-pulse\"></i>\n </span>\n <button\n *ngIf=\"(chatService.streaming$ | async) && (chatService.stoppingGeneration$ | async) === false\"\n type=\"button\"\n class=\"btn btn-light\"\n aria-label=\"Stop generating\"\n [sqTooltip]=\"'chat.stopGeneration' | transloco\"\n (click)=\"stopGeneration()\">\n <i class=\"fas fa-stop\"></i>\n </button>\n </div>\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>{{ 'chat.issueType' | transloco }}</h5>\n <select class=\"form-select mb-4\" [(ngModel)]=\"issueType\">\n <option [value]=\"''\">{{ 'chat.chooseIssueType' | transloco }}</option>\n <option *ngFor=\"let type of (issueTypes ?? defaultIssueTypes)\" [value]=\"type\">{{ type | transloco }}</option>\n </select>\n <h5>{{ 'chat.askUnlikeReasons' | transloco }}</h5>\n </ng-container>\n <ng-container *ngIf=\"type === 'like'\">\n <h5>{{ 'chat.askLikeReasons' | transloco }}</h5>\n </ng-container>\n <textarea class=\"form-control border border-neutral-200\" [(ngModel)]=\"reportComment\" [placeholder]=\"'chat.writeComment' | transloco\"></textarea>\n <div class=\"d-flex flex-row-reverse gap-1 mt-2\">\n <button class=\"btn btn-primary\" [disabled]=\"type === 'dislike' && !issueType\" (click)=\"sendReport()\">{{ 'chat.send' | transloco }}</button>\n <button class=\"btn btn-light\" (click)=\"ignoreReport()\">{{ 'chat.doNotSend' | transloco }}</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\" aria-label=\"Hide debug messages\">\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-uploaded-doc-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;--ast-report-bg: #070707}: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);gap:.5rem}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%}.btn.sq-retry{display:flex;margin:auto;background:var(--ast-error-bg, rgba(249, 58, 55, .2));font-weight:var(--font-weight-bold, 500)}.btn.sq-retry .attempts{display:flex;border-radius:100%;background:#fff;height:20px;width:20px;place-content:center;align-items:center}.issue-report{background-color:var(--ast-report-bg, white)}.text-end{text-align:right}.small{font-size:.875em}.text-muted{--bs-text-opacity: 1;color:var(--bs-secondary-color)}.d-flex{display:flex}.flex-row-reverse{flex-direction:row-reverse}.flex-grow-1{flex-grow:1}.spinner-grow,.spinner-border{display:inline-block;width:var(--bs-spinner-width);height:var(--bs-spinner-height);vertical-align:var(--bs-spinner-vertical-align);border-radius:50%;animation:var(--bs-spinner-animation-speed) linear infinite var(--bs-spinner-animation-name)}.text-primary{--bs-text-opacity: 1;color:rgba(var(--bs-primary-rgb),var(--bs-text-opacity))}.d-block{display:block}.btn{--bs-border-radius: .25rem;--bs-btn-padding-x: .75rem;--bs-btn-padding-y: .375rem;--bs-btn-font-family: ;--bs-btn-font-size: 1rem;--bs-btn-font-weight: 400;--bs-btn-line-height: 1.5;--bs-btn-color: var(--bs-body-color);--bs-btn-bg: transparent;--bs-btn-border-width: var(--bs-border-width);--bs-btn-border-color: transparent;--bs-btn-border-radius: var(--bs-border-radius);--bs-btn-hover-border-color: transparent;--bs-btn-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);--bs-btn-disabled-opacity: .65;--bs-btn-focus-box-shadow: 0 0 0 .25rem rgba(var(--bs-btn-focus-shadow-rgb), .5);display:inline-block;padding:var(--bs-btn-padding-y) var(--bs-btn-padding-x);font-family:var(--bs-btn-font-family);font-size:var(--bs-btn-font-size);font-weight:var(--bs-btn-font-weight);line-height:var(--bs-btn-line-height);color:var(--bs-btn-color);text-align:center;text-decoration:none;vertical-align:middle;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none;border:var(--bs-btn-border-width) solid var(--bs-btn-border-color);border-radius:var(--bs-btn-border-radius);background-color:var(--bs-btn-bg);transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}.btn-primary{--bs-btn-color: #fff;--bs-btn-bg: #0d6efd;--bs-btn-border-color: #0d6efd;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #0b5ed7;--bs-btn-hover-border-color: #0a58ca;--bs-btn-focus-shadow-rgb: 49, 132, 253;--bs-btn-active-color: #fff;--bs-btn-active-bg: #0a58ca;--bs-btn-active-border-color: #0a53be;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color: #fff;--bs-btn-disabled-bg: #0d6efd;--bs-btn-disabled-border-color: #0d6efd}.btn-light{--bs-btn-color: #000;--bs-btn-bg: #f8f9fa;--bs-btn-border-color: #f8f9fa;--bs-btn-hover-color: #000;--bs-btn-hover-bg: #d3d4d5;--bs-btn-hover-border-color: #c6c7c8;--bs-btn-focus-shadow-rgb: 211, 212, 213;--bs-btn-active-color: #000;--bs-btn-active-bg: #c6c7c8;--bs-btn-active-border-color: #babbbc;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color: #000;--bs-btn-disabled-bg: #f8f9fa;--bs-btn-disabled-border-color: #f8f9fa}.form-control{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:var(--bs-body-color);-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--bs-body-bg);background-clip:padding-box;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}.form-control:disabled{background-color:var(--bs-body-bg)}.form-select{--bs-form-select-bg-img: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e\");display:block;width:100%;padding:.375rem 2.25rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:var(--bs-body-color);-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--bs-body-bg);background-image:var(--bs-form-select-bg-img),var(--bs-form-select-bg-icon, none);background-repeat:no-repeat;background-position:right .75rem center;background-size:16px 12px;border:var(--bs-border-width, 1px) solid var(--bs-border-color, oklch(92.2% 0 0));border-radius:var(--bs-border-radius);transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}\n"] }]
|
|
4625
4776
|
}], propDecorators: { instanceId: [{
|
|
4626
4777
|
type: Input
|
|
4627
4778
|
}], query: [{
|
|
@@ -4892,11 +5043,11 @@ class SavedChatsComponent {
|
|
|
4892
5043
|
;
|
|
4893
5044
|
}
|
|
4894
5045
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SavedChatsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4895
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: SavedChatsComponent, isStandalone: true, selector: "sq-saved-chats-v3", inputs: { instanceId: "instanceId" }, outputs: { load: "load", delete: "delete" }, providers: [provideTranslocoScope('saved-chats', 'chat')], ngImport: i0, template: "<ng-container *ngIf=\"(chatService.assistantConfig$ | async)?.savedChatSettings.display\">\n <div *ngIf=\"chatService.savedChatsError$ | async\" class=\"alert alert-danger\">\n {{ 'savedChats.listError' | transloco }}\n </div>\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.chatId === savedChat.id\">\n <span class=\"title me-1\" [sqTooltip]=\"savedChat.title\">{{savedChat.title}}</span>\n <
|
|
5046
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: SavedChatsComponent, isStandalone: true, selector: "sq-saved-chats-v3", inputs: { instanceId: "instanceId" }, outputs: { load: "load", delete: "delete" }, providers: [SavedChatsService, provideTranslocoScope('saved-chats', 'chat')], ngImport: i0, template: "<ng-container *ngIf=\"(chatService.assistantConfig$ | async)?.savedChatSettings.display\">\n <div *ngIf=\"chatService.savedChatsError$ | async\" class=\"alert alert-danger\">\n {{ 'savedChats.listError' | transloco }}\n </div>\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.chatId === savedChat.id\">\n <span class=\"title me-1\" [sqTooltip]=\"savedChat.title\">{{savedChat.title}}</span>\n <button\n type=\"button\"\n (click)=\"renameDialog.showModal($event, savedChat)\"\n [sqTooltip]=\"'savedChats.rename' | transloco\"\n class=\"mx-1 bg-transparent border-0 p-0 m-0 cursor-pointer text-inherit leading-none inline-flex items-center justify-center\"\n >\n <i class=\"fas fa-pen saved-chat-actions\"></i>\n </button>\n <button\n type=\"button\"\n (click)=\"deleteDialog.showModal($event, savedChat)\"\n [sqTooltip]=\"'savedChats.delete' | transloco\"\n class=\"ms-1 bg-transparent border-0 p-0 m-0 cursor-pointer text-inherit leading-none inline-flex items-center justify-center\"\n >\n <i class=\"fas fa-trash saved-chat-actions\"></i>\n </button>\n </div>\n </div>\n</ng-container>\n\n<sq-dialog-delete-saved-chat [chatService]=\"chatService\" (delete)=\"delete.emit($event)\" #deleteDialog />\n<sq-dialog-rename-saved-chat [chatService]=\"chatService\" #renameDialog />\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-uploaded-doc-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;--ast-report-bg: #070707}.saved-chats .saved-chat-date{font-size:12px;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,.saved-chats .saved-chat:hover button,.saved-chats .saved-chat.active button{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: FormsModule }, { kind: "directive", type: TooltipDirective, selector: "[sqTooltip]", inputs: ["sqTooltip", "sqTooltipData", "sqTooltipTemplate", "placement", "fallbackPlacements", "delay", "hoverableTooltip", "tooltipClass"] }, { kind: "component", type: DialogRenameSavedChatComponent, selector: "sq-dialog-rename-saved-chat", inputs: ["chatService"] }, { kind: "component", type: DialogDeleteSavedChatComponent, selector: "sq-dialog-delete-saved-chat", inputs: ["chatService"], outputs: ["delete"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] }); }
|
|
4896
5047
|
}
|
|
4897
5048
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SavedChatsComponent, decorators: [{
|
|
4898
5049
|
type: Component,
|
|
4899
|
-
args: [{ selector: 'sq-saved-chats-v3', standalone: true, providers: [provideTranslocoScope('saved-chats', 'chat')], imports: [CommonModule, FormsModule, TooltipDirective, DialogRenameSavedChatComponent, DialogDeleteSavedChatComponent, TranslocoPipe], template: "<ng-container *ngIf=\"(chatService.assistantConfig$ | async)?.savedChatSettings.display\">\n <div *ngIf=\"chatService.savedChatsError$ | async\" class=\"alert alert-danger\">\n {{ 'savedChats.listError' | transloco }}\n </div>\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.chatId === savedChat.id\">\n <span class=\"title me-1\" [sqTooltip]=\"savedChat.title\">{{savedChat.title}}</span>\n <
|
|
5050
|
+
args: [{ selector: 'sq-saved-chats-v3', standalone: true, providers: [SavedChatsService, provideTranslocoScope('saved-chats', 'chat')], imports: [CommonModule, FormsModule, TooltipDirective, DialogRenameSavedChatComponent, DialogDeleteSavedChatComponent, TranslocoPipe], template: "<ng-container *ngIf=\"(chatService.assistantConfig$ | async)?.savedChatSettings.display\">\n <div *ngIf=\"chatService.savedChatsError$ | async\" class=\"alert alert-danger\">\n {{ 'savedChats.listError' | transloco }}\n </div>\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.chatId === savedChat.id\">\n <span class=\"title me-1\" [sqTooltip]=\"savedChat.title\">{{savedChat.title}}</span>\n <button\n type=\"button\"\n (click)=\"renameDialog.showModal($event, savedChat)\"\n [sqTooltip]=\"'savedChats.rename' | transloco\"\n class=\"mx-1 bg-transparent border-0 p-0 m-0 cursor-pointer text-inherit leading-none inline-flex items-center justify-center\"\n >\n <i class=\"fas fa-pen saved-chat-actions\"></i>\n </button>\n <button\n type=\"button\"\n (click)=\"deleteDialog.showModal($event, savedChat)\"\n [sqTooltip]=\"'savedChats.delete' | transloco\"\n class=\"ms-1 bg-transparent border-0 p-0 m-0 cursor-pointer text-inherit leading-none inline-flex items-center justify-center\"\n >\n <i class=\"fas fa-trash saved-chat-actions\"></i>\n </button>\n </div>\n </div>\n</ng-container>\n\n<sq-dialog-delete-saved-chat [chatService]=\"chatService\" (delete)=\"delete.emit($event)\" #deleteDialog />\n<sq-dialog-rename-saved-chat [chatService]=\"chatService\" #renameDialog />\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-uploaded-doc-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;--ast-report-bg: #070707}.saved-chats .saved-chat-date{font-size:12px;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,.saved-chats .saved-chat:hover button,.saved-chats .saved-chat.active button{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"] }]
|
|
4900
5051
|
}], propDecorators: { instanceId: [{
|
|
4901
5052
|
type: Input
|
|
4902
5053
|
}], load: [{
|
|
@@ -4905,126 +5056,27 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
|
|
|
4905
5056
|
type: Output
|
|
4906
5057
|
}] } });
|
|
4907
5058
|
|
|
4908
|
-
class ChatPrompt {
|
|
4909
|
-
constructor(formBuilder) {
|
|
4910
|
-
this.formBuilder = formBuilder;
|
|
4911
|
-
this.model = input({});
|
|
4912
|
-
}
|
|
4913
|
-
ngOnInit() {
|
|
4914
|
-
this.inputControl = new UntypedFormControl(this.model().output, this.model().validators || Validators.required);
|
|
4915
|
-
this.form = this.formBuilder.group({
|
|
4916
|
-
input: this.inputControl
|
|
4917
|
-
});
|
|
4918
|
-
this.formChanges.add(this.form.valueChanges.subscribe(() => this.model().output = this.inputControl.value));
|
|
4919
|
-
}
|
|
4920
|
-
ngOnDestroy() {
|
|
4921
|
-
this.formChanges.unsubscribe();
|
|
4922
|
-
}
|
|
4923
|
-
get title() {
|
|
4924
|
-
return this.model().title ?? "msg#modal.prompt.title";
|
|
4925
|
-
}
|
|
4926
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ChatPrompt, deps: [{ token: i2.UntypedFormBuilder }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4927
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: ChatPrompt, isStandalone: true, selector: "sq-chat-prompt", inputs: { model: { classPropertyName: "model", publicName: "model", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
4928
|
-
<dialog [title]="title" #dialog>
|
|
4929
|
-
@if(title) {
|
|
4930
|
-
<h5 class="modal-title">{{title}}</h5>
|
|
4931
|
-
}
|
|
4932
|
-
<form name="prompt" novalidate [formGroup]="form">
|
|
4933
|
-
<div class="mb-3 sq-form-group">
|
|
4934
|
-
<label class="form-label" for="input">{{model().message}}</label>
|
|
4935
|
-
@if(!model().rowCount) {
|
|
4936
|
-
<input type="text" class="form-control" id="input" formControlName="input" spellcheck="off">
|
|
4937
|
-
}
|
|
4938
|
-
@if(!!model().rowCount) {
|
|
4939
|
-
<textarea type="text" class="form-control" id="input" formControlName="input" spellcheck="on" rows="{{model().rowCount}}"></textarea>
|
|
4940
|
-
}
|
|
4941
|
-
</div>
|
|
4942
|
-
</form>
|
|
4943
|
-
<section class="flex justify-end gap-2 mt-4">
|
|
4944
|
-
<button class="btn btn-ghost outline-none w-24" (click)="dialog.close()">
|
|
4945
|
-
Cancel
|
|
4946
|
-
</button>
|
|
4947
|
-
|
|
4948
|
-
<button class="btn btn-primary w-24">
|
|
4949
|
-
OK
|
|
4950
|
-
</button>
|
|
4951
|
-
</section>
|
|
4952
|
-
</dialog>
|
|
4953
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { 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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }] }); }
|
|
4954
|
-
}
|
|
4955
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ChatPrompt, decorators: [{
|
|
4956
|
-
type: Component,
|
|
4957
|
-
args: [{
|
|
4958
|
-
selector: "sq-chat-prompt",
|
|
4959
|
-
template: `
|
|
4960
|
-
<dialog [title]="title" #dialog>
|
|
4961
|
-
@if(title) {
|
|
4962
|
-
<h5 class="modal-title">{{title}}</h5>
|
|
4963
|
-
}
|
|
4964
|
-
<form name="prompt" novalidate [formGroup]="form">
|
|
4965
|
-
<div class="mb-3 sq-form-group">
|
|
4966
|
-
<label class="form-label" for="input">{{model().message}}</label>
|
|
4967
|
-
@if(!model().rowCount) {
|
|
4968
|
-
<input type="text" class="form-control" id="input" formControlName="input" spellcheck="off">
|
|
4969
|
-
}
|
|
4970
|
-
@if(!!model().rowCount) {
|
|
4971
|
-
<textarea type="text" class="form-control" id="input" formControlName="input" spellcheck="on" rows="{{model().rowCount}}"></textarea>
|
|
4972
|
-
}
|
|
4973
|
-
</div>
|
|
4974
|
-
</form>
|
|
4975
|
-
<section class="flex justify-end gap-2 mt-4">
|
|
4976
|
-
<button class="btn btn-ghost outline-none w-24" (click)="dialog.close()">
|
|
4977
|
-
Cancel
|
|
4978
|
-
</button>
|
|
4979
|
-
|
|
4980
|
-
<button class="btn btn-primary w-24">
|
|
4981
|
-
OK
|
|
4982
|
-
</button>
|
|
4983
|
-
</section>
|
|
4984
|
-
</dialog>
|
|
4985
|
-
`,
|
|
4986
|
-
standalone: true,
|
|
4987
|
-
imports: [CommonModule, ReactiveFormsModule],
|
|
4988
|
-
}]
|
|
4989
|
-
}], ctorParameters: () => [{ type: i2.UntypedFormBuilder }] });
|
|
4990
|
-
|
|
4991
5059
|
class DocumentsUploadService {
|
|
4992
5060
|
constructor() {
|
|
4993
|
-
|
|
5061
|
+
this.REQUEST_URL = "api/v1/plugin/SinequaAssistantREST";
|
|
5062
|
+
/** Documents upload configuration. */
|
|
4994
5063
|
this.uploadConfig$ = new BehaviorSubject(undefined);
|
|
5064
|
+
/** Emit the list of indexed documents */
|
|
5065
|
+
this.uploadedDocuments$ = new BehaviorSubject([]);
|
|
4995
5066
|
this.appService = inject(AppService);
|
|
4996
5067
|
this.http = inject(HttpClient);
|
|
4997
5068
|
}
|
|
4998
5069
|
/**
|
|
4999
|
-
* Initializes the file upload service
|
|
5000
|
-
*
|
|
5001
|
-
* @param chatService - An instance of ChatService. If not provided, an error is thrown.
|
|
5002
|
-
* @throws {Error} If the chatService instance is not provided or if there is an error during initialization.
|
|
5070
|
+
* Initializes the file upload service.
|
|
5003
5071
|
*/
|
|
5004
|
-
init(
|
|
5005
|
-
if (!chatService)
|
|
5006
|
-
throw new Error('A chatService instance must be provided');
|
|
5007
|
-
this.chatService = chatService;
|
|
5072
|
+
init() {
|
|
5008
5073
|
try {
|
|
5009
|
-
this.getRequestsUrl();
|
|
5010
5074
|
this.getUploadConfig();
|
|
5011
5075
|
}
|
|
5012
5076
|
catch (error) {
|
|
5013
5077
|
throw new Error(error);
|
|
5014
5078
|
}
|
|
5015
5079
|
}
|
|
5016
|
-
/**
|
|
5017
|
-
* Fetch the endpoint to use for the file upload related requests
|
|
5018
|
-
* @throws {Error} If the property 'restEndpoint' is not provided in the assistant configuration
|
|
5019
|
-
*/
|
|
5020
|
-
getRequestsUrl() {
|
|
5021
|
-
if (!!this.chatService.assistantConfig$.value.connectionSettings.restEndpoint) {
|
|
5022
|
-
this.REQUEST_URL = this.chatService.assistantConfig$.value.connectionSettings.restEndpoint;
|
|
5023
|
-
}
|
|
5024
|
-
else {
|
|
5025
|
-
throw new Error(`The property 'restEndpoint' must be provided when attempting to use 'REST' in assistant instance`);
|
|
5026
|
-
}
|
|
5027
|
-
}
|
|
5028
5080
|
/**
|
|
5029
5081
|
* Retrieves the upload configuration for documents.
|
|
5030
5082
|
* The response, which contains the upload configuration, is emitted to the `uploadConfig$` observable.
|
|
@@ -5034,10 +5086,9 @@ class DocumentsUploadService {
|
|
|
5034
5086
|
getUploadConfig() {
|
|
5035
5087
|
const data = {
|
|
5036
5088
|
action: "documentsUploadConfigGet",
|
|
5037
|
-
appName: this.appService.appName
|
|
5038
|
-
debug: this.chatService.assistantConfig$.value.defaultValues.debug
|
|
5089
|
+
appName: this.appService.appName
|
|
5039
5090
|
};
|
|
5040
|
-
from(post(
|
|
5091
|
+
from(post(this.REQUEST_URL, data)).pipe(take$1(1), catchError$1((error) => {
|
|
5041
5092
|
throw new Error(`Error invoking documentsUploadConfigGet: ${error}`);
|
|
5042
5093
|
})).subscribe((res) => this.uploadConfig$.next(res));
|
|
5043
5094
|
}
|
|
@@ -5102,8 +5153,7 @@ class DocumentsUploadService {
|
|
|
5102
5153
|
// Add the required "data" field as a JSON string
|
|
5103
5154
|
const data = {
|
|
5104
5155
|
action: "documentsupload",
|
|
5105
|
-
appName: this.appService.appName
|
|
5106
|
-
debug: this.chatService.assistantConfig$.value.defaultValues.debug
|
|
5156
|
+
appName: this.appService.appName
|
|
5107
5157
|
};
|
|
5108
5158
|
formData.append('data', JSON.stringify(data));
|
|
5109
5159
|
let headers = new HttpHeaders({ 'Accept': 'application/json' });
|
|
@@ -5117,7 +5167,7 @@ class DocumentsUploadService {
|
|
|
5117
5167
|
};
|
|
5118
5168
|
if (enableProgress)
|
|
5119
5169
|
options['reportProgress'] = true;
|
|
5120
|
-
const url = `${globalConfig.backendUrl}/${
|
|
5170
|
+
const url = `${globalConfig.backendUrl}/${this.REQUEST_URL}`;
|
|
5121
5171
|
/**
|
|
5122
5172
|
* Need to use the HttpClient directly to avoid the JSONMethodPluginService's behavior
|
|
5123
5173
|
* because it is altering the request and thus making it unable to properly set the Content-Type header with the boundary
|
|
@@ -5158,10 +5208,9 @@ class DocumentsUploadService {
|
|
|
5158
5208
|
const data = {
|
|
5159
5209
|
action: "documentsUploadStatus",
|
|
5160
5210
|
appName: this.appService.appName,
|
|
5161
|
-
statusToken: token
|
|
5162
|
-
debug: this.chatService.assistantConfig$.value.defaultValues.debug
|
|
5211
|
+
statusToken: token
|
|
5163
5212
|
};
|
|
5164
|
-
return from(post(
|
|
5213
|
+
return from(post(this.REQUEST_URL, data)).pipe(catchError$1((error) => {
|
|
5165
5214
|
throw new Error(`Error invoking documentsUploadStatus: ${error}`);
|
|
5166
5215
|
}));
|
|
5167
5216
|
}
|
|
@@ -5190,8 +5239,7 @@ class DocumentsUploadService {
|
|
|
5190
5239
|
getDocumentsList(columns, skip, count) {
|
|
5191
5240
|
const data = {
|
|
5192
5241
|
action: "documentsList",
|
|
5193
|
-
appName: this.appService.appName
|
|
5194
|
-
debug: this.chatService.assistantConfig$.value.defaultValues.debug
|
|
5242
|
+
appName: this.appService.appName
|
|
5195
5243
|
};
|
|
5196
5244
|
if (columns)
|
|
5197
5245
|
data["columns"] = columns;
|
|
@@ -5199,7 +5247,7 @@ class DocumentsUploadService {
|
|
|
5199
5247
|
data["skip"] = skip;
|
|
5200
5248
|
if (count)
|
|
5201
5249
|
data["count"] = count;
|
|
5202
|
-
return from(post(
|
|
5250
|
+
return from(post(this.REQUEST_URL, data)).pipe(tap((res) => this.uploadedDocuments$.next(res.docs)), catchError$1((error) => {
|
|
5203
5251
|
throw new Error(`Error invoking documentsList: ${error}`);
|
|
5204
5252
|
}));
|
|
5205
5253
|
}
|
|
@@ -5217,10 +5265,9 @@ class DocumentsUploadService {
|
|
|
5217
5265
|
const data = {
|
|
5218
5266
|
action: "documentsDelete",
|
|
5219
5267
|
docIds,
|
|
5220
|
-
appName: this.appService.appName
|
|
5221
|
-
debug: this.chatService.assistantConfig$.value.defaultValues.debug
|
|
5268
|
+
appName: this.appService.appName
|
|
5222
5269
|
};
|
|
5223
|
-
return from(post(
|
|
5270
|
+
return from(post(this.REQUEST_URL, data)).pipe(catchError$1((error) => {
|
|
5224
5271
|
throw new Error(`Error invoking documentsDelete: ${error}`);
|
|
5225
5272
|
}));
|
|
5226
5273
|
}
|
|
@@ -5236,10 +5283,9 @@ class DocumentsUploadService {
|
|
|
5236
5283
|
deleteAllDocuments() {
|
|
5237
5284
|
const data = {
|
|
5238
5285
|
action: "documentsDeleteAll",
|
|
5239
|
-
appName: this.appService.appName
|
|
5240
|
-
debug: this.chatService.assistantConfig$.value.defaultValues.debug
|
|
5286
|
+
appName: this.appService.appName
|
|
5241
5287
|
};
|
|
5242
|
-
return from(post(
|
|
5288
|
+
return from(post(this.REQUEST_URL, data)).pipe(catchError$1((error) => {
|
|
5243
5289
|
throw new Error(`Error invoking documentsDeleteAll: ${error}`);
|
|
5244
5290
|
}));
|
|
5245
5291
|
}
|
|
@@ -5267,10 +5313,13 @@ class DocumentsUploadService {
|
|
|
5267
5313
|
return bytes / (1024 * 1024);
|
|
5268
5314
|
}
|
|
5269
5315
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DocumentsUploadService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
5270
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DocumentsUploadService }); }
|
|
5316
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DocumentsUploadService, providedIn: 'root' }); }
|
|
5271
5317
|
}
|
|
5272
5318
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DocumentsUploadService, decorators: [{
|
|
5273
|
-
type: Injectable
|
|
5319
|
+
type: Injectable,
|
|
5320
|
+
args: [{
|
|
5321
|
+
providedIn: 'root'
|
|
5322
|
+
}]
|
|
5274
5323
|
}] });
|
|
5275
5324
|
|
|
5276
5325
|
class DocumentUploadComponent {
|
|
@@ -5296,13 +5345,13 @@ class DocumentUploadComponent {
|
|
|
5296
5345
|
this.uploading$ = new BehaviorSubject(false);
|
|
5297
5346
|
this.uploadingInfos$ = new BehaviorSubject(undefined);
|
|
5298
5347
|
this._subscription = new Subscription();
|
|
5299
|
-
this.instanceManagerService = inject(InstanceManagerService);
|
|
5300
5348
|
this.documentsUploadService = inject(DocumentsUploadService);
|
|
5301
5349
|
this.notificationsService = inject(NotificationsService);
|
|
5350
|
+
this.appService = inject(AppService);
|
|
5302
5351
|
this.transloco = inject(TranslocoService);
|
|
5303
5352
|
}
|
|
5304
5353
|
ngOnInit() {
|
|
5305
|
-
this._subscription.add(of(isAuthenticated()).pipe(
|
|
5354
|
+
this._subscription.add(of(isAuthenticated()).pipe(switchMap((_) => this.appService.init()), tap((_) => this.documentsUploadService.init()), catchError$1((error) => {
|
|
5306
5355
|
console.error(error);
|
|
5307
5356
|
this.notificationsService.error(error);
|
|
5308
5357
|
return EMPTY;
|
|
@@ -5325,9 +5374,6 @@ class DocumentUploadComponent {
|
|
|
5325
5374
|
ngOnDestroy() {
|
|
5326
5375
|
this._subscription.unsubscribe();
|
|
5327
5376
|
}
|
|
5328
|
-
instantiateChatService() {
|
|
5329
|
-
this.chatService = this.instanceManagerService.getInstance(this.instanceId);
|
|
5330
|
-
}
|
|
5331
5377
|
/**
|
|
5332
5378
|
* Handles the submission of files.
|
|
5333
5379
|
*
|
|
@@ -5477,11 +5523,14 @@ class DocumentUploadComponent {
|
|
|
5477
5523
|
this.indexing$.next(true);
|
|
5478
5524
|
// Combine immediate API call with interval-based polling
|
|
5479
5525
|
this._subscription.add(interval(this.pollingInterval).pipe(startWith(0), // Trigger the API call immediately
|
|
5480
|
-
switchMap(() => this.documentsUploadService.getIndexingStatus(token)), tap((res) => this.indexingInfos$.next(res)), takeWhile((response) => !response.isCompleted, true),
|
|
5526
|
+
switchMap(() => this.documentsUploadService.getIndexingStatus(token)), tap((res) => this.indexingInfos$.next(res)), takeWhile((response) => !response.isCompleted, true), // Use takeWhileInclusive() pattern to ensure that the last value where isCompleted === true is also included.
|
|
5527
|
+
catchError$1((err) => {
|
|
5481
5528
|
console.error(err);
|
|
5482
5529
|
this.notificationsService.error(this.transloco.translate('chatDocumentsUpload.errorIndexingStatus'));
|
|
5483
5530
|
return EMPTY;
|
|
5484
5531
|
}), finalize$1(() => {
|
|
5532
|
+
// Refresh the list of uploaded documents at the end of indexing
|
|
5533
|
+
this.documentsUploadService.getDocumentsList().pipe(take$1(1)).subscribe();
|
|
5485
5534
|
// Clear the indexing flags
|
|
5486
5535
|
this.indexing$.next(false);
|
|
5487
5536
|
this.indexingInfos$.next(undefined);
|
|
@@ -5502,14 +5551,12 @@ class DocumentUploadComponent {
|
|
|
5502
5551
|
return completed / total;
|
|
5503
5552
|
}
|
|
5504
5553
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DocumentUploadComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
5505
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: DocumentUploadComponent, isStandalone: true, selector: "sq-document-upload", inputs: {
|
|
5554
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: DocumentUploadComponent, isStandalone: true, selector: "sq-document-upload", inputs: { pollingInterval: "pollingInterval" }, providers: [provideTranslocoScope('chat-documents-upload')], viewQueries: [{ propertyName: "flow", first: true, predicate: ["flow"], descendants: true, static: true }], ngImport: i0, template: "<ng-container #flow=\"flow\" [flowConfig]=\"flowConfig\"></ng-container>\n<div class=\"file-upload-container\">\n <input\n type=\"file\"\n flowButton\n [flow]=\"flow.flowJs\"\n multiple\n hidden\n #fileInput>\n <div\n flowDrop\n [flow]=\"flow.flowJs\"\n (dragenter)=\"onDragenter()\"\n (dragleave)=\"onDragleave($event)\"\n (drop)=\"onDrop()\"\n (click)=\"fileInput.click()\"\n class=\"dropzone\"\n [ngClass]=\"{'dropzone--active': (dragging$ | async)}\"\n [hidden]=\"(uploading$ | async) || (indexing$ | async)\">\n <ng-container *ngIf=\"!(dragging$ | async); else draggingContent\">\n <i class=\"fas fa-cloud-upload-alt\"></i>\n <span>{{ 'chatDocumentsUpload.dragAndDrop' | transloco }}</span>\n <span class=\"text-orange\">{{ 'chatDocumentsUpload.clickToBrowse' | transloco }}</span>\n </ng-container>\n <ng-template #draggingContent>\n <span>{{ 'chatDocumentsUpload.dropFiles' | transloco }}</span>\n </ng-template>\n </div>\n\n <div *ngIf=\"(uploading$ | async) || (indexing$ | async)\" class=\"dropzone dropzone--active\">\n <ng-container *ngIf=\"(uploading$ | async); else indexingState\">\n <i class=\"fas fa-spinner fa-pulse\"></i>\n <span>\n {{ 'chatDocumentsUpload.uploadingFiles' | transloco: { count: (flow.transfers$ | async)!.transfers.length } }}\n </span>\n <span *ngIf=\"(uploadingInfos$ | async) as uploadingInfos\">{{ uploadingInfos.progress | number:'1.0-0' }}%</span>\n </ng-container>\n <ng-template #indexingState>\n <i class=\"fas fa-spinner fa-pulse\"></i>\n <ng-container *ngIf=\"indexingInfos$ | async as indexingInfo\">\n <span>\n {{ 'chatDocumentsUpload.indexingFiles' | transloco: { count: indexingInfo.docs.length } }}\n </span>\n <span>{{ getIndexingProgress(indexingInfo) * 100 | number:'1.0-0' }}%</span>\n </ng-container>\n </ng-template>\n </div>\n\n <ul *ngIf=\"errorAlerts.length > 0\" class=\"error-list mt-3\">\n <li *ngFor=\"let error of errorAlerts\">\n {{ error }}\n </li>\n </ul>\n\n <div *ngIf=\"((flow.transfers$ | async)?.transfers?.length > 0) && !(uploading$ | async)\" class=\"file-list mt-3\">\n <ul>\n <li *ngFor=\"let transfer of (flow.transfers$ | async)!.transfers; trackBy: trackTransfer\">\n <sq-format-icon [extension]=\"transfer.flowFile.getExtension()\" class=\"me-1\"></sq-format-icon>\n <span class=\"me-1\" [title]=\"transfer.name\">{{ transfer.name }}</span>\n <button\n type=\"button\"\n (click)=\"flow.cancelFile(transfer)\"\n [title]=\"'chatDocumentsUpload.cancel' | transloco\"\n class=\"bg-transparent border-0 p-0 m-0 cursor-pointer text-inherit leading-none inline-flex items-center justify-center\"\n >\n <i class=\"fas fa-trash\"></i>\n </button>\n </li>\n </ul>\n </div>\n\n <div class=\"d-flex mt-2\">\n <button\n type=\"button\"\n class=\"btn btn-light cancel-btn me-2\"\n (click)=\"flow.cancel()\"\n [disabled]=\"!((flow.transfers$ | async)?.transfers?.length > 0) || (uploading$ | async) || (indexing$ | async)\">\n {{ 'chatDocumentsUpload.cancel' | transloco }}\n </button>\n <button\n type=\"button\"\n class=\"upload-btn\"\n (click)=\"upload()\"\n [disabled]=\"!((flow.transfers$ | async)?.transfers?.length > 0) || (uploading$ | async) || (indexing$ | async)\">\n {{ 'chatDocumentsUpload.upload' | transloco }}\n </button>\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-uploaded-doc-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;--ast-report-bg: #070707}@keyframes dash-move{0%{background-position:0 0}to{background-position:100% 0}}.file-upload-container{width:100%;position:relative;padding:20px;background-color:var(--ast-primary-bg, #f2f8fe)}.file-upload-container .dropzone{display:flex;flex-direction:column;justify-content:center;align-items:center;height:100px;border:2px dashed var(--ast-primary-color, #005DA7);border-color:var(--ast-secondary-color, #FF732E) var(--ast-primary-color, #005DA7) var(--ast-primary-color, #005DA7) var(--ast-secondary-color, #FF732E);border-radius:5px;padding:10px;cursor:pointer;background-color:var(--ast-primary-bg, #f2f8fe);transition:background-color .3s ease;color:var(--ast-primary-color, #005DA7)}.file-upload-container .dropzone--active{background-color:var(--ast-secondary-bg, #FFF8F1);color:var(--ast-secondary-color, #FF732E);border-color:var(--ast-secondary-color, #FF732E)}.file-upload-container .dropzone i{font-size:x-large}.file-upload-container .dropzone span{margin:0;font-size:small}.file-upload-container .dropzone span.text-orange{color:var(--ast-secondary-color, #FF732E)}.file-upload-container .file-list h6{color:#a9a9a9}.file-upload-container .file-list ul{list-style-type:none;padding:0}.file-upload-container .file-list ul li{display:flex;align-items:center;padding:10px;background-color:var(--ast-primary-bg, #f2f8fe);margin-bottom:5px;border-radius:5px;font-size:small}.file-upload-container .file-list ul li span{flex-grow:1;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.file-upload-container .file-list ul li i{cursor:pointer}.file-upload-container .file-list ul li i:hover{color:var(--ast-primary-color, #005DA7)}.file-upload-container .error-list{display:flex;flex-direction:column;list-style:disc;background:var(--ast-error-color, rgba(249, 58, 55, .7));color:#fff;border-radius:5px}.file-upload-container .error-list li{padding:3px}.file-upload-container .upload-btn{background:linear-gradient(to right,#1d4ed8,#ec4899,#f97316);color:#fff;border:none;padding:8px 16px;border-radius:5px;cursor:pointer;width:100%}.file-upload-container .upload-btn:hover{background:linear-gradient(to right,#1d4ed8cc,#ec4899cc,#f97316cc)}.file-upload-container .upload-btn[disabled]{opacity:.3;cursor:not-allowed}.file-upload-container .cancel-btn{cursor:pointer;pointer-events:unset;width:100%}.file-upload-container .cancel-btn[disabled]{opacity:.3;cursor:not-allowed}\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: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i1.DecimalPipe, name: "number" }, { kind: "ngmodule", type: NgxFlowModule }, { kind: "directive", type: i2$1.ButtonDirective, selector: "[flowButton]", inputs: ["flowDirectoryOnly", "flowAttributes", "flow"] }, { kind: "directive", type: i2$1.DropDirective, selector: "[flowDrop]", inputs: ["flow"], exportAs: ["flowDrop"] }, { kind: "directive", type: i2$1.FlowDirective, selector: "[flowConfig]", inputs: ["flowConfig"], exportAs: ["flow"] }, { kind: "component", type: FormatIconComponent, selector: "sq-format-icon", inputs: ["extension"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] }); }
|
|
5506
5555
|
}
|
|
5507
5556
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DocumentUploadComponent, decorators: [{
|
|
5508
5557
|
type: Component,
|
|
5509
|
-
args: [{ selector: "sq-document-upload", standalone: true, providers: [
|
|
5510
|
-
}], propDecorators: {
|
|
5511
|
-
type: Input
|
|
5512
|
-
}], pollingInterval: [{
|
|
5558
|
+
args: [{ selector: "sq-document-upload", standalone: true, providers: [provideTranslocoScope('chat-documents-upload')], imports: [CommonModule, NgxFlowModule, FormatIconComponent, TranslocoPipe], template: "<ng-container #flow=\"flow\" [flowConfig]=\"flowConfig\"></ng-container>\n<div class=\"file-upload-container\">\n <input\n type=\"file\"\n flowButton\n [flow]=\"flow.flowJs\"\n multiple\n hidden\n #fileInput>\n <div\n flowDrop\n [flow]=\"flow.flowJs\"\n (dragenter)=\"onDragenter()\"\n (dragleave)=\"onDragleave($event)\"\n (drop)=\"onDrop()\"\n (click)=\"fileInput.click()\"\n class=\"dropzone\"\n [ngClass]=\"{'dropzone--active': (dragging$ | async)}\"\n [hidden]=\"(uploading$ | async) || (indexing$ | async)\">\n <ng-container *ngIf=\"!(dragging$ | async); else draggingContent\">\n <i class=\"fas fa-cloud-upload-alt\"></i>\n <span>{{ 'chatDocumentsUpload.dragAndDrop' | transloco }}</span>\n <span class=\"text-orange\">{{ 'chatDocumentsUpload.clickToBrowse' | transloco }}</span>\n </ng-container>\n <ng-template #draggingContent>\n <span>{{ 'chatDocumentsUpload.dropFiles' | transloco }}</span>\n </ng-template>\n </div>\n\n <div *ngIf=\"(uploading$ | async) || (indexing$ | async)\" class=\"dropzone dropzone--active\">\n <ng-container *ngIf=\"(uploading$ | async); else indexingState\">\n <i class=\"fas fa-spinner fa-pulse\"></i>\n <span>\n {{ 'chatDocumentsUpload.uploadingFiles' | transloco: { count: (flow.transfers$ | async)!.transfers.length } }}\n </span>\n <span *ngIf=\"(uploadingInfos$ | async) as uploadingInfos\">{{ uploadingInfos.progress | number:'1.0-0' }}%</span>\n </ng-container>\n <ng-template #indexingState>\n <i class=\"fas fa-spinner fa-pulse\"></i>\n <ng-container *ngIf=\"indexingInfos$ | async as indexingInfo\">\n <span>\n {{ 'chatDocumentsUpload.indexingFiles' | transloco: { count: indexingInfo.docs.length } }}\n </span>\n <span>{{ getIndexingProgress(indexingInfo) * 100 | number:'1.0-0' }}%</span>\n </ng-container>\n </ng-template>\n </div>\n\n <ul *ngIf=\"errorAlerts.length > 0\" class=\"error-list mt-3\">\n <li *ngFor=\"let error of errorAlerts\">\n {{ error }}\n </li>\n </ul>\n\n <div *ngIf=\"((flow.transfers$ | async)?.transfers?.length > 0) && !(uploading$ | async)\" class=\"file-list mt-3\">\n <ul>\n <li *ngFor=\"let transfer of (flow.transfers$ | async)!.transfers; trackBy: trackTransfer\">\n <sq-format-icon [extension]=\"transfer.flowFile.getExtension()\" class=\"me-1\"></sq-format-icon>\n <span class=\"me-1\" [title]=\"transfer.name\">{{ transfer.name }}</span>\n <button\n type=\"button\"\n (click)=\"flow.cancelFile(transfer)\"\n [title]=\"'chatDocumentsUpload.cancel' | transloco\"\n class=\"bg-transparent border-0 p-0 m-0 cursor-pointer text-inherit leading-none inline-flex items-center justify-center\"\n >\n <i class=\"fas fa-trash\"></i>\n </button>\n </li>\n </ul>\n </div>\n\n <div class=\"d-flex mt-2\">\n <button\n type=\"button\"\n class=\"btn btn-light cancel-btn me-2\"\n (click)=\"flow.cancel()\"\n [disabled]=\"!((flow.transfers$ | async)?.transfers?.length > 0) || (uploading$ | async) || (indexing$ | async)\">\n {{ 'chatDocumentsUpload.cancel' | transloco }}\n </button>\n <button\n type=\"button\"\n class=\"upload-btn\"\n (click)=\"upload()\"\n [disabled]=\"!((flow.transfers$ | async)?.transfers?.length > 0) || (uploading$ | async) || (indexing$ | async)\">\n {{ 'chatDocumentsUpload.upload' | transloco }}\n </button>\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-uploaded-doc-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;--ast-report-bg: #070707}@keyframes dash-move{0%{background-position:0 0}to{background-position:100% 0}}.file-upload-container{width:100%;position:relative;padding:20px;background-color:var(--ast-primary-bg, #f2f8fe)}.file-upload-container .dropzone{display:flex;flex-direction:column;justify-content:center;align-items:center;height:100px;border:2px dashed var(--ast-primary-color, #005DA7);border-color:var(--ast-secondary-color, #FF732E) var(--ast-primary-color, #005DA7) var(--ast-primary-color, #005DA7) var(--ast-secondary-color, #FF732E);border-radius:5px;padding:10px;cursor:pointer;background-color:var(--ast-primary-bg, #f2f8fe);transition:background-color .3s ease;color:var(--ast-primary-color, #005DA7)}.file-upload-container .dropzone--active{background-color:var(--ast-secondary-bg, #FFF8F1);color:var(--ast-secondary-color, #FF732E);border-color:var(--ast-secondary-color, #FF732E)}.file-upload-container .dropzone i{font-size:x-large}.file-upload-container .dropzone span{margin:0;font-size:small}.file-upload-container .dropzone span.text-orange{color:var(--ast-secondary-color, #FF732E)}.file-upload-container .file-list h6{color:#a9a9a9}.file-upload-container .file-list ul{list-style-type:none;padding:0}.file-upload-container .file-list ul li{display:flex;align-items:center;padding:10px;background-color:var(--ast-primary-bg, #f2f8fe);margin-bottom:5px;border-radius:5px;font-size:small}.file-upload-container .file-list ul li span{flex-grow:1;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.file-upload-container .file-list ul li i{cursor:pointer}.file-upload-container .file-list ul li i:hover{color:var(--ast-primary-color, #005DA7)}.file-upload-container .error-list{display:flex;flex-direction:column;list-style:disc;background:var(--ast-error-color, rgba(249, 58, 55, .7));color:#fff;border-radius:5px}.file-upload-container .error-list li{padding:3px}.file-upload-container .upload-btn{background:linear-gradient(to right,#1d4ed8,#ec4899,#f97316);color:#fff;border:none;padding:8px 16px;border-radius:5px;cursor:pointer;width:100%}.file-upload-container .upload-btn:hover{background:linear-gradient(to right,#1d4ed8cc,#ec4899cc,#f97316cc)}.file-upload-container .upload-btn[disabled]{opacity:.3;cursor:not-allowed}.file-upload-container .cancel-btn{cursor:pointer;pointer-events:unset;width:100%}.file-upload-container .cancel-btn[disabled]{opacity:.3;cursor:not-allowed}\n"] }]
|
|
5559
|
+
}], propDecorators: { pollingInterval: [{
|
|
5513
5560
|
type: Input
|
|
5514
5561
|
}], flow: [{
|
|
5515
5562
|
type: ViewChild,
|
|
@@ -5521,14 +5568,17 @@ class DocumentListComponent {
|
|
|
5521
5568
|
this.groupedUploadedDocuments$ = new BehaviorSubject([]);
|
|
5522
5569
|
this.deletingAll = false;
|
|
5523
5570
|
this._subscription = new Subscription();
|
|
5524
|
-
this.instanceManagerService = inject(InstanceManagerService);
|
|
5525
5571
|
this.documentsUploadService = inject(DocumentsUploadService);
|
|
5526
5572
|
this.notificationsService = inject(NotificationsService);
|
|
5573
|
+
this.appService = inject(AppService);
|
|
5527
5574
|
this.transloco = inject(TranslocoService);
|
|
5528
5575
|
this.assistantUtils = inject(AssistantUtils);
|
|
5529
5576
|
}
|
|
5530
5577
|
ngOnInit() {
|
|
5531
|
-
this._subscription.add(of(isAuthenticated()).pipe(
|
|
5578
|
+
this._subscription.add(of(isAuthenticated()).pipe(switchMap((_) => this.appService.init()), tap((_) => {
|
|
5579
|
+
this.onUpdateUploadedDocumentsList();
|
|
5580
|
+
this.documentsUploadService.getDocumentsList();
|
|
5581
|
+
}), catchError$1((error) => {
|
|
5532
5582
|
console.error(error);
|
|
5533
5583
|
this.notificationsService.error(error);
|
|
5534
5584
|
return EMPTY;
|
|
@@ -5538,26 +5588,23 @@ class DocumentListComponent {
|
|
|
5538
5588
|
ngOnDestroy() {
|
|
5539
5589
|
this._subscription.unsubscribe();
|
|
5540
5590
|
}
|
|
5541
|
-
instantiateChatService() {
|
|
5542
|
-
this.chatService = this.instanceManagerService.getInstance(this.instanceId);
|
|
5543
|
-
}
|
|
5544
5591
|
/**
|
|
5545
5592
|
* Updates the list of uploaded documents by fetching the latest data from the service.
|
|
5546
5593
|
* The fetched documents are grouped by date.
|
|
5547
5594
|
*
|
|
5548
5595
|
* @returns {void}
|
|
5549
5596
|
*/
|
|
5550
|
-
|
|
5597
|
+
onUpdateUploadedDocumentsList() {
|
|
5551
5598
|
this._subscription.add(combineLatest([
|
|
5552
|
-
this.documentsUploadService.
|
|
5599
|
+
this.documentsUploadService.uploadedDocuments$,
|
|
5553
5600
|
this.transloco.langChanges$
|
|
5554
5601
|
]).pipe(tap(([uploadedDocuments]) => {
|
|
5555
|
-
this.groupedUploadedDocuments$.next(this._groupUploadedDocumentsByDate(uploadedDocuments
|
|
5602
|
+
this.groupedUploadedDocuments$.next(this._groupUploadedDocumentsByDate(uploadedDocuments));
|
|
5556
5603
|
}), catchError$1((error) => {
|
|
5557
5604
|
console.error(error);
|
|
5558
5605
|
this.notificationsService.error(error);
|
|
5559
5606
|
return EMPTY;
|
|
5560
|
-
})
|
|
5607
|
+
}))
|
|
5561
5608
|
.subscribe());
|
|
5562
5609
|
}
|
|
5563
5610
|
deleteDocument(event, doc) {
|
|
@@ -5583,8 +5630,7 @@ class DocumentListComponent {
|
|
|
5583
5630
|
.pipe(tap(() => {
|
|
5584
5631
|
this.notificationsService.success(this.transloco.translate('chatDocumentsUpload.deleteDocumentSuccess', { title: this.documentToDelete.fileName }));
|
|
5585
5632
|
this.documentToDelete = undefined;
|
|
5586
|
-
|
|
5587
|
-
}), catchError$1((error) => {
|
|
5633
|
+
}), switchMap(() => this.documentsUploadService.getDocumentsList()), catchError$1((error) => {
|
|
5588
5634
|
console.error(error);
|
|
5589
5635
|
this.notificationsService.error(this.transloco.translate('chatDocumentsUpload.deleteDocumentError', { title: this.documentToDelete.fileName }));
|
|
5590
5636
|
return EMPTY;
|
|
@@ -5613,8 +5659,7 @@ class DocumentListComponent {
|
|
|
5613
5659
|
.pipe(tap(() => {
|
|
5614
5660
|
this.deletingAll = false;
|
|
5615
5661
|
this.notificationsService.success(this.transloco.translate('chatDocumentsUpload.deleteAllDocumentsSuccess'));
|
|
5616
|
-
|
|
5617
|
-
}), catchError$1((error) => {
|
|
5662
|
+
}), switchMap(() => this.documentsUploadService.getDocumentsList()), catchError$1((error) => {
|
|
5618
5663
|
console.error(error);
|
|
5619
5664
|
this.notificationsService.error(this.transloco.translate('chatDocumentsUpload.deleteAllDocumentsError'));
|
|
5620
5665
|
return EMPTY;
|
|
@@ -5622,6 +5667,9 @@ class DocumentListComponent {
|
|
|
5622
5667
|
.subscribe());
|
|
5623
5668
|
}
|
|
5624
5669
|
_groupUploadedDocumentsByDate(docs) {
|
|
5670
|
+
if (!docs || docs.length === 0) {
|
|
5671
|
+
return [];
|
|
5672
|
+
}
|
|
5625
5673
|
const groupedUploadedDocuments = new Map();
|
|
5626
5674
|
docs
|
|
5627
5675
|
.sort((a, b) => parseISO(b.indexationTime).getTime() - parseISO(a.indexationTime).getTime())
|
|
@@ -5636,28 +5684,24 @@ class DocumentListComponent {
|
|
|
5636
5684
|
;
|
|
5637
5685
|
}
|
|
5638
5686
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DocumentListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
5639
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: DocumentListComponent, isStandalone: true, selector: "sq-document-list",
|
|
5687
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: DocumentListComponent, isStandalone: true, selector: "sq-document-list", providers: [provideTranslocoScope('chat-documents-upload')], ngImport: i0, template: "<div class=\"alert alert-danger\" *ngIf=\"deletingAll\">\n <span>{{ 'chatDocumentsUpload.deleteAllDocumentsText' | transloco }}</span>\n <div class=\"d-flex gap-2\">\n <button class=\"btn btn-light w-100\" (click)=\"deletingAll=false\">{{ 'chatDocumentsUpload.cancel' | transloco }}</button>\n <button class=\"btn btn-secondary w-100\" (click)=\"performDeleteAllDocuments()\">{{ 'chatDocumentsUpload.confirm' | transloco }}</button>\n </div>\n</div>\n\n<div *ngFor=\"let group of (groupedUploadedDocuments$ | async)\" class=\"uploaded-docs\">\n <span class=\"uploaded-docs-date\">{{group.key}}</span>\n <div *ngFor=\"let doc of group.value\">\n <div class=\"uploaded-doc p-2\">\n <sq-format-icon [extension]=\"doc.fileExt\" class=\"me-1\"></sq-format-icon>\n <span class=\"title me-1\" [title]=\"doc.fileName\">{{doc.fileName}}</span>\n <button\n type=\"button\"\n (click)=\"deleteDocument($event, doc)\"\n [title]=\"'chatDocumentsUpload.delete' | transloco\"\n class=\"bg-transparent border-0 p-0 m-0 cursor-pointer text-inherit leading-none inline-flex items-center justify-center\"\n >\n <i class=\"uploaded-doc-actions fas fa-trash ms-1\"></i>\n </button>\n </div>\n\n <div class=\"alert alert-warning\" *ngIf=\"documentToDelete && documentToDelete.id === doc.id\">\n <span>\n {{ 'chatDocumentsUpload.deleteDocumentText' | transloco: { title: documentToDelete!.fileName } }}\n </span>\n <div class=\"d-flex gap-2\">\n <button class=\"btn btn-light w-100\" (click)=\"documentToDelete=undefined\">{{ 'chatDocumentsUpload.cancel' | transloco }}</button>\n <button class=\"btn btn-secondary w-100\" (click)=\"performDeleteDocument()\">{{ 'chatDocumentsUpload.confirm' | transloco }}</button>\n </div>\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-uploaded-doc-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;--ast-report-bg: #070707}.uploaded-docs{padding:.3rem 1rem}.uploaded-docs-date{font-size:12px;font-weight:500;color:#a9a9a9;margin-top:.5rem}.uploaded-docs .uploaded-doc{display:flex;align-items:center;cursor:pointer;margin-left:.25rem}.uploaded-docs .uploaded-doc span{flex-grow:1;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.uploaded-docs .uploaded-doc .uploaded-doc-actions{display:none}.uploaded-docs .uploaded-doc .uploaded-doc-actions:hover{color:var(--ast-primary-color, #005DA7)}.uploaded-docs .uploaded-doc:hover{background-color:var(--ast-uploaded-doc-hover-background, #f2f8fe)}.uploaded-docs .uploaded-doc:hover .uploaded-doc-actions{display:block}.uploaded-docs .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: "component", type: FormatIconComponent, selector: "sq-format-icon", inputs: ["extension"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] }); }
|
|
5640
5688
|
}
|
|
5641
5689
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DocumentListComponent, decorators: [{
|
|
5642
5690
|
type: Component,
|
|
5643
|
-
args: [{ selector: "sq-document-list", standalone: true, providers: [
|
|
5644
|
-
}]
|
|
5645
|
-
type: Input
|
|
5646
|
-
}] } });
|
|
5691
|
+
args: [{ selector: "sq-document-list", standalone: true, providers: [provideTranslocoScope('chat-documents-upload')], imports: [CommonModule, FormatIconComponent, TranslocoPipe], template: "<div class=\"alert alert-danger\" *ngIf=\"deletingAll\">\n <span>{{ 'chatDocumentsUpload.deleteAllDocumentsText' | transloco }}</span>\n <div class=\"d-flex gap-2\">\n <button class=\"btn btn-light w-100\" (click)=\"deletingAll=false\">{{ 'chatDocumentsUpload.cancel' | transloco }}</button>\n <button class=\"btn btn-secondary w-100\" (click)=\"performDeleteAllDocuments()\">{{ 'chatDocumentsUpload.confirm' | transloco }}</button>\n </div>\n</div>\n\n<div *ngFor=\"let group of (groupedUploadedDocuments$ | async)\" class=\"uploaded-docs\">\n <span class=\"uploaded-docs-date\">{{group.key}}</span>\n <div *ngFor=\"let doc of group.value\">\n <div class=\"uploaded-doc p-2\">\n <sq-format-icon [extension]=\"doc.fileExt\" class=\"me-1\"></sq-format-icon>\n <span class=\"title me-1\" [title]=\"doc.fileName\">{{doc.fileName}}</span>\n <button\n type=\"button\"\n (click)=\"deleteDocument($event, doc)\"\n [title]=\"'chatDocumentsUpload.delete' | transloco\"\n class=\"bg-transparent border-0 p-0 m-0 cursor-pointer text-inherit leading-none inline-flex items-center justify-center\"\n >\n <i class=\"uploaded-doc-actions fas fa-trash ms-1\"></i>\n </button>\n </div>\n\n <div class=\"alert alert-warning\" *ngIf=\"documentToDelete && documentToDelete.id === doc.id\">\n <span>\n {{ 'chatDocumentsUpload.deleteDocumentText' | transloco: { title: documentToDelete!.fileName } }}\n </span>\n <div class=\"d-flex gap-2\">\n <button class=\"btn btn-light w-100\" (click)=\"documentToDelete=undefined\">{{ 'chatDocumentsUpload.cancel' | transloco }}</button>\n <button class=\"btn btn-secondary w-100\" (click)=\"performDeleteDocument()\">{{ 'chatDocumentsUpload.confirm' | transloco }}</button>\n </div>\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-uploaded-doc-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;--ast-report-bg: #070707}.uploaded-docs{padding:.3rem 1rem}.uploaded-docs-date{font-size:12px;font-weight:500;color:#a9a9a9;margin-top:.5rem}.uploaded-docs .uploaded-doc{display:flex;align-items:center;cursor:pointer;margin-left:.25rem}.uploaded-docs .uploaded-doc span{flex-grow:1;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.uploaded-docs .uploaded-doc .uploaded-doc-actions{display:none}.uploaded-docs .uploaded-doc .uploaded-doc-actions:hover{color:var(--ast-primary-color, #005DA7)}.uploaded-docs .uploaded-doc:hover{background-color:var(--ast-uploaded-doc-hover-background, #f2f8fe)}.uploaded-docs .uploaded-doc:hover .uploaded-doc-actions{display:block}.uploaded-docs .title{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n"] }]
|
|
5692
|
+
}] });
|
|
5647
5693
|
|
|
5648
5694
|
class DocumentOverviewComponent {
|
|
5649
5695
|
constructor() {
|
|
5650
5696
|
this.disabledUpload = true;
|
|
5651
5697
|
this.onUpload = new EventEmitter();
|
|
5652
|
-
this.uploadedDocuments$ = new BehaviorSubject([]);
|
|
5653
5698
|
this._subscription = new Subscription();
|
|
5654
|
-
this.instanceManagerService = inject(InstanceManagerService);
|
|
5655
5699
|
this.documentsUploadService = inject(DocumentsUploadService);
|
|
5656
5700
|
this.notificationsService = inject(NotificationsService);
|
|
5701
|
+
this.appService = inject(AppService);
|
|
5657
5702
|
}
|
|
5658
|
-
;
|
|
5659
5703
|
ngOnInit() {
|
|
5660
|
-
this._subscription.add(of(isAuthenticated()).pipe(
|
|
5704
|
+
this._subscription.add(of(isAuthenticated()).pipe(switchMap((_) => this.appService.init()), switchMap((_) => this.documentsUploadService.getDocumentsList()), catchError$1((error) => {
|
|
5661
5705
|
console.error(error);
|
|
5662
5706
|
this.notificationsService.error(error);
|
|
5663
5707
|
return EMPTY;
|
|
@@ -5667,42 +5711,409 @@ class DocumentOverviewComponent {
|
|
|
5667
5711
|
ngOnDestroy() {
|
|
5668
5712
|
this._subscription.unsubscribe();
|
|
5669
5713
|
}
|
|
5670
|
-
instantiateChatService() {
|
|
5671
|
-
this.chatService = this.instanceManagerService.getInstance(this.instanceId);
|
|
5672
|
-
}
|
|
5673
|
-
/**
|
|
5674
|
-
* Updates the list of uploaded documents by fetching the latest data from the service.
|
|
5675
|
-
*
|
|
5676
|
-
* @returns {void}
|
|
5677
|
-
*/
|
|
5678
|
-
updateUploadedDocumentsList() {
|
|
5679
|
-
this._subscription.add(this.documentsUploadService.getDocumentsList()
|
|
5680
|
-
.pipe(tap((uploadedDocuments) => {
|
|
5681
|
-
this.uploadedDocuments$.next(uploadedDocuments.docs);
|
|
5682
|
-
}), catchError$1((error) => {
|
|
5683
|
-
console.error(error);
|
|
5684
|
-
this.notificationsService.error(error);
|
|
5685
|
-
return EMPTY;
|
|
5686
|
-
}), take$1(1))
|
|
5687
|
-
.subscribe());
|
|
5688
|
-
}
|
|
5689
5714
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DocumentOverviewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
5690
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: DocumentOverviewComponent, isStandalone: true, selector: "sq-document-overview", inputs: {
|
|
5715
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: DocumentOverviewComponent, isStandalone: true, selector: "sq-document-overview", inputs: { disabledUpload: "disabledUpload" }, outputs: { onUpload: "onUpload" }, providers: [provideTranslocoScope('chat-documents-upload')], ngImport: i0, template: "<div class=\"d-flex\">\n <span class=\"overview-text flex-grow-1\">\n {{ 'chatDocumentsUpload.uploadedDocuments' | transloco: { count: (documentsUploadService.uploadedDocuments$ | async)?.length || 0 } }}\n </span>\n <button disabled class=\"btn btn-light\" [title]=\"'chatDocumentsUpload.uploadToSources' | transloco\" (click)=\"onUpload.emit()\" [disabled]=\"disabledUpload\">\n <i class=\"fas fa-cloud-upload-alt\"></i>\n </button>\n</div>\n", styles: [".overview-text{font-style:italic;padding:.5rem .8rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] }); }
|
|
5691
5716
|
}
|
|
5692
5717
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DocumentOverviewComponent, decorators: [{
|
|
5693
5718
|
type: Component,
|
|
5694
|
-
args: [{ selector: "sq-document-overview", standalone: true, providers: [
|
|
5695
|
-
}], propDecorators: {
|
|
5696
|
-
type: Input
|
|
5697
|
-
}], disabledUpload: [{
|
|
5719
|
+
args: [{ selector: "sq-document-overview", standalone: true, providers: [provideTranslocoScope('chat-documents-upload')], imports: [CommonModule, TranslocoPipe], template: "<div class=\"d-flex\">\n <span class=\"overview-text flex-grow-1\">\n {{ 'chatDocumentsUpload.uploadedDocuments' | transloco: { count: (documentsUploadService.uploadedDocuments$ | async)?.length || 0 } }}\n </span>\n <button disabled class=\"btn btn-light\" [title]=\"'chatDocumentsUpload.uploadToSources' | transloco\" (click)=\"onUpload.emit()\" [disabled]=\"disabledUpload\">\n <i class=\"fas fa-cloud-upload-alt\"></i>\n </button>\n</div>\n", styles: [".overview-text{font-style:italic;padding:.5rem .8rem}\n"] }]
|
|
5720
|
+
}], propDecorators: { disabledUpload: [{
|
|
5698
5721
|
type: Input
|
|
5699
5722
|
}], onUpload: [{
|
|
5700
5723
|
type: Output
|
|
5701
5724
|
}] } });
|
|
5702
5725
|
|
|
5726
|
+
class CopyToClipboardDirective {
|
|
5727
|
+
constructor() {
|
|
5728
|
+
this.el = inject((ElementRef));
|
|
5729
|
+
this.text = input("");
|
|
5730
|
+
}
|
|
5731
|
+
onClick() {
|
|
5732
|
+
if (!this.text()) {
|
|
5733
|
+
return;
|
|
5734
|
+
}
|
|
5735
|
+
// The text is encoded from the markdown-it plugin, so we decode it first
|
|
5736
|
+
const decodedText = decodeURIComponent(this.text());
|
|
5737
|
+
if (navigator.clipboard && navigator.clipboard.writeText) {
|
|
5738
|
+
navigator.clipboard
|
|
5739
|
+
.writeText(decodedText)
|
|
5740
|
+
.then(() => {
|
|
5741
|
+
// Provide visual feedback to the user
|
|
5742
|
+
const originalHTML = this.el.nativeElement.innerHTML;
|
|
5743
|
+
this.el.nativeElement.innerHTML =
|
|
5744
|
+
'<svg data-testid="geist-icon" height="16" stroke-linejoin="round" viewBox="0 0 16 16" width="16" aria-hidden="true" style="color: currentcolor;"><path fill-rule="evenodd" clip-rule="evenodd" d="M15.5607 3.99999L15.0303 4.53032L6.23744 13.3232C5.55403 14.0066 4.44599 14.0066 3.76257 13.3232L4.2929 12.7929L3.76257 13.3232L0.969676 10.5303L0.439346 9.99999L1.50001 8.93933L2.03034 9.46966L4.82323 12.2626C4.92086 12.3602 5.07915 12.3602 5.17678 12.2626L13.9697 3.46966L14.5 2.93933L15.5607 3.99999Z" fill="currentColor"></path></svg>';
|
|
5745
|
+
setTimeout(() => {
|
|
5746
|
+
this.el.nativeElement.innerHTML = originalHTML;
|
|
5747
|
+
}, 2000);
|
|
5748
|
+
})
|
|
5749
|
+
.catch((err) => {
|
|
5750
|
+
console.error("Failed to copy text: ", err);
|
|
5751
|
+
});
|
|
5752
|
+
}
|
|
5753
|
+
else {
|
|
5754
|
+
// Fallback for older browsers
|
|
5755
|
+
const textarea = document.createElement("textarea");
|
|
5756
|
+
textarea.value = decodedText;
|
|
5757
|
+
textarea.style.position = "fixed"; // Prevent scrolling to bottom of page in MS Edge.
|
|
5758
|
+
textarea.style.opacity = "0";
|
|
5759
|
+
document.body.appendChild(textarea);
|
|
5760
|
+
textarea.focus();
|
|
5761
|
+
textarea.select();
|
|
5762
|
+
try {
|
|
5763
|
+
document.execCommand("copy");
|
|
5764
|
+
// Provide visual feedback to the user
|
|
5765
|
+
const originalHTML = this.el.nativeElement.innerHTML;
|
|
5766
|
+
this.el.nativeElement.innerHTML =
|
|
5767
|
+
'<svg data-testid="geist-icon" height="16" stroke-linejoin="round" viewBox="0 0 16 16" width="16" aria-hidden="true" style="color: currentcolor;"><path fill-rule="evenodd" clip-rule="evenodd" d="M15.5607 3.99999L15.0303 4.53032L6.23744 13.3232C5.55403 14.0066 4.44599 14.0066 3.76257 13.3232L4.2929 12.7929L3.76257 13.3232L0.969676 10.5303L0.439346 9.99999L1.50001 8.93933L2.03034 9.46966L4.82323 12.2626C4.92086 12.3602 5.07915 12.3602 5.17678 12.2626L13.9697 3.46966L14.5 2.93933L15.5607 3.99999Z" fill="currentColor"></path></svg>';
|
|
5768
|
+
setTimeout(() => {
|
|
5769
|
+
this.el.nativeElement.innerHTML = originalHTML;
|
|
5770
|
+
}, 2000);
|
|
5771
|
+
}
|
|
5772
|
+
catch (err) {
|
|
5773
|
+
console.error("Fallback: Oops, unable to copy", err);
|
|
5774
|
+
}
|
|
5775
|
+
document.body.removeChild(textarea);
|
|
5776
|
+
}
|
|
5777
|
+
}
|
|
5778
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CopyToClipboardDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
5779
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "18.2.13", type: CopyToClipboardDirective, isStandalone: true, selector: "[copy-to-clipboard]", inputs: { text: { classPropertyName: "text", publicName: "text", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "click": "onClick()" } }, ngImport: i0 }); }
|
|
5780
|
+
}
|
|
5781
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CopyToClipboardDirective, decorators: [{
|
|
5782
|
+
type: Directive,
|
|
5783
|
+
args: [{
|
|
5784
|
+
selector: "[copy-to-clipboard]",
|
|
5785
|
+
standalone: true,
|
|
5786
|
+
host: {
|
|
5787
|
+
"(click)": "onClick()",
|
|
5788
|
+
},
|
|
5789
|
+
}]
|
|
5790
|
+
}] });
|
|
5791
|
+
|
|
5792
|
+
/*
|
|
5793
|
+
* Web Element Reference Components
|
|
5794
|
+
* Those components are used to display a reference (page, image, document) in the chat interface.
|
|
5795
|
+
* It uses a tooltip to show additional information about the reference.
|
|
5796
|
+
* The component emits custom events when the user interacts with it.
|
|
5797
|
+
*/
|
|
5798
|
+
class ReferenceComponent {
|
|
5799
|
+
constructor() {
|
|
5800
|
+
this.ref = {};
|
|
5801
|
+
}
|
|
5802
|
+
ngOnChanges() {
|
|
5803
|
+
if (!this.attachment)
|
|
5804
|
+
return;
|
|
5805
|
+
try {
|
|
5806
|
+
const obj = JSON.parse(decodeURIComponent(atob(this.attachment)));
|
|
5807
|
+
this.ref = obj;
|
|
5808
|
+
}
|
|
5809
|
+
catch (error) {
|
|
5810
|
+
console.error("Error parsing attachment", error, this.attachment);
|
|
5811
|
+
}
|
|
5812
|
+
}
|
|
5813
|
+
onOpenPreview(attachment, partId) {
|
|
5814
|
+
// Émettre un événement personnalisé pour le web element using the service
|
|
5815
|
+
dispatchEvent(new CustomEvent("onOpenPreview", {
|
|
5816
|
+
detail: { reference: attachment, partId: partId || this.id },
|
|
5817
|
+
}));
|
|
5818
|
+
}
|
|
5819
|
+
onOpenDocument(attachment, partId) {
|
|
5820
|
+
// Émettre un événement personnalisé pour le web element using the service
|
|
5821
|
+
dispatchEvent(new CustomEvent("onOpenDocument", {
|
|
5822
|
+
detail: { reference: attachment, partId: partId || this.id },
|
|
5823
|
+
}));
|
|
5824
|
+
}
|
|
5825
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ReferenceComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
5826
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ReferenceComponent, isStandalone: true, selector: "reference", inputs: { id: "id", attachment: "attachment", rank: "rank" }, providers: [], usesOnChanges: true, ngImport: i0, template: `
|
|
5827
|
+
<a
|
|
5828
|
+
class="reference"
|
|
5829
|
+
role="button"
|
|
5830
|
+
[sqTooltip]="ref"
|
|
5831
|
+
[sqTooltipTemplate]="tooltipTpl"
|
|
5832
|
+
[hoverableTooltip]="true"
|
|
5833
|
+
(click)="onOpenPreview(ref)"
|
|
5834
|
+
>{{ id }}</a>
|
|
5835
|
+
|
|
5836
|
+
<!-- tooltip template -->
|
|
5837
|
+
<ng-template #tooltipTpl>
|
|
5838
|
+
<sq-chat-reference
|
|
5839
|
+
class="expanded"
|
|
5840
|
+
[attachment]="ref"
|
|
5841
|
+
[reference]="ref.contextId"
|
|
5842
|
+
[partId]="ref.$partId"
|
|
5843
|
+
(openPreview)="onOpenPreview($event, $event.$partId)"
|
|
5844
|
+
(openDocument)="onOpenDocument($event, $event.$partId)"
|
|
5845
|
+
></sq-chat-reference>
|
|
5846
|
+
</ng-template>
|
|
5847
|
+
`, isInline: true, styles: ["div{border:1px solid #ccc;padding:8px;border-radius:4px;display:flex;gap:8px;flex-direction:column}\n"], dependencies: [{ kind: "directive", type: TooltipDirective, selector: "[sqTooltip]", inputs: ["sqTooltip", "sqTooltipData", "sqTooltipTemplate", "placement", "fallbackPlacements", "delay", "hoverableTooltip", "tooltipClass"] }, { kind: "component", type: ChatReferenceComponent, selector: "sq-chat-reference", inputs: ["reference", "attachment", "partId", "referenceMap", "images", "pages"], outputs: ["openDocument", "openPreview"] }] }); }
|
|
5848
|
+
}
|
|
5849
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ReferenceComponent, decorators: [{
|
|
5850
|
+
type: Component,
|
|
5851
|
+
args: [{ selector: "reference", imports: [TooltipDirective, ChatReferenceComponent], providers: [], template: `
|
|
5852
|
+
<a
|
|
5853
|
+
class="reference"
|
|
5854
|
+
role="button"
|
|
5855
|
+
[sqTooltip]="ref"
|
|
5856
|
+
[sqTooltipTemplate]="tooltipTpl"
|
|
5857
|
+
[hoverableTooltip]="true"
|
|
5858
|
+
(click)="onOpenPreview(ref)"
|
|
5859
|
+
>{{ id }}</a>
|
|
5860
|
+
|
|
5861
|
+
<!-- tooltip template -->
|
|
5862
|
+
<ng-template #tooltipTpl>
|
|
5863
|
+
<sq-chat-reference
|
|
5864
|
+
class="expanded"
|
|
5865
|
+
[attachment]="ref"
|
|
5866
|
+
[reference]="ref.contextId"
|
|
5867
|
+
[partId]="ref.$partId"
|
|
5868
|
+
(openPreview)="onOpenPreview($event, $event.$partId)"
|
|
5869
|
+
(openDocument)="onOpenDocument($event, $event.$partId)"
|
|
5870
|
+
></sq-chat-reference>
|
|
5871
|
+
</ng-template>
|
|
5872
|
+
`, standalone: true, styles: ["div{border:1px solid #ccc;padding:8px;border-radius:4px;display:flex;gap:8px;flex-direction:column}\n"] }]
|
|
5873
|
+
}], propDecorators: { id: [{
|
|
5874
|
+
type: Input
|
|
5875
|
+
}], attachment: [{
|
|
5876
|
+
type: Input
|
|
5877
|
+
}], rank: [{
|
|
5878
|
+
type: Input
|
|
5879
|
+
}] } });
|
|
5880
|
+
class PageReferenceComponent {
|
|
5881
|
+
constructor() {
|
|
5882
|
+
this.ref = {};
|
|
5883
|
+
}
|
|
5884
|
+
ngOnChanges() {
|
|
5885
|
+
if (!this.attachment)
|
|
5886
|
+
return;
|
|
5887
|
+
try {
|
|
5888
|
+
const obj = JSON.parse(decodeURIComponent(atob(this.attachment)));
|
|
5889
|
+
this.ref = obj;
|
|
5890
|
+
}
|
|
5891
|
+
catch (error) {
|
|
5892
|
+
console.error("Error parsing attachment", error, this.attachment);
|
|
5893
|
+
}
|
|
5894
|
+
}
|
|
5895
|
+
onOpenPreview(attachment, partId) {
|
|
5896
|
+
// Émettre un événement personnalisé pour le web element using the service
|
|
5897
|
+
dispatchEvent(new CustomEvent("onOpenPreview", {
|
|
5898
|
+
detail: { reference: attachment, partId: partId || this.id },
|
|
5899
|
+
}));
|
|
5900
|
+
}
|
|
5901
|
+
onOpenDocument(attachment, partId) {
|
|
5902
|
+
// Émettre un événement personnalisé pour le web element using the service
|
|
5903
|
+
dispatchEvent(new CustomEvent("onOpenDocument", {
|
|
5904
|
+
detail: { reference: attachment, partId: partId || this.id },
|
|
5905
|
+
}));
|
|
5906
|
+
}
|
|
5907
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PageReferenceComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
5908
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: PageReferenceComponent, isStandalone: true, selector: "page-reference", inputs: { id: "id", attachment: "attachment" }, providers: [], usesOnChanges: true, ngImport: i0, template: `
|
|
5909
|
+
<span
|
|
5910
|
+
class="reference"
|
|
5911
|
+
[sqTooltip]="{ obj: ref, id }"
|
|
5912
|
+
[sqTooltipTemplate]="pageTooltipTpl"
|
|
5913
|
+
[hoverableTooltip]="true"
|
|
5914
|
+
>
|
|
5915
|
+
Page-{{ id }}
|
|
5916
|
+
</span>
|
|
5917
|
+
<ng-template #pageTooltipTpl let-ref>
|
|
5918
|
+
<InlinePageReference
|
|
5919
|
+
style="max-width: 30vw;"
|
|
5920
|
+
[id]="ref.id"
|
|
5921
|
+
[ref]="ref.obj"
|
|
5922
|
+
(openPreview)="onOpenPreview($event, $event.$partId)"
|
|
5923
|
+
(openDocument)="onOpenPreview($event, $event.$partId)"
|
|
5924
|
+
/>
|
|
5925
|
+
</ng-template>
|
|
5926
|
+
`, isInline: true, styles: ["div{border:1px solid #ccc;padding:8px;border-radius:4px;display:flex;gap:8px;flex-direction:column}\n"], dependencies: [{ kind: "directive", type: TooltipDirective, selector: "[sqTooltip]", inputs: ["sqTooltip", "sqTooltipData", "sqTooltipTemplate", "placement", "fallbackPlacements", "delay", "hoverableTooltip", "tooltipClass"] }, { kind: "component", type: InlinePageReferenceComponent, selector: "InlinePageReference", inputs: ["id", "ref"], outputs: ["openPreview", "openDocument", "openModal"] }] }); }
|
|
5927
|
+
}
|
|
5928
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PageReferenceComponent, decorators: [{
|
|
5929
|
+
type: Component,
|
|
5930
|
+
args: [{ selector: "page-reference", imports: [TooltipDirective, InlinePageReferenceComponent], providers: [], template: `
|
|
5931
|
+
<span
|
|
5932
|
+
class="reference"
|
|
5933
|
+
[sqTooltip]="{ obj: ref, id }"
|
|
5934
|
+
[sqTooltipTemplate]="pageTooltipTpl"
|
|
5935
|
+
[hoverableTooltip]="true"
|
|
5936
|
+
>
|
|
5937
|
+
Page-{{ id }}
|
|
5938
|
+
</span>
|
|
5939
|
+
<ng-template #pageTooltipTpl let-ref>
|
|
5940
|
+
<InlinePageReference
|
|
5941
|
+
style="max-width: 30vw;"
|
|
5942
|
+
[id]="ref.id"
|
|
5943
|
+
[ref]="ref.obj"
|
|
5944
|
+
(openPreview)="onOpenPreview($event, $event.$partId)"
|
|
5945
|
+
(openDocument)="onOpenPreview($event, $event.$partId)"
|
|
5946
|
+
/>
|
|
5947
|
+
</ng-template>
|
|
5948
|
+
`, standalone: true, styles: ["div{border:1px solid #ccc;padding:8px;border-radius:4px;display:flex;gap:8px;flex-direction:column}\n"] }]
|
|
5949
|
+
}], propDecorators: { id: [{
|
|
5950
|
+
type: Input
|
|
5951
|
+
}], attachment: [{
|
|
5952
|
+
type: Input
|
|
5953
|
+
}] } });
|
|
5954
|
+
class ImageReferenceComponent {
|
|
5955
|
+
constructor() {
|
|
5956
|
+
this.ref = {};
|
|
5957
|
+
}
|
|
5958
|
+
ngOnChanges() {
|
|
5959
|
+
if (!this.attachment)
|
|
5960
|
+
return;
|
|
5961
|
+
try {
|
|
5962
|
+
const obj = JSON.parse(decodeURIComponent(atob(this.attachment)));
|
|
5963
|
+
this.ref = obj;
|
|
5964
|
+
}
|
|
5965
|
+
catch (error) {
|
|
5966
|
+
console.error("Error parsing attachment", error, this.attachment);
|
|
5967
|
+
}
|
|
5968
|
+
}
|
|
5969
|
+
onOpenPreview(attachment, partId) {
|
|
5970
|
+
// Émettre un événement personnalisé pour le web element using the service
|
|
5971
|
+
dispatchEvent(new CustomEvent("onOpenPreview", {
|
|
5972
|
+
detail: { reference: attachment, partId: partId || this.id },
|
|
5973
|
+
}));
|
|
5974
|
+
}
|
|
5975
|
+
onOpenDocument(attachment, partId) {
|
|
5976
|
+
// Émettre un événement personnalisé pour le web element using the service
|
|
5977
|
+
dispatchEvent(new CustomEvent("onOpenDocument", {
|
|
5978
|
+
detail: { reference: attachment, partId: partId || this.id },
|
|
5979
|
+
}));
|
|
5980
|
+
}
|
|
5981
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ImageReferenceComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
5982
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ImageReferenceComponent, isStandalone: true, selector: "image-reference", inputs: { id: "id", attachment: "attachment" }, providers: [], usesOnChanges: true, ngImport: i0, template: `
|
|
5983
|
+
<span
|
|
5984
|
+
class="reference"
|
|
5985
|
+
[sqTooltip]="{ obj: ref, id }"
|
|
5986
|
+
[sqTooltipTemplate]="imageTooltipTpl"
|
|
5987
|
+
[hoverableTooltip]="true"
|
|
5988
|
+
>
|
|
5989
|
+
Img-{{ this.id }}
|
|
5990
|
+
</span>
|
|
5991
|
+
<ng-template #imageTooltipTpl let-ref>
|
|
5992
|
+
<InlineImageReference
|
|
5993
|
+
style="max-width: 30vw;"
|
|
5994
|
+
[id]="ref.id"
|
|
5995
|
+
[ref]="ref.obj"
|
|
5996
|
+
(openPreview)="onOpenPreview($event, $event.$partId)"
|
|
5997
|
+
(openDocument)="onOpenDocument($event, $event.$partId)"
|
|
5998
|
+
/>
|
|
5999
|
+
</ng-template>
|
|
6000
|
+
`, isInline: true, styles: ["div{border:1px solid #ccc;padding:8px;border-radius:4px;display:flex;gap:8px;flex-direction:column}\n"], dependencies: [{ kind: "directive", type: TooltipDirective, selector: "[sqTooltip]", inputs: ["sqTooltip", "sqTooltipData", "sqTooltipTemplate", "placement", "fallbackPlacements", "delay", "hoverableTooltip", "tooltipClass"] }, { kind: "component", type: InlineImageReferenceComponent, selector: "InlineImageReference", inputs: ["id", "ref"], outputs: ["openPreview", "openDocument", "openModal"] }] }); }
|
|
6001
|
+
}
|
|
6002
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ImageReferenceComponent, decorators: [{
|
|
6003
|
+
type: Component,
|
|
6004
|
+
args: [{ selector: "image-reference", imports: [TooltipDirective, InlineImageReferenceComponent], providers: [], template: `
|
|
6005
|
+
<span
|
|
6006
|
+
class="reference"
|
|
6007
|
+
[sqTooltip]="{ obj: ref, id }"
|
|
6008
|
+
[sqTooltipTemplate]="imageTooltipTpl"
|
|
6009
|
+
[hoverableTooltip]="true"
|
|
6010
|
+
>
|
|
6011
|
+
Img-{{ this.id }}
|
|
6012
|
+
</span>
|
|
6013
|
+
<ng-template #imageTooltipTpl let-ref>
|
|
6014
|
+
<InlineImageReference
|
|
6015
|
+
style="max-width: 30vw;"
|
|
6016
|
+
[id]="ref.id"
|
|
6017
|
+
[ref]="ref.obj"
|
|
6018
|
+
(openPreview)="onOpenPreview($event, $event.$partId)"
|
|
6019
|
+
(openDocument)="onOpenDocument($event, $event.$partId)"
|
|
6020
|
+
/>
|
|
6021
|
+
</ng-template>
|
|
6022
|
+
`, standalone: true, styles: ["div{border:1px solid #ccc;padding:8px;border-radius:4px;display:flex;gap:8px;flex-direction:column}\n"] }]
|
|
6023
|
+
}], propDecorators: { id: [{
|
|
6024
|
+
type: Input
|
|
6025
|
+
}], attachment: [{
|
|
6026
|
+
type: Input
|
|
6027
|
+
}] } });
|
|
6028
|
+
class CodeBlockReferenceComponent {
|
|
6029
|
+
constructor() {
|
|
6030
|
+
this.langname = "";
|
|
6031
|
+
this.el = inject(ElementRef);
|
|
6032
|
+
this.encodeCode = '';
|
|
6033
|
+
}
|
|
6034
|
+
ngAfterViewInit() {
|
|
6035
|
+
// get the code content
|
|
6036
|
+
const codeEl = this.el.nativeElement.querySelector("code");
|
|
6037
|
+
const code = codeEl ? codeEl.textContent : "";
|
|
6038
|
+
this.encodeCode = encodeURIComponent(code);
|
|
6039
|
+
}
|
|
6040
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CodeBlockReferenceComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6041
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: CodeBlockReferenceComponent, isStandalone: true, selector: "code-block-reference", inputs: { langname: "langname" }, ngImport: i0, template: `
|
|
6042
|
+
<div class="card mb-2">
|
|
6043
|
+
<div class="card-header d-flex justify-content-end align-items-center">
|
|
6044
|
+
<span class="me-auto">{{ langname || 'code'}}</span>
|
|
6045
|
+
<button class="btn btn-light btn-sm" copy-to-clipboard [text]="encodeCode">
|
|
6046
|
+
<svg data-testid="geist-icon" height="16" stroke-linejoin="round" viewBox="0 0 16 16" width="16" aria-hidden="true" style="color: currentcolor;"><path fill-rule="evenodd" clip-rule="evenodd" d="M2.75 0.5C1.7835 0.5 1 1.2835 1 2.25V9.75C1 10.7165 1.7835 11.5 2.75 11.5H3.75H4.5V10H3.75H2.75C2.61193 10 2.5 9.88807 2.5 9.75V2.25C2.5 2.11193 2.61193 2 2.75 2H8.25C8.38807 2 8.5 2.11193 8.5 2.25V3H10V2.25C10 1.2835 9.2165 0.5 8.25 0.5H2.75ZM7.75 4.5C6.7835 4.5 6 5.2835 6 6.25V13.75C6 14.7165 6.7835 15.5 7.75 15.5H13.25C14.2165 15.5 15 14.7165 15 13.75V6.25C15 5.2835 14.2165 4.5 13.25 4.5H7.75ZM7.5 6.25C7.5 6.11193 7.61193 6 7.75 6H13.25C13.3881 6 13.5 6.11193 13.5 6.25V13.75C13.5 13.8881 13.3881 14 13.25 14H7.75C7.61193 14 7.5 13.8881 7.5 13.75V6.25Z" fill="currentColor"></path></svg>
|
|
6047
|
+
</button>
|
|
6048
|
+
</div>
|
|
6049
|
+
<ng-content></ng-content>
|
|
6050
|
+
</div>
|
|
6051
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: CopyToClipboardDirective, selector: "[copy-to-clipboard]", inputs: ["text"] }] }); }
|
|
6052
|
+
}
|
|
6053
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CodeBlockReferenceComponent, decorators: [{
|
|
6054
|
+
type: Component,
|
|
6055
|
+
args: [{
|
|
6056
|
+
selector: "code-block-reference",
|
|
6057
|
+
imports: [CopyToClipboardDirective],
|
|
6058
|
+
template: `
|
|
6059
|
+
<div class="card mb-2">
|
|
6060
|
+
<div class="card-header d-flex justify-content-end align-items-center">
|
|
6061
|
+
<span class="me-auto">{{ langname || 'code'}}</span>
|
|
6062
|
+
<button class="btn btn-light btn-sm" copy-to-clipboard [text]="encodeCode">
|
|
6063
|
+
<svg data-testid="geist-icon" height="16" stroke-linejoin="round" viewBox="0 0 16 16" width="16" aria-hidden="true" style="color: currentcolor;"><path fill-rule="evenodd" clip-rule="evenodd" d="M2.75 0.5C1.7835 0.5 1 1.2835 1 2.25V9.75C1 10.7165 1.7835 11.5 2.75 11.5H3.75H4.5V10H3.75H2.75C2.61193 10 2.5 9.88807 2.5 9.75V2.25C2.5 2.11193 2.61193 2 2.75 2H8.25C8.38807 2 8.5 2.11193 8.5 2.25V3H10V2.25C10 1.2835 9.2165 0.5 8.25 0.5H2.75ZM7.75 4.5C6.7835 4.5 6 5.2835 6 6.25V13.75C6 14.7165 6.7835 15.5 7.75 15.5H13.25C14.2165 15.5 15 14.7165 15 13.75V6.25C15 5.2835 14.2165 4.5 13.25 4.5H7.75ZM7.5 6.25C7.5 6.11193 7.61193 6 7.75 6H13.25C13.3881 6 13.5 6.11193 13.5 6.25V13.75C13.5 13.8881 13.3881 14 13.25 14H7.75C7.61193 14 7.5 13.8881 7.5 13.75V6.25Z" fill="currentColor"></path></svg>
|
|
6064
|
+
</button>
|
|
6065
|
+
</div>
|
|
6066
|
+
<ng-content></ng-content>
|
|
6067
|
+
</div>
|
|
6068
|
+
`,
|
|
6069
|
+
standalone: true,
|
|
6070
|
+
}]
|
|
6071
|
+
}], propDecorators: { langname: [{
|
|
6072
|
+
type: Input
|
|
6073
|
+
}] } });
|
|
6074
|
+
|
|
6075
|
+
/**
|
|
6076
|
+
* Service to register custom elements in the Angular application.
|
|
6077
|
+
* This service is used to define custom elements that can be used in the application.
|
|
6078
|
+
* It is called through APP_INITIALIZER to ensure that custom elements are registered before the application starts.
|
|
6079
|
+
*/
|
|
6080
|
+
class CustomElementsService {
|
|
6081
|
+
constructor() {
|
|
6082
|
+
this._injector = inject(Injector);
|
|
6083
|
+
}
|
|
6084
|
+
// called through APP_INITIALIZER
|
|
6085
|
+
setupCustomElements() {
|
|
6086
|
+
const referenceElement = createCustomElement(ReferenceComponent, {
|
|
6087
|
+
injector: this._injector,
|
|
6088
|
+
});
|
|
6089
|
+
customElements.define("reference-component", referenceElement);
|
|
6090
|
+
const pageReference = createCustomElement(PageReferenceComponent, {
|
|
6091
|
+
injector: this._injector,
|
|
6092
|
+
});
|
|
6093
|
+
customElements.define("page-reference", pageReference);
|
|
6094
|
+
const imageReference = createCustomElement(ImageReferenceComponent, {
|
|
6095
|
+
injector: this._injector,
|
|
6096
|
+
});
|
|
6097
|
+
customElements.define("image-reference", imageReference);
|
|
6098
|
+
const codeReference = createCustomElement(CodeBlockReferenceComponent, {
|
|
6099
|
+
injector: this._injector,
|
|
6100
|
+
});
|
|
6101
|
+
customElements.define("code-block-reference", codeReference);
|
|
6102
|
+
}
|
|
6103
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CustomElementsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
6104
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CustomElementsService, providedIn: "root" }); }
|
|
6105
|
+
}
|
|
6106
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CustomElementsService, decorators: [{
|
|
6107
|
+
type: Injectable,
|
|
6108
|
+
args: [{ providedIn: "root" }]
|
|
6109
|
+
}] });
|
|
6110
|
+
function initializeCustomElements(customElementsService) {
|
|
6111
|
+
return () => customElementsService.setupCustomElements();
|
|
6112
|
+
}
|
|
6113
|
+
|
|
5703
6114
|
/**
|
|
5704
6115
|
* Generated bundle index. Do not edit.
|
|
5705
6116
|
*/
|
|
5706
6117
|
|
|
5707
|
-
export { ChatComponent,
|
|
6118
|
+
export { ChatComponent, ChatService, ChatSettingsV3Component, CodeBlockReferenceComponent, CustomElementsService, DocumentListComponent, DocumentOverviewComponent, DocumentUploadComponent, DocumentsUploadService, FormatIconComponent, ImageReferenceComponent, InitialsAvatarComponent, InstanceManagerService, NotificationsService, PageReferenceComponent, ReferenceComponent, SavedChatsComponent, chatConfigSchema, connectionSettingsSchema, initializeCustomElements };
|
|
5708
6119
|
//# sourceMappingURL=sinequa-assistant-chat.mjs.map
|