@sinequa/assistant 3.9.4 → 3.9.6-rc1
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 +50 -13
- 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 +293 -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 +913 -498
- 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, afterNextRender, 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
|
-
acc.push({
|
|
1080
|
-
type: "text",
|
|
1081
|
-
value: leadingText,
|
|
1082
|
-
end: ref.index,
|
|
1083
|
-
});
|
|
1240
|
+
|
|
1241
|
+
const GROUPING_REGEX = /<([a-z]+)>[\s\S]*?<\/\1>/gm;
|
|
1242
|
+
class SafeHtmlPipe {
|
|
1243
|
+
constructor(sanitizer) {
|
|
1244
|
+
this.sanitizer = sanitizer;
|
|
1084
1245
|
}
|
|
1085
|
-
|
|
1246
|
+
transform(html) {
|
|
1247
|
+
return this.sanitizer.bypassSecurityTrustHtml(html);
|
|
1248
|
+
}
|
|
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 > 1) {
|
|
1304
|
+
this.localSliceIndex = html.lastIndexOf(blocks.at(-1) || "");
|
|
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[0]);
|
|
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
1527
|
/**
|
|
1393
|
-
*
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
/**
|
|
1402
|
-
* Match all references in a given message
|
|
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
|
}
|
|
@@ -4146,11 +4274,20 @@ class ChatComponent {
|
|
|
4146
4274
|
* If the chat is meant to be initialized with event === "Query", the corresponding user query message will be added to the chat history
|
|
4147
4275
|
*/
|
|
4148
4276
|
loadDefaultChat() {
|
|
4277
|
+
const date = (new Date()).toLocaleString('en-US', { weekday: 'long', month: 'long', day: '2-digit', year: 'numeric' });
|
|
4149
4278
|
// Define the default system prompt and user prompt messages
|
|
4150
|
-
const systemMsg = {
|
|
4279
|
+
const systemMsg = {
|
|
4280
|
+
role: 'system',
|
|
4281
|
+
content: AssistantUtils.formatPrompt(this.transloco.translate(this.config.defaultValues.systemPrompt), { principal: this.principalService.principal, date }),
|
|
4282
|
+
additionalProperties: { display: false, messageId: guid() }
|
|
4283
|
+
};
|
|
4151
4284
|
// backward compatibility with old configuration files
|
|
4152
4285
|
const userPrompt = this.config.defaultValues.userPrompt.replace(/\{\{(.*?)\}\}/g, '[[$1]]');
|
|
4153
|
-
const userMsg = {
|
|
4286
|
+
const userMsg = {
|
|
4287
|
+
role: 'user',
|
|
4288
|
+
content: AssistantUtils.formatPrompt(this.transloco.translate(userPrompt), { principal: this.principalService.principal, date }),
|
|
4289
|
+
additionalProperties: { display: this.config.modeSettings.displayUserPrompt, messageId: guid() }
|
|
4290
|
+
};
|
|
4154
4291
|
if (this.config.modeSettings.initialization.event === 'Query') {
|
|
4155
4292
|
this._handleQueryMode(systemMsg, userMsg);
|
|
4156
4293
|
}
|
|
@@ -4362,9 +4499,11 @@ class ChatComponent {
|
|
|
4362
4499
|
if (i >= 0) {
|
|
4363
4500
|
this.messages$.next(this.messages$.value.slice(0, i + 1));
|
|
4364
4501
|
// Rank of this found first previous 'user' message in the chat history
|
|
4502
|
+
const rankFirstPreviousUserMessage = this.assistantUtils.getMessageRankInChatHistory(this.chatService.chatHistory, this.messages$.value[i].additionalProperties.messageId);
|
|
4503
|
+
// Rank of the assistant's message on which the user clicked to regenerate
|
|
4365
4504
|
const rank = this.assistantUtils.getMessageRankInChatHistory(this.chatService.chatHistory, message.additionalProperties.messageId);
|
|
4366
4505
|
// Define and Update the chat history based on which the assistant will generate a new answer
|
|
4367
|
-
this.chatService.chatHistory = this.chatService.chatHistory.slice(0,
|
|
4506
|
+
this.chatService.chatHistory = this.chatService.chatHistory.slice(0, rankFirstPreviousUserMessage);
|
|
4368
4507
|
// Fetch the answer
|
|
4369
4508
|
this.fetch(this.chatService.chatHistory);
|
|
4370
4509
|
this.chatService.generateAuditEvent('ast-regenerate.click', { 'rank': rank, 'message-id': message.additionalProperties.messageId });
|
|
@@ -4529,11 +4668,16 @@ class ChatComponent {
|
|
|
4529
4668
|
/**
|
|
4530
4669
|
* Handle the click on a suggested action.
|
|
4531
4670
|
* @param action Suggested action.
|
|
4532
|
-
* @param index
|
|
4671
|
+
* @param index index of the message containing the suggested action.
|
|
4672
|
+
* @returns void
|
|
4533
4673
|
*/
|
|
4534
4674
|
suggestActionClick(action, index) {
|
|
4535
4675
|
this.suggestAction.emit(action);
|
|
4536
|
-
|
|
4676
|
+
const details = {
|
|
4677
|
+
'text': action.content,
|
|
4678
|
+
'suggestedAction-type': action.type
|
|
4679
|
+
};
|
|
4680
|
+
this.chatService.generateAuditEvent('ast-suggested-action.click', details);
|
|
4537
4681
|
}
|
|
4538
4682
|
/**
|
|
4539
4683
|
* It looks for the debug messages available in the current group of "assistant" messages.
|
|
@@ -4611,15 +4755,23 @@ class ChatComponent {
|
|
|
4611
4755
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ChatComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4612
4756
|
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: [
|
|
4613
4757
|
ChatService,
|
|
4758
|
+
AssistantConfigurationService,
|
|
4759
|
+
AssistantTokensTrackingService,
|
|
4760
|
+
SavedChatsService,
|
|
4761
|
+
DebugMessageService,
|
|
4614
4762
|
provideTranslocoScope('chat')
|
|
4615
|
-
], 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 }); }
|
|
4763
|
+
], 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 }); }
|
|
4616
4764
|
}
|
|
4617
4765
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ChatComponent, decorators: [{
|
|
4618
4766
|
type: Component,
|
|
4619
4767
|
args: [{ selector: 'sq-chat-v3', providers: [
|
|
4620
4768
|
ChatService,
|
|
4769
|
+
AssistantConfigurationService,
|
|
4770
|
+
AssistantTokensTrackingService,
|
|
4771
|
+
SavedChatsService,
|
|
4772
|
+
DebugMessageService,
|
|
4621
4773
|
provideTranslocoScope('chat')
|
|
4622
|
-
], 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"] }]
|
|
4774
|
+
], 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"] }]
|
|
4623
4775
|
}], propDecorators: { instanceId: [{
|
|
4624
4776
|
type: Input
|
|
4625
4777
|
}], query: [{
|
|
@@ -4890,11 +5042,11 @@ class SavedChatsComponent {
|
|
|
4890
5042
|
;
|
|
4891
5043
|
}
|
|
4892
5044
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SavedChatsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4893
|
-
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 <
|
|
5045
|
+
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" }] }); }
|
|
4894
5046
|
}
|
|
4895
5047
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SavedChatsComponent, decorators: [{
|
|
4896
5048
|
type: Component,
|
|
4897
|
-
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 <
|
|
5049
|
+
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"] }]
|
|
4898
5050
|
}], propDecorators: { instanceId: [{
|
|
4899
5051
|
type: Input
|
|
4900
5052
|
}], load: [{
|
|
@@ -4903,126 +5055,27 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
|
|
|
4903
5055
|
type: Output
|
|
4904
5056
|
}] } });
|
|
4905
5057
|
|
|
4906
|
-
class ChatPrompt {
|
|
4907
|
-
constructor(formBuilder) {
|
|
4908
|
-
this.formBuilder = formBuilder;
|
|
4909
|
-
this.model = input({});
|
|
4910
|
-
}
|
|
4911
|
-
ngOnInit() {
|
|
4912
|
-
this.inputControl = new UntypedFormControl(this.model().output, this.model().validators || Validators.required);
|
|
4913
|
-
this.form = this.formBuilder.group({
|
|
4914
|
-
input: this.inputControl
|
|
4915
|
-
});
|
|
4916
|
-
this.formChanges.add(this.form.valueChanges.subscribe(() => this.model().output = this.inputControl.value));
|
|
4917
|
-
}
|
|
4918
|
-
ngOnDestroy() {
|
|
4919
|
-
this.formChanges.unsubscribe();
|
|
4920
|
-
}
|
|
4921
|
-
get title() {
|
|
4922
|
-
return this.model().title ?? "msg#modal.prompt.title";
|
|
4923
|
-
}
|
|
4924
|
-
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 }); }
|
|
4925
|
-
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: `
|
|
4926
|
-
<dialog [title]="title" #dialog>
|
|
4927
|
-
@if(title) {
|
|
4928
|
-
<h5 class="modal-title">{{title}}</h5>
|
|
4929
|
-
}
|
|
4930
|
-
<form name="prompt" novalidate [formGroup]="form">
|
|
4931
|
-
<div class="mb-3 sq-form-group">
|
|
4932
|
-
<label class="form-label" for="input">{{model().message}}</label>
|
|
4933
|
-
@if(!model().rowCount) {
|
|
4934
|
-
<input type="text" class="form-control" id="input" formControlName="input" spellcheck="off">
|
|
4935
|
-
}
|
|
4936
|
-
@if(!!model().rowCount) {
|
|
4937
|
-
<textarea type="text" class="form-control" id="input" formControlName="input" spellcheck="on" rows="{{model().rowCount}}"></textarea>
|
|
4938
|
-
}
|
|
4939
|
-
</div>
|
|
4940
|
-
</form>
|
|
4941
|
-
<section class="flex justify-end gap-2 mt-4">
|
|
4942
|
-
<button class="btn btn-ghost outline-none w-24" (click)="dialog.close()">
|
|
4943
|
-
Cancel
|
|
4944
|
-
</button>
|
|
4945
|
-
|
|
4946
|
-
<button class="btn btn-primary w-24">
|
|
4947
|
-
OK
|
|
4948
|
-
</button>
|
|
4949
|
-
</section>
|
|
4950
|
-
</dialog>
|
|
4951
|
-
`, 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"] }] }); }
|
|
4952
|
-
}
|
|
4953
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ChatPrompt, decorators: [{
|
|
4954
|
-
type: Component,
|
|
4955
|
-
args: [{
|
|
4956
|
-
selector: "sq-chat-prompt",
|
|
4957
|
-
template: `
|
|
4958
|
-
<dialog [title]="title" #dialog>
|
|
4959
|
-
@if(title) {
|
|
4960
|
-
<h5 class="modal-title">{{title}}</h5>
|
|
4961
|
-
}
|
|
4962
|
-
<form name="prompt" novalidate [formGroup]="form">
|
|
4963
|
-
<div class="mb-3 sq-form-group">
|
|
4964
|
-
<label class="form-label" for="input">{{model().message}}</label>
|
|
4965
|
-
@if(!model().rowCount) {
|
|
4966
|
-
<input type="text" class="form-control" id="input" formControlName="input" spellcheck="off">
|
|
4967
|
-
}
|
|
4968
|
-
@if(!!model().rowCount) {
|
|
4969
|
-
<textarea type="text" class="form-control" id="input" formControlName="input" spellcheck="on" rows="{{model().rowCount}}"></textarea>
|
|
4970
|
-
}
|
|
4971
|
-
</div>
|
|
4972
|
-
</form>
|
|
4973
|
-
<section class="flex justify-end gap-2 mt-4">
|
|
4974
|
-
<button class="btn btn-ghost outline-none w-24" (click)="dialog.close()">
|
|
4975
|
-
Cancel
|
|
4976
|
-
</button>
|
|
4977
|
-
|
|
4978
|
-
<button class="btn btn-primary w-24">
|
|
4979
|
-
OK
|
|
4980
|
-
</button>
|
|
4981
|
-
</section>
|
|
4982
|
-
</dialog>
|
|
4983
|
-
`,
|
|
4984
|
-
standalone: true,
|
|
4985
|
-
imports: [CommonModule, ReactiveFormsModule],
|
|
4986
|
-
}]
|
|
4987
|
-
}], ctorParameters: () => [{ type: i2.UntypedFormBuilder }] });
|
|
4988
|
-
|
|
4989
5058
|
class DocumentsUploadService {
|
|
4990
5059
|
constructor() {
|
|
4991
|
-
|
|
5060
|
+
this.REQUEST_URL = "api/v1/plugin/SinequaAssistantREST";
|
|
5061
|
+
/** Documents upload configuration. */
|
|
4992
5062
|
this.uploadConfig$ = new BehaviorSubject(undefined);
|
|
5063
|
+
/** Emit the list of indexed documents */
|
|
5064
|
+
this.uploadedDocuments$ = new BehaviorSubject([]);
|
|
4993
5065
|
this.appService = inject(AppService);
|
|
4994
5066
|
this.http = inject(HttpClient);
|
|
4995
5067
|
}
|
|
4996
5068
|
/**
|
|
4997
|
-
* Initializes the file upload service
|
|
4998
|
-
*
|
|
4999
|
-
* @param chatService - An instance of ChatService. If not provided, an error is thrown.
|
|
5000
|
-
* @throws {Error} If the chatService instance is not provided or if there is an error during initialization.
|
|
5069
|
+
* Initializes the file upload service.
|
|
5001
5070
|
*/
|
|
5002
|
-
init(
|
|
5003
|
-
if (!chatService)
|
|
5004
|
-
throw new Error('A chatService instance must be provided');
|
|
5005
|
-
this.chatService = chatService;
|
|
5071
|
+
init() {
|
|
5006
5072
|
try {
|
|
5007
|
-
this.getRequestsUrl();
|
|
5008
5073
|
this.getUploadConfig();
|
|
5009
5074
|
}
|
|
5010
5075
|
catch (error) {
|
|
5011
5076
|
throw new Error(error);
|
|
5012
5077
|
}
|
|
5013
5078
|
}
|
|
5014
|
-
/**
|
|
5015
|
-
* Fetch the endpoint to use for the file upload related requests
|
|
5016
|
-
* @throws {Error} If the property 'restEndpoint' is not provided in the assistant configuration
|
|
5017
|
-
*/
|
|
5018
|
-
getRequestsUrl() {
|
|
5019
|
-
if (!!this.chatService.assistantConfig$.value.connectionSettings.restEndpoint) {
|
|
5020
|
-
this.REQUEST_URL = this.chatService.assistantConfig$.value.connectionSettings.restEndpoint;
|
|
5021
|
-
}
|
|
5022
|
-
else {
|
|
5023
|
-
throw new Error(`The property 'restEndpoint' must be provided when attempting to use 'REST' in assistant instance`);
|
|
5024
|
-
}
|
|
5025
|
-
}
|
|
5026
5079
|
/**
|
|
5027
5080
|
* Retrieves the upload configuration for documents.
|
|
5028
5081
|
* The response, which contains the upload configuration, is emitted to the `uploadConfig$` observable.
|
|
@@ -5032,10 +5085,9 @@ class DocumentsUploadService {
|
|
|
5032
5085
|
getUploadConfig() {
|
|
5033
5086
|
const data = {
|
|
5034
5087
|
action: "documentsUploadConfigGet",
|
|
5035
|
-
appName: this.appService.appName
|
|
5036
|
-
debug: this.chatService.assistantConfig$.value.defaultValues.debug
|
|
5088
|
+
appName: this.appService.appName
|
|
5037
5089
|
};
|
|
5038
|
-
from(post(
|
|
5090
|
+
from(post(this.REQUEST_URL, data)).pipe(take$1(1), catchError$1((error) => {
|
|
5039
5091
|
throw new Error(`Error invoking documentsUploadConfigGet: ${error}`);
|
|
5040
5092
|
})).subscribe((res) => this.uploadConfig$.next(res));
|
|
5041
5093
|
}
|
|
@@ -5100,8 +5152,7 @@ class DocumentsUploadService {
|
|
|
5100
5152
|
// Add the required "data" field as a JSON string
|
|
5101
5153
|
const data = {
|
|
5102
5154
|
action: "documentsupload",
|
|
5103
|
-
appName: this.appService.appName
|
|
5104
|
-
debug: this.chatService.assistantConfig$.value.defaultValues.debug
|
|
5155
|
+
appName: this.appService.appName
|
|
5105
5156
|
};
|
|
5106
5157
|
formData.append('data', JSON.stringify(data));
|
|
5107
5158
|
let headers = new HttpHeaders({ 'Accept': 'application/json' });
|
|
@@ -5115,7 +5166,7 @@ class DocumentsUploadService {
|
|
|
5115
5166
|
};
|
|
5116
5167
|
if (enableProgress)
|
|
5117
5168
|
options['reportProgress'] = true;
|
|
5118
|
-
const url = `${globalConfig.backendUrl}/${
|
|
5169
|
+
const url = `${globalConfig.backendUrl}/${this.REQUEST_URL}`;
|
|
5119
5170
|
/**
|
|
5120
5171
|
* Need to use the HttpClient directly to avoid the JSONMethodPluginService's behavior
|
|
5121
5172
|
* because it is altering the request and thus making it unable to properly set the Content-Type header with the boundary
|
|
@@ -5156,10 +5207,9 @@ class DocumentsUploadService {
|
|
|
5156
5207
|
const data = {
|
|
5157
5208
|
action: "documentsUploadStatus",
|
|
5158
5209
|
appName: this.appService.appName,
|
|
5159
|
-
statusToken: token
|
|
5160
|
-
debug: this.chatService.assistantConfig$.value.defaultValues.debug
|
|
5210
|
+
statusToken: token
|
|
5161
5211
|
};
|
|
5162
|
-
return from(post(
|
|
5212
|
+
return from(post(this.REQUEST_URL, data)).pipe(catchError$1((error) => {
|
|
5163
5213
|
throw new Error(`Error invoking documentsUploadStatus: ${error}`);
|
|
5164
5214
|
}));
|
|
5165
5215
|
}
|
|
@@ -5188,8 +5238,7 @@ class DocumentsUploadService {
|
|
|
5188
5238
|
getDocumentsList(columns, skip, count) {
|
|
5189
5239
|
const data = {
|
|
5190
5240
|
action: "documentsList",
|
|
5191
|
-
appName: this.appService.appName
|
|
5192
|
-
debug: this.chatService.assistantConfig$.value.defaultValues.debug
|
|
5241
|
+
appName: this.appService.appName
|
|
5193
5242
|
};
|
|
5194
5243
|
if (columns)
|
|
5195
5244
|
data["columns"] = columns;
|
|
@@ -5197,7 +5246,7 @@ class DocumentsUploadService {
|
|
|
5197
5246
|
data["skip"] = skip;
|
|
5198
5247
|
if (count)
|
|
5199
5248
|
data["count"] = count;
|
|
5200
|
-
return from(post(
|
|
5249
|
+
return from(post(this.REQUEST_URL, data)).pipe(tap((res) => this.uploadedDocuments$.next(res.docs)), catchError$1((error) => {
|
|
5201
5250
|
throw new Error(`Error invoking documentsList: ${error}`);
|
|
5202
5251
|
}));
|
|
5203
5252
|
}
|
|
@@ -5215,10 +5264,9 @@ class DocumentsUploadService {
|
|
|
5215
5264
|
const data = {
|
|
5216
5265
|
action: "documentsDelete",
|
|
5217
5266
|
docIds,
|
|
5218
|
-
appName: this.appService.appName
|
|
5219
|
-
debug: this.chatService.assistantConfig$.value.defaultValues.debug
|
|
5267
|
+
appName: this.appService.appName
|
|
5220
5268
|
};
|
|
5221
|
-
return from(post(
|
|
5269
|
+
return from(post(this.REQUEST_URL, data)).pipe(catchError$1((error) => {
|
|
5222
5270
|
throw new Error(`Error invoking documentsDelete: ${error}`);
|
|
5223
5271
|
}));
|
|
5224
5272
|
}
|
|
@@ -5234,10 +5282,9 @@ class DocumentsUploadService {
|
|
|
5234
5282
|
deleteAllDocuments() {
|
|
5235
5283
|
const data = {
|
|
5236
5284
|
action: "documentsDeleteAll",
|
|
5237
|
-
appName: this.appService.appName
|
|
5238
|
-
debug: this.chatService.assistantConfig$.value.defaultValues.debug
|
|
5285
|
+
appName: this.appService.appName
|
|
5239
5286
|
};
|
|
5240
|
-
return from(post(
|
|
5287
|
+
return from(post(this.REQUEST_URL, data)).pipe(catchError$1((error) => {
|
|
5241
5288
|
throw new Error(`Error invoking documentsDeleteAll: ${error}`);
|
|
5242
5289
|
}));
|
|
5243
5290
|
}
|
|
@@ -5265,10 +5312,13 @@ class DocumentsUploadService {
|
|
|
5265
5312
|
return bytes / (1024 * 1024);
|
|
5266
5313
|
}
|
|
5267
5314
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DocumentsUploadService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
5268
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DocumentsUploadService }); }
|
|
5315
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DocumentsUploadService, providedIn: 'root' }); }
|
|
5269
5316
|
}
|
|
5270
5317
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DocumentsUploadService, decorators: [{
|
|
5271
|
-
type: Injectable
|
|
5318
|
+
type: Injectable,
|
|
5319
|
+
args: [{
|
|
5320
|
+
providedIn: 'root'
|
|
5321
|
+
}]
|
|
5272
5322
|
}] });
|
|
5273
5323
|
|
|
5274
5324
|
class DocumentUploadComponent {
|
|
@@ -5294,13 +5344,13 @@ class DocumentUploadComponent {
|
|
|
5294
5344
|
this.uploading$ = new BehaviorSubject(false);
|
|
5295
5345
|
this.uploadingInfos$ = new BehaviorSubject(undefined);
|
|
5296
5346
|
this._subscription = new Subscription();
|
|
5297
|
-
this.instanceManagerService = inject(InstanceManagerService);
|
|
5298
5347
|
this.documentsUploadService = inject(DocumentsUploadService);
|
|
5299
5348
|
this.notificationsService = inject(NotificationsService);
|
|
5349
|
+
this.appService = inject(AppService);
|
|
5300
5350
|
this.transloco = inject(TranslocoService);
|
|
5301
5351
|
}
|
|
5302
5352
|
ngOnInit() {
|
|
5303
|
-
this._subscription.add(of(isAuthenticated()).pipe(
|
|
5353
|
+
this._subscription.add(of(isAuthenticated()).pipe(switchMap((_) => this.appService.init()), tap((_) => this.documentsUploadService.init()), catchError$1((error) => {
|
|
5304
5354
|
console.error(error);
|
|
5305
5355
|
this.notificationsService.error(error);
|
|
5306
5356
|
return EMPTY;
|
|
@@ -5323,9 +5373,6 @@ class DocumentUploadComponent {
|
|
|
5323
5373
|
ngOnDestroy() {
|
|
5324
5374
|
this._subscription.unsubscribe();
|
|
5325
5375
|
}
|
|
5326
|
-
instantiateChatService() {
|
|
5327
|
-
this.chatService = this.instanceManagerService.getInstance(this.instanceId);
|
|
5328
|
-
}
|
|
5329
5376
|
/**
|
|
5330
5377
|
* Handles the submission of files.
|
|
5331
5378
|
*
|
|
@@ -5475,11 +5522,14 @@ class DocumentUploadComponent {
|
|
|
5475
5522
|
this.indexing$.next(true);
|
|
5476
5523
|
// Combine immediate API call with interval-based polling
|
|
5477
5524
|
this._subscription.add(interval(this.pollingInterval).pipe(startWith(0), // Trigger the API call immediately
|
|
5478
|
-
switchMap(() => this.documentsUploadService.getIndexingStatus(token)), tap((res) => this.indexingInfos$.next(res)), takeWhile((response) => !response.isCompleted, true),
|
|
5525
|
+
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.
|
|
5526
|
+
catchError$1((err) => {
|
|
5479
5527
|
console.error(err);
|
|
5480
5528
|
this.notificationsService.error(this.transloco.translate('chatDocumentsUpload.errorIndexingStatus'));
|
|
5481
5529
|
return EMPTY;
|
|
5482
5530
|
}), finalize$1(() => {
|
|
5531
|
+
// Refresh the list of uploaded documents at the end of indexing
|
|
5532
|
+
this.documentsUploadService.getDocumentsList().pipe(take$1(1)).subscribe();
|
|
5483
5533
|
// Clear the indexing flags
|
|
5484
5534
|
this.indexing$.next(false);
|
|
5485
5535
|
this.indexingInfos$.next(undefined);
|
|
@@ -5500,14 +5550,12 @@ class DocumentUploadComponent {
|
|
|
5500
5550
|
return completed / total;
|
|
5501
5551
|
}
|
|
5502
5552
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DocumentUploadComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
5503
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: DocumentUploadComponent, isStandalone: true, selector: "sq-document-upload", inputs: {
|
|
5553
|
+
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" }] }); }
|
|
5504
5554
|
}
|
|
5505
5555
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DocumentUploadComponent, decorators: [{
|
|
5506
5556
|
type: Component,
|
|
5507
|
-
args: [{ selector: "sq-document-upload", standalone: true, providers: [
|
|
5508
|
-
}], propDecorators: {
|
|
5509
|
-
type: Input
|
|
5510
|
-
}], pollingInterval: [{
|
|
5557
|
+
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"] }]
|
|
5558
|
+
}], propDecorators: { pollingInterval: [{
|
|
5511
5559
|
type: Input
|
|
5512
5560
|
}], flow: [{
|
|
5513
5561
|
type: ViewChild,
|
|
@@ -5519,14 +5567,17 @@ class DocumentListComponent {
|
|
|
5519
5567
|
this.groupedUploadedDocuments$ = new BehaviorSubject([]);
|
|
5520
5568
|
this.deletingAll = false;
|
|
5521
5569
|
this._subscription = new Subscription();
|
|
5522
|
-
this.instanceManagerService = inject(InstanceManagerService);
|
|
5523
5570
|
this.documentsUploadService = inject(DocumentsUploadService);
|
|
5524
5571
|
this.notificationsService = inject(NotificationsService);
|
|
5572
|
+
this.appService = inject(AppService);
|
|
5525
5573
|
this.transloco = inject(TranslocoService);
|
|
5526
5574
|
this.assistantUtils = inject(AssistantUtils);
|
|
5527
5575
|
}
|
|
5528
5576
|
ngOnInit() {
|
|
5529
|
-
this._subscription.add(of(isAuthenticated()).pipe(
|
|
5577
|
+
this._subscription.add(of(isAuthenticated()).pipe(switchMap((_) => this.appService.init()), tap((_) => {
|
|
5578
|
+
this.onUpdateUploadedDocumentsList();
|
|
5579
|
+
this.documentsUploadService.getDocumentsList();
|
|
5580
|
+
}), catchError$1((error) => {
|
|
5530
5581
|
console.error(error);
|
|
5531
5582
|
this.notificationsService.error(error);
|
|
5532
5583
|
return EMPTY;
|
|
@@ -5536,26 +5587,23 @@ class DocumentListComponent {
|
|
|
5536
5587
|
ngOnDestroy() {
|
|
5537
5588
|
this._subscription.unsubscribe();
|
|
5538
5589
|
}
|
|
5539
|
-
instantiateChatService() {
|
|
5540
|
-
this.chatService = this.instanceManagerService.getInstance(this.instanceId);
|
|
5541
|
-
}
|
|
5542
5590
|
/**
|
|
5543
5591
|
* Updates the list of uploaded documents by fetching the latest data from the service.
|
|
5544
5592
|
* The fetched documents are grouped by date.
|
|
5545
5593
|
*
|
|
5546
5594
|
* @returns {void}
|
|
5547
5595
|
*/
|
|
5548
|
-
|
|
5596
|
+
onUpdateUploadedDocumentsList() {
|
|
5549
5597
|
this._subscription.add(combineLatest([
|
|
5550
|
-
this.documentsUploadService.
|
|
5598
|
+
this.documentsUploadService.uploadedDocuments$,
|
|
5551
5599
|
this.transloco.langChanges$
|
|
5552
5600
|
]).pipe(tap(([uploadedDocuments]) => {
|
|
5553
|
-
this.groupedUploadedDocuments$.next(this._groupUploadedDocumentsByDate(uploadedDocuments
|
|
5601
|
+
this.groupedUploadedDocuments$.next(this._groupUploadedDocumentsByDate(uploadedDocuments));
|
|
5554
5602
|
}), catchError$1((error) => {
|
|
5555
5603
|
console.error(error);
|
|
5556
5604
|
this.notificationsService.error(error);
|
|
5557
5605
|
return EMPTY;
|
|
5558
|
-
})
|
|
5606
|
+
}))
|
|
5559
5607
|
.subscribe());
|
|
5560
5608
|
}
|
|
5561
5609
|
deleteDocument(event, doc) {
|
|
@@ -5581,8 +5629,7 @@ class DocumentListComponent {
|
|
|
5581
5629
|
.pipe(tap(() => {
|
|
5582
5630
|
this.notificationsService.success(this.transloco.translate('chatDocumentsUpload.deleteDocumentSuccess', { title: this.documentToDelete.fileName }));
|
|
5583
5631
|
this.documentToDelete = undefined;
|
|
5584
|
-
|
|
5585
|
-
}), catchError$1((error) => {
|
|
5632
|
+
}), switchMap(() => this.documentsUploadService.getDocumentsList()), catchError$1((error) => {
|
|
5586
5633
|
console.error(error);
|
|
5587
5634
|
this.notificationsService.error(this.transloco.translate('chatDocumentsUpload.deleteDocumentError', { title: this.documentToDelete.fileName }));
|
|
5588
5635
|
return EMPTY;
|
|
@@ -5611,8 +5658,7 @@ class DocumentListComponent {
|
|
|
5611
5658
|
.pipe(tap(() => {
|
|
5612
5659
|
this.deletingAll = false;
|
|
5613
5660
|
this.notificationsService.success(this.transloco.translate('chatDocumentsUpload.deleteAllDocumentsSuccess'));
|
|
5614
|
-
|
|
5615
|
-
}), catchError$1((error) => {
|
|
5661
|
+
}), switchMap(() => this.documentsUploadService.getDocumentsList()), catchError$1((error) => {
|
|
5616
5662
|
console.error(error);
|
|
5617
5663
|
this.notificationsService.error(this.transloco.translate('chatDocumentsUpload.deleteAllDocumentsError'));
|
|
5618
5664
|
return EMPTY;
|
|
@@ -5620,6 +5666,9 @@ class DocumentListComponent {
|
|
|
5620
5666
|
.subscribe());
|
|
5621
5667
|
}
|
|
5622
5668
|
_groupUploadedDocumentsByDate(docs) {
|
|
5669
|
+
if (!docs || docs.length === 0) {
|
|
5670
|
+
return [];
|
|
5671
|
+
}
|
|
5623
5672
|
const groupedUploadedDocuments = new Map();
|
|
5624
5673
|
docs
|
|
5625
5674
|
.sort((a, b) => parseISO(b.indexationTime).getTime() - parseISO(a.indexationTime).getTime())
|
|
@@ -5634,28 +5683,24 @@ class DocumentListComponent {
|
|
|
5634
5683
|
;
|
|
5635
5684
|
}
|
|
5636
5685
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DocumentListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
5637
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: DocumentListComponent, isStandalone: true, selector: "sq-document-list",
|
|
5686
|
+
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" }] }); }
|
|
5638
5687
|
}
|
|
5639
5688
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DocumentListComponent, decorators: [{
|
|
5640
5689
|
type: Component,
|
|
5641
|
-
args: [{ selector: "sq-document-list", standalone: true, providers: [
|
|
5642
|
-
}]
|
|
5643
|
-
type: Input
|
|
5644
|
-
}] } });
|
|
5690
|
+
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"] }]
|
|
5691
|
+
}] });
|
|
5645
5692
|
|
|
5646
5693
|
class DocumentOverviewComponent {
|
|
5647
5694
|
constructor() {
|
|
5648
5695
|
this.disabledUpload = true;
|
|
5649
5696
|
this.onUpload = new EventEmitter();
|
|
5650
|
-
this.uploadedDocuments$ = new BehaviorSubject([]);
|
|
5651
5697
|
this._subscription = new Subscription();
|
|
5652
|
-
this.instanceManagerService = inject(InstanceManagerService);
|
|
5653
5698
|
this.documentsUploadService = inject(DocumentsUploadService);
|
|
5654
5699
|
this.notificationsService = inject(NotificationsService);
|
|
5700
|
+
this.appService = inject(AppService);
|
|
5655
5701
|
}
|
|
5656
|
-
;
|
|
5657
5702
|
ngOnInit() {
|
|
5658
|
-
this._subscription.add(of(isAuthenticated()).pipe(
|
|
5703
|
+
this._subscription.add(of(isAuthenticated()).pipe(switchMap((_) => this.appService.init()), tap((_) => this.documentsUploadService.getDocumentsList()), catchError$1((error) => {
|
|
5659
5704
|
console.error(error);
|
|
5660
5705
|
this.notificationsService.error(error);
|
|
5661
5706
|
return EMPTY;
|
|
@@ -5665,42 +5710,412 @@ class DocumentOverviewComponent {
|
|
|
5665
5710
|
ngOnDestroy() {
|
|
5666
5711
|
this._subscription.unsubscribe();
|
|
5667
5712
|
}
|
|
5668
|
-
instantiateChatService() {
|
|
5669
|
-
this.chatService = this.instanceManagerService.getInstance(this.instanceId);
|
|
5670
|
-
}
|
|
5671
|
-
/**
|
|
5672
|
-
* Updates the list of uploaded documents by fetching the latest data from the service.
|
|
5673
|
-
*
|
|
5674
|
-
* @returns {void}
|
|
5675
|
-
*/
|
|
5676
|
-
updateUploadedDocumentsList() {
|
|
5677
|
-
this._subscription.add(this.documentsUploadService.getDocumentsList()
|
|
5678
|
-
.pipe(tap((uploadedDocuments) => {
|
|
5679
|
-
this.uploadedDocuments$.next(uploadedDocuments.docs);
|
|
5680
|
-
}), catchError$1((error) => {
|
|
5681
|
-
console.error(error);
|
|
5682
|
-
this.notificationsService.error(error);
|
|
5683
|
-
return EMPTY;
|
|
5684
|
-
}), take$1(1))
|
|
5685
|
-
.subscribe());
|
|
5686
|
-
}
|
|
5687
5713
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DocumentOverviewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
5688
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: DocumentOverviewComponent, isStandalone: true, selector: "sq-document-overview", inputs: {
|
|
5714
|
+
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" }] }); }
|
|
5689
5715
|
}
|
|
5690
5716
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DocumentOverviewComponent, decorators: [{
|
|
5691
5717
|
type: Component,
|
|
5692
|
-
args: [{ selector: "sq-document-overview", standalone: true, providers: [
|
|
5693
|
-
}], propDecorators: {
|
|
5694
|
-
type: Input
|
|
5695
|
-
}], disabledUpload: [{
|
|
5718
|
+
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"] }]
|
|
5719
|
+
}], propDecorators: { disabledUpload: [{
|
|
5696
5720
|
type: Input
|
|
5697
5721
|
}], onUpload: [{
|
|
5698
5722
|
type: Output
|
|
5699
5723
|
}] } });
|
|
5700
5724
|
|
|
5725
|
+
class CopyToClipboardDirective {
|
|
5726
|
+
constructor() {
|
|
5727
|
+
this.el = inject((ElementRef));
|
|
5728
|
+
this.text = input("");
|
|
5729
|
+
}
|
|
5730
|
+
onClick() {
|
|
5731
|
+
if (!this.text()) {
|
|
5732
|
+
return;
|
|
5733
|
+
}
|
|
5734
|
+
// The text is encoded from the markdown-it plugin, so we decode it first
|
|
5735
|
+
const decodedText = decodeURIComponent(this.text());
|
|
5736
|
+
if (navigator.clipboard && navigator.clipboard.writeText) {
|
|
5737
|
+
navigator.clipboard
|
|
5738
|
+
.writeText(decodedText)
|
|
5739
|
+
.then(() => {
|
|
5740
|
+
// Provide visual feedback to the user
|
|
5741
|
+
const originalHTML = this.el.nativeElement.innerHTML;
|
|
5742
|
+
this.el.nativeElement.innerHTML =
|
|
5743
|
+
'<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>';
|
|
5744
|
+
setTimeout(() => {
|
|
5745
|
+
this.el.nativeElement.innerHTML = originalHTML;
|
|
5746
|
+
}, 2000);
|
|
5747
|
+
})
|
|
5748
|
+
.catch((err) => {
|
|
5749
|
+
console.error("Failed to copy text: ", err);
|
|
5750
|
+
});
|
|
5751
|
+
}
|
|
5752
|
+
else {
|
|
5753
|
+
// Fallback for older browsers
|
|
5754
|
+
const textarea = document.createElement("textarea");
|
|
5755
|
+
textarea.value = decodedText;
|
|
5756
|
+
textarea.style.position = "fixed"; // Prevent scrolling to bottom of page in MS Edge.
|
|
5757
|
+
textarea.style.opacity = "0";
|
|
5758
|
+
document.body.appendChild(textarea);
|
|
5759
|
+
textarea.focus();
|
|
5760
|
+
textarea.select();
|
|
5761
|
+
try {
|
|
5762
|
+
document.execCommand("copy");
|
|
5763
|
+
// Provide visual feedback to the user
|
|
5764
|
+
const originalHTML = this.el.nativeElement.innerHTML;
|
|
5765
|
+
this.el.nativeElement.innerHTML =
|
|
5766
|
+
'<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>';
|
|
5767
|
+
setTimeout(() => {
|
|
5768
|
+
this.el.nativeElement.innerHTML = originalHTML;
|
|
5769
|
+
}, 2000);
|
|
5770
|
+
}
|
|
5771
|
+
catch (err) {
|
|
5772
|
+
console.error("Fallback: Oops, unable to copy", err);
|
|
5773
|
+
}
|
|
5774
|
+
document.body.removeChild(textarea);
|
|
5775
|
+
}
|
|
5776
|
+
}
|
|
5777
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CopyToClipboardDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
5778
|
+
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 }); }
|
|
5779
|
+
}
|
|
5780
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CopyToClipboardDirective, decorators: [{
|
|
5781
|
+
type: Directive,
|
|
5782
|
+
args: [{
|
|
5783
|
+
selector: "[copy-to-clipboard]",
|
|
5784
|
+
standalone: true,
|
|
5785
|
+
host: {
|
|
5786
|
+
"(click)": "onClick()",
|
|
5787
|
+
},
|
|
5788
|
+
}]
|
|
5789
|
+
}] });
|
|
5790
|
+
|
|
5791
|
+
/*
|
|
5792
|
+
* Web Element Reference Component
|
|
5793
|
+
* This component is used to display a reference in the chat interface.
|
|
5794
|
+
* It uses a tooltip to show additional information about the reference.
|
|
5795
|
+
* The component emits custom events when the user interacts with it.
|
|
5796
|
+
*
|
|
5797
|
+
* This component is based on the remark template.
|
|
5798
|
+
*
|
|
5799
|
+
* <!-- Chat reference (badge with file and part number) -->
|
|
5800
|
+
* <ng-template remarkTemplate="chat-reference" let-ref>
|
|
5801
|
+
* @let attachment = referenceMap.get(ref.refId);
|
|
5802
|
+
* @if (attachment) {
|
|
5803
|
+
* <a
|
|
5804
|
+
* class="reference"
|
|
5805
|
+
* role="button"
|
|
5806
|
+
* [sqTooltip]="attachment"
|
|
5807
|
+
* [sqTooltipTemplate]="tooltipTpl"
|
|
5808
|
+
* [hoverableTooltip]="true"
|
|
5809
|
+
* (click)="openAttachmentPreview(attachment, ref.refId)"
|
|
5810
|
+
* >
|
|
5811
|
+
* {{ref.refId}}
|
|
5812
|
+
* </a>
|
|
5813
|
+
* }
|
|
5814
|
+
* @else {
|
|
5815
|
+
* <ng-template #staticRefTpl>
|
|
5816
|
+
* <span class="reference">{{ ref.refId }}</span>
|
|
5817
|
+
* </ng-template>
|
|
5818
|
+
* }
|
|
5819
|
+
* </ng-template>
|
|
5820
|
+
*/
|
|
5821
|
+
class ReferenceComponent {
|
|
5822
|
+
constructor() {
|
|
5823
|
+
this.ref = signal({});
|
|
5824
|
+
afterNextRender(() => {
|
|
5825
|
+
const obj = JSON.parse(decodeURIComponent(atob(this.attachment)));
|
|
5826
|
+
this.ref.set(obj);
|
|
5827
|
+
});
|
|
5828
|
+
}
|
|
5829
|
+
onOpenPreview(attachment, partId) {
|
|
5830
|
+
// Émettre un événement personnalisé pour le web element using the service
|
|
5831
|
+
dispatchEvent(new CustomEvent("onOpenPreview", {
|
|
5832
|
+
detail: { reference: attachment, partId: partId || this.id },
|
|
5833
|
+
}));
|
|
5834
|
+
}
|
|
5835
|
+
onOpenDocument(attachment, partId) {
|
|
5836
|
+
// Émettre un événement personnalisé pour le web element using the service
|
|
5837
|
+
dispatchEvent(new CustomEvent("onOpenDocument", {
|
|
5838
|
+
detail: { reference: attachment, partId: partId || this.id },
|
|
5839
|
+
}));
|
|
5840
|
+
}
|
|
5841
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ReferenceComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
5842
|
+
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: [], ngImport: i0, template: `
|
|
5843
|
+
<a
|
|
5844
|
+
class="reference"
|
|
5845
|
+
role="button"
|
|
5846
|
+
[sqTooltip]="ref()"
|
|
5847
|
+
[sqTooltipTemplate]="tooltipTpl"
|
|
5848
|
+
[hoverableTooltip]="true"
|
|
5849
|
+
(click)="onOpenPreview(ref())"
|
|
5850
|
+
>{{ id }}</a>
|
|
5851
|
+
|
|
5852
|
+
<!-- tooltip template -->
|
|
5853
|
+
<ng-template #tooltipTpl>
|
|
5854
|
+
<sq-chat-reference
|
|
5855
|
+
class="expanded"
|
|
5856
|
+
[attachment]="ref()"
|
|
5857
|
+
[reference]="ref().contextId"
|
|
5858
|
+
[partId]="ref().$partId"
|
|
5859
|
+
(openPreview)="onOpenPreview($event, $event.$partId)"
|
|
5860
|
+
(openDocument)="onOpenDocument($event, $event.$partId)"
|
|
5861
|
+
></sq-chat-reference>
|
|
5862
|
+
</ng-template>
|
|
5863
|
+
`, 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"] }] }); }
|
|
5864
|
+
}
|
|
5865
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ReferenceComponent, decorators: [{
|
|
5866
|
+
type: Component,
|
|
5867
|
+
args: [{ selector: "reference", imports: [TooltipDirective, ChatReferenceComponent], providers: [], template: `
|
|
5868
|
+
<a
|
|
5869
|
+
class="reference"
|
|
5870
|
+
role="button"
|
|
5871
|
+
[sqTooltip]="ref()"
|
|
5872
|
+
[sqTooltipTemplate]="tooltipTpl"
|
|
5873
|
+
[hoverableTooltip]="true"
|
|
5874
|
+
(click)="onOpenPreview(ref())"
|
|
5875
|
+
>{{ id }}</a>
|
|
5876
|
+
|
|
5877
|
+
<!-- tooltip template -->
|
|
5878
|
+
<ng-template #tooltipTpl>
|
|
5879
|
+
<sq-chat-reference
|
|
5880
|
+
class="expanded"
|
|
5881
|
+
[attachment]="ref()"
|
|
5882
|
+
[reference]="ref().contextId"
|
|
5883
|
+
[partId]="ref().$partId"
|
|
5884
|
+
(openPreview)="onOpenPreview($event, $event.$partId)"
|
|
5885
|
+
(openDocument)="onOpenDocument($event, $event.$partId)"
|
|
5886
|
+
></sq-chat-reference>
|
|
5887
|
+
</ng-template>
|
|
5888
|
+
`, standalone: true, styles: ["div{border:1px solid #ccc;padding:8px;border-radius:4px;display:flex;gap:8px;flex-direction:column}\n"] }]
|
|
5889
|
+
}], ctorParameters: () => [], propDecorators: { id: [{
|
|
5890
|
+
type: Input
|
|
5891
|
+
}], attachment: [{
|
|
5892
|
+
type: Input
|
|
5893
|
+
}], rank: [{
|
|
5894
|
+
type: Input
|
|
5895
|
+
}] } });
|
|
5896
|
+
class PageReferenceComponent {
|
|
5897
|
+
constructor() {
|
|
5898
|
+
this.ref = signal({});
|
|
5899
|
+
afterNextRender(() => {
|
|
5900
|
+
const obj = JSON.parse(decodeURIComponent(atob(this.attachment)));
|
|
5901
|
+
this.ref.set(obj);
|
|
5902
|
+
});
|
|
5903
|
+
}
|
|
5904
|
+
onOpenPreview(attachment, partId) {
|
|
5905
|
+
// Émettre un événement personnalisé pour le web element using the service
|
|
5906
|
+
dispatchEvent(new CustomEvent("onOpenPreview", {
|
|
5907
|
+
detail: { reference: attachment, partId: partId || this.id },
|
|
5908
|
+
}));
|
|
5909
|
+
}
|
|
5910
|
+
onOpenDocument(attachment, partId) {
|
|
5911
|
+
// Émettre un événement personnalisé pour le web element using the service
|
|
5912
|
+
dispatchEvent(new CustomEvent("onOpenDocument", {
|
|
5913
|
+
detail: { reference: attachment, partId: partId || this.id },
|
|
5914
|
+
}));
|
|
5915
|
+
}
|
|
5916
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PageReferenceComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
5917
|
+
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: [], ngImport: i0, template: `
|
|
5918
|
+
<span
|
|
5919
|
+
class="reference"
|
|
5920
|
+
[sqTooltip]="{ obj: ref(), id }"
|
|
5921
|
+
[sqTooltipTemplate]="pageTooltipTpl"
|
|
5922
|
+
[hoverableTooltip]="true"
|
|
5923
|
+
>
|
|
5924
|
+
Page-{{ id }}
|
|
5925
|
+
</span>
|
|
5926
|
+
<ng-template #pageTooltipTpl let-ref>
|
|
5927
|
+
<InlinePageReference
|
|
5928
|
+
style="max-width: 30vw;"
|
|
5929
|
+
[id]="ref.id"
|
|
5930
|
+
[ref]="ref.obj"
|
|
5931
|
+
(openPreview)="onOpenPreview($event, $event.$partId)"
|
|
5932
|
+
(openDocument)="onOpenPreview($event, $event.$partId)"
|
|
5933
|
+
/>
|
|
5934
|
+
</ng-template>
|
|
5935
|
+
`, 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"] }] }); }
|
|
5936
|
+
}
|
|
5937
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PageReferenceComponent, decorators: [{
|
|
5938
|
+
type: Component,
|
|
5939
|
+
args: [{ selector: "page-reference", imports: [TooltipDirective, InlinePageReferenceComponent], providers: [], template: `
|
|
5940
|
+
<span
|
|
5941
|
+
class="reference"
|
|
5942
|
+
[sqTooltip]="{ obj: ref(), id }"
|
|
5943
|
+
[sqTooltipTemplate]="pageTooltipTpl"
|
|
5944
|
+
[hoverableTooltip]="true"
|
|
5945
|
+
>
|
|
5946
|
+
Page-{{ id }}
|
|
5947
|
+
</span>
|
|
5948
|
+
<ng-template #pageTooltipTpl let-ref>
|
|
5949
|
+
<InlinePageReference
|
|
5950
|
+
style="max-width: 30vw;"
|
|
5951
|
+
[id]="ref.id"
|
|
5952
|
+
[ref]="ref.obj"
|
|
5953
|
+
(openPreview)="onOpenPreview($event, $event.$partId)"
|
|
5954
|
+
(openDocument)="onOpenPreview($event, $event.$partId)"
|
|
5955
|
+
/>
|
|
5956
|
+
</ng-template>
|
|
5957
|
+
`, standalone: true, styles: ["div{border:1px solid #ccc;padding:8px;border-radius:4px;display:flex;gap:8px;flex-direction:column}\n"] }]
|
|
5958
|
+
}], ctorParameters: () => [], propDecorators: { id: [{
|
|
5959
|
+
type: Input
|
|
5960
|
+
}], attachment: [{
|
|
5961
|
+
type: Input
|
|
5962
|
+
}] } });
|
|
5963
|
+
class ImageReferenceComponent {
|
|
5964
|
+
constructor() {
|
|
5965
|
+
this.ref = signal({});
|
|
5966
|
+
afterNextRender(() => {
|
|
5967
|
+
const obj = JSON.parse(decodeURIComponent(atob(this.attachment)));
|
|
5968
|
+
this.ref.set(obj);
|
|
5969
|
+
});
|
|
5970
|
+
}
|
|
5971
|
+
onOpenPreview(attachment, partId) {
|
|
5972
|
+
// Émettre un événement personnalisé pour le web element using the service
|
|
5973
|
+
dispatchEvent(new CustomEvent("onOpenPreview", {
|
|
5974
|
+
detail: { reference: attachment, partId: partId || this.id },
|
|
5975
|
+
}));
|
|
5976
|
+
}
|
|
5977
|
+
onOpenDocument(attachment, partId) {
|
|
5978
|
+
// Émettre un événement personnalisé pour le web element using the service
|
|
5979
|
+
dispatchEvent(new CustomEvent("onOpenDocument", {
|
|
5980
|
+
detail: { reference: attachment, partId: partId || this.id },
|
|
5981
|
+
}));
|
|
5982
|
+
}
|
|
5983
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ImageReferenceComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
5984
|
+
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: [], ngImport: i0, template: `
|
|
5985
|
+
<span
|
|
5986
|
+
class="reference"
|
|
5987
|
+
[sqTooltip]="{ obj: ref(), id }"
|
|
5988
|
+
[sqTooltipTemplate]="imageTooltipTpl"
|
|
5989
|
+
[hoverableTooltip]="true"
|
|
5990
|
+
>
|
|
5991
|
+
Img-{{ this.id }}
|
|
5992
|
+
</span>
|
|
5993
|
+
<ng-template #imageTooltipTpl let-ref>
|
|
5994
|
+
<InlineImageReference
|
|
5995
|
+
style="max-width: 30vw;"
|
|
5996
|
+
[id]="ref.id"
|
|
5997
|
+
[ref]="ref.obj"
|
|
5998
|
+
(openPreview)="onOpenPreview($event, $event.$partId)"
|
|
5999
|
+
(openDocument)="onOpenDocument($event, $event.$partId)"
|
|
6000
|
+
/>
|
|
6001
|
+
</ng-template>
|
|
6002
|
+
`, 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"] }] }); }
|
|
6003
|
+
}
|
|
6004
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ImageReferenceComponent, decorators: [{
|
|
6005
|
+
type: Component,
|
|
6006
|
+
args: [{ selector: "image-reference", imports: [TooltipDirective, InlineImageReferenceComponent], providers: [], template: `
|
|
6007
|
+
<span
|
|
6008
|
+
class="reference"
|
|
6009
|
+
[sqTooltip]="{ obj: ref(), id }"
|
|
6010
|
+
[sqTooltipTemplate]="imageTooltipTpl"
|
|
6011
|
+
[hoverableTooltip]="true"
|
|
6012
|
+
>
|
|
6013
|
+
Img-{{ this.id }}
|
|
6014
|
+
</span>
|
|
6015
|
+
<ng-template #imageTooltipTpl let-ref>
|
|
6016
|
+
<InlineImageReference
|
|
6017
|
+
style="max-width: 30vw;"
|
|
6018
|
+
[id]="ref.id"
|
|
6019
|
+
[ref]="ref.obj"
|
|
6020
|
+
(openPreview)="onOpenPreview($event, $event.$partId)"
|
|
6021
|
+
(openDocument)="onOpenDocument($event, $event.$partId)"
|
|
6022
|
+
/>
|
|
6023
|
+
</ng-template>
|
|
6024
|
+
`, standalone: true, styles: ["div{border:1px solid #ccc;padding:8px;border-radius:4px;display:flex;gap:8px;flex-direction:column}\n"] }]
|
|
6025
|
+
}], ctorParameters: () => [], propDecorators: { id: [{
|
|
6026
|
+
type: Input
|
|
6027
|
+
}], attachment: [{
|
|
6028
|
+
type: Input
|
|
6029
|
+
}] } });
|
|
6030
|
+
class CodeBlockReferenceComponent {
|
|
6031
|
+
constructor() {
|
|
6032
|
+
this.el = inject(ElementRef);
|
|
6033
|
+
this.langname = "";
|
|
6034
|
+
this.encodeCode = '';
|
|
6035
|
+
}
|
|
6036
|
+
ngAfterViewInit() {
|
|
6037
|
+
// get the code content
|
|
6038
|
+
const codeEl = this.el.nativeElement.querySelector("code");
|
|
6039
|
+
const code = codeEl ? codeEl.textContent : "";
|
|
6040
|
+
this.encodeCode = encodeURIComponent(code);
|
|
6041
|
+
}
|
|
6042
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CodeBlockReferenceComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6043
|
+
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: `
|
|
6044
|
+
<div class="card mb-2">
|
|
6045
|
+
<div class="card-header d-flex justify-content-end align-items-center">
|
|
6046
|
+
<span class="me-auto">{{ langname || 'code'}}</span>
|
|
6047
|
+
<button class="btn btn-light btn-sm" copy-to-clipboard [text]="encodeCode">
|
|
6048
|
+
<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>
|
|
6049
|
+
</button>
|
|
6050
|
+
</div>
|
|
6051
|
+
<ng-content></ng-content>
|
|
6052
|
+
</div>
|
|
6053
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: CopyToClipboardDirective, selector: "[copy-to-clipboard]", inputs: ["text"] }] }); }
|
|
6054
|
+
}
|
|
6055
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CodeBlockReferenceComponent, decorators: [{
|
|
6056
|
+
type: Component,
|
|
6057
|
+
args: [{
|
|
6058
|
+
selector: "code-block-reference",
|
|
6059
|
+
imports: [CopyToClipboardDirective],
|
|
6060
|
+
template: `
|
|
6061
|
+
<div class="card mb-2">
|
|
6062
|
+
<div class="card-header d-flex justify-content-end align-items-center">
|
|
6063
|
+
<span class="me-auto">{{ langname || 'code'}}</span>
|
|
6064
|
+
<button class="btn btn-light btn-sm" copy-to-clipboard [text]="encodeCode">
|
|
6065
|
+
<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>
|
|
6066
|
+
</button>
|
|
6067
|
+
</div>
|
|
6068
|
+
<ng-content></ng-content>
|
|
6069
|
+
</div>
|
|
6070
|
+
`,
|
|
6071
|
+
standalone: true,
|
|
6072
|
+
}]
|
|
6073
|
+
}], propDecorators: { langname: [{
|
|
6074
|
+
type: Input
|
|
6075
|
+
}] } });
|
|
6076
|
+
|
|
6077
|
+
/**
|
|
6078
|
+
* Service to register custom elements in the Angular application.
|
|
6079
|
+
* This service is used to define custom elements that can be used in the application.
|
|
6080
|
+
* It is called through APP_INITIALIZER to ensure that custom elements are registered before the application starts.
|
|
6081
|
+
*/
|
|
6082
|
+
class CustomElementsService {
|
|
6083
|
+
constructor() {
|
|
6084
|
+
this._injector = inject(Injector);
|
|
6085
|
+
}
|
|
6086
|
+
// called through APP_INITIALIZER
|
|
6087
|
+
setupCustomElements() {
|
|
6088
|
+
const referenceElement = createCustomElement(ReferenceComponent, {
|
|
6089
|
+
injector: this._injector,
|
|
6090
|
+
});
|
|
6091
|
+
customElements.define("reference-component", referenceElement);
|
|
6092
|
+
const pageReference = createCustomElement(PageReferenceComponent, {
|
|
6093
|
+
injector: this._injector,
|
|
6094
|
+
});
|
|
6095
|
+
customElements.define("page-reference", pageReference);
|
|
6096
|
+
const imageReference = createCustomElement(ImageReferenceComponent, {
|
|
6097
|
+
injector: this._injector,
|
|
6098
|
+
});
|
|
6099
|
+
customElements.define("image-reference", imageReference);
|
|
6100
|
+
const codeReference = createCustomElement(CodeBlockReferenceComponent, {
|
|
6101
|
+
injector: this._injector,
|
|
6102
|
+
});
|
|
6103
|
+
customElements.define("code-block-reference", codeReference);
|
|
6104
|
+
}
|
|
6105
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CustomElementsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
6106
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CustomElementsService, providedIn: "root" }); }
|
|
6107
|
+
}
|
|
6108
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CustomElementsService, decorators: [{
|
|
6109
|
+
type: Injectable,
|
|
6110
|
+
args: [{ providedIn: "root" }]
|
|
6111
|
+
}] });
|
|
6112
|
+
function initializeCustomElements(customElementsService) {
|
|
6113
|
+
return () => customElementsService.setupCustomElements();
|
|
6114
|
+
}
|
|
6115
|
+
|
|
5701
6116
|
/**
|
|
5702
6117
|
* Generated bundle index. Do not edit.
|
|
5703
6118
|
*/
|
|
5704
6119
|
|
|
5705
|
-
export { ChatComponent,
|
|
6120
|
+
export { ChatComponent, ChatService, ChatSettingsV3Component, CodeBlockReferenceComponent, CustomElementsService, DocumentListComponent, DocumentOverviewComponent, DocumentUploadComponent, DocumentsUploadService, FormatIconComponent, ImageReferenceComponent, InitialsAvatarComponent, InstanceManagerService, NotificationsService, PageReferenceComponent, ReferenceComponent, SavedChatsComponent, chatConfigSchema, connectionSettingsSchema, initializeCustomElements };
|
|
5706
6121
|
//# sourceMappingURL=sinequa-assistant-chat.mjs.map
|