@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.
Files changed (69) hide show
  1. package/chat/chat-message/chat-message.component.d.ts +17 -25
  2. package/chat/chat-message/i18n/de.json +11 -0
  3. package/chat/chat-reference/chat-reference.component.d.ts +18 -8
  4. package/chat/chat-reference/i18n/de.json +4 -0
  5. package/chat/chat-settings-v3/i18n/de.json +14 -0
  6. package/chat/chat.component.d.ts +2 -1
  7. package/chat/debug-message/debug-message-details/debug-message-details.component.d.ts +2 -3
  8. package/chat/debug-message/i18n/de.json +3 -0
  9. package/chat/dialogs/i18n/de.json +19 -0
  10. package/chat/directives/copy-to-clipboard.directive.d.ts +8 -0
  11. package/chat/documents-upload/document-list/document-list.component.d.ts +4 -9
  12. package/chat/documents-upload/document-overview/document-overview.component.d.ts +3 -17
  13. package/chat/documents-upload/document-upload/document-upload.component.d.ts +3 -8
  14. package/chat/documents-upload/documents-upload.service.d.ts +7 -16
  15. package/chat/documents-upload/i18n/de.json +24 -0
  16. package/chat/i18n/de.json +42 -0
  17. package/chat/markdown-it-plugins/code-block.plugin.d.ts +2 -0
  18. package/chat/markdown-it-plugins/image-reference.plugin.d.ts +3 -0
  19. package/chat/markdown-it-plugins/link.plugin.d.ts +5 -0
  20. package/chat/markdown-it-plugins/page-reference.plugin.d.ts +3 -0
  21. package/chat/markdown-it-plugins/reference.plugin.d.ts +7 -0
  22. package/chat/public-api.d.ts +2 -1
  23. package/chat/references/i18n/de.json +6 -0
  24. package/chat/references/references.component.d.ts +43 -0
  25. package/chat/saved-chats/i18n/de.json +5 -0
  26. package/chat/services/app.service.d.ts +2 -1
  27. package/chat/services/custom-elements.service.d.ts +13 -0
  28. package/chat/smart-renderer/smart-renderer.d.ts +23 -0
  29. package/chat/token-progress-bar/i18n/de.json +4 -0
  30. package/chat/tooltip/tooltip.directive.d.ts +2 -2
  31. package/chat/types.d.ts +8 -42
  32. package/esm2022/chat/chat-message/chat-message.component.mjs +33 -135
  33. package/esm2022/chat/chat-reference/chat-reference.component.mjs +60 -26
  34. package/esm2022/chat/chat-settings-v3/chat-settings-v3.component.mjs +1 -1
  35. package/esm2022/chat/chat.component.mjs +50 -13
  36. package/esm2022/chat/chat.service.mjs +3 -2
  37. package/esm2022/chat/debug-message/debug-message-details/debug-message-details.component.mjs +2 -2
  38. package/esm2022/chat/debug-message/debug-message.service.mjs +4 -7
  39. package/esm2022/chat/directives/copy-to-clipboard.directive.mjs +68 -0
  40. package/esm2022/chat/documents-upload/document-list/document-list.component.mjs +21 -22
  41. package/esm2022/chat/documents-upload/document-overview/document-overview.component.mjs +8 -31
  42. package/esm2022/chat/documents-upload/document-upload/document-upload.component.mjs +12 -14
  43. package/esm2022/chat/documents-upload/documents-upload.service.mjs +25 -44
  44. package/esm2022/chat/markdown-it-plugins/code-block.plugin.mjs +14 -0
  45. package/esm2022/chat/markdown-it-plugins/image-reference.plugin.mjs +58 -0
  46. package/esm2022/chat/markdown-it-plugins/link.plugin.mjs +15 -0
  47. package/esm2022/chat/markdown-it-plugins/page-reference.plugin.mjs +60 -0
  48. package/esm2022/chat/markdown-it-plugins/reference.plugin.mjs +68 -0
  49. package/esm2022/chat/public-api.mjs +3 -2
  50. package/esm2022/chat/references/references.component.mjs +293 -0
  51. package/esm2022/chat/saved-chats/saved-chats.component.mjs +4 -3
  52. package/esm2022/chat/saved-chats/saved-chats.service.mjs +9 -12
  53. package/esm2022/chat/services/app.service.mjs +8 -2
  54. package/esm2022/chat/services/assistant-configuration.service.mjs +9 -18
  55. package/esm2022/chat/services/assistant-metadata.service.mjs +3 -3
  56. package/esm2022/chat/services/assistant-tokens-tracking.service.mjs +3 -6
  57. package/esm2022/chat/services/custom-elements.service.mjs +43 -0
  58. package/esm2022/chat/smart-renderer/smart-renderer.mjs +103 -0
  59. package/esm2022/chat/tooltip/tooltip.directive.mjs +9 -9
  60. package/esm2022/chat/types.mjs +2 -5
  61. package/fesm2022/sinequa-assistant-chat.mjs +913 -498
  62. package/fesm2022/sinequa-assistant-chat.mjs.map +1 -1
  63. package/package.json +4 -6
  64. package/chat/prompt.component.d.ts +0 -25
  65. package/chat/unified-plugins/embedded-image-reference.plugin.d.ts +0 -3
  66. package/chat/unified-plugins/embedded-page-reference.plugin.d.ts +0 -3
  67. package/esm2022/chat/prompt.component.mjs +0 -88
  68. package/esm2022/chat/unified-plugins/embedded-image-reference.plugin.mjs +0 -56
  69. 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, HostBinding, HostListener, Pipe, input, output, viewChild, LOCALE_ID, InjectionToken, ElementRef, computed, createComponent, ChangeDetectorRef, ViewChild, ContentChild, signal } from '@angular/core';
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, UntypedFormControl, Validators, ReactiveFormsModule } from '@angular/forms';
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, fetchApp, fetchUserSettings, fetchPrincipal, guid, Audit, setGlobalConfig } from '@sinequa/atomic';
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()" }, properties: { "class.has-tooltip": "this.hasTooltip" } }, ngImport: i0 }); }
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.openDocument = new EventEmitter();
657
- this.openPreview = new EventEmitter();
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['$expanded'] = !this.attachment['$expanded'];
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: "14.0.0", version: "18.2.13", type: ChatReferenceComponent, isStandalone: true, selector: "sq-chat-reference", inputs: { reference: "reference", attachment: "attachment", partId: "partId" }, outputs: { openDocument: "openDocument", openPreview: "openPreview" }, providers: [provideTranslocoScope('chat-reference')], ngImport: i0, template: "<div [class.reference-tooltip]=\"!!partId\">\n <div class=\"reference-data\" [class.expanded]=\"attachment['$expanded'] || !!partId\" (click)=\"expandAttachment()\">\n <span class=\"reference me-1\">{{reference}}</span>\n <sq-format-icon [extension]=\"attachment.record.fileext\"></sq-format-icon>\n <a [id]=\"'attachment-'+attachment.recordId\">\n {{attachment.record.title}}\n </a>\n <i class=\"fas fa-eye\" (click)=\"$event.stopPropagation(); openPreview.emit(attachment)\" [sqTooltip]=\"!partId ? ('chatReference.previewDocument' | transloco) : ''\"></i>\n <i class=\"fas fa-arrow-up-right-from-square\" *ngIf=\"attachment.record.url1 || attachment.record.originalUrl\"\n (click)=\"$event.stopPropagation(); openDocument.emit(attachment)\" [sqTooltip]=\"!partId ? ('chatReference.openDocument' | transloco) : ''\">\n </i>\n </div>\n <div class=\"reference-passages\" *ngIf=\"!!partId || (attachment['$expanded']) && parts.length\">\n <div class=\"reference-passage\" *ngFor=\"let part of parts\">\n <span class=\"reference me-1\">{{reference}}.{{part.partId}}</span>\n <span class=\"w-100 pe-2\" [innerHTML]=\"part.text\"></span>\n </div>\n </div>\n</div>\n", styles: [".ast-primary{color:var(--ast-primary-color, #005DA7);background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover{background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover:hover{color:var(--ast-primary-color, #005DA7)}.ast-secondary{color:var(--ast-secondary-color, #FF732E);background-color:var(--ast-secondary-bg, #FFF8F1)}.ast-error{background-color:var(--ast-error-bg, rgba(249, 58, 55, .2));color:var(--ast-action-buttons-color, inherit)}.ast-error:hover{color:var(--ast-error-color, rgba(249, 58, 55, .7))}.ast-btn{border:0;text-align:left;padding-top:.5rem;padding-bottom:.5rem;display:flex;align-items:center}.dark{--ast-primary-bg: #0d0701;--ast-primary-color: #008cd1;--ast-secondary-bg: #00070e;--ast-secondary-color: #ffa258;--ast-input-bg: #070707;--ast-input-color: rgba(222, 218, 218, .75);--ast-muted-color: rgba(222, 218, 218, .75);--ast-saved-chat-hover-background: #262421;--ast-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 a{color:var(--ast-secondary-color, #FF732E);flex-grow:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-weight:var(--font-weight-bold, 500);cursor:pointer}.reference-data i{padding:var(--ast-size-1, .25rem);margin-left:var(--ast-size-1, .25rem);cursor:pointer;color:var(--ast-reference-icon-color, black)}.reference-data i.active{color:var(--ast-reference-icon-active-color, white);background-color:var(--ast-secondary-color, #FF732E)}.reference-data:not(.expanded) i{opacity:0}.reference-data:not(.expanded):hover i{opacity:1}.reference-passages{white-space:normal;font-style:italic;font-weight:400;padding:1rem 0;color:var(--ast-reference-passages-color, black)}.reference-passages .reference-passage{display:flex;align-items:baseline;padding-left:2.5rem;padding-right:1rem;word-wrap:break-word}.reference-passages .reference-passage+.reference-passage{padding-top:1rem}.reference-passages .reference-passage .reference{white-space:nowrap;margin-right:var(--ast-size-2, .5rem)}sq-format-icon{margin-left:var(--ast-size-1, .25rem);margin-right:var(--ast-size-2, .5rem);color:var(--ast-secondary-color, #FF732E)}.reference-tooltip{max-width:600px!important;box-shadow:0 .5rem 1rem #00000026;padding:.5rem;font-size:.875rem}.w-100{width:100%}\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: "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" }] }); }
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: 'sq-chat-reference', standalone: true, imports: [CommonModule, FormatIconComponent, TooltipDirective, TranslocoPipe], providers: [provideTranslocoScope('chat-reference')], template: "<div [class.reference-tooltip]=\"!!partId\">\n <div class=\"reference-data\" [class.expanded]=\"attachment['$expanded'] || !!partId\" (click)=\"expandAttachment()\">\n <span class=\"reference me-1\">{{reference}}</span>\n <sq-format-icon [extension]=\"attachment.record.fileext\"></sq-format-icon>\n <a [id]=\"'attachment-'+attachment.recordId\">\n {{attachment.record.title}}\n </a>\n <i class=\"fas fa-eye\" (click)=\"$event.stopPropagation(); openPreview.emit(attachment)\" [sqTooltip]=\"!partId ? ('chatReference.previewDocument' | transloco) : ''\"></i>\n <i class=\"fas fa-arrow-up-right-from-square\" *ngIf=\"attachment.record.url1 || attachment.record.originalUrl\"\n (click)=\"$event.stopPropagation(); openDocument.emit(attachment)\" [sqTooltip]=\"!partId ? ('chatReference.openDocument' | transloco) : ''\">\n </i>\n </div>\n <div class=\"reference-passages\" *ngIf=\"!!partId || (attachment['$expanded']) && parts.length\">\n <div class=\"reference-passage\" *ngFor=\"let part of parts\">\n <span class=\"reference me-1\">{{reference}}.{{part.partId}}</span>\n <span class=\"w-100 pe-2\" [innerHTML]=\"part.text\"></span>\n </div>\n </div>\n</div>\n", styles: [".ast-primary{color:var(--ast-primary-color, #005DA7);background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover{background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover:hover{color:var(--ast-primary-color, #005DA7)}.ast-secondary{color:var(--ast-secondary-color, #FF732E);background-color:var(--ast-secondary-bg, #FFF8F1)}.ast-error{background-color:var(--ast-error-bg, rgba(249, 58, 55, .2));color:var(--ast-action-buttons-color, inherit)}.ast-error:hover{color:var(--ast-error-color, rgba(249, 58, 55, .7))}.ast-btn{border:0;text-align:left;padding-top:.5rem;padding-bottom:.5rem;display:flex;align-items:center}.dark{--ast-primary-bg: #0d0701;--ast-primary-color: #008cd1;--ast-secondary-bg: #00070e;--ast-secondary-color: #ffa258;--ast-input-bg: #070707;--ast-input-color: rgba(222, 218, 218, .75);--ast-muted-color: rgba(222, 218, 218, .75);--ast-saved-chat-hover-background: #262421;--ast-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 a{color:var(--ast-secondary-color, #FF732E);flex-grow:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-weight:var(--font-weight-bold, 500);cursor:pointer}.reference-data i{padding:var(--ast-size-1, .25rem);margin-left:var(--ast-size-1, .25rem);cursor:pointer;color:var(--ast-reference-icon-color, black)}.reference-data i.active{color:var(--ast-reference-icon-active-color, white);background-color:var(--ast-secondary-color, #FF732E)}.reference-data:not(.expanded) i{opacity:0}.reference-data:not(.expanded):hover i{opacity:1}.reference-passages{white-space:normal;font-style:italic;font-weight:400;padding:1rem 0;color:var(--ast-reference-passages-color, black)}.reference-passages .reference-passage{display:flex;align-items:baseline;padding-left:2.5rem;padding-right:1rem;word-wrap:break-word}.reference-passages .reference-passage+.reference-passage{padding-top:1rem}.reference-passages .reference-passage .reference{white-space:nowrap;margin-right:var(--ast-size-2, .5rem)}sq-format-icon{margin-left:var(--ast-size-1, .25rem);margin-right:var(--ast-size-2, .5rem);color:var(--ast-secondary-color, #FF732E)}.reference-tooltip{max-width:600px!important;box-shadow:0 .5rem 1rem #00000026;padding:.5rem;font-size:.875rem}.w-100{width:100%}\n"] }]
675
- }], propDecorators: { reference: [{
676
- type: Input
677
- }], attachment: [{
678
- type: Input
679
- }], partId: [{
680
- type: Input
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 embeddedImageReferencePlugin(tree) {
992
- visit(tree, "text", (node, index, parent) => {
993
- const refs = Array.from(node.value.matchAll(EMBEDDED_IMAGE_REGEX));
994
- if (refs.length === 0)
995
- return CONTINUE;
996
- const nodes = getContentNodes$1(node, refs);
997
- if (nodes.length === 0)
998
- return CONTINUE;
999
- parent.children.splice(index, 1, ...nodes);
1000
- return index + nodes.length;
1001
- });
1002
- return tree;
1003
- }
1004
- /** Transform node text content into a set of node */
1005
- function getContentNodes$1(node, refs) {
1006
- let nodes = refs.reduce((acc, ref) => {
1007
- handleLeadingText$1(acc, node, ref);
1008
- acc.push({
1009
- type: EMBEDDED_IMAGE_NAME,
1010
- value: ref[2],
1011
- end: ref.index + ref[0].length,
1012
- });
1013
- return acc;
1014
- }, []);
1015
- handleTrailingText$1(node, refs, nodes);
1016
- return nodes;
1017
- }
1018
- /** Compute last block ending for leading text */
1019
- function handleLeadingText$1(acc, node, ref) {
1020
- const lastEnd = acc.at(-1)?.end ?? 0;
1021
- const leadingText = node.value.substring(lastEnd, ref.index);
1022
- if (leadingText !== "") {
1023
- acc.push({
1024
- type: "text",
1025
- value: leadingText,
1026
- end: ref.index,
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
- return acc;
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
- /** Compute last block ending for trailing text */
1032
- function handleTrailingText$1(node, refs, nodes) {
1033
- const lastEnd = refs.at(-1)?.index ?? 0;
1034
- const trailingText = node.value.substring(lastEnd + (refs.at(-1)?.[0].length ?? 0));
1035
- if (trailingText !== "") {
1036
- nodes.push({
1037
- type: "text",
1038
- value: trailingText,
1039
- end: node.value.length,
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 embeddedPageReferencePlugin(tree) {
1047
- visit(tree, "text", (node, index, parent) => {
1048
- const refs = Array.from(node.value.matchAll(EMBEDDED_PAGE_REGEX));
1049
- if (refs.length === 0)
1050
- return CONTINUE;
1051
- const nodes = getContentNodes(node, refs);
1052
- if (nodes.length === 0)
1053
- return CONTINUE;
1054
- parent.children.splice(index, 1, ...nodes);
1055
- return index + nodes.length;
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
- return tree;
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
- /** Transform node text content into a set of node */
1060
- function getContentNodes(node, refs) {
1061
- let nodes = refs.reduce((acc, ref) => {
1062
- handleLeadingText(acc, node, ref);
1063
- acc.push({
1064
- type: EMBEDDED_PAGE_NAME,
1065
- value: ref[2],
1066
- boundingBox: ref[3],
1067
- end: ref.index + ref[0].length,
1068
- });
1069
- return acc;
1070
- }, []);
1071
- handleTrailingText(node, refs, nodes);
1072
- return nodes;
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
- /** Compute last block ending for leading text */
1075
- function handleLeadingText(acc, node, ref) {
1076
- const lastEnd = acc.at(-1)?.end ?? 0;
1077
- const leadingText = node.value.substring(lastEnd, ref.index);
1078
- if (leadingText !== "") {
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
- return acc;
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
- /** Compute last block ending for trailing text */
1088
- function handleTrailingText(node, refs, nodes) {
1089
- const lastEnd = refs.at(-1)?.index ?? 0;
1090
- const trailingText = node.value.substring(lastEnd + (refs.at(-1)?.[0].length ?? 0));
1091
- if (trailingText !== "") {
1092
- nodes.push({
1093
- type: "text",
1094
- value: trailingText,
1095
- end: node.value.length,
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
- this.references = [];
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
- * This Unified plugin looks a text nodes and replaces any reference in the
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 ([![Example image](https://example.com/image.png)](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
- * Reformat [ids: 12.2, 42.5] to [12.2][42.5]
1394
- */
1395
- reformatReferences(content) {
1396
- return content.replace(/\[(?:ids?:?\s*)?(?:documents?:?\s*)?(\s*(?:,?\s*\d+(?:\.\d+)?(?:\.part)?\s*)+)\]/g, (str, match) => `[${match
1397
- .replace(/\.part/g, "")
1398
- .split(",")
1399
- .join("] [")}]`);
1400
- }
1401
- /**
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
- getReferenceMatches(content) {
1405
- return Array.from(content.matchAll(/\[(\s*\d+(?:\.\d+)?\s*)\]/g));
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, providedIn: 'root' }); }
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
- // fetch the standard app config to get the defaultValues of the chat config for the given instance
2276
- // Persist the app in the app service
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
- const url = context.getAssistantConfigValue()?.connectionSettings.restEndpoint;
2384
- if (url) {
2385
- context.setRESTRequestsUrl(url);
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, providedIn: 'root' }); }
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, providedIn: 'root' }); }
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, providedIn: 'root' }); }
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$1.highlightAll();
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
- this.isAtBottom = this._toggleScrollButtonVisibility();
3883
- this.cdr.detectChanges();
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 = { role: 'system', content: this.config.defaultValues.systemPrompt, additionalProperties: { display: false, messageId: guid() } };
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 = { role: 'user', content: AssistantUtils.formatPrompt(this.transloco.translate(userPrompt), { principal: this.principalService.principal }), additionalProperties: { display: this.config.modeSettings.displayUserPrompt, messageId: guid() } };
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, rank);
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 Rank of the message in the chatHistory related to the suggested action.
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
- this.chatService.generateAuditEvent('ast-suggested-action.click', { 'text': action.content, 'suggestedAction-type': action.type });
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 <i class=\"saved-chat-actions fas fa-pen mx-1\" [sqTooltip]=\"'savedChats.rename' | transloco\" (click)=\"renameDialog.showModal($event, savedChat)\"></i>\n <i class=\"saved-chat-actions fas fa-trash ms-1\" [sqTooltip]=\"'savedChats.delete' | transloco\" (click)=\"deleteDialog.showModal($event, savedChat)\"></i>\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{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" }] }); }
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 <i class=\"saved-chat-actions fas fa-pen mx-1\" [sqTooltip]=\"'savedChats.rename' | transloco\" (click)=\"renameDialog.showModal($event, savedChat)\"></i>\n <i class=\"saved-chat-actions fas fa-trash ms-1\" [sqTooltip]=\"'savedChats.delete' | transloco\" (click)=\"deleteDialog.showModal($event, savedChat)\"></i>\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{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"] }]
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
- /** Documents' upload configuration. */
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 with the provided chat service instance.
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(chatService) {
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(`plugin/${this.REQUEST_URL}`, data)).pipe(take$1(1), catchError$1((error) => {
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}/${globalConfig.apiPath}/plugin/${this.REQUEST_URL}`;
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(`plugin/${this.REQUEST_URL}`, data)).pipe(catchError$1((error) => {
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(`plugin/${this.REQUEST_URL}`, data)).pipe(catchError$1((error) => {
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(`plugin/${this.REQUEST_URL}`, data)).pipe(catchError$1((error) => {
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(`plugin/${this.REQUEST_URL}`, data)).pipe(catchError$1((error) => {
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(tap((_) => this.instantiateChatService()), switchMap((_) => this.chatService.assistantConfig$), filter((config) => !!config), tap((_) => this.documentsUploadService.init(this.chatService)), catchError$1((error) => {
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), catchError$1((err) => {
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: { instanceId: "instanceId", pollingInterval: "pollingInterval" }, providers: [DocumentsUploadService, 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 [title]=\"transfer.name\">{{ transfer.name }}</span>\n <i class=\"fas fa-trash ms-1\" (click)=\"flow.cancelFile(transfer)\" [title]=\"'chatDocumentsUpload.cancel' | transloco\"></i>\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" }] }); }
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: [DocumentsUploadService, 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 [title]=\"transfer.name\">{{ transfer.name }}</span>\n <i class=\"fas fa-trash ms-1\" (click)=\"flow.cancelFile(transfer)\" [title]=\"'chatDocumentsUpload.cancel' | transloco\"></i>\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"] }]
5508
- }], propDecorators: { instanceId: [{
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(tap((_) => this.instantiateChatService()), switchMap((_) => this.chatService.assistantConfig$), filter((config) => !!config), tap((_) => this.documentsUploadService.init(this.chatService)), tap((_) => this.updateUploadedDocumentsList()), catchError$1((error) => {
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
- updateUploadedDocumentsList() {
5596
+ onUpdateUploadedDocumentsList() {
5549
5597
  this._subscription.add(combineLatest([
5550
- this.documentsUploadService.getDocumentsList(),
5598
+ this.documentsUploadService.uploadedDocuments$,
5551
5599
  this.transloco.langChanges$
5552
5600
  ]).pipe(tap(([uploadedDocuments]) => {
5553
- this.groupedUploadedDocuments$.next(this._groupUploadedDocumentsByDate(uploadedDocuments.docs));
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
- }), take$1(1))
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
- this.updateUploadedDocumentsList();
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
- this.updateUploadedDocumentsList();
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", inputs: { instanceId: "instanceId" }, providers: [DocumentsUploadService, 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 <i class=\"uploaded-doc-actions fas fa-trash ms-1\" [title]=\"'chatDocumentsUpload.delete' | transloco\"\n (click)=\"deleteDocument($event, doc)\"></i>\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" }] }); }
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: [DocumentsUploadService, 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 <i class=\"uploaded-doc-actions fas fa-trash ms-1\" [title]=\"'chatDocumentsUpload.delete' | transloco\"\n (click)=\"deleteDocument($event, doc)\"></i>\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"] }]
5642
- }], propDecorators: { instanceId: [{
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(tap((_) => this.instantiateChatService()), switchMap((_) => this.chatService.assistantConfig$), filter((config) => !!config), tap((_) => this.documentsUploadService.init(this.chatService)), tap((_) => this.updateUploadedDocumentsList()), catchError$1((error) => {
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: { instanceId: "instanceId", disabledUpload: "disabledUpload" }, outputs: { onUpload: "onUpload" }, providers: [DocumentsUploadService, provideTranslocoScope('chat-documents-upload')], ngImport: i0, template: "<div class=\"d-flex\">\n <span class=\"overview-text flex-grow-1\">\n {{ 'chatDocumentsUpload.uploadedDocuments' | transloco: { count: (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" }] }); }
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: [DocumentsUploadService, 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: (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"] }]
5693
- }], propDecorators: { instanceId: [{
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, ChatPrompt, ChatService, ChatSettingsV3Component, DocumentListComponent, DocumentOverviewComponent, DocumentUploadComponent, DocumentsUploadService, FormatIconComponent, InitialsAvatarComponent, InstanceManagerService, NotificationsService, SavedChatsComponent, chatConfigSchema, connectionSettingsSchema };
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