@sinequa/assistant 3.7.7 → 3.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/chat/charts/chart/chart.component.d.ts +13 -13
- package/chat/chat-message/chat-message.component.d.ts +85 -81
- package/chat/chat-message/i18n/en.json +11 -0
- package/chat/chat-message/i18n/fr.json +11 -0
- package/chat/chat-reference/chat-reference.component.d.ts +14 -14
- package/chat/chat-reference/i18n/en.json +4 -0
- package/chat/chat-reference/i18n/fr.json +4 -0
- package/chat/chat-settings-v3/chat-settings-v3.component.d.ts +48 -49
- package/chat/chat-settings-v3/i18n/en.json +14 -0
- package/chat/chat-settings-v3/i18n/fr.json +14 -0
- package/chat/chat.component.d.ts +388 -1410
- package/chat/chat.service.d.ts +247 -228
- package/chat/debug-message/debug-message.component.d.ts +17 -17
- package/chat/debug-message/i18n/en.json +3 -0
- package/chat/debug-message/i18n/fr.json +3 -0
- package/chat/dialogs/delete-saved-chat.component.d.ts +22 -0
- package/chat/dialogs/i18n/en.json +19 -0
- package/chat/dialogs/i18n/fr.json +19 -0
- package/chat/dialogs/rename-saved-chat.component.d.ts +21 -0
- package/chat/dialogs/updates.component.d.ts +15 -0
- package/chat/documents-upload/document-list/document-list.component.d.ts +68 -0
- package/chat/documents-upload/document-overview/document-overview.component.d.ts +31 -0
- package/chat/documents-upload/document-upload/document-upload.component.d.ts +96 -0
- package/chat/documents-upload/documents-upload.model.d.ts +66 -0
- package/chat/documents-upload/documents-upload.service.d.ts +170 -0
- package/chat/documents-upload/i18n/en.json +24 -0
- package/chat/documents-upload/i18n/fr.json +24 -0
- package/chat/format-icon/format-icon.component.d.ts +10 -10
- package/chat/format-icon/icons.d.ts +5 -5
- package/chat/i18n/en.json +42 -0
- package/chat/i18n/fr.json +42 -0
- package/chat/index.d.ts +5 -5
- package/chat/initials-avatar/initials-avatar.component.d.ts +35 -35
- package/chat/instance-manager.service.d.ts +28 -28
- package/chat/pipes/message-content.pipe.d.ts +16 -0
- package/chat/prompt.component.d.ts +25 -21
- package/chat/public-api.d.ts +17 -12
- package/chat/references/i18n/en.json +6 -0
- package/chat/references/i18n/fr.json +6 -0
- package/chat/references/inline-image-reference.d.ts +21 -0
- package/chat/references/inline-page-reference.d.ts +21 -0
- package/chat/rest-chat.service.d.ts +31 -33
- package/chat/saved-chats/i18n/en.json +4 -0
- package/chat/saved-chats/i18n/fr.json +4 -0
- package/chat/saved-chats/saved-chats.component.d.ts +30 -36
- package/chat/services/app.service.d.ts +8 -0
- package/chat/services/dialog.service.d.ts +12 -0
- package/chat/services/notification.service.d.ts +10 -0
- package/chat/services/principal.service.d.ts +7 -0
- package/chat/services/search.service.d.ts +7 -0
- package/chat/services/signalR.web.service.d.ts +45 -0
- package/chat/services/ui.service.d.ts +13 -0
- package/chat/services/user-settings.service.d.ts +7 -0
- package/chat/styles/assistant.scss +2 -0
- package/chat/token-progress-bar/i18n/en.json +4 -0
- package/chat/token-progress-bar/i18n/fr.json +4 -0
- package/chat/token-progress-bar/token-progress-bar.component.d.ts +24 -27
- package/chat/tooltip/tooltip.component.d.ts +12 -0
- package/chat/tooltip/tooltip.directive.d.ts +81 -0
- package/chat/types/message-content.types.d.ts +54 -0
- package/chat/types/message-reference.types.d.ts +11 -0
- package/chat/types.d.ts +913 -817
- package/chat/unified-plugins/embedded-image-reference.plugin.d.ts +3 -0
- package/chat/unified-plugins/embedded-page-reference.plugin.d.ts +3 -0
- package/chat/utils/assistant-json.d.ts +2 -0
- package/chat/websocket-chat.service.d.ts +102 -103
- package/esm2022/chat/charts/chart/chart.component.mjs +40 -0
- package/esm2022/chat/chat-message/chat-message.component.mjs +351 -0
- package/esm2022/chat/chat-reference/chat-reference.component.mjs +40 -0
- package/esm2022/chat/chat-settings-v3/chat-settings-v3.component.mjs +118 -0
- package/esm2022/chat/chat.component.mjs +1090 -0
- package/esm2022/chat/chat.service.mjs +417 -0
- package/esm2022/chat/debug-message/debug-message.component.mjs +43 -0
- package/esm2022/chat/dialogs/delete-saved-chat.component.mjs +81 -0
- package/esm2022/chat/dialogs/rename-saved-chat.component.mjs +84 -0
- package/esm2022/chat/dialogs/updates.component.mjs +61 -0
- package/esm2022/chat/documents-upload/document-list/document-list.component.mjs +140 -0
- package/esm2022/chat/documents-upload/document-overview/document-overview.component.mjs +65 -0
- package/esm2022/chat/documents-upload/document-upload/document-upload.component.mjs +256 -0
- package/esm2022/chat/documents-upload/documents-upload.model.mjs +2 -0
- package/esm2022/chat/documents-upload/documents-upload.service.mjs +291 -0
- package/{esm2020 → esm2022}/chat/format-icon/format-icon.component.mjs +23 -23
- package/{esm2020 → esm2022}/chat/format-icon/icons.mjs +137 -137
- package/{esm2020 → esm2022}/chat/initials-avatar/initials-avatar.component.mjs +60 -60
- package/esm2022/chat/instance-manager.service.mjs +46 -0
- package/esm2022/chat/pipes/message-content.pipe.mjs +34 -0
- package/esm2022/chat/prompt.component.mjs +88 -0
- package/esm2022/chat/public-api.mjs +18 -0
- package/esm2022/chat/references/inline-image-reference.mjs +110 -0
- package/esm2022/chat/references/inline-page-reference.mjs +110 -0
- package/esm2022/chat/rest-chat.service.mjs +296 -0
- package/esm2022/chat/saved-chats/saved-chats.component.mjs +82 -0
- package/esm2022/chat/services/app.service.mjs +19 -0
- package/esm2022/chat/services/dialog.service.mjs +40 -0
- package/esm2022/chat/services/notification.service.mjs +25 -0
- package/esm2022/chat/services/principal.service.mjs +16 -0
- package/esm2022/chat/services/search.service.mjs +13 -0
- package/esm2022/chat/services/signalR.web.service.mjs +79 -0
- package/esm2022/chat/services/ui.service.mjs +61 -0
- package/esm2022/chat/services/user-settings.service.mjs +22 -0
- package/{esm2020 → esm2022}/chat/sinequa-assistant-chat.mjs +4 -4
- package/esm2022/chat/token-progress-bar/token-progress-bar.component.mjs +52 -0
- package/esm2022/chat/tooltip/tooltip.component.mjs +44 -0
- package/esm2022/chat/tooltip/tooltip.directive.mjs +203 -0
- package/esm2022/chat/types/message-content.types.mjs +2 -0
- package/esm2022/chat/types/message-reference.types.mjs +2 -0
- package/esm2022/chat/types.mjs +130 -0
- package/esm2022/chat/unified-plugins/embedded-image-reference.plugin.mjs +57 -0
- package/esm2022/chat/unified-plugins/embedded-page-reference.plugin.mjs +57 -0
- package/esm2022/chat/utils/assistant-json.mjs +12 -0
- package/esm2022/chat/websocket-chat.service.mjs +654 -0
- package/{esm2020 → esm2022}/public-api.mjs +2 -2
- package/{esm2020 → esm2022}/sinequa-assistant.mjs +4 -4
- package/fesm2022/sinequa-assistant-chat.mjs +5340 -0
- package/fesm2022/sinequa-assistant-chat.mjs.map +1 -0
- package/{fesm2015 → fesm2022}/sinequa-assistant.mjs +3 -3
- package/index.d.ts +5 -5
- package/package.json +51 -22
- package/public-api.d.ts +1 -1
- package/chat/messages/de.d.ts +0 -4
- package/chat/messages/en.d.ts +0 -4
- package/chat/messages/fr.d.ts +0 -4
- package/chat/messages/index.d.ts +0 -4
- package/esm2020/chat/charts/chart/chart.component.mjs +0 -40
- package/esm2020/chat/chat-message/chat-message.component.mjs +0 -263
- package/esm2020/chat/chat-reference/chat-reference.component.mjs +0 -40
- package/esm2020/chat/chat-settings-v3/chat-settings-v3.component.mjs +0 -114
- package/esm2020/chat/chat.component.mjs +0 -1072
- package/esm2020/chat/chat.service.mjs +0 -333
- package/esm2020/chat/debug-message/debug-message.component.mjs +0 -43
- package/esm2020/chat/instance-manager.service.mjs +0 -46
- package/esm2020/chat/messages/de.mjs +0 -4
- package/esm2020/chat/messages/en.mjs +0 -4
- package/esm2020/chat/messages/fr.mjs +0 -4
- package/esm2020/chat/messages/index.mjs +0 -9
- package/esm2020/chat/prompt.component.mjs +0 -88
- package/esm2020/chat/public-api.mjs +0 -13
- package/esm2020/chat/rest-chat.service.mjs +0 -241
- package/esm2020/chat/saved-chats/saved-chats.component.mjs +0 -175
- package/esm2020/chat/token-progress-bar/token-progress-bar.component.mjs +0 -54
- package/esm2020/chat/types.mjs +0 -101
- package/esm2020/chat/websocket-chat.service.mjs +0 -641
- package/fesm2015/sinequa-assistant-chat.mjs +0 -3416
- package/fesm2015/sinequa-assistant-chat.mjs.map +0 -1
- package/fesm2020/sinequa-assistant-chat.mjs +0 -3388
- package/fesm2020/sinequa-assistant-chat.mjs.map +0 -1
- package/fesm2020/sinequa-assistant.mjs +0 -9
- package/fesm2020/sinequa-assistant.mjs.map +0 -1
- /package/{fesm2015 → fesm2022}/sinequa-assistant.mjs.map +0 -0
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { CommonModule } from '@angular/common';
|
|
2
|
-
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
|
3
|
-
import { UtilsModule } from '@sinequa/components/utils';
|
|
4
|
-
import { FormatIconComponent } from '../format-icon/format-icon.component';
|
|
5
|
-
import * as i0 from "@angular/core";
|
|
6
|
-
import * as i1 from "@angular/common";
|
|
7
|
-
import * as i2 from "@sinequa/components/utils";
|
|
8
|
-
export class ChatReferenceComponent {
|
|
9
|
-
constructor() {
|
|
10
|
-
this.openDocument = new EventEmitter();
|
|
11
|
-
this.openPreview = new EventEmitter();
|
|
12
|
-
}
|
|
13
|
-
get parts() {
|
|
14
|
-
if (!this.attachment)
|
|
15
|
-
return [];
|
|
16
|
-
return this.attachment.parts.filter(part => (!this.partId || part.partId === this.partId) && !!part.text);
|
|
17
|
-
}
|
|
18
|
-
expandAttachment() {
|
|
19
|
-
if (this.partId)
|
|
20
|
-
return;
|
|
21
|
-
this.attachment['$expanded'] = !this.attachment['$expanded'];
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
ChatReferenceComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ChatReferenceComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
25
|
-
ChatReferenceComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: ChatReferenceComponent, isStandalone: true, selector: "sq-chat-reference", inputs: { reference: "reference", attachment: "attachment", partId: "partId" }, outputs: { openDocument: "openDocument", openPreview: "openPreview" }, ngImport: i0, template: "<div [class.reference-tooltip]=\"!!partId\">\n <div class=\"reference-data\" [class.expanded]=\"attachment['$expanded'] || !!partId\" (click)=\"expandAttachment()\">\n <span class=\"reference me-1\">{{reference}}</span>\n <sq-format-icon [extension]=\"attachment.record.fileext\"></sq-format-icon>\n <a [id]=\"'attachment-'+attachment.recordId\">\n {{attachment.record.title}}\n </a>\n <i class=\"fas fa-eye\" (click)=\"$event.stopPropagation(); openPreview.emit(attachment)\" [sqTooltip]=\"!partId ? 'Preview document' : ''\"></i>\n <i class=\"fas fa-arrow-up-right-from-square\" *ngIf=\"attachment.record.url1 || attachment.record.originalUrl\"\n (click)=\"$event.stopPropagation(); openDocument.emit(attachment)\" [sqTooltip]=\"!partId ? 'Open document' : ''\">\n </i>\n </div>\n <div class=\"reference-passages\" *ngIf=\"!!partId || (attachment['$expanded']) && parts.length\">\n <div class=\"reference-passage\" *ngFor=\"let part of parts\">\n <span class=\"reference me-1\">{{reference}}.{{part.partId}}</span>\n <span class=\"w-100 pe-2\" [innerHTML]=\"part.text\"></span>\n </div>\n </div>\n</div>\n", styles: [".ast-primary{color:var(--ast-primary-color, #005DA7);background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover{background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover:hover{color:var(--ast-primary-color, #005DA7)}.ast-secondary{color:var(--ast-secondary-color, #FF732E);background-color:var(--ast-secondary-bg, #FFF8F1)}.ast-error{background-color:var(--ast-error-bg, rgba(249, 58, 55, .2));color:var(--ast-action-buttons-color, inherit)}.ast-error:hover{color:var(--ast-error-color, rgba(249, 58, 55, .7))}.ast-btn{border:0;text-align:left;padding-top:.5rem;padding-bottom:.5rem;display:flex;align-items:center}.dark{--ast-primary-bg: #0d0701;--ast-primary-color: #008cd1;--ast-secondary-bg: #00070e;--ast-secondary-color: #ffa258;--ast-input-bg: #070707;--ast-input-color: rgba(222, 218, 218, .75);--ast-muted-color: rgba(222, 218, 218, .75);--ast-saved-chat-hover-background: #262421;--ast-message-table-border-color: #333333;--ast-message-table-tr-bg: #070707;--ast-message-table-tr-border-color: #222222;--ast-reference-icon-color: white;--ast-reference-icon-active-color: black;--ast-reference-passages-color: white;--ast-reference-expanded-hover-bg: #262421;--ast-message-reference-color: black;--ast-action-buttons-color: white;--ast-action-buttons-hover-color: #6dbee6;--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}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: UtilsModule }, { kind: "directive", type: i2.TooltipDirective, selector: "[sqTooltip]", inputs: ["sqTooltip", "sqTooltipData", "sqTooltipTemplate", "placement", "fallbackPlacements", "delay", "hoverableTooltip", "tooltipClass"] }, { kind: "component", type: FormatIconComponent, selector: "sq-format-icon", inputs: ["extension"] }] });
|
|
26
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ChatReferenceComponent, decorators: [{
|
|
27
|
-
type: Component,
|
|
28
|
-
args: [{ selector: 'sq-chat-reference', standalone: true, imports: [CommonModule, UtilsModule, FormatIconComponent], template: "<div [class.reference-tooltip]=\"!!partId\">\n <div class=\"reference-data\" [class.expanded]=\"attachment['$expanded'] || !!partId\" (click)=\"expandAttachment()\">\n <span class=\"reference me-1\">{{reference}}</span>\n <sq-format-icon [extension]=\"attachment.record.fileext\"></sq-format-icon>\n <a [id]=\"'attachment-'+attachment.recordId\">\n {{attachment.record.title}}\n </a>\n <i class=\"fas fa-eye\" (click)=\"$event.stopPropagation(); openPreview.emit(attachment)\" [sqTooltip]=\"!partId ? 'Preview document' : ''\"></i>\n <i class=\"fas fa-arrow-up-right-from-square\" *ngIf=\"attachment.record.url1 || attachment.record.originalUrl\"\n (click)=\"$event.stopPropagation(); openDocument.emit(attachment)\" [sqTooltip]=\"!partId ? 'Open document' : ''\">\n </i>\n </div>\n <div class=\"reference-passages\" *ngIf=\"!!partId || (attachment['$expanded']) && parts.length\">\n <div class=\"reference-passage\" *ngFor=\"let part of parts\">\n <span class=\"reference me-1\">{{reference}}.{{part.partId}}</span>\n <span class=\"w-100 pe-2\" [innerHTML]=\"part.text\"></span>\n </div>\n </div>\n</div>\n", styles: [".ast-primary{color:var(--ast-primary-color, #005DA7);background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover{background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover:hover{color:var(--ast-primary-color, #005DA7)}.ast-secondary{color:var(--ast-secondary-color, #FF732E);background-color:var(--ast-secondary-bg, #FFF8F1)}.ast-error{background-color:var(--ast-error-bg, rgba(249, 58, 55, .2));color:var(--ast-action-buttons-color, inherit)}.ast-error:hover{color:var(--ast-error-color, rgba(249, 58, 55, .7))}.ast-btn{border:0;text-align:left;padding-top:.5rem;padding-bottom:.5rem;display:flex;align-items:center}.dark{--ast-primary-bg: #0d0701;--ast-primary-color: #008cd1;--ast-secondary-bg: #00070e;--ast-secondary-color: #ffa258;--ast-input-bg: #070707;--ast-input-color: rgba(222, 218, 218, .75);--ast-muted-color: rgba(222, 218, 218, .75);--ast-saved-chat-hover-background: #262421;--ast-message-table-border-color: #333333;--ast-message-table-tr-bg: #070707;--ast-message-table-tr-border-color: #222222;--ast-reference-icon-color: white;--ast-reference-icon-active-color: black;--ast-reference-passages-color: white;--ast-reference-expanded-hover-bg: #262421;--ast-message-reference-color: black;--ast-action-buttons-color: white;--ast-action-buttons-hover-color: #6dbee6;--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}\n"] }]
|
|
29
|
-
}], propDecorators: { reference: [{
|
|
30
|
-
type: Input
|
|
31
|
-
}], attachment: [{
|
|
32
|
-
type: Input
|
|
33
|
-
}], partId: [{
|
|
34
|
-
type: Input
|
|
35
|
-
}], openDocument: [{
|
|
36
|
-
type: Output
|
|
37
|
-
}], openPreview: [{
|
|
38
|
-
type: Output
|
|
39
|
-
}] } });
|
|
40
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hhdC1yZWZlcmVuY2UuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvYXNzaXN0YW50L2NoYXQvY2hhdC1yZWZlcmVuY2UvY2hhdC1yZWZlcmVuY2UuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvYXNzaXN0YW50L2NoYXQvY2hhdC1yZWZlcmVuY2UvY2hhdC1yZWZlcmVuY2UuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDdkUsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ3hELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLHNDQUFzQyxDQUFDOzs7O0FBVTNFLE1BQU0sT0FBTyxzQkFBc0I7SUFQbkM7UUFhWSxpQkFBWSxHQUFHLElBQUksWUFBWSxFQUF5QixDQUFDO1FBQ3pELGdCQUFXLEdBQUcsSUFBSSxZQUFZLEVBQXlCLENBQUM7S0FXbkU7SUFUQyxJQUFJLEtBQUs7UUFDUCxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVU7WUFBRSxPQUFPLEVBQUUsQ0FBQztRQUNoQyxPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxJQUFJLElBQUksQ0FBQyxNQUFNLEtBQUssSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDNUcsQ0FBQztJQUVELGdCQUFnQjtRQUNkLElBQUksSUFBSSxDQUFDLE1BQU07WUFBRSxPQUFPO1FBQ3hCLElBQUksQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQy9ELENBQUM7O21IQWpCVSxzQkFBc0I7dUdBQXRCLHNCQUFzQixvT0NibkMsNHNDQW1CQSxvK0dEUlksWUFBWSwrUEFBRSxXQUFXLHVQQUFFLG1CQUFtQjsyRkFFN0Msc0JBQXNCO2tCQVBsQyxTQUFTOytCQUNFLG1CQUFtQixjQUdqQixJQUFJLFdBQ1AsQ0FBQyxZQUFZLEVBQUUsV0FBVyxFQUFFLG1CQUFtQixDQUFDOzhCQUloRCxTQUFTO3NCQUFqQixLQUFLO2dCQUNHLFVBQVU7c0JBQWxCLEtBQUs7Z0JBQ0csTUFBTTtzQkFBZCxLQUFLO2dCQUVJLFlBQVk7c0JBQXJCLE1BQU07Z0JBQ0csV0FBVztzQkFBcEIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBDb21wb25lbnQsIEV2ZW50RW1pdHRlciwgSW5wdXQsIE91dHB1dCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgVXRpbHNNb2R1bGUgfSBmcm9tICdAc2luZXF1YS9jb21wb25lbnRzL3V0aWxzJztcbmltcG9ydCB7IEZvcm1hdEljb25Db21wb25lbnQgfSBmcm9tICcuLi9mb3JtYXQtaWNvbi9mb3JtYXQtaWNvbi5jb21wb25lbnQnO1xuaW1wb3J0IHsgQ2hhdENvbnRleHRBdHRhY2htZW50LCBEb2N1bWVudFBhcnQgfSBmcm9tICcuLi90eXBlcyc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ3NxLWNoYXQtcmVmZXJlbmNlJyxcbiAgdGVtcGxhdGVVcmw6ICcuL2NoYXQtcmVmZXJlbmNlLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vY2hhdC1yZWZlcmVuY2UuY29tcG9uZW50LnNjc3MnXSxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW0NvbW1vbk1vZHVsZSwgVXRpbHNNb2R1bGUsIEZvcm1hdEljb25Db21wb25lbnRdXG59KVxuZXhwb3J0IGNsYXNzIENoYXRSZWZlcmVuY2VDb21wb25lbnQge1xuXG4gIEBJbnB1dCgpIHJlZmVyZW5jZTogc3RyaW5nO1xuICBASW5wdXQoKSBhdHRhY2htZW50OiBDaGF0Q29udGV4dEF0dGFjaG1lbnQ7XG4gIEBJbnB1dCgpIHBhcnRJZD86IG51bWJlcjtcblxuICBAT3V0cHV0KCkgb3BlbkRvY3VtZW50ID0gbmV3IEV2ZW50RW1pdHRlcjxDaGF0Q29udGV4dEF0dGFjaG1lbnQ+KCk7XG4gIEBPdXRwdXQoKSBvcGVuUHJldmlldyA9IG5ldyBFdmVudEVtaXR0ZXI8Q2hhdENvbnRleHRBdHRhY2htZW50PigpO1xuXG4gIGdldCBwYXJ0cygpOiBEb2N1bWVudFBhcnRbXSB7XG4gICAgaWYgKCF0aGlzLmF0dGFjaG1lbnQpIHJldHVybiBbXTtcbiAgICByZXR1cm4gdGhpcy5hdHRhY2htZW50LnBhcnRzLmZpbHRlcihwYXJ0ID0+ICghdGhpcy5wYXJ0SWQgfHwgcGFydC5wYXJ0SWQgPT09IHRoaXMucGFydElkKSAmJiAhIXBhcnQudGV4dCk7XG4gIH1cblxuICBleHBhbmRBdHRhY2htZW50KCkge1xuICAgIGlmICh0aGlzLnBhcnRJZCkgcmV0dXJuO1xuICAgIHRoaXMuYXR0YWNobWVudFsnJGV4cGFuZGVkJ10gPSAhdGhpcy5hdHRhY2htZW50WyckZXhwYW5kZWQnXTtcbiAgfVxufVxuIiwiPGRpdiBbY2xhc3MucmVmZXJlbmNlLXRvb2x0aXBdPVwiISFwYXJ0SWRcIj5cbiAgICA8ZGl2IGNsYXNzPVwicmVmZXJlbmNlLWRhdGFcIiBbY2xhc3MuZXhwYW5kZWRdPVwiYXR0YWNobWVudFsnJGV4cGFuZGVkJ10gfHwgISFwYXJ0SWRcIiAoY2xpY2spPVwiZXhwYW5kQXR0YWNobWVudCgpXCI+XG4gICAgICAgIDxzcGFuIGNsYXNzPVwicmVmZXJlbmNlIG1lLTFcIj57e3JlZmVyZW5jZX19PC9zcGFuPlxuICAgICAgICA8c3EtZm9ybWF0LWljb24gW2V4dGVuc2lvbl09XCJhdHRhY2htZW50LnJlY29yZC5maWxlZXh0XCI+PC9zcS1mb3JtYXQtaWNvbj5cbiAgICAgICAgPGEgW2lkXT1cIidhdHRhY2htZW50LScrYXR0YWNobWVudC5yZWNvcmRJZFwiPlxuICAgICAgICAgICAge3thdHRhY2htZW50LnJlY29yZC50aXRsZX19XG4gICAgICAgIDwvYT5cbiAgICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtZXllXCIgKGNsaWNrKT1cIiRldmVudC5zdG9wUHJvcGFnYXRpb24oKTsgb3BlblByZXZpZXcuZW1pdChhdHRhY2htZW50KVwiIFtzcVRvb2x0aXBdPVwiIXBhcnRJZCA/ICdQcmV2aWV3IGRvY3VtZW50JyA6ICcnXCI+PC9pPlxuICAgICAgICA8aSBjbGFzcz1cImZhcyBmYS1hcnJvdy11cC1yaWdodC1mcm9tLXNxdWFyZVwiICpuZ0lmPVwiYXR0YWNobWVudC5yZWNvcmQudXJsMSB8fCBhdHRhY2htZW50LnJlY29yZC5vcmlnaW5hbFVybFwiXG4gICAgICAgICAgICAoY2xpY2spPVwiJGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpOyBvcGVuRG9jdW1lbnQuZW1pdChhdHRhY2htZW50KVwiIFtzcVRvb2x0aXBdPVwiIXBhcnRJZCA/ICdPcGVuIGRvY3VtZW50JyA6ICcnXCI+XG4gICAgICAgIDwvaT5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwicmVmZXJlbmNlLXBhc3NhZ2VzXCIgKm5nSWY9XCIhIXBhcnRJZCB8fCAoYXR0YWNobWVudFsnJGV4cGFuZGVkJ10pICYmIHBhcnRzLmxlbmd0aFwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwicmVmZXJlbmNlLXBhc3NhZ2VcIiAqbmdGb3I9XCJsZXQgcGFydCBvZiBwYXJ0c1wiPlxuICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJyZWZlcmVuY2UgbWUtMVwiPnt7cmVmZXJlbmNlfX0ue3twYXJ0LnBhcnRJZH19PC9zcGFuPlxuICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJ3LTEwMCBwZS0yXCIgW2lubmVySFRNTF09XCJwYXJ0LnRleHRcIj48L3NwYW4+XG4gICAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuPC9kaXY+XG4iXX0=
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
import { Component, EventEmitter, Input, Output, inject } from "@angular/core";
|
|
2
|
-
import { Subscription, filter, switchMap, tap } from "rxjs";
|
|
3
|
-
import { InstanceManagerService } from "../instance-manager.service";
|
|
4
|
-
import { PrincipalWebService } from "@sinequa/core/web-services";
|
|
5
|
-
import { CommonModule } from "@angular/common";
|
|
6
|
-
import { FormsModule } from "@angular/forms";
|
|
7
|
-
import { LoginService } from "@sinequa/core/login";
|
|
8
|
-
import { Utils } from "@sinequa/core/base";
|
|
9
|
-
import { AppService } from "@sinequa/core/app-utils";
|
|
10
|
-
import * as i0 from "@angular/core";
|
|
11
|
-
import * as i1 from "@angular/common";
|
|
12
|
-
import * as i2 from "@angular/forms";
|
|
13
|
-
export class ChatSettingsV3Component {
|
|
14
|
-
constructor() {
|
|
15
|
-
this._update = new EventEmitter();
|
|
16
|
-
this._cancel = new EventEmitter();
|
|
17
|
-
this.subscription = new Subscription();
|
|
18
|
-
this.functions = [];
|
|
19
|
-
this.isAdmin = false;
|
|
20
|
-
this.loginService = inject(LoginService);
|
|
21
|
-
this.instanceManagerService = inject(InstanceManagerService);
|
|
22
|
-
this.principalService = inject(PrincipalWebService);
|
|
23
|
-
this.appService = inject(AppService);
|
|
24
|
-
}
|
|
25
|
-
ngOnInit() {
|
|
26
|
-
this.subscription.add(this.loginService.events.pipe(filter(e => e.type === 'login-complete'), tap(_ => this.instantiateChatService()), switchMap(() => this.chatService.initConfig$), filter(initConfig => !!initConfig)).subscribe(_ => {
|
|
27
|
-
this.isAdmin = this.principalService.principal.isAdministrator;
|
|
28
|
-
// Init config with a copy of the original chat config, so that it won't be modified by the user until he clicks on save
|
|
29
|
-
this.config = JSON.parse(JSON.stringify(this.chatService.assistantConfig$.value));
|
|
30
|
-
this.selectedModel = this.chatService.getModel(this.config.defaultValues.service_id, this.config.defaultValues.model_id);
|
|
31
|
-
this.initFunctionsList();
|
|
32
|
-
}));
|
|
33
|
-
}
|
|
34
|
-
ngOnDestroy() {
|
|
35
|
-
this.subscription.unsubscribe();
|
|
36
|
-
}
|
|
37
|
-
get hasPrompts() {
|
|
38
|
-
return this.isAdmin
|
|
39
|
-
|| !!this.config.uiSettings.displaySystemPrompt
|
|
40
|
-
|| !!this.config.uiSettings.displayUserPrompt;
|
|
41
|
-
}
|
|
42
|
-
get hasAdvancedParameters() {
|
|
43
|
-
return this.isAdmin
|
|
44
|
-
|| !!this.config.uiSettings.temperature
|
|
45
|
-
|| !!this.config.uiSettings.top_p
|
|
46
|
-
|| !!this.config.uiSettings.max_tokens;
|
|
47
|
-
}
|
|
48
|
-
get hasModel() {
|
|
49
|
-
return this.isAdmin
|
|
50
|
-
|| !!this.config.uiSettings.servicesModels
|
|
51
|
-
|| !!this.config.uiSettings.functions
|
|
52
|
-
|| !!this.config.uiSettings.debug
|
|
53
|
-
|| !!this.config.uiSettings.temperature
|
|
54
|
-
|| !!this.config.uiSettings.top_p
|
|
55
|
-
|| !!this.config.uiSettings.max_tokens;
|
|
56
|
-
}
|
|
57
|
-
instantiateChatService() {
|
|
58
|
-
this.chatService = this.instanceManagerService.getInstance(this.instanceId);
|
|
59
|
-
}
|
|
60
|
-
onChatModelChange(selectedModel) {
|
|
61
|
-
// Update properties based on the selected model
|
|
62
|
-
this.config.defaultValues.service_id = selectedModel.serviceId;
|
|
63
|
-
this.config.defaultValues.model_id = selectedModel.modelId;
|
|
64
|
-
}
|
|
65
|
-
getFunctionDescription(name) {
|
|
66
|
-
return this.chatService.functions?.find(fn => fn.functionName === name)?.description || "";
|
|
67
|
-
}
|
|
68
|
-
toggleFunctionsSelection(name) {
|
|
69
|
-
// Update the enabled property of the function
|
|
70
|
-
const index = this.config.defaultValues.functions.findIndex(func => func.name === name);
|
|
71
|
-
this.config.defaultValues.functions[index].enabled = this.functions[index].enabled;
|
|
72
|
-
}
|
|
73
|
-
initFunctionsList() {
|
|
74
|
-
this.functions = this.config.defaultValues.functions.filter(func => !!this.chatService.functions?.find(fn => fn.functionName === func.name));
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Save the new chat config in the chat service and the user preferences
|
|
78
|
-
* If the user has never modified the default values, we need to save the hash of the standard default values, as defined by the admin, in order to properly track changes afterwards.
|
|
79
|
-
*/
|
|
80
|
-
save() {
|
|
81
|
-
const userSettingsConfig = this.chatService.assistants[this.instanceId] || {};
|
|
82
|
-
if (!userSettingsConfig.defaultValues) { // At this point, it is the very first time the user makes changes to the default values
|
|
83
|
-
const standardChatConfig = this.appService.app?.data?.assistants?.[this.instanceId];
|
|
84
|
-
const hashes = { ...userSettingsConfig.hashes, "applied-defaultValues-hash": Utils.sha512(JSON.stringify(standardChatConfig.defaultValues)) };
|
|
85
|
-
this.chatService.updateChatConfig(this.config, hashes);
|
|
86
|
-
}
|
|
87
|
-
else {
|
|
88
|
-
this.chatService.updateChatConfig(this.config);
|
|
89
|
-
}
|
|
90
|
-
this.chatService.generateAuditEvent("configuration.edit", { 'configuration': JSON.stringify(this.config) });
|
|
91
|
-
this._update.emit(this.config);
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* Cancel the current changes
|
|
95
|
-
*/
|
|
96
|
-
cancel() {
|
|
97
|
-
this._cancel.emit(this.chatService.assistantConfig$.value);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
ChatSettingsV3Component.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ChatSettingsV3Component, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
101
|
-
ChatSettingsV3Component.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: ChatSettingsV3Component, isStandalone: true, selector: "sq-chat-settings-v3", inputs: { instanceId: "instanceId" }, outputs: { _update: "update", _cancel: "cancel" }, ngImport: i0, template: "<div class=\"sq-chat-settings\" *ngIf=\"isAdmin || config.uiSettings.display\">\n <div class=\"settings-panel card-body small\" *ngIf=\"config\">\n\n <h5 *ngIf=\"hasModel\">Model</h5>\n <div class=\"mb-2\" *ngIf=\"isAdmin || config.uiSettings.servicesModels\">\n <label for=\"gllmModel\" class=\"form-label\">Model</label>\n <select class=\"form-select\" id=\"gllmModel\" [(ngModel)]=\"selectedModel\" (ngModelChange)=\"onChatModelChange($event)\">\n <option *ngFor=\"let model of chatService.models\" [ngValue]=\"model\">{{model.displayName}}</option>\n </select>\n </div>\n\n <div class=\"mb-4\" *ngIf=\"isAdmin || config.uiSettings.functions\">\n <label for=\"gllmFunctions\" class=\"form-label\">Functions</label>\n <div id=\"gllmFunctions\" *ngFor=\"let func of functions\" class=\"multi-option form-check form-switch\">\n <input class=\"form-check-input\" type=\"checkbox\" role=\"switch\" [id]=\"func.name\" [(ngModel)]=\"func.enabled\"\n (ngModelChange)=\"toggleFunctionsSelection(func.name)\">\n <label class=\"form-check-label\" [for]=\"func.name\" [title]=\"getFunctionDescription(func.name)\">{{ func.name }}</label>\n </div>\n </div>\n\n <div class=\"form-check form-switch mb-2\" *ngIf=\"isAdmin || config.uiSettings.debug\">\n <input class=\"form-check-input\" type=\"checkbox\" role=\"switch\" id=\"debug\" [(ngModel)]=\"config.defaultValues.debug\">\n <label class=\"form-check-label\" for=\"debug\">Debug</label>\n </div>\n\n <details *ngIf=\"hasAdvancedParameters\">\n <summary>Advanced parameters</summary>\n <div class=\"mb-2\" *ngIf=\"isAdmin || config.uiSettings.temperature\">\n <label for=\"temperature\" class=\"form-label\">Temperature: {{config.defaultValues.temperature}}</label>\n <input type=\"range\" class=\"form-range form-range-sm\" min=\"0\" max=\"2\" step=\"0.1\" id=\"temperature\"\n [(ngModel)]=\"config.defaultValues.temperature\">\n </div>\n <div class=\"mb-2\" *ngIf=\"isAdmin || config.uiSettings.top_p\">\n <label for=\"top-p\" class=\"form-label\">Top P: {{config.defaultValues.top_p}}</label>\n <input type=\"range\" class=\"form-range form-range-sm\" min=\"0\" max=\"1\" step=\"0.05\" id=\"top-p\"\n [(ngModel)]=\"config.defaultValues.top_p\">\n </div>\n <div class=\"mb-2\" *ngIf=\"isAdmin || config.uiSettings.max_tokens\">\n <label for=\"max-tokens\" class=\"form-label\">Max generated tokens per answer:\n {{config.defaultValues.max_tokens}}</label>\n <input type=\"range\" class=\"form-range form-range-sm\" min=\"1\" max=\"2048\" step=\"1\" id=\"max-tokens\"\n [(ngModel)]=\"config.defaultValues.max_tokens\">\n </div>\n </details>\n\n <hr>\n\n <h5 *ngIf=\"hasPrompts\">Prompts</h5>\n <div class=\"mb-2\" *ngIf=\"isAdmin || config.uiSettings.displaySystemPrompt\">\n <label for=\"initialSystemPrompt\" class=\"form-label\">System prompt (hidden)</label>\n <textarea class=\"form-control\" id=\"initialSystemPrompt\" [(ngModel)]=\"config.defaultValues.systemPrompt\"></textarea>\n </div>\n <div class=\"mb-2\" *ngIf=\"isAdmin || config.uiSettings.displayUserPrompt\">\n <label for=\"initialUserPrompt\" class=\"form-label\">Initial user prompt</label>\n <textarea class=\"form-control\" id=\"initialUserPrompt\" [(ngModel)]=\"config.defaultValues.userPrompt\"></textarea>\n </div>\n\n </div>\n\n <div class=\"buttons-panel d-flex justify-content-end\">\n <button class=\"btn btn-light me-1\" (click)=\"cancel()\">Cancel</button>\n <button class=\"btn btn-primary\" *ngIf=\"config\" (click)=\"save()\">Save</button>\n </div>\n\n</div>\n", styles: [":host{display:block;width:var(--ast-chat-settings-width, 100%);max-width:100%;height:100%;margin-left:auto;margin-right:auto;padding-top:var(--ast-chat-settings-padding-top, 0);padding-bottom:var(--ast-chat-settings-padding-bottom, 0)}.sq-chat-settings{display:flex;flex-direction:column;height:100%}.sq-chat-settings .settings-panel{flex-grow:1;overflow:auto}.sq-chat-settings .buttons-panel{padding-top:.5rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: 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.RangeValueAccessor, selector: "input[type=range][formControlName],input[type=range][formControl],input[type=range][ngModel]" }, { kind: "directive", type: i2.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { 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"] }] });
|
|
102
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ChatSettingsV3Component, decorators: [{
|
|
103
|
-
type: Component,
|
|
104
|
-
args: [{ selector: 'sq-chat-settings-v3', standalone: true, imports: [CommonModule, FormsModule], template: "<div class=\"sq-chat-settings\" *ngIf=\"isAdmin || config.uiSettings.display\">\n <div class=\"settings-panel card-body small\" *ngIf=\"config\">\n\n <h5 *ngIf=\"hasModel\">Model</h5>\n <div class=\"mb-2\" *ngIf=\"isAdmin || config.uiSettings.servicesModels\">\n <label for=\"gllmModel\" class=\"form-label\">Model</label>\n <select class=\"form-select\" id=\"gllmModel\" [(ngModel)]=\"selectedModel\" (ngModelChange)=\"onChatModelChange($event)\">\n <option *ngFor=\"let model of chatService.models\" [ngValue]=\"model\">{{model.displayName}}</option>\n </select>\n </div>\n\n <div class=\"mb-4\" *ngIf=\"isAdmin || config.uiSettings.functions\">\n <label for=\"gllmFunctions\" class=\"form-label\">Functions</label>\n <div id=\"gllmFunctions\" *ngFor=\"let func of functions\" class=\"multi-option form-check form-switch\">\n <input class=\"form-check-input\" type=\"checkbox\" role=\"switch\" [id]=\"func.name\" [(ngModel)]=\"func.enabled\"\n (ngModelChange)=\"toggleFunctionsSelection(func.name)\">\n <label class=\"form-check-label\" [for]=\"func.name\" [title]=\"getFunctionDescription(func.name)\">{{ func.name }}</label>\n </div>\n </div>\n\n <div class=\"form-check form-switch mb-2\" *ngIf=\"isAdmin || config.uiSettings.debug\">\n <input class=\"form-check-input\" type=\"checkbox\" role=\"switch\" id=\"debug\" [(ngModel)]=\"config.defaultValues.debug\">\n <label class=\"form-check-label\" for=\"debug\">Debug</label>\n </div>\n\n <details *ngIf=\"hasAdvancedParameters\">\n <summary>Advanced parameters</summary>\n <div class=\"mb-2\" *ngIf=\"isAdmin || config.uiSettings.temperature\">\n <label for=\"temperature\" class=\"form-label\">Temperature: {{config.defaultValues.temperature}}</label>\n <input type=\"range\" class=\"form-range form-range-sm\" min=\"0\" max=\"2\" step=\"0.1\" id=\"temperature\"\n [(ngModel)]=\"config.defaultValues.temperature\">\n </div>\n <div class=\"mb-2\" *ngIf=\"isAdmin || config.uiSettings.top_p\">\n <label for=\"top-p\" class=\"form-label\">Top P: {{config.defaultValues.top_p}}</label>\n <input type=\"range\" class=\"form-range form-range-sm\" min=\"0\" max=\"1\" step=\"0.05\" id=\"top-p\"\n [(ngModel)]=\"config.defaultValues.top_p\">\n </div>\n <div class=\"mb-2\" *ngIf=\"isAdmin || config.uiSettings.max_tokens\">\n <label for=\"max-tokens\" class=\"form-label\">Max generated tokens per answer:\n {{config.defaultValues.max_tokens}}</label>\n <input type=\"range\" class=\"form-range form-range-sm\" min=\"1\" max=\"2048\" step=\"1\" id=\"max-tokens\"\n [(ngModel)]=\"config.defaultValues.max_tokens\">\n </div>\n </details>\n\n <hr>\n\n <h5 *ngIf=\"hasPrompts\">Prompts</h5>\n <div class=\"mb-2\" *ngIf=\"isAdmin || config.uiSettings.displaySystemPrompt\">\n <label for=\"initialSystemPrompt\" class=\"form-label\">System prompt (hidden)</label>\n <textarea class=\"form-control\" id=\"initialSystemPrompt\" [(ngModel)]=\"config.defaultValues.systemPrompt\"></textarea>\n </div>\n <div class=\"mb-2\" *ngIf=\"isAdmin || config.uiSettings.displayUserPrompt\">\n <label for=\"initialUserPrompt\" class=\"form-label\">Initial user prompt</label>\n <textarea class=\"form-control\" id=\"initialUserPrompt\" [(ngModel)]=\"config.defaultValues.userPrompt\"></textarea>\n </div>\n\n </div>\n\n <div class=\"buttons-panel d-flex justify-content-end\">\n <button class=\"btn btn-light me-1\" (click)=\"cancel()\">Cancel</button>\n <button class=\"btn btn-primary\" *ngIf=\"config\" (click)=\"save()\">Save</button>\n </div>\n\n</div>\n", styles: [":host{display:block;width:var(--ast-chat-settings-width, 100%);max-width:100%;height:100%;margin-left:auto;margin-right:auto;padding-top:var(--ast-chat-settings-padding-top, 0);padding-bottom:var(--ast-chat-settings-padding-bottom, 0)}.sq-chat-settings{display:flex;flex-direction:column;height:100%}.sq-chat-settings .settings-panel{flex-grow:1;overflow:auto}.sq-chat-settings .buttons-panel{padding-top:.5rem}\n"] }]
|
|
105
|
-
}], propDecorators: { instanceId: [{
|
|
106
|
-
type: Input
|
|
107
|
-
}], _update: [{
|
|
108
|
-
type: Output,
|
|
109
|
-
args: ["update"]
|
|
110
|
-
}], _cancel: [{
|
|
111
|
-
type: Output,
|
|
112
|
-
args: ["cancel"]
|
|
113
|
-
}] } });
|
|
114
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hhdC1zZXR0aW5ncy12My5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9hc3Npc3RhbnQvY2hhdC9jaGF0LXNldHRpbmdzLXYzL2NoYXQtc2V0dGluZ3MtdjMuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvYXNzaXN0YW50L2NoYXQvY2hhdC1zZXR0aW5ncy12My9jaGF0LXNldHRpbmdzLXYzLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBcUIsTUFBTSxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUdsRyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQzVELE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQ3JFLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ2pFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDN0MsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ25ELE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUMzQyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0seUJBQXlCLENBQUM7Ozs7QUFTckQsTUFBTSxPQUFPLHVCQUF1QjtJQVBwQztRQVdvQixZQUFPLEdBQUcsSUFBSSxZQUFZLEVBQWMsQ0FBQztRQUN6QyxZQUFPLEdBQUcsSUFBSSxZQUFZLEVBQWMsQ0FBQztRQUkzRCxpQkFBWSxHQUFHLElBQUksWUFBWSxFQUFFLENBQUM7UUFFbEMsY0FBUyxHQUF1QyxFQUFF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SUFDN0QsQ0FBQzs7b0hBN0dVLHVCQUF1Qjt3R0FBdkIsdUJBQXVCLHdLQ25CcEMsbXFIQWlFQSxzZERoRFksWUFBWSwrUEFBRSxXQUFXOzJGQUV4Qix1QkFBdUI7a0JBUG5DLFNBQVM7K0JBQ0UscUJBQXFCLGNBR25CLElBQUksV0FDUCxDQUFDLFlBQVksRUFBRSxXQUFXLENBQUM7OEJBSTNCLFVBQVU7c0JBQWxCLEtBQUs7Z0JBRVksT0FBTztzQkFBeEIsTUFBTTt1QkFBQyxRQUFRO2dCQUNFLE9BQU87c0JBQXhCLE1BQU07dUJBQUMsUUFBUSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgRXZlbnRFbWl0dGVyLCBJbnB1dCwgT25EZXN0cm95LCBPbkluaXQsIE91dHB1dCwgaW5qZWN0IH0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcbmltcG9ydCB7IENoYXRTZXJ2aWNlIH0gZnJvbSBcIi4uL2NoYXQuc2VydmljZVwiO1xuaW1wb3J0IHsgQ2hhdENvbmZpZywgR2xsbU1vZGVsRGVzY3JpcHRpb24gfSBmcm9tIFwiLi4vdHlwZXNcIjtcbmltcG9ydCB7IFN1YnNjcmlwdGlvbiwgZmlsdGVyLCBzd2l0Y2hNYXAsIHRhcCB9IGZyb20gXCJyeGpzXCI7XG5pbXBvcnQgeyBJbnN0YW5jZU1hbmFnZXJTZXJ2aWNlIH0gZnJvbSBcIi4uL2luc3RhbmNlLW1hbmFnZXIuc2VydmljZVwiO1xuaW1wb3J0IHsgUHJpbmNpcGFsV2ViU2VydmljZSB9IGZyb20gXCJAc2luZXF1YS9jb3JlL3dlYi1zZXJ2aWNlc1wiO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSBcIkBhbmd1bGFyL2NvbW1vblwiO1xuaW1wb3J0IHsgRm9ybXNNb2R1bGUgfSBmcm9tIFwiQGFuZ3VsYXIvZm9ybXNcIjtcbmltcG9ydCB7IExvZ2luU2VydmljZSB9IGZyb20gXCJAc2luZXF1YS9jb3JlL2xvZ2luXCI7XG5pbXBvcnQgeyBVdGlscyB9IGZyb20gXCJAc2luZXF1YS9jb3JlL2Jhc2VcIjtcbmltcG9ydCB7IEFwcFNlcnZpY2UgfSBmcm9tIFwiQHNpbmVxdWEvY29yZS9hcHAtdXRpbHNcIjtcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnc3EtY2hhdC1zZXR0aW5ncy12MycsXG4gIHRlbXBsYXRlVXJsOiAnLi9jaGF0LXNldHRpbmdzLXYzLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbXCIuL2NoYXQtc2V0dGluZ3MtdjMuY29tcG9uZW50LnNjc3NcIl0sXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtDb21tb25Nb2R1bGUsIEZvcm1zTW9kdWxlXVxufSlcbmV4cG9ydCBjbGFzcyBDaGF0U2V0dGluZ3NWM0NvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95IHtcbiAgLyoqIERlZmluZSB0aGUga2V5IGJhc2VkIG9uIGl0LCB0aGUgYXBwcm9wcmlhdGUgY2hhdFNlcnZpY2UgaW5zdGFuY2Ugd2lsbCBiZSByZXR1cm5lZCBmcm9tIGluc3RhbmNlTWFuYWdlclNlcnZpY2UgKi9cbiAgQElucHV0KCkgaW5zdGFuY2VJZDogc3RyaW5nO1xuXG4gIEBPdXRwdXQoXCJ1cGRhdGVcIikgX3VwZGF0ZSA9IG5ldyBFdmVudEVtaXR0ZXI8Q2hhdENvbmZpZz4oKTtcbiAgQE91dHB1dChcImNhbmNlbFwiKSBfY2FuY2VsID0gbmV3IEV2ZW50RW1pdHRlcjxDaGF0Q29uZmlnPigpO1xuXG4gIGNoYXRTZXJ2aWNlOiBDaGF0U2VydmljZTtcbiAgY29uZmlnOiBDaGF0Q29uZmlnO1xuICBzdWJzY3JpcHRpb24gPSBuZXcgU3Vic2NyaXB0aW9uKCk7XG4gIHNlbGVjdGVkTW9kZWw6IEdsbG1Nb2RlbERlc2NyaXB0aW9uIHwgdW5kZWZpbmVkO1xuICBmdW5jdGlvbnM6IHtuYW1lOiBzdHJpbmcsIGVuYWJsZWQ6IGJvb2xlYW59W10gPSBbXTtcbiAgaXNBZG1pbiA9IGZhbHNlO1xuXG4gIHB1YmxpYyBsb2dpblNlcnZpY2UgPSBpbmplY3QoTG9naW5TZXJ2aWNlKTtcbiAgcHVibGljIGluc3RhbmNlTWFuYWdlclNlcnZpY2UgPSBpbmplY3QoSW5zdGFuY2VNYW5hZ2VyU2VydmljZSk7XG4gIHB1YmxpYyBwcmluY2lwYWxTZXJ2aWNlID0gaW5qZWN0KFByaW5jaXBhbFdlYlNlcnZpY2UpO1xuICBwdWJsaWMgYXBwU2VydmljZSA9IGluamVjdChBcHBTZXJ2aWNlKTtcblxuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICB0aGlzLnN1YnNjcmlwdGlvbi5hZGQoXG4gICAgICB0aGlzLmxvZ2luU2VydmljZS5ldmVudHMucGlwZShcbiAgICAgICAgZmlsdGVyKGUgPT4gZS50eXBlID09PSAnbG9naW4tY29tcGxldGUnKSxcbiAgICAgICAgdGFwKF8gPT4gdGhpcy5pbnN0YW50aWF0ZUNoYXRTZXJ2aWNlKCkpLFxuICAgICAgICBzd2l0Y2hNYXAoKCkgPT4gdGhpcy5jaGF0U2VydmljZS5pbml0Q29uZmlnJCksXG4gICAgICAgIGZpbHRlcihpbml0Q29uZmlnID0+ICEhaW5pdENvbmZpZylcbiAgICAgICkuc3Vic2NyaWJlKF8gPT4ge1xuICAgICAgICB0aGlzLmlzQWRtaW4gPSB0aGlzLnByaW5jaXBhbFNlcnZpY2UucHJpbmNpcGFsIS5pc0FkbWluaXN0cmF0b3I7XG4gICAgICAgIC8vIEluaXQgY29uZmlnIHdpdGggYSBjb3B5IG9mIHRoZSBvcmlnaW5hbCBjaGF0IGNvbmZpZywgc28gdGhhdCBpdCB3b24ndCBiZSBtb2RpZmllZCBieSB0aGUgdXNlciB1bnRpbCBoZSBjbGlja3Mgb24gc2F2ZVxuICAgICAgICB0aGlzLmNvbmZpZyA9IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkodGhpcy5jaGF0U2VydmljZS5hc3Npc3RhbnRDb25maWckLnZhbHVlKSk7XG4gICAgICAgIHRoaXMuc2VsZWN0ZWRNb2RlbCA9IHRoaXMuY2hhdFNlcnZpY2UuZ2V0TW9kZWwodGhpcy5jb25maWcuZGVmYXVsdFZhbHVlcy5zZXJ2aWNlX2lkLCB0aGlzLmNvbmZpZy5kZWZhdWx0VmFsdWVzLm1vZGVsX2lkKTtcbiAgICAgICAgdGhpcy5pbml0RnVuY3Rpb25zTGlzdCgpO1xuICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5zdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgfVxuXG4gIGdldCBoYXNQcm9tcHRzKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmlzQWRtaW5cbiAgICAgIHx8ICEhdGhpcy5jb25maWcudWlTZXR0aW5ncy5kaXNwbGF5U3lzdGVtUHJvbXB0XG4gICAgICB8fCAhIXRoaXMuY29uZmlnLnVpU2V0dGluZ3MuZGlzcGxheVVzZXJQcm9tcHQ7XG4gIH1cblxuICBnZXQgaGFzQWR2YW5jZWRQYXJhbWV0ZXJzKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmlzQWRtaW5cbiAgICAgIHx8ICEhdGhpcy5jb25maWcudWlTZXR0aW5ncy50ZW1wZXJhdHVyZVxuICAgICAgfHwgISF0aGlzLmNvbmZpZy51aVNldHRpbmdzLnRvcF9wXG4gICAgICB8fCAhIXRoaXMuY29uZmlnLnVpU2V0dGluZ3MubWF4X3Rva2VucztcbiAgfVxuXG4gIGdldCBoYXNNb2RlbCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5pc0FkbWluXG4gICAgICB8fCAhIXRoaXMuY29uZmlnLnVpU2V0dGluZ3Muc2VydmljZXNNb2RlbHNcbiAgICAgIHx8ICEhdGhpcy5jb25maWcudWlTZXR0aW5ncy5mdW5jdGlvbnNcbiAgICAgIHx8ICEhdGhpcy5jb25maWcudWlTZXR0aW5ncy5kZWJ1Z1xuICAgICAgfHwgISF0aGlzLmNvbmZpZy51aVNldHRpbmdzLnRlbXBlcmF0dXJlXG4gICAgICB8fCAhIXRoaXMuY29uZmlnLnVpU2V0dGluZ3MudG9wX3BcbiAgICAgIHx8ICEhdGhpcy5jb25maWcudWlTZXR0aW5ncy5tYXhfdG9rZW5zO1xuICB9XG5cbiAgaW5zdGFudGlhdGVDaGF0U2VydmljZSgpOiB2b2lkIHtcbiAgICB0aGlzLmNoYXRTZXJ2aWNlID0gdGhpcy5pbnN0YW5jZU1hbmFnZXJTZXJ2aWNlLmdldEluc3RhbmNlKHRoaXMuaW5zdGFuY2VJZCk7XG4gIH1cblxuICBvbkNoYXRNb2RlbENoYW5nZShzZWxlY3RlZE1vZGVsOiBHbGxtTW9kZWxEZXNjcmlwdGlvbikge1xuICAgIC8vIFVwZGF0ZSBwcm9wZXJ0aWVzIGJhc2VkIG9uIHRoZSBzZWxlY3RlZCBtb2RlbFxuICAgIHRoaXMuY29uZmlnLmRlZmF1bHRWYWx1ZXMuc2VydmljZV9pZCA9IHNlbGVjdGVkTW9kZWwuc2VydmljZUlkO1xuICAgIHRoaXMuY29uZmlnLmRlZmF1bHRWYWx1ZXMubW9kZWxfaWQgPSBzZWxlY3RlZE1vZGVsLm1vZGVsSWQ7XG4gIH1cblxuICBnZXRGdW5jdGlvbkRlc2NyaXB0aW9uKG5hbWU6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuY2hhdFNlcnZpY2UuZnVuY3Rpb25zPy5maW5kKGZuID0+IGZuLmZ1bmN0aW9uTmFtZSA9PT0gbmFtZSk/LmRlc2NyaXB0aW9uIHx8IFwiXCI7XG4gIH1cblxuICB0b2dnbGVGdW5jdGlvbnNTZWxlY3Rpb24obmFtZTogc3RyaW5nKSB7XG4gICAgLy8gVXBkYXRlIHRoZSBlbmFibGVkIHByb3BlcnR5IG9mIHRoZSBmdW5jdGlvblxuICAgIGNvbnN0IGluZGV4ID0gdGhpcy5jb25maWcuZGVmYXVsdFZhbHVlcy5mdW5jdGlvbnMuZmluZEluZGV4KGZ1bmMgPT4gZnVuYy5uYW1lID09PSBuYW1lKTtcbiAgICB0aGlzLmNvbmZpZy5kZWZhdWx0VmFsdWVzLmZ1bmN0aW9uc1tpbmRleF0uZW5hYmxlZCA9IHRoaXMuZnVuY3Rpb25zW2luZGV4XS5lbmFibGVkO1xuICB9XG5cbiAgcHJpdmF0ZSBpbml0RnVuY3Rpb25zTGlzdCgpOiB2b2lkIHtcbiAgICB0aGlzLmZ1bmN0aW9ucyA9IHRoaXMuY29uZmlnLmRlZmF1bHRWYWx1ZXMuZnVuY3Rpb25zLmZpbHRlcihmdW5jID0+ICEhdGhpcy5jaGF0U2VydmljZS5mdW5jdGlvbnM/LmZpbmQoZm4gPT4gZm4uZnVuY3Rpb25OYW1lID09PSBmdW5jLm5hbWUpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTYXZlIHRoZSBuZXcgY2hhdCBjb25maWcgaW4gdGhlIGNoYXQgc2VydmljZSBhbmQgdGhlIHVzZXIgcHJlZmVyZW5jZXNcbiAgICogSWYgdGhlIHVzZXIgaGFzIG5ldmVyIG1vZGlmaWVkIHRoZSBkZWZhdWx0IHZhbHVlcywgd2UgbmVlZCB0byBzYXZlIHRoZSBoYXNoIG9mIHRoZSBzdGFuZGFyZCBkZWZhdWx0IHZhbHVlcywgYXMgZGVmaW5lZCBieSB0aGUgYWRtaW4sIGluIG9yZGVyIHRvIHByb3Blcmx5IHRyYWNrIGNoYW5nZXMgYWZ0ZXJ3YXJkcy5cbiAgICovXG4gIHNhdmUoKSB7XG4gICAgY29uc3QgdXNlclNldHRpbmdzQ29uZmlnID0gdGhpcy5jaGF0U2VydmljZS5hc3Npc3RhbnRzW3RoaXMuaW5zdGFuY2VJZF0gfHwge307XG4gICAgaWYgKCF1c2VyU2V0dGluZ3NDb25maWcuZGVmYXVsdFZhbHVlcykgeyAvLyBBdCB0aGlzIHBvaW50LCBpdCBpcyB0aGUgdmVyeSBmaXJzdCB0aW1lIHRoZSB1c2VyIG1ha2VzIGNoYW5nZXMgdG8gdGhlIGRlZmF1bHQgdmFsdWVzXG4gICAgICBjb25zdCBzdGFuZGFyZENoYXRDb25maWcgPSB0aGlzLmFwcFNlcnZpY2UuYXBwPy5kYXRhPy5hc3Npc3RhbnRzPy5bdGhpcy5pbnN0YW5jZUlkXTtcbiAgICAgIGNvbnN0IGhhc2hlcyA9IHsgLi4udXNlclNldHRpbmdzQ29uZmlnLmhhc2hlcywgXCJhcHBsaWVkLWRlZmF1bHRWYWx1ZXMtaGFzaFwiOiBVdGlscy5zaGE1MTIoSlNPTi5zdHJpbmdpZnkoc3RhbmRhcmRDaGF0Q29uZmlnLmRlZmF1bHRWYWx1ZXMpKSB9O1xuICAgICAgdGhpcy5jaGF0U2VydmljZS51cGRhdGVDaGF0Q29uZmlnKHRoaXMuY29uZmlnLCBoYXNoZXMpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmNoYXRTZXJ2aWNlLnVwZGF0ZUNoYXRDb25maWcodGhpcy5jb25maWcpO1xuICAgIH1cbiAgICB0aGlzLmNoYXRTZXJ2aWNlLmdlbmVyYXRlQXVkaXRFdmVudChcImNvbmZpZ3VyYXRpb24uZWRpdFwiLCB7ICdjb25maWd1cmF0aW9uJzogSlNPTi5zdHJpbmdpZnkodGhpcy5jb25maWcpIH0pO1xuICAgIHRoaXMuX3VwZGF0ZS5lbWl0KHRoaXMuY29uZmlnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDYW5jZWwgdGhlIGN1cnJlbnQgY2hhbmdlc1xuICAgKi9cbiAgY2FuY2VsKCkge1xuICAgIHRoaXMuX2NhbmNlbC5lbWl0KHRoaXMuY2hhdFNlcnZpY2UuYXNzaXN0YW50Q29uZmlnJC52YWx1ZSk7XG4gIH1cbn1cbiIsIjxkaXYgY2xhc3M9XCJzcS1jaGF0LXNldHRpbmdzXCIgKm5nSWY9XCJpc0FkbWluIHx8IGNvbmZpZy51aVNldHRpbmdzLmRpc3BsYXlcIj5cbiAgPGRpdiBjbGFzcz1cInNldHRpbmdzLXBhbmVsIGNhcmQtYm9keSBzbWFsbFwiICpuZ0lmPVwiY29uZmlnXCI+XG5cbiAgICA8aDUgKm5nSWY9XCJoYXNNb2RlbFwiPk1vZGVsPC9oNT5cbiAgICA8ZGl2IGNsYXNzPVwibWItMlwiICpuZ0lmPVwiaXNBZG1pbiB8fCBjb25maWcudWlTZXR0aW5ncy5zZXJ2aWNlc01vZGVsc1wiPlxuICAgICAgPGxhYmVsIGZvcj1cImdsbG1Nb2RlbFwiIGNsYXNzPVwiZm9ybS1sYWJlbFwiPk1vZGVsPC9sYWJlbD5cbiAgICAgIDxzZWxlY3QgY2xhc3M9XCJmb3JtLXNlbGVjdFwiIGlkPVwiZ2xsbU1vZGVsXCIgWyhuZ01vZGVsKV09XCJzZWxlY3RlZE1vZGVsXCIgKG5nTW9kZWxDaGFuZ2UpPVwib25DaGF0TW9kZWxDaGFuZ2UoJGV2ZW50KVwiPlxuICAgICAgICA8b3B0aW9uICpuZ0Zvcj1cImxldCBtb2RlbCBvZiBjaGF0U2VydmljZS5tb2RlbHNcIiBbbmdWYWx1ZV09XCJtb2RlbFwiPnt7bW9kZWwuZGlzcGxheU5hbWV9fTwvb3B0aW9uPlxuICAgICAgPC9zZWxlY3Q+XG4gICAgPC9kaXY+XG5cbiAgICA8ZGl2IGNsYXNzPVwibWItNFwiICpuZ0lmPVwiaXNBZG1pbiB8fCBjb25maWcudWlTZXR0aW5ncy5mdW5jdGlvbnNcIj5cbiAgICAgIDxsYWJlbCBmb3I9XCJnbGxtRnVuY3Rpb25zXCIgY2xhc3M9XCJmb3JtLWxhYmVsXCI+RnVuY3Rpb25zPC9sYWJlbD5cbiAgICAgIDxkaXYgaWQ9XCJnbGxtRnVuY3Rpb25zXCIgKm5nRm9yPVwibGV0IGZ1bmMgb2YgZnVuY3Rpb25zXCIgY2xhc3M9XCJtdWx0aS1vcHRpb24gZm9ybS1jaGVjayBmb3JtLXN3aXRjaFwiPlxuICAgICAgICA8aW5wdXQgY2xhc3M9XCJmb3JtLWNoZWNrLWlucHV0XCIgdHlwZT1cImNoZWNrYm94XCIgcm9sZT1cInN3aXRjaFwiIFtpZF09XCJmdW5jLm5hbWVcIiBbKG5nTW9kZWwpXT1cImZ1bmMuZW5hYmxlZFwiXG4gICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwidG9nZ2xlRnVuY3Rpb25zU2VsZWN0aW9uKGZ1bmMubmFtZSlcIj5cbiAgICAgICAgPGxhYmVsIGNsYXNzPVwiZm9ybS1jaGVjay1sYWJlbFwiIFtmb3JdPVwiZnVuYy5uYW1lXCIgW3RpdGxlXT1cImdldEZ1bmN0aW9uRGVzY3JpcHRpb24oZnVuYy5uYW1lKVwiPnt7IGZ1bmMubmFtZSB9fTwvbGFiZWw+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cblxuICAgIDxkaXYgY2xhc3M9XCJmb3JtLWNoZWNrIGZvcm0tc3dpdGNoIG1iLTJcIiAqbmdJZj1cImlzQWRtaW4gfHwgY29uZmlnLnVpU2V0dGluZ3MuZGVidWdcIj5cbiAgICAgIDxpbnB1dCBjbGFzcz1cImZvcm0tY2hlY2staW5wdXRcIiB0eXBlPVwiY2hlY2tib3hcIiByb2xlPVwic3dpdGNoXCIgaWQ9XCJkZWJ1Z1wiIFsobmdNb2RlbCldPVwiY29uZmlnLmRlZmF1bHRWYWx1ZXMuZGVidWdcIj5cbiAgICAgIDxsYWJlbCBjbGFzcz1cImZvcm0tY2hlY2stbGFiZWxcIiBmb3I9XCJkZWJ1Z1wiPkRlYnVnPC9sYWJlbD5cbiAgICA8L2Rpdj5cblxuICAgIDxkZXRhaWxzICpuZ0lmPVwiaGFzQWR2YW5jZWRQYXJhbWV0ZXJzXCI+XG4gICAgICA8c3VtbWFyeT5BZHZhbmNlZCBwYXJhbWV0ZXJzPC9zdW1tYXJ5PlxuICAgICAgPGRpdiBjbGFzcz1cIm1iLTJcIiAqbmdJZj1cImlzQWRtaW4gfHwgY29uZmlnLnVpU2V0dGluZ3MudGVtcGVyYXR1cmVcIj5cbiAgICAgICAgPGxhYmVsIGZvcj1cInRlbXBlcmF0dXJlXCIgY2xhc3M9XCJmb3JtLWxhYmVsXCI+VGVtcGVyYXR1cmU6IHt7Y29uZmlnLmRlZmF1bHRWYWx1ZXMudGVtcGVyYXR1cmV9fTwvbGFiZWw+XG4gICAgICAgIDxpbnB1dCB0eXBlPVwicmFuZ2VcIiBjbGFzcz1cImZvcm0tcmFuZ2UgZm9ybS1yYW5nZS1zbVwiIG1pbj1cIjBcIiBtYXg9XCIyXCIgc3RlcD1cIjAuMVwiIGlkPVwidGVtcGVyYXR1cmVcIlxuICAgICAgICAgIFsobmdNb2RlbCldPVwiY29uZmlnLmRlZmF1bHRWYWx1ZXMudGVtcGVyYXR1cmVcIj5cbiAgICAgIDwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cIm1iLTJcIiAqbmdJZj1cImlzQWRtaW4gfHwgY29uZmlnLnVpU2V0dGluZ3MudG9wX3BcIj5cbiAgICAgICAgPGxhYmVsIGZvcj1cInRvcC1wXCIgY2xhc3M9XCJmb3JtLWxhYmVsXCI+VG9wIFA6IHt7Y29uZmlnLmRlZmF1bHRWYWx1ZXMudG9wX3B9fTwvbGFiZWw+XG4gICAgICAgIDxpbnB1dCB0eXBlPVwicmFuZ2VcIiBjbGFzcz1cImZvcm0tcmFuZ2UgZm9ybS1yYW5nZS1zbVwiIG1pbj1cIjBcIiBtYXg9XCIxXCIgc3RlcD1cIjAuMDVcIiBpZD1cInRvcC1wXCJcbiAgICAgICAgICBbKG5nTW9kZWwpXT1cImNvbmZpZy5kZWZhdWx0VmFsdWVzLnRvcF9wXCI+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3M9XCJtYi0yXCIgKm5nSWY9XCJpc0FkbWluIHx8IGNvbmZpZy51aVNldHRpbmdzLm1heF90b2tlbnNcIj5cbiAgICAgICAgPGxhYmVsIGZvcj1cIm1heC10b2tlbnNcIiBjbGFzcz1cImZvcm0tbGFiZWxcIj5NYXggZ2VuZXJhdGVkIHRva2VucyBwZXIgYW5zd2VyOlxuICAgICAgICAgIHt7Y29uZmlnLmRlZmF1bHRWYWx1ZXMubWF4X3Rva2Vuc319PC9sYWJlbD5cbiAgICAgICAgPGlucHV0IHR5cGU9XCJyYW5nZVwiIGNsYXNzPVwiZm9ybS1yYW5nZSBmb3JtLXJhbmdlLXNtXCIgbWluPVwiMVwiIG1heD1cIjIwNDhcIiBzdGVwPVwiMVwiIGlkPVwibWF4LXRva2Vuc1wiXG4gICAgICAgICAgWyhuZ01vZGVsKV09XCJjb25maWcuZGVmYXVsdFZhbHVlcy5tYXhfdG9rZW5zXCI+XG4gICAgICA8L2Rpdj5cbiAgICA8L2RldGFpbHM+XG5cbiAgICA8aHI+XG5cbiAgICA8aDUgKm5nSWY9XCJoYXNQcm9tcHRzXCI+UHJvbXB0czwvaDU+XG4gICAgPGRpdiBjbGFzcz1cIm1iLTJcIiAqbmdJZj1cImlzQWRtaW4gfHwgY29uZmlnLnVpU2V0dGluZ3MuZGlzcGxheVN5c3RlbVByb21wdFwiPlxuICAgICAgPGxhYmVsIGZvcj1cImluaXRpYWxTeXN0ZW1Qcm9tcHRcIiBjbGFzcz1cImZvcm0tbGFiZWxcIj5TeXN0ZW0gcHJvbXB0IChoaWRkZW4pPC9sYWJlbD5cbiAgICAgIDx0ZXh0YXJlYSBjbGFzcz1cImZvcm0tY29udHJvbFwiIGlkPVwiaW5pdGlhbFN5c3RlbVByb21wdFwiIFsobmdNb2RlbCldPVwiY29uZmlnLmRlZmF1bHRWYWx1ZXMuc3lzdGVtUHJvbXB0XCI+PC90ZXh0YXJlYT5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwibWItMlwiICpuZ0lmPVwiaXNBZG1pbiB8fCBjb25maWcudWlTZXR0aW5ncy5kaXNwbGF5VXNlclByb21wdFwiPlxuICAgICAgPGxhYmVsIGZvcj1cImluaXRpYWxVc2VyUHJvbXB0XCIgY2xhc3M9XCJmb3JtLWxhYmVsXCI+SW5pdGlhbCB1c2VyIHByb21wdDwvbGFiZWw+XG4gICAgICA8dGV4dGFyZWEgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIiBpZD1cImluaXRpYWxVc2VyUHJvbXB0XCIgWyhuZ01vZGVsKV09XCJjb25maWcuZGVmYXVsdFZhbHVlcy51c2VyUHJvbXB0XCI+PC90ZXh0YXJlYT5cbiAgICA8L2Rpdj5cblxuICA8L2Rpdj5cblxuICA8ZGl2IGNsYXNzPVwiYnV0dG9ucy1wYW5lbCBkLWZsZXgganVzdGlmeS1jb250ZW50LWVuZFwiPlxuICAgIDxidXR0b24gY2xhc3M9XCJidG4gYnRuLWxpZ2h0IG1lLTFcIiAoY2xpY2spPVwiY2FuY2VsKClcIj5DYW5jZWw8L2J1dHRvbj5cbiAgICA8YnV0dG9uIGNsYXNzPVwiYnRuIGJ0bi1wcmltYXJ5XCIgKm5nSWY9XCJjb25maWdcIiAoY2xpY2spPVwic2F2ZSgpXCI+U2F2ZTwvYnV0dG9uPlxuICA8L2Rpdj5cblxuPC9kaXY+XG4iXX0=
|