@sinequa/assistant 3.1.1 → 3.2.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/chat-message/chat-message.component.d.ts +2 -0
- package/chat/chat-settings-v3/chat-settings-v3.component.d.ts +8 -3
- package/chat/chat.component.d.ts +164 -145
- package/chat/chat.service.d.ts +21 -914
- package/chat/prompt.component.d.ts +21 -0
- package/chat/public-api.d.ts +1 -0
- package/chat/rest-chat.service.d.ts +4 -2
- package/chat/saved-chats/saved-chats.component.d.ts +5 -3
- package/chat/styles/assistant.scss +21 -1
- package/chat/types.d.ts +284 -866
- package/chat/websocket-chat.service.d.ts +4 -2
- package/esm2020/chat/chat-message/chat-message.component.mjs +5 -3
- package/esm2020/chat/chat-reference/chat-reference.component.mjs +3 -3
- package/esm2020/chat/chat-settings-v3/chat-settings-v3.component.mjs +22 -24
- package/esm2020/chat/chat.component.mjs +88 -33
- package/esm2020/chat/chat.service.mjs +68 -24
- package/esm2020/chat/prompt.component.mjs +88 -0
- package/esm2020/chat/public-api.mjs +2 -1
- package/esm2020/chat/rest-chat.service.mjs +41 -18
- package/esm2020/chat/saved-chats/saved-chats.component.mjs +38 -7
- package/esm2020/chat/types.mjs +50 -54
- package/esm2020/chat/websocket-chat.service.mjs +46 -19
- package/fesm2015/sinequa-assistant-chat.mjs +428 -172
- package/fesm2015/sinequa-assistant-chat.mjs.map +1 -1
- package/fesm2020/sinequa-assistant-chat.mjs +429 -176
- package/fesm2020/sinequa-assistant-chat.mjs.map +1 -1
- package/package.json +4 -2
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Injectable, EventEmitter, inject, Component, Input, Output, ViewEncapsulation, ChangeDetectionStrategy, ChangeDetectorRef, ViewChild, ContentChild } from '@angular/core';
|
|
2
|
+
import { Injectable, EventEmitter, inject, Component, Input, Output, ViewEncapsulation, ChangeDetectionStrategy, ChangeDetectorRef, ViewChild, ContentChild, Inject } from '@angular/core';
|
|
3
3
|
import { Subscription, filter, tap, switchMap, BehaviorSubject, Subject, forkJoin, map, catchError, throwError, shareReplay, fromEvent, merge, takeUntil, finalize } from 'rxjs';
|
|
4
4
|
import * as i3 from '@sinequa/core/web-services';
|
|
5
5
|
import { PrincipalWebService, UserSettingsWebService, AuditWebService, SignalRWebService, JsonMethodPluginService } from '@sinequa/core/web-services';
|
|
6
6
|
import * as i1 from '@angular/common';
|
|
7
7
|
import { CommonModule } from '@angular/common';
|
|
8
8
|
import * as i2 from '@angular/forms';
|
|
9
|
-
import { FormsModule } from '@angular/forms';
|
|
9
|
+
import { FormsModule, Validators, UntypedFormControl, ReactiveFormsModule } from '@angular/forms';
|
|
10
10
|
import { LoginService, AuthenticationService } from '@sinequa/core/login';
|
|
11
11
|
import { Action } from '@sinequa/components/action';
|
|
12
12
|
import { AbstractFacet } from '@sinequa/components/facet';
|
|
@@ -16,9 +16,12 @@ import { UserPreferences } from '@sinequa/components/user-settings';
|
|
|
16
16
|
import { NotificationsService } from '@sinequa/core/notification';
|
|
17
17
|
import { z } from 'zod';
|
|
18
18
|
import { AppService } from '@sinequa/core/app-utils';
|
|
19
|
-
import
|
|
19
|
+
import * as i6$1 from '@sinequa/core/intl';
|
|
20
|
+
import { IntlService, IntlModule } from '@sinequa/core/intl';
|
|
20
21
|
import get from 'lodash/get';
|
|
21
22
|
import { Utils } from '@sinequa/core/base';
|
|
23
|
+
import * as i1$2 from '@sinequa/core/modal';
|
|
24
|
+
import { ModalService, ModalButton, ModalModule, MODAL_MODEL } from '@sinequa/core/modal';
|
|
22
25
|
import { HttpTransportType, LogLevel } from '@microsoft/signalr';
|
|
23
26
|
import { unified } from 'unified';
|
|
24
27
|
import remarkParse from 'remark-parse';
|
|
@@ -31,8 +34,13 @@ import { CollapseModule } from '@sinequa/components/collapse';
|
|
|
31
34
|
import * as i6 from 'ngx-remark';
|
|
32
35
|
import { RemarkModule } from 'ngx-remark';
|
|
33
36
|
import SafeColor from 'safecolor';
|
|
34
|
-
import
|
|
37
|
+
import 'prismjs-components-importer/esm';
|
|
38
|
+
import 'prismjs/plugins/autoloader/prism-autoloader';
|
|
35
39
|
import { parseISO, isToday, isYesterday, isThisWeek, differenceInDays, endOfYesterday, isThisMonth, differenceInMonths, isThisQuarter, isThisYear, differenceInYears, format } from 'date-fns';
|
|
40
|
+
import * as i4 from '@sinequa/components/modal';
|
|
41
|
+
import { BsModalModule } from '@sinequa/components/modal';
|
|
42
|
+
import * as i5$1 from '@sinequa/core/validation';
|
|
43
|
+
import { ValidationModule } from '@sinequa/core/validation';
|
|
36
44
|
|
|
37
45
|
/**
|
|
38
46
|
* A service to create and manage instances of ChatService dynamically based on the provided component references and the implementation type (http or websocket)
|
|
@@ -83,6 +91,7 @@ class ChatSettingsV3Component {
|
|
|
83
91
|
this._update = new EventEmitter();
|
|
84
92
|
this._cancel = new EventEmitter();
|
|
85
93
|
this.subscription = new Subscription();
|
|
94
|
+
this.functions = [];
|
|
86
95
|
this.isAdmin = false;
|
|
87
96
|
this.loginService = inject(LoginService);
|
|
88
97
|
this.instanceManagerService = inject(InstanceManagerService);
|
|
@@ -93,8 +102,8 @@ class ChatSettingsV3Component {
|
|
|
93
102
|
this.isAdmin = this.principalService.principal.isAdministrator;
|
|
94
103
|
// 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
|
|
95
104
|
this.config = JSON.parse(JSON.stringify(this.chatService.chatConfig$.value));
|
|
96
|
-
this.selectedModel = this.chatService.getModel(this.config.
|
|
97
|
-
this.
|
|
105
|
+
this.selectedModel = this.chatService.getModel(this.config.defaultValues.service_id, this.config.defaultValues.model_id);
|
|
106
|
+
this.initFunctionsList();
|
|
98
107
|
}));
|
|
99
108
|
}
|
|
100
109
|
ngOnDestroy() {
|
|
@@ -102,14 +111,14 @@ class ChatSettingsV3Component {
|
|
|
102
111
|
}
|
|
103
112
|
get hasPrompts() {
|
|
104
113
|
return this.isAdmin
|
|
105
|
-
|| !!this.config.uiSettings.
|
|
106
|
-
|| !!this.config.uiSettings.
|
|
114
|
+
|| !!this.config.uiSettings.displaySystemPrompt
|
|
115
|
+
|| !!this.config.uiSettings.displayUserPrompt;
|
|
107
116
|
}
|
|
108
117
|
get hasAdvancedParameters() {
|
|
109
118
|
return this.isAdmin
|
|
110
119
|
|| !!this.config.uiSettings.temperature
|
|
111
120
|
|| !!this.config.uiSettings.top_p
|
|
112
|
-
|| !!this.config.uiSettings.
|
|
121
|
+
|| !!this.config.uiSettings.max_tokens;
|
|
113
122
|
}
|
|
114
123
|
get hasModel() {
|
|
115
124
|
return this.isAdmin
|
|
@@ -118,49 +127,46 @@ class ChatSettingsV3Component {
|
|
|
118
127
|
|| !!this.config.uiSettings.debug
|
|
119
128
|
|| !!this.config.uiSettings.temperature
|
|
120
129
|
|| !!this.config.uiSettings.top_p
|
|
121
|
-
|| !!this.config.uiSettings.
|
|
130
|
+
|| !!this.config.uiSettings.max_tokens;
|
|
122
131
|
}
|
|
123
132
|
instantiateChatService() {
|
|
124
133
|
this.chatService = this.instanceManagerService.getInstance(this.instanceId);
|
|
125
134
|
}
|
|
126
135
|
onChatModelChange(selectedModel) {
|
|
127
136
|
// Update properties based on the selected model
|
|
128
|
-
this.config.
|
|
129
|
-
this.config.
|
|
137
|
+
this.config.defaultValues.service_id = selectedModel.serviceId;
|
|
138
|
+
this.config.defaultValues.model_id = selectedModel.modelId;
|
|
139
|
+
}
|
|
140
|
+
getFunctionDescription(name) {
|
|
141
|
+
return this.chatService.functions?.find(fn => fn.functionName === name)?.description || "";
|
|
130
142
|
}
|
|
131
143
|
toggleFunctionsSelection(name) {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
else {
|
|
136
|
-
this.config.functions.push(name);
|
|
137
|
-
}
|
|
144
|
+
// Update the enabled property of the function
|
|
145
|
+
const index = this.config.defaultValues.functions.findIndex(func => func.name === name);
|
|
146
|
+
this.config.defaultValues.functions[index].enabled = this.functions[index].enabled;
|
|
138
147
|
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
(this.chatService.functions || []).forEach(item => {
|
|
142
|
-
item['selected'] = this.config.functions.includes(item.functionName);
|
|
143
|
-
});
|
|
148
|
+
initFunctionsList() {
|
|
149
|
+
this.functions = this.config.defaultValues.functions.filter(func => !!this.chatService.functions?.find(fn => fn.functionName === func.name));
|
|
144
150
|
}
|
|
145
151
|
/**
|
|
146
152
|
* Save the new chat config in the chat service and the user preferences
|
|
147
153
|
*/
|
|
148
154
|
save() {
|
|
149
155
|
this.chatService.updateChatConfig(this.config);
|
|
150
|
-
this._update.emit();
|
|
156
|
+
this._update.emit(this.config);
|
|
151
157
|
}
|
|
152
158
|
/**
|
|
153
159
|
* Cancel the current changes
|
|
154
160
|
*/
|
|
155
161
|
cancel() {
|
|
156
|
-
this._cancel.emit();
|
|
162
|
+
this._cancel.emit(this.chatService.chatConfig$.value);
|
|
157
163
|
}
|
|
158
164
|
}
|
|
159
165
|
ChatSettingsV3Component.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ChatSettingsV3Component, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
160
|
-
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\">\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
|
|
166
|
+
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\" (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"] }] });
|
|
161
167
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ChatSettingsV3Component, decorators: [{
|
|
162
168
|
type: Component,
|
|
163
|
-
args: [{ selector: 'sq-chat-settings-v3', standalone: true, imports: [CommonModule, FormsModule], template: "<div class=\"sq-chat-settings\">\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
|
|
169
|
+
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\" (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"] }]
|
|
164
170
|
}], propDecorators: { instanceId: [{
|
|
165
171
|
type: Input
|
|
166
172
|
}], _update: [{
|
|
@@ -171,8 +177,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImpor
|
|
|
171
177
|
args: ["cancel"]
|
|
172
178
|
}] } });
|
|
173
179
|
|
|
174
|
-
// Define the Zod representation for the
|
|
175
|
-
const
|
|
180
|
+
// Define the Zod representation for the connectionSettings object
|
|
181
|
+
const connectionSettingsSchema = z.object({
|
|
176
182
|
restEndpoint: z.string().optional(),
|
|
177
183
|
websocketEndpoint: z.string().optional(),
|
|
178
184
|
signalRTransport: z.enum(["WebSockets", "ServerSentEvents", "LongPolling", "None"]),
|
|
@@ -186,50 +192,10 @@ const serviceSettingsSchema = z.object({
|
|
|
186
192
|
model_id: z.string(),
|
|
187
193
|
temperature: z.number(),
|
|
188
194
|
top_p: z.number(),
|
|
189
|
-
|
|
190
|
-
results_per_prompt: z.number(),
|
|
191
|
-
presence_penalty: z.number(),
|
|
192
|
-
frequency_penalty: z.number(),
|
|
193
|
-
});
|
|
194
|
-
// Define the Zod representation for the TextChunksOptions interface
|
|
195
|
-
const textChunksOptionsSchema = z.object({
|
|
196
|
-
extendMode: z.enum(['None', 'Sentence', 'Chars']).optional(),
|
|
197
|
-
extendScope: z.number().optional(),
|
|
198
|
-
});
|
|
199
|
-
// Define the Zod representation for the contextOptions object
|
|
200
|
-
const contextOptionsSchema = z.object({
|
|
201
|
-
docColumns: z.array(z.string()),
|
|
202
|
-
textChunkFillGaps: z.number(),
|
|
203
|
-
html: z.boolean(),
|
|
204
|
-
topPassagesOptions: z.object({
|
|
205
|
-
topPassages: z.number(),
|
|
206
|
-
topPassagesMinScore: z.number(),
|
|
207
|
-
textChunkOptions: textChunksOptionsSchema,
|
|
208
|
-
}),
|
|
209
|
-
matchingPassagesOptions: z.object({
|
|
210
|
-
matchingPassagesPerDoc: z.number(),
|
|
211
|
-
fromTopDocuments: z.number(),
|
|
212
|
-
matchingPassagesMinScore: z.number(),
|
|
213
|
-
textChunkOptions: textChunksOptionsSchema,
|
|
214
|
-
}),
|
|
215
|
-
relevantExtractsOptions: z.object({
|
|
216
|
-
topRelevantExtractsPerDoc: z.number(),
|
|
217
|
-
fromTopDocuments: z.number(),
|
|
218
|
-
textChunkOptions: textChunksOptionsSchema,
|
|
219
|
-
}),
|
|
220
|
-
htmlOptions: z.object({
|
|
221
|
-
images: z.boolean(),
|
|
222
|
-
links: z.boolean(),
|
|
223
|
-
tables: z.boolean(),
|
|
224
|
-
extendTables: z.boolean(),
|
|
225
|
-
}),
|
|
226
|
-
});
|
|
227
|
-
// Define the Zod representation for the contextSettings object
|
|
228
|
-
const contextSettingsSchema = z.object({
|
|
229
|
-
app: z.string().optional(),
|
|
230
|
-
query: z.object({}).optional(),
|
|
231
|
-
contextOptions: contextOptionsSchema,
|
|
195
|
+
max_tokens: z.number()
|
|
232
196
|
});
|
|
197
|
+
// Define the Zod representation for the additionalServiceSettings object
|
|
198
|
+
const additionalServiceSettingsSchema = z.object({});
|
|
233
199
|
// Define the Zod representation for the uiSettings object
|
|
234
200
|
const uiSettingsSchema = z.object({
|
|
235
201
|
display: z.boolean(),
|
|
@@ -237,22 +203,58 @@ const uiSettingsSchema = z.object({
|
|
|
237
203
|
functions: z.boolean(),
|
|
238
204
|
temperature: z.boolean(),
|
|
239
205
|
top_p: z.boolean(),
|
|
240
|
-
|
|
206
|
+
max_tokens: z.boolean(),
|
|
241
207
|
debug: z.boolean(),
|
|
242
208
|
displaySystemPrompt: z.boolean(),
|
|
209
|
+
displayUserPrompt: z.boolean()
|
|
210
|
+
});
|
|
211
|
+
// Define the Zod representation for the defaultValues object
|
|
212
|
+
const defaultValuesSchema = z.object({
|
|
213
|
+
service_id: z.string(),
|
|
214
|
+
model_id: z.string(),
|
|
215
|
+
functions: z.array(z.object({
|
|
216
|
+
name: z.string(),
|
|
217
|
+
enabled: z.boolean()
|
|
218
|
+
})),
|
|
219
|
+
temperature: z.number(),
|
|
220
|
+
top_p: z.number(),
|
|
221
|
+
max_tokens: z.number(),
|
|
222
|
+
debug: z.boolean(),
|
|
243
223
|
systemPrompt: z.string(),
|
|
224
|
+
userPrompt: z.string()
|
|
225
|
+
});
|
|
226
|
+
// Define the Zod representation for the modeSettings object
|
|
227
|
+
const initializationSchema = z.object({
|
|
228
|
+
event: z.enum(['Query', 'Prompt']),
|
|
229
|
+
forcedWorkflow: z.string().optional(),
|
|
230
|
+
displayUserQuery: z.boolean().optional(), // Optional for event 'Prompt'
|
|
231
|
+
}).refine(data => ((data.event === "Query") ? (!!data.forcedWorkflow && data.displayUserQuery !== undefined && data.displayUserQuery !== null) : true), {
|
|
232
|
+
message: "The 'forcedWorkflow' and 'displayUserQuery' properties must be provided when the initialization's event is 'Query'.",
|
|
233
|
+
});
|
|
234
|
+
const modeSettingsSchema = z.object({
|
|
235
|
+
enabledUserInput: z.boolean(),
|
|
244
236
|
displayUserPrompt: z.boolean(),
|
|
245
|
-
|
|
237
|
+
sendUserPrompt: z.boolean(),
|
|
238
|
+
initialization: initializationSchema
|
|
239
|
+
});
|
|
240
|
+
// Define the Zod representation for the savedChatSettings object
|
|
241
|
+
const savedChatSettingsSchema = z.object({
|
|
242
|
+
enabled: z.boolean(),
|
|
243
|
+
display: z.boolean()
|
|
244
|
+
});
|
|
245
|
+
// Define the Zod representation for the globalSettings object
|
|
246
|
+
const globalSettingsSchema = z.object({
|
|
247
|
+
disclaimer: z.string().optional(),
|
|
246
248
|
});
|
|
247
249
|
// Define the Zod representation for the entire ChatConfig object
|
|
248
250
|
const chatConfigSchema = z.object({
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
251
|
+
connectionSettings: connectionSettingsSchema,
|
|
252
|
+
defaultValues: defaultValuesSchema,
|
|
253
|
+
modeSettings: modeSettingsSchema,
|
|
252
254
|
uiSettings: uiSettingsSchema,
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
255
|
+
additionalServiceSettings: additionalServiceSettingsSchema,
|
|
256
|
+
savedChatSettings: savedChatSettingsSchema,
|
|
257
|
+
globalSettings: globalSettingsSchema
|
|
256
258
|
});
|
|
257
259
|
|
|
258
260
|
class ChatService {
|
|
@@ -269,7 +271,6 @@ class ChatService {
|
|
|
269
271
|
this.savedChats$ = new BehaviorSubject([]);
|
|
270
272
|
/** Emit the saved chat to load */
|
|
271
273
|
this.loadSavedChat$ = new BehaviorSubject(undefined);
|
|
272
|
-
this.searchService = inject(SearchService);
|
|
273
274
|
this.userSettingsService = inject(UserSettingsWebService);
|
|
274
275
|
this.notificationsService = inject(NotificationsService);
|
|
275
276
|
this.auditService = inject(AuditWebService);
|
|
@@ -277,6 +278,7 @@ class ChatService {
|
|
|
277
278
|
this.loginService = inject(LoginService);
|
|
278
279
|
this.appService = inject(AppService);
|
|
279
280
|
this.intlService = inject(IntlService);
|
|
281
|
+
this.modalService = inject(ModalService);
|
|
280
282
|
}
|
|
281
283
|
get assistants() {
|
|
282
284
|
if (!this.userSettingsService.userSettings)
|
|
@@ -314,24 +316,68 @@ class ChatService {
|
|
|
314
316
|
this._savedChatId = savedChatId;
|
|
315
317
|
}
|
|
316
318
|
/**
|
|
317
|
-
* Initialize the chat config by
|
|
318
|
-
*
|
|
319
|
+
* Initialize the chat config by managing ONLY sub-object **defaultValues** configs of the standard app config (defined in the customization json tab ) and the user preferences.
|
|
320
|
+
* To do so, a tracking mechanism is implemented to notify the user about the available updates in the defaultValues object of the standard app config.
|
|
321
|
+
* The rest of the config object coming from "standard app config" is used as it is without any override.
|
|
322
|
+
* Thus, the user preferences are used only for the defaultValues object.
|
|
323
|
+
* This provide a centralized way to manage the rest of the config object by admins and ensure a unique common behavior for all users.
|
|
319
324
|
*/
|
|
320
325
|
initChatConfig() {
|
|
321
326
|
const key = this.chatInstanceId;
|
|
322
327
|
const userSettingsConfig = this.assistants[key] || {};
|
|
323
|
-
const
|
|
324
|
-
// Validate the object against the schema
|
|
328
|
+
const standardChatConfig = this.appService.app?.data?.assistants?.[key];
|
|
325
329
|
try {
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
...
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
330
|
+
// Validate the whole config object against the schema
|
|
331
|
+
chatConfigSchema.parse(standardChatConfig);
|
|
332
|
+
// If the user preferences do not contain a config's defaultValues object, keep using the standard app config and nothing to store in the user preferences
|
|
333
|
+
if (!userSettingsConfig.defaultValues) {
|
|
334
|
+
this.chatConfig$.next({ ...standardChatConfig });
|
|
335
|
+
this.initConfig$.next(true);
|
|
336
|
+
}
|
|
337
|
+
else { // If the user has its own defaultValues in its userSettings, then we need to check for potential updates made by admins in the meantime and how he wants to manage them
|
|
338
|
+
// Retrieve already stored hashes in the user settings if exists
|
|
339
|
+
const appliedDefaultValuesHash = userSettingsConfig.hashes?.["applied-defaultValues-hash"];
|
|
340
|
+
const skippedDefaultValuesHash = userSettingsConfig.hashes?.["skipped-defaultValues-hash"];
|
|
341
|
+
// Create a hash of the current defaultValues of the standardChatConfig
|
|
342
|
+
const currentDefaultValuesHash = Utils.sha512(JSON.stringify(standardChatConfig.defaultValues));
|
|
343
|
+
// Implement the tracking mechanism to notify the user about the available updates in the defaultValues object of the standard app config
|
|
344
|
+
const condition = (currentDefaultValuesHash !== appliedDefaultValuesHash) && (currentDefaultValuesHash !== skippedDefaultValuesHash);
|
|
345
|
+
if (condition) {
|
|
346
|
+
this.modalService
|
|
347
|
+
.confirm({
|
|
348
|
+
title: "Available updates !",
|
|
349
|
+
message: "Changes have been made to the default configuration. Do you want to update your own version ?",
|
|
350
|
+
buttons: [
|
|
351
|
+
new ModalButton({ result: -4 /* ModalResult.No */, text: "See no more" }),
|
|
352
|
+
new ModalButton({ result: -7 /* ModalResult.Ignore */, text: "Remind me later" }),
|
|
353
|
+
new ModalButton({ result: -1 /* ModalResult.OK */, text: "Update", primary: true })
|
|
354
|
+
],
|
|
355
|
+
confirmType: 2 /* ConfirmType.Warning */
|
|
356
|
+
}).then(res => {
|
|
357
|
+
if (res === -1 /* ModalResult.OK */) {
|
|
358
|
+
const hashes = { "applied-defaultValues-hash": currentDefaultValuesHash, "skipped-defaultValues-hash": undefined };
|
|
359
|
+
// Update the chat config and store its defaultValues in the user preferences
|
|
360
|
+
this.updateChatConfig({ ...standardChatConfig }, hashes, true);
|
|
361
|
+
this.initConfig$.next(true);
|
|
362
|
+
}
|
|
363
|
+
else if (res === -4 /* ModalResult.No */) {
|
|
364
|
+
// Do not notify the user about changes while this skipped version is not updated
|
|
365
|
+
const hashes = { ...userSettingsConfig.hashes, "skipped-defaultValues-hash": currentDefaultValuesHash };
|
|
366
|
+
this.updateChatConfig({ ...standardChatConfig, defaultValues: userSettingsConfig.defaultValues }, hashes, false);
|
|
367
|
+
this.initConfig$.next(true);
|
|
368
|
+
}
|
|
369
|
+
else {
|
|
370
|
+
// Just pick the version in the user settings, nothing to be updated
|
|
371
|
+
this.chatConfig$.next({ ...standardChatConfig, defaultValues: userSettingsConfig.defaultValues });
|
|
372
|
+
this.initConfig$.next(true);
|
|
373
|
+
}
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
else { // No available updates Or updates has been already skipped, then just pick the version in the user settings
|
|
377
|
+
this.chatConfig$.next({ ...standardChatConfig, defaultValues: userSettingsConfig.defaultValues });
|
|
378
|
+
this.initConfig$.next(true);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
335
381
|
}
|
|
336
382
|
catch (error) {
|
|
337
383
|
this.notificationsService.error(`Missing valid configuration for the assistant instance '${key}'`);
|
|
@@ -339,25 +385,25 @@ class ChatService {
|
|
|
339
385
|
}
|
|
340
386
|
}
|
|
341
387
|
/**
|
|
342
|
-
* Update the chat config and store
|
|
388
|
+
* Update the chat config and store its defaultValues in the user preferences
|
|
343
389
|
* @param config The updated chat config
|
|
344
390
|
* @param notify Whether to notify the user about the update
|
|
345
391
|
* @param successCallback The callback to execute if the update is successful
|
|
346
392
|
* @param errorCallback The callback to execute if the update fails
|
|
347
393
|
*/
|
|
348
|
-
updateChatConfig(config, notify = true, successCallback, errorCallback) {
|
|
394
|
+
updateChatConfig(config, hashes, notify = true, successCallback, errorCallback) {
|
|
349
395
|
this.chatConfig$.next(config);
|
|
350
396
|
const assistants = Object.assign({}, this.assistants);
|
|
351
|
-
assistants[this.chatInstanceId] = config;
|
|
352
|
-
this.userSettingsService.patch({ assistants }).subscribe(next => {
|
|
353
|
-
if (notify) {
|
|
354
|
-
successCallback ? successCallback() : this.notificationsService.success(`The configuration of the assistant instance '${this.chatInstanceId}' has been successfully updated`);
|
|
355
|
-
}
|
|
356
|
-
}, error => {
|
|
397
|
+
assistants[this.chatInstanceId] = { ...assistants[this.chatInstanceId], defaultValues: config.defaultValues, hashes };
|
|
398
|
+
this.userSettingsService.patch({ assistants }).subscribe(next => { }, error => {
|
|
357
399
|
if (notify) {
|
|
358
400
|
errorCallback ? errorCallback() : this.notificationsService.error(`The update of the assistant instance '${this.chatInstanceId}' configuration failed`);
|
|
359
401
|
}
|
|
360
402
|
console.error("Could not patch assistants!", error);
|
|
403
|
+
}, () => {
|
|
404
|
+
if (notify) {
|
|
405
|
+
successCallback ? successCallback() : this.notificationsService.success(`The assistant instance '${this.chatInstanceId}' configuration has been successfully updated`);
|
|
406
|
+
}
|
|
361
407
|
});
|
|
362
408
|
}
|
|
363
409
|
/**
|
|
@@ -480,8 +526,8 @@ class WebSocketChatService extends ChatService {
|
|
|
480
526
|
* It can be overridden by the app config
|
|
481
527
|
*/
|
|
482
528
|
getRequestsUrl() {
|
|
483
|
-
if (this.chatConfig$.value.
|
|
484
|
-
this.REQUEST_URL = this.chatConfig$.value.
|
|
529
|
+
if (this.chatConfig$.value.connectionSettings.websocketEndpoint) {
|
|
530
|
+
this.REQUEST_URL = this.chatConfig$.value.connectionSettings.websocketEndpoint;
|
|
485
531
|
}
|
|
486
532
|
else {
|
|
487
533
|
throw new Error(`The property 'websocketEndpoint' must be provided when attempting to use 'WebSocket' in assistant instance`);
|
|
@@ -495,7 +541,7 @@ class WebSocketChatService extends ChatService {
|
|
|
495
541
|
modelsSubject.complete();
|
|
496
542
|
});
|
|
497
543
|
// Send the request to get the list of models
|
|
498
|
-
this.connection.invoke('ListModels', { debug: this.chatConfig$.value.debug })
|
|
544
|
+
this.connection.invoke('ListModels', { debug: this.chatConfig$.value.defaultValues.debug })
|
|
499
545
|
.catch(error => {
|
|
500
546
|
console.error('Error invoking ListModels:', error);
|
|
501
547
|
modelsSubject.complete();
|
|
@@ -506,12 +552,12 @@ class WebSocketChatService extends ChatService {
|
|
|
506
552
|
listFunctions() {
|
|
507
553
|
const functionsSubject = new Subject();
|
|
508
554
|
this.connection.on('ListFunctions', (res) => {
|
|
509
|
-
this.functions = res.functions;
|
|
555
|
+
this.functions = res.functions?.filter(func => func.enabled);
|
|
510
556
|
functionsSubject.next(this.functions);
|
|
511
557
|
functionsSubject.complete();
|
|
512
558
|
});
|
|
513
559
|
// Send the request to get the list of functions
|
|
514
|
-
this.connection.invoke('ListFunctions', { debug: this.chatConfig$.value.debug })
|
|
560
|
+
this.connection.invoke('ListFunctions', { debug: this.chatConfig$.value.defaultValues.debug })
|
|
515
561
|
.catch(error => {
|
|
516
562
|
console.error('Error invoking ListFunctions:', error);
|
|
517
563
|
functionsSubject.complete();
|
|
@@ -519,22 +565,28 @@ class WebSocketChatService extends ChatService {
|
|
|
519
565
|
});
|
|
520
566
|
return functionsSubject.asObservable();
|
|
521
567
|
}
|
|
522
|
-
fetch(messages, query
|
|
568
|
+
fetch(messages, query) {
|
|
523
569
|
// Start streaming by invoking the Chat method
|
|
524
570
|
this.streaming$.next(true);
|
|
525
571
|
// Prepare the payload to send to the Chat method
|
|
526
572
|
const data = {
|
|
527
573
|
history: messages,
|
|
528
|
-
functions: this.chatConfig$.value.functions,
|
|
529
|
-
debug: this.chatConfig$.value.debug,
|
|
530
|
-
serviceSettings:
|
|
531
|
-
|
|
532
|
-
|
|
574
|
+
functions: this.chatConfig$.value.defaultValues.functions?.filter(func => func.enabled).map(func => func.name),
|
|
575
|
+
debug: this.chatConfig$.value.defaultValues.debug,
|
|
576
|
+
serviceSettings: {
|
|
577
|
+
service_id: this.chatConfig$.value.defaultValues.service_id,
|
|
578
|
+
model_id: this.chatConfig$.value.defaultValues.model_id,
|
|
579
|
+
top_p: this.chatConfig$.value.defaultValues.top_p,
|
|
580
|
+
temperature: this.chatConfig$.value.defaultValues.temperature,
|
|
581
|
+
max_tokens: this.chatConfig$.value.defaultValues.max_tokens,
|
|
582
|
+
...this.chatConfig$.value.additionalServiceSettings
|
|
583
|
+
},
|
|
584
|
+
appQuery: {
|
|
533
585
|
app: this.appService.appName,
|
|
534
586
|
query
|
|
535
587
|
}
|
|
536
588
|
};
|
|
537
|
-
if (this.chatConfig$.value.
|
|
589
|
+
if (this.chatConfig$.value.savedChatSettings.enabled) {
|
|
538
590
|
data.instanceId = this.chatInstanceId;
|
|
539
591
|
data.savedChatId = this.savedChatId;
|
|
540
592
|
}
|
|
@@ -554,7 +606,7 @@ class WebSocketChatService extends ChatService {
|
|
|
554
606
|
);
|
|
555
607
|
// Invoke the Chat method
|
|
556
608
|
this.connection.invoke('Chat', data)
|
|
557
|
-
.then(() => this.notifyAudit(this.chatHistory, this.chatConfig$.value.
|
|
609
|
+
.then(() => this.notifyAudit(this.chatHistory, this.chatConfig$.value.defaultValues.service_id)) // When the server indicates it has successfully finished invoking the method, notify the audit service with the recent chat history
|
|
558
610
|
.catch(error => {
|
|
559
611
|
console.error('Error invoking Chat:', error);
|
|
560
612
|
return Promise.resolve(); // Return a resolved promise to handle the error and prevent unhandled promise rejection
|
|
@@ -593,7 +645,7 @@ class WebSocketChatService extends ChatService {
|
|
|
593
645
|
listSavedChat() {
|
|
594
646
|
const data = {
|
|
595
647
|
instanceId: this.chatInstanceId,
|
|
596
|
-
debug: this.chatConfig$.value.debug
|
|
648
|
+
debug: this.chatConfig$.value.defaultValues.debug
|
|
597
649
|
};
|
|
598
650
|
this.connection.on('SavedChatList', (res) => {
|
|
599
651
|
this.savedChats$.next(res.savedChats); // emits the result to the savedChats$ subject
|
|
@@ -610,7 +662,7 @@ class WebSocketChatService extends ChatService {
|
|
|
610
662
|
const data = {
|
|
611
663
|
instanceId: this.chatInstanceId,
|
|
612
664
|
savedChatId: id,
|
|
613
|
-
debug: this.chatConfig$.value.debug
|
|
665
|
+
debug: this.chatConfig$.value.defaultValues.debug
|
|
614
666
|
};
|
|
615
667
|
this.connection.on('SavedChatGet', (res) => {
|
|
616
668
|
savedChatSubject.next(res.savedChat);
|
|
@@ -625,12 +677,33 @@ class WebSocketChatService extends ChatService {
|
|
|
625
677
|
});
|
|
626
678
|
return savedChatSubject.asObservable();
|
|
627
679
|
}
|
|
680
|
+
updateSavedChat(id, name) {
|
|
681
|
+
const updateSavedChatSubject = new Subject();
|
|
682
|
+
const data = {
|
|
683
|
+
instanceId: this.chatInstanceId,
|
|
684
|
+
savedChatId: id,
|
|
685
|
+
title: name,
|
|
686
|
+
debug: this.chatConfig$.value.defaultValues.debug
|
|
687
|
+
};
|
|
688
|
+
this.connection.on('SavedChatUpdate', (res) => {
|
|
689
|
+
updateSavedChatSubject.next(res.savedChat);
|
|
690
|
+
updateSavedChatSubject.complete();
|
|
691
|
+
});
|
|
692
|
+
// Invoke the method SavedChatUpdate
|
|
693
|
+
this.connection.invoke('SavedChatUpdate', data)
|
|
694
|
+
.catch(error => {
|
|
695
|
+
console.error('Error invoking SavedChatUpdate:', error);
|
|
696
|
+
updateSavedChatSubject.complete();
|
|
697
|
+
return Promise.resolve();
|
|
698
|
+
});
|
|
699
|
+
return updateSavedChatSubject.asObservable();
|
|
700
|
+
}
|
|
628
701
|
deleteSavedChat(ids) {
|
|
629
702
|
const deleteSavedChatSubject = new Subject();
|
|
630
703
|
const data = {
|
|
631
704
|
instanceId: this.chatInstanceId,
|
|
632
705
|
SavedChatIds: ids,
|
|
633
|
-
debug: this.chatConfig$.value.debug
|
|
706
|
+
debug: this.chatConfig$.value.defaultValues.debug
|
|
634
707
|
};
|
|
635
708
|
this.connection.on('SavedChatDelete', (res) => {
|
|
636
709
|
deleteSavedChatSubject.next(res.deleteCount);
|
|
@@ -792,7 +865,7 @@ class WebSocketChatService extends ChatService {
|
|
|
792
865
|
return this.signalRService.stopConnection(this.connection);
|
|
793
866
|
}
|
|
794
867
|
getTransports() {
|
|
795
|
-
switch (this.chatConfig$.value?.
|
|
868
|
+
switch (this.chatConfig$.value?.connectionSettings.signalRTransport) {
|
|
796
869
|
case "WebSockets":
|
|
797
870
|
return HttpTransportType.WebSockets;
|
|
798
871
|
case "ServerSentEvents":
|
|
@@ -804,7 +877,7 @@ class WebSocketChatService extends ChatService {
|
|
|
804
877
|
}
|
|
805
878
|
}
|
|
806
879
|
getLogLevel() {
|
|
807
|
-
switch (this.chatConfig$.value?.
|
|
880
|
+
switch (this.chatConfig$.value?.connectionSettings.signalRLogLevel) {
|
|
808
881
|
case "Critical":
|
|
809
882
|
return LogLevel.Critical; // Log level for diagnostic messages that indicate a failure that will terminate the entire application.
|
|
810
883
|
case "Debug":
|
|
@@ -1078,10 +1151,10 @@ class ChatReferenceComponent {
|
|
|
1078
1151
|
}
|
|
1079
1152
|
}
|
|
1080
1153
|
ChatReferenceComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ChatReferenceComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1081
|
-
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\">\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\" (click)=\"expandAttachment()\">\n {{attachment.record.title}}\n </a>\n <i class=\"fas fa-eye\" (click)=\"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)=\"openDocument.emit(attachment.record)\" [sqTooltip]=\"!partId ? 'Open document' : ''\"></i>\n </div>\n <div class=\"reference-passages\" *ngIf=\"!!partId || (attachment['$expanded']) && parts.length\">\n <div class=\"reference-passage\" *ngFor=\"let part of parts\">\n <span class=\"reference me-1\">{{reference}}.{{part.partId}}</span>\n <span [innerHTML]=\"part.text\"></span>\n </div>\n </div>\n</div>", 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-btn{border:0;text-align:left;padding-top:.5rem;padding-bottom:.5rem;display:flex;align-items:center}: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
|
|
1154
|
+
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\">\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\" (click)=\"expandAttachment()\">\n {{attachment.record.title}}\n </a>\n <i class=\"fas fa-eye\" (click)=\"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)=\"openDocument.emit(attachment.record)\" [sqTooltip]=\"!partId ? 'Open document' : ''\"></i>\n </div>\n <div class=\"reference-passages\" *ngIf=\"!!partId || (attachment['$expanded']) && parts.length\">\n <div class=\"reference-passage\" *ngFor=\"let part of parts\">\n <span class=\"reference me-1\">{{reference}}.{{part.partId}}</span>\n <span [innerHTML]=\"part.text\"></span>\n </div>\n </div>\n</div>", 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-btn{border:0;text-align:left;padding-top:.5rem;padding-bottom:.5rem;display:flex;align-items:center}.dark{--ast-primary-bg: #0d0701;--ast-primary-color: #008cd1;--ast-secondary-bg: #00070e;--ast-secondary-color: #ffa258;--ast-input-bg: #070707;--ast-input-color: rgba(222, 218, 218, .75);--ast-muted-color: rgba(222, 218, 218, .75);--ast-saved-chat-hover-background: #262421;--ast-message-table-border-color: #333333;--ast-message-table-tr-bg: #070707;--ast-message-table-tr-border-color: #222222;--ast-reference-icon-color: white;--ast-reference-icon-active-color: black;--ast-reference-passages-color: white;--ast-reference-expanded-hover-bg: #262421;--ast-message-reference-color: black}:host ::ng-deep .reference,:host ::ng-deep .message-content .reference,:host ::ng-deep .attachment .reference{position:relative;bottom:var(--ast-reference-bottom, .3em);font-weight:var(--ast-reference-font-weight, bold);padding:var(--ast-reference-padding, 0 .2em);margin:var(--ast-reference-margin, 0 .1em);border-radius:var(--ast-reference-border-radius, .2em);background-color:var(--ast-reference-background-color, lightblue);color:var(--ast-reference-color, black)}:host ::ng-deep .reference,:host ::ng-deep .message-content .reference{font-size:var(--ast-reference-message-font-size, .7em)}:host ::ng-deep .attachment .reference{font-size:var(--ast-reference-attachment-font-size, 13px)}:host{display:block}:host.expanded,:host:hover{background-color:var(--ast-reference-expanded-hover-bg, white)}.reference-data{display:flex;flex-direction:row;align-items:baseline;padding:var(--ast-size-1, .25rem)}.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{margin-right:var(--ast-size-2, .5rem)}sq-format-icon{margin-left:var(--ast-size-1, .25rem);margin-right:var(--ast-size-2, .5rem);color:var(--ast-secondary-color, #FF732E)}.reference-tooltip{max-width:600px!important;box-shadow:0 .5rem 1rem #00000026;padding:.5rem;font-size:.875rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: UtilsModule }, { kind: "directive", type: i2$1.TooltipDirective, selector: "[sqTooltip]", inputs: ["sqTooltip", "sqTooltipData", "sqTooltipTemplate", "placement", "fallbackPlacements", "delay", "hoverableTooltip", "tooltipClass"] }, { kind: "component", type: FormatIconComponent, selector: "sq-format-icon", inputs: ["extension"] }] });
|
|
1082
1155
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ChatReferenceComponent, decorators: [{
|
|
1083
1156
|
type: Component,
|
|
1084
|
-
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\">\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\" (click)=\"expandAttachment()\">\n {{attachment.record.title}}\n </a>\n <i class=\"fas fa-eye\" (click)=\"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)=\"openDocument.emit(attachment.record)\" [sqTooltip]=\"!partId ? 'Open document' : ''\"></i>\n </div>\n <div class=\"reference-passages\" *ngIf=\"!!partId || (attachment['$expanded']) && parts.length\">\n <div class=\"reference-passage\" *ngFor=\"let part of parts\">\n <span class=\"reference me-1\">{{reference}}.{{part.partId}}</span>\n <span [innerHTML]=\"part.text\"></span>\n </div>\n </div>\n</div>", 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-btn{border:0;text-align:left;padding-top:.5rem;padding-bottom:.5rem;display:flex;align-items:center}: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
|
|
1157
|
+
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\">\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\" (click)=\"expandAttachment()\">\n {{attachment.record.title}}\n </a>\n <i class=\"fas fa-eye\" (click)=\"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)=\"openDocument.emit(attachment.record)\" [sqTooltip]=\"!partId ? 'Open document' : ''\"></i>\n </div>\n <div class=\"reference-passages\" *ngIf=\"!!partId || (attachment['$expanded']) && parts.length\">\n <div class=\"reference-passage\" *ngFor=\"let part of parts\">\n <span class=\"reference me-1\">{{reference}}.{{part.partId}}</span>\n <span [innerHTML]=\"part.text\"></span>\n </div>\n </div>\n</div>", 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-btn{border:0;text-align:left;padding-top:.5rem;padding-bottom:.5rem;display:flex;align-items:center}.dark{--ast-primary-bg: #0d0701;--ast-primary-color: #008cd1;--ast-secondary-bg: #00070e;--ast-secondary-color: #ffa258;--ast-input-bg: #070707;--ast-input-color: rgba(222, 218, 218, .75);--ast-muted-color: rgba(222, 218, 218, .75);--ast-saved-chat-hover-background: #262421;--ast-message-table-border-color: #333333;--ast-message-table-tr-bg: #070707;--ast-message-table-tr-border-color: #222222;--ast-reference-icon-color: white;--ast-reference-icon-active-color: black;--ast-reference-passages-color: white;--ast-reference-expanded-hover-bg: #262421;--ast-message-reference-color: black}:host ::ng-deep .reference,:host ::ng-deep .message-content .reference,:host ::ng-deep .attachment .reference{position:relative;bottom:var(--ast-reference-bottom, .3em);font-weight:var(--ast-reference-font-weight, bold);padding:var(--ast-reference-padding, 0 .2em);margin:var(--ast-reference-margin, 0 .1em);border-radius:var(--ast-reference-border-radius, .2em);background-color:var(--ast-reference-background-color, lightblue);color:var(--ast-reference-color, black)}:host ::ng-deep .reference,:host ::ng-deep .message-content .reference{font-size:var(--ast-reference-message-font-size, .7em)}:host ::ng-deep .attachment .reference{font-size:var(--ast-reference-attachment-font-size, 13px)}:host{display:block}:host.expanded,:host:hover{background-color:var(--ast-reference-expanded-hover-bg, white)}.reference-data{display:flex;flex-direction:row;align-items:baseline;padding:var(--ast-size-1, .25rem)}.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{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"] }]
|
|
1085
1158
|
}], propDecorators: { reference: [{
|
|
1086
1159
|
type: Input
|
|
1087
1160
|
}], attachment: [{
|
|
@@ -1228,11 +1301,11 @@ class ChatMessageComponent {
|
|
|
1228
1301
|
}
|
|
1229
1302
|
}
|
|
1230
1303
|
ChatMessageComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ChatMessageComponent, deps: [{ token: i1$1.SearchService }, { token: i2$1.UIService }, { token: i3.PrincipalWebService }, { token: i0.ChangeDetectorRef }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
1231
|
-
ChatMessageComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: ChatMessageComponent, isStandalone: true, selector: "sq-chat-message", inputs: { message: "message", conversation: "conversation", assistantIcon: "assistantIcon", streaming: "streaming", canEdit: "canEdit", canRegenerate: "canRegenerate", canCopy: "canCopy" }, outputs: { referenceClicked: "referenceClicked", edit: "edit", regenerate: "regenerate", openPreview: "openPreview" }, usesOnChanges: true, ngImport: i0, template: "<!-- Message icon -->\n<span class=\"message-icon\" [title]=\"message.role\">\n <i [ngClass]=\"assistantIcon\" [style.--sq-size.px]=\"24\" *ngIf=\"message.role === 'assistant'\"></i>\n <sq-initials-avatar [fullName]=\"name\" *ngIf=\"message.role !== 'assistant'\"></sq-initials-avatar>\n</span>\n\n<!-- Message body -->\n<div class=\"flex-grow-1\" style=\"min-width: 0;\" [ngClass]=\"'message-'+message.role\">\n\n <div *ngIf=\"message.additionalProperties.$progress as progress\" class=\"small ms-3 mb-2\">\n <a href=\"#\" (click)=\"collapseProgress = !collapseProgress; false\" class=\"text-muted\">\n View progress\n <i class=\"fas fa-chevron-{{collapseProgress? 'right' : 'down'}}\"></i>\n </a>\n <sq-collapse [collapsed]=\"collapseProgress\">\n <ng-template>\n <ul class=\"list-unstyled\">\n <li *ngFor=\"let step of progress\"
|
|
1304
|
+
ChatMessageComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: ChatMessageComponent, isStandalone: true, selector: "sq-chat-message", inputs: { message: "message", conversation: "conversation", assistantIcon: "assistantIcon", streaming: "streaming", canEdit: "canEdit", canRegenerate: "canRegenerate", canCopy: "canCopy" }, outputs: { referenceClicked: "referenceClicked", edit: "edit", regenerate: "regenerate", openPreview: "openPreview" }, usesOnChanges: true, ngImport: i0, template: "<!-- Message icon -->\n<span class=\"message-icon\" [title]=\"message.role\">\n <i [ngClass]=\"assistantIcon\" [style.--sq-size.px]=\"24\" *ngIf=\"message.role === 'assistant'\"></i>\n <sq-initials-avatar [fullName]=\"name\" *ngIf=\"message.role !== 'assistant'\"></sq-initials-avatar>\n</span>\n\n<!-- Message body -->\n<div class=\"flex-grow-1\" style=\"min-width: 0;\" [ngClass]=\"'message-'+message.role\">\n\n <div *ngIf=\"message.additionalProperties.$progress as progress\" class=\"small ms-3 mb-2\">\n <a href=\"#\" (click)=\"collapseProgress = !collapseProgress; false\" class=\"text-muted\">\n View progress\n <i class=\"fas fa-chevron-{{collapseProgress? 'right' : 'down'}}\"></i>\n </a>\n <sq-collapse [collapsed]=\"collapseProgress\">\n <ng-template>\n <ul class=\"list-unstyled\">\n <li *ngFor=\"let step of progress\">\n <i class=\"fas fa-fw fa-check text-success\" *ngIf=\"step.done\"></i>\n <i class=\"fas fa-fw fa-spin fa-circle-notch\" *ngIf=\"!step.done\"></i>\n <span class=\"ms-2 fw-bold\">{{step.title}}</span>\n <span *ngIf=\"step.content\">: {{step.content}}</span>\n </li>\n </ul>\n </ng-template>\n </sq-collapse>\n </div>\n\n <div class=\"message-content\" *ngIf=\"message.content\">\n\n <remark *ngIf=\"message.role === 'assistant'\" [markdown]=\"message.content\" [processor]=\"processor\">\n\n <ng-template remarkTemplate=\"chat-reference\" let-ref>\n\n <a *ngIf=\"referenceMap.get(ref.refId) as attachment; else staticRefTpl\"\n (click)=\"openDocument(attachment.record)\"\n class=\"reference\"\n [sqTooltip]=\"attachment\"\n [sqTooltipTemplate]=\"tooltipTpl\"\n [hoverableTooltip]=\"true\"\n >{{ref.refId}}</a>\n\n <ng-template #staticRefTpl>\n <span class=\"reference\">{{ref.refId}}</span>\n </ng-template>\n\n </ng-template>\n\n <ng-template remarkTemplate=\"streaming-placeholder\">\n <span class=\"placeholder-glow\" *ngIf=\"streaming\">\n <span class=\"placeholder ms-1\"></span>\n </span>\n </ng-template>\n\n <ng-template remarkTemplate=\"code\" let-node>\n <div class=\"card mb-2\">\n <div class=\"card-header d-flex justify-content-between align-items-center\">\n <span>{{node.lang}}</span>\n <button class=\"btn btn-light btn-sm\" (click)=\"copyToClipboard(node.value)\"><i class=\"far fa-fw fa-clipboard\"></i> Copy code</button>\n </div>\n <pre class=\"language-{{node.lang}} my-0 rounded-0 rounded-bottom\"><code class=\"language-{{node.lang}}\">{{node.value}}</code></pre>\n </div>\n </ng-template>\n\n </remark>\n\n <p *ngIf=\"message.role === 'user'\">{{message.content}}</p>\n\n <!-- List of reference, if any -->\n <div *ngIf=\"references?.length\" class=\"references\">\n <span class=\"references-title\">References</span> <i class=\"fas references-collapse\" [class.fa-chevron-down]=\"showReferences\" [class.fa-chevron-right]=\"!showReferences\" (click)=\"showReferences=!showReferences\"></i>\n <sq-collapse [collapsed]=\"!showReferences\">\n <ng-template>\n <ul>\n <ng-container *ngFor=\"let reference of references\">\n <li *ngIf=\"referenceMap.get(reference) as attachment\" class=\"text-truncate\">\n <sq-chat-reference [class.expanded]=\"attachment.$expanded\" [attachment]=\"attachment\" [reference]=\"reference\"\n (openPreview)=\"openPreview.emit($event)\" (openDocument)=\"openDocument($event)\"></sq-chat-reference>\n </li>\n </ng-container>\n </ul>\n </ng-template>\n </sq-collapse>\n </div>\n \n </div>\n\n <!-- Edit / Regenerate floating actions -->\n <div class=\"sq-chat-message-action\">\n <button class=\"btn btn-sm\" *ngIf=\"canEdit\" sqTooltip=\"Edit message\"\n (click)=\"edit.emit(message)\">\n <i class=\"fas fa-edit\"></i>\n </button>\n <button class=\"btn btn-sm\" *ngIf=\"canCopy\" sqTooltip=\"Copy to clipboard\"\n (click)=\"copyToClipboard(message.content)\">\n <i class=\"far fa-clipboard\"></i>\n </button>\n <button class=\"btn btn-sm\" *ngIf=\"canRegenerate\" sqTooltip=\"Regenerate message\"\n (click)=\"regenerate.emit(message)\">\n <i class=\"fas fa-sync-alt\"></i>\n </button>\n </div>\n\n <ng-template #tooltipTpl let-ref>\n <sq-chat-reference class=\"expanded\"\n [attachment]=\"ref\"\n [reference]=\"ref.contextId\"\n [partId]=\"ref.$partId\"\n (openPreview)=\"openPreview.emit($event)\"\n (openDocument)=\"openDocument($event)\">\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-btn{border:0;text-align:left;padding-top:.5rem;padding-bottom:.5rem;display:flex;align-items:center}.dark{--ast-primary-bg: #0d0701;--ast-primary-color: #008cd1;--ast-secondary-bg: #00070e;--ast-secondary-color: #ffa258;--ast-input-bg: #070707;--ast-input-color: rgba(222, 218, 218, .75);--ast-muted-color: rgba(222, 218, 218, .75);--ast-saved-chat-hover-background: #262421;--ast-message-table-border-color: #333333;--ast-message-table-tr-bg: #070707;--ast-message-table-tr-border-color: #222222;--ast-reference-icon-color: white;--ast-reference-icon-active-color: black;--ast-reference-passages-color: white;--ast-reference-expanded-hover-bg: #262421;--ast-message-reference-color: black}:host{display:flex}:host:not(:hover) .sq-chat-message-action{display:none}.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%}.message-content .references{margin-top:var(--ast-size-5, 1.25rem)}.message-content .references ul{border-left:.2rem solid var(--ast-secondary-color, #FF732E);padding-left:var(--ast-size-5, 1.25rem);margin-top:var(--ast-size-2, .5rem)}.message-content .references .references-title{font-weight:var(--font-weight-bold, 500)}.message-content .references .references-collapse{cursor:pointer;margin-left:var(--ast-size-2, .5rem)}.message-content ::ng-deep p:last-child{margin-bottom:0}.message-content ::ng-deep .placeholder-glow .placeholder{animation-duration:.4s;width:12px;height:var(--ast-size-4, 1rem);vertical-align:text-bottom}.message-content ::ng-deep img{max-width:100%}.message-content ::ng-deep table{display:block;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-assistant .message-content{background:var(--ast-secondary-bg, #FFF8F1)}.message-user .message-content{background:var(--ast-primary-bg, #f2f8fe);font-weight:var(--ast-user-font-weight, var(--font-weight-bold, 500))}.sq-chat-message-action{position:absolute;right:calc(0rem - var(--ast-size-2, .5rem));top:var(--ast-size-2, .5rem);display:flex;flex-direction:column}.message-icon{margin-top:var(--ast-size-3, .75rem);margin-right:var(--ast-size-4, 1rem)}\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: "ngmodule", type: UtilsModule }, { kind: "directive", type: i2$1.TooltipDirective, selector: "[sqTooltip]", inputs: ["sqTooltip", "sqTooltipData", "sqTooltipTemplate", "placement", "fallbackPlacements", "delay", "hoverableTooltip", "tooltipClass"] }, { kind: "ngmodule", type: CollapseModule }, { kind: "component", type: i5.Collapse, selector: "sq-collapse", inputs: ["collapsed"] }, { kind: "ngmodule", type: RemarkModule }, { kind: "component", type: i6.RemarkComponent, selector: "remark", inputs: ["markdown", "processor", "debug"] }, { kind: "directive", type: i6.RemarkTemplateDirective, selector: "[remarkTemplate]", inputs: ["remarkTemplate"] }, { kind: "component", type: InitialsAvatarComponent, selector: "sq-initials-avatar", inputs: ["fullName", "size"] }, { kind: "component", type: ChatReferenceComponent, selector: "sq-chat-reference", inputs: ["reference", "attachment", "partId"], outputs: ["openDocument", "openPreview"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1232
1305
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ChatMessageComponent, decorators: [{
|
|
1233
1306
|
type: Component,
|
|
1234
1307
|
args: [{ selector: "sq-chat-message", changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [CommonModule, UtilsModule, CollapseModule, RemarkModule,
|
|
1235
|
-
InitialsAvatarComponent, ChatReferenceComponent], template: "<!-- Message icon -->\n<span class=\"message-icon\" [title]=\"message.role\">\n <i [ngClass]=\"assistantIcon\" [style.--sq-size.px]=\"24\" *ngIf=\"message.role === 'assistant'\"></i>\n <sq-initials-avatar [fullName]=\"name\" *ngIf=\"message.role !== 'assistant'\"></sq-initials-avatar>\n</span>\n\n<!-- Message body -->\n<div class=\"flex-grow-1\" style=\"min-width: 0;\" [ngClass]=\"'message-'+message.role\">\n\n <div *ngIf=\"message.additionalProperties.$progress as progress\" class=\"small ms-3 mb-2\">\n <a href=\"#\" (click)=\"collapseProgress = !collapseProgress; false\" class=\"text-muted\">\n View progress\n <i class=\"fas fa-chevron-{{collapseProgress? 'right' : 'down'}}\"></i>\n </a>\n <sq-collapse [collapsed]=\"collapseProgress\">\n <ng-template>\n <ul class=\"list-unstyled\">\n <li *ngFor=\"let step of progress\"
|
|
1308
|
+
InitialsAvatarComponent, ChatReferenceComponent], template: "<!-- Message icon -->\n<span class=\"message-icon\" [title]=\"message.role\">\n <i [ngClass]=\"assistantIcon\" [style.--sq-size.px]=\"24\" *ngIf=\"message.role === 'assistant'\"></i>\n <sq-initials-avatar [fullName]=\"name\" *ngIf=\"message.role !== 'assistant'\"></sq-initials-avatar>\n</span>\n\n<!-- Message body -->\n<div class=\"flex-grow-1\" style=\"min-width: 0;\" [ngClass]=\"'message-'+message.role\">\n\n <div *ngIf=\"message.additionalProperties.$progress as progress\" class=\"small ms-3 mb-2\">\n <a href=\"#\" (click)=\"collapseProgress = !collapseProgress; false\" class=\"text-muted\">\n View progress\n <i class=\"fas fa-chevron-{{collapseProgress? 'right' : 'down'}}\"></i>\n </a>\n <sq-collapse [collapsed]=\"collapseProgress\">\n <ng-template>\n <ul class=\"list-unstyled\">\n <li *ngFor=\"let step of progress\">\n <i class=\"fas fa-fw fa-check text-success\" *ngIf=\"step.done\"></i>\n <i class=\"fas fa-fw fa-spin fa-circle-notch\" *ngIf=\"!step.done\"></i>\n <span class=\"ms-2 fw-bold\">{{step.title}}</span>\n <span *ngIf=\"step.content\">: {{step.content}}</span>\n </li>\n </ul>\n </ng-template>\n </sq-collapse>\n </div>\n\n <div class=\"message-content\" *ngIf=\"message.content\">\n\n <remark *ngIf=\"message.role === 'assistant'\" [markdown]=\"message.content\" [processor]=\"processor\">\n\n <ng-template remarkTemplate=\"chat-reference\" let-ref>\n\n <a *ngIf=\"referenceMap.get(ref.refId) as attachment; else staticRefTpl\"\n (click)=\"openDocument(attachment.record)\"\n class=\"reference\"\n [sqTooltip]=\"attachment\"\n [sqTooltipTemplate]=\"tooltipTpl\"\n [hoverableTooltip]=\"true\"\n >{{ref.refId}}</a>\n\n <ng-template #staticRefTpl>\n <span class=\"reference\">{{ref.refId}}</span>\n </ng-template>\n\n </ng-template>\n\n <ng-template remarkTemplate=\"streaming-placeholder\">\n <span class=\"placeholder-glow\" *ngIf=\"streaming\">\n <span class=\"placeholder ms-1\"></span>\n </span>\n </ng-template>\n\n <ng-template remarkTemplate=\"code\" let-node>\n <div class=\"card mb-2\">\n <div class=\"card-header d-flex justify-content-between align-items-center\">\n <span>{{node.lang}}</span>\n <button class=\"btn btn-light btn-sm\" (click)=\"copyToClipboard(node.value)\"><i class=\"far fa-fw fa-clipboard\"></i> Copy code</button>\n </div>\n <pre class=\"language-{{node.lang}} my-0 rounded-0 rounded-bottom\"><code class=\"language-{{node.lang}}\">{{node.value}}</code></pre>\n </div>\n </ng-template>\n\n </remark>\n\n <p *ngIf=\"message.role === 'user'\">{{message.content}}</p>\n\n <!-- List of reference, if any -->\n <div *ngIf=\"references?.length\" class=\"references\">\n <span class=\"references-title\">References</span> <i class=\"fas references-collapse\" [class.fa-chevron-down]=\"showReferences\" [class.fa-chevron-right]=\"!showReferences\" (click)=\"showReferences=!showReferences\"></i>\n <sq-collapse [collapsed]=\"!showReferences\">\n <ng-template>\n <ul>\n <ng-container *ngFor=\"let reference of references\">\n <li *ngIf=\"referenceMap.get(reference) as attachment\" class=\"text-truncate\">\n <sq-chat-reference [class.expanded]=\"attachment.$expanded\" [attachment]=\"attachment\" [reference]=\"reference\"\n (openPreview)=\"openPreview.emit($event)\" (openDocument)=\"openDocument($event)\"></sq-chat-reference>\n </li>\n </ng-container>\n </ul>\n </ng-template>\n </sq-collapse>\n </div>\n \n </div>\n\n <!-- Edit / Regenerate floating actions -->\n <div class=\"sq-chat-message-action\">\n <button class=\"btn btn-sm\" *ngIf=\"canEdit\" sqTooltip=\"Edit message\"\n (click)=\"edit.emit(message)\">\n <i class=\"fas fa-edit\"></i>\n </button>\n <button class=\"btn btn-sm\" *ngIf=\"canCopy\" sqTooltip=\"Copy to clipboard\"\n (click)=\"copyToClipboard(message.content)\">\n <i class=\"far fa-clipboard\"></i>\n </button>\n <button class=\"btn btn-sm\" *ngIf=\"canRegenerate\" sqTooltip=\"Regenerate message\"\n (click)=\"regenerate.emit(message)\">\n <i class=\"fas fa-sync-alt\"></i>\n </button>\n </div>\n\n <ng-template #tooltipTpl let-ref>\n <sq-chat-reference class=\"expanded\"\n [attachment]=\"ref\"\n [reference]=\"ref.contextId\"\n [partId]=\"ref.$partId\"\n (openPreview)=\"openPreview.emit($event)\"\n (openDocument)=\"openDocument($event)\">\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-btn{border:0;text-align:left;padding-top:.5rem;padding-bottom:.5rem;display:flex;align-items:center}.dark{--ast-primary-bg: #0d0701;--ast-primary-color: #008cd1;--ast-secondary-bg: #00070e;--ast-secondary-color: #ffa258;--ast-input-bg: #070707;--ast-input-color: rgba(222, 218, 218, .75);--ast-muted-color: rgba(222, 218, 218, .75);--ast-saved-chat-hover-background: #262421;--ast-message-table-border-color: #333333;--ast-message-table-tr-bg: #070707;--ast-message-table-tr-border-color: #222222;--ast-reference-icon-color: white;--ast-reference-icon-active-color: black;--ast-reference-passages-color: white;--ast-reference-expanded-hover-bg: #262421;--ast-message-reference-color: black}:host{display:flex}:host:not(:hover) .sq-chat-message-action{display:none}.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%}.message-content .references{margin-top:var(--ast-size-5, 1.25rem)}.message-content .references ul{border-left:.2rem solid var(--ast-secondary-color, #FF732E);padding-left:var(--ast-size-5, 1.25rem);margin-top:var(--ast-size-2, .5rem)}.message-content .references .references-title{font-weight:var(--font-weight-bold, 500)}.message-content .references .references-collapse{cursor:pointer;margin-left:var(--ast-size-2, .5rem)}.message-content ::ng-deep p:last-child{margin-bottom:0}.message-content ::ng-deep .placeholder-glow .placeholder{animation-duration:.4s;width:12px;height:var(--ast-size-4, 1rem);vertical-align:text-bottom}.message-content ::ng-deep img{max-width:100%}.message-content ::ng-deep table{display:block;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-assistant .message-content{background:var(--ast-secondary-bg, #FFF8F1)}.message-user .message-content{background:var(--ast-primary-bg, #f2f8fe);font-weight:var(--ast-user-font-weight, var(--font-weight-bold, 500))}.sq-chat-message-action{position:absolute;right:calc(0rem - var(--ast-size-2, .5rem));top:var(--ast-size-2, .5rem);display:flex;flex-direction:column}.message-icon{margin-top:var(--ast-size-3, .75rem);margin-right:var(--ast-size-4, 1rem)}\n"] }]
|
|
1236
1309
|
}], ctorParameters: function () { return [{ type: i1$1.SearchService }, { type: i2$1.UIService }, { type: i3.PrincipalWebService }, { type: i0.ChangeDetectorRef }, { type: i0.ElementRef }]; }, propDecorators: { message: [{
|
|
1237
1310
|
type: Input
|
|
1238
1311
|
}], conversation: [{
|
|
@@ -1275,7 +1348,10 @@ class RestChatService extends ChatService {
|
|
|
1275
1348
|
this.listFunctions()
|
|
1276
1349
|
])),
|
|
1277
1350
|
// Map the results of parallel requests to a boolean indicating success
|
|
1278
|
-
map(([models, functions]) =>
|
|
1351
|
+
map(([models, functions]) => {
|
|
1352
|
+
this.initProcess$.next(true);
|
|
1353
|
+
return !!models && !!functions;
|
|
1354
|
+
}),
|
|
1279
1355
|
// Any errors during the process are caught, logged, and re-thrown to propagate the error further
|
|
1280
1356
|
catchError((error) => {
|
|
1281
1357
|
console.error('Error occurred:', error);
|
|
@@ -1289,8 +1365,8 @@ class RestChatService extends ChatService {
|
|
|
1289
1365
|
* It can be overridden by the app config
|
|
1290
1366
|
*/
|
|
1291
1367
|
getRequestsUrl() {
|
|
1292
|
-
if (this.chatConfig$.value.
|
|
1293
|
-
this.REQUEST_URL = this.chatConfig$.value.
|
|
1368
|
+
if (this.chatConfig$.value.connectionSettings.restEndpoint) {
|
|
1369
|
+
this.REQUEST_URL = this.chatConfig$.value.connectionSettings.restEndpoint;
|
|
1294
1370
|
}
|
|
1295
1371
|
else {
|
|
1296
1372
|
throw new Error(`The property 'restEndpoint' must be provided when attempting to use 'REST' in assistant instance`);
|
|
@@ -1299,7 +1375,7 @@ class RestChatService extends ChatService {
|
|
|
1299
1375
|
listModels() {
|
|
1300
1376
|
const data = {
|
|
1301
1377
|
action: "listmodels",
|
|
1302
|
-
debug: this.chatConfig$.value.debug
|
|
1378
|
+
debug: this.chatConfig$.value.defaultValues.debug
|
|
1303
1379
|
};
|
|
1304
1380
|
return this.jsonMethodWebService.get(this.REQUEST_URL, data).pipe(map(res => res.models), tap(models => this.models = models?.filter(model => !!model.enable)), catchError((error) => {
|
|
1305
1381
|
console.error('Error invoking listmodels:', error);
|
|
@@ -1309,30 +1385,36 @@ class RestChatService extends ChatService {
|
|
|
1309
1385
|
listFunctions() {
|
|
1310
1386
|
const data = {
|
|
1311
1387
|
action: "listfunctions",
|
|
1312
|
-
debug: this.chatConfig$.value.debug
|
|
1388
|
+
debug: this.chatConfig$.value.defaultValues.debug
|
|
1313
1389
|
};
|
|
1314
|
-
return this.jsonMethodWebService.get(this.REQUEST_URL, data).pipe(map(res => res.functions), tap(functions => this.functions = functions), catchError((error) => {
|
|
1390
|
+
return this.jsonMethodWebService.get(this.REQUEST_URL, data).pipe(map(res => res.functions), tap((functions) => this.functions = functions?.filter(func => func.enabled && !!this.chatConfig$.value.defaultValues.functions.find(fn => fn.name === func.functionName))), catchError((error) => {
|
|
1315
1391
|
console.error('Error invoking listfunctions:', error);
|
|
1316
1392
|
return throwError(() => error);
|
|
1317
1393
|
}));
|
|
1318
1394
|
}
|
|
1319
|
-
fetch(messages, query
|
|
1395
|
+
fetch(messages, query) {
|
|
1320
1396
|
// Start streaming by invoking the Chat method
|
|
1321
1397
|
this.streaming$.next(true);
|
|
1322
1398
|
// Prepare the payload to send to the Chat method
|
|
1323
1399
|
const data = {
|
|
1324
1400
|
action: "chat",
|
|
1325
1401
|
history: messages,
|
|
1326
|
-
functions: this.chatConfig$.value.functions,
|
|
1327
|
-
debug: this.chatConfig$.value.debug,
|
|
1328
|
-
serviceSettings:
|
|
1329
|
-
|
|
1330
|
-
|
|
1402
|
+
functions: this.chatConfig$.value.defaultValues.functions?.filter(func => func.enabled).map(func => func.name),
|
|
1403
|
+
debug: this.chatConfig$.value.defaultValues.debug,
|
|
1404
|
+
serviceSettings: {
|
|
1405
|
+
service_id: this.chatConfig$.value.defaultValues.service_id,
|
|
1406
|
+
model_id: this.chatConfig$.value.defaultValues.model_id,
|
|
1407
|
+
top_p: this.chatConfig$.value.defaultValues.top_p,
|
|
1408
|
+
temperature: this.chatConfig$.value.defaultValues.temperature,
|
|
1409
|
+
max_tokens: this.chatConfig$.value.defaultValues.max_tokens,
|
|
1410
|
+
...this.chatConfig$.value.additionalServiceSettings
|
|
1411
|
+
},
|
|
1412
|
+
appQuery: {
|
|
1331
1413
|
app: this.appService.appName,
|
|
1332
1414
|
query
|
|
1333
1415
|
}
|
|
1334
1416
|
};
|
|
1335
|
-
if (this.chatConfig$.value.
|
|
1417
|
+
if (this.chatConfig$.value.savedChatSettings.enabled) {
|
|
1336
1418
|
data.instanceId = this.chatInstanceId;
|
|
1337
1419
|
data.savedChatId = this.savedChatId;
|
|
1338
1420
|
}
|
|
@@ -1370,13 +1452,13 @@ class RestChatService extends ChatService {
|
|
|
1370
1452
|
this.chatHistory = res.history;
|
|
1371
1453
|
// Return the result
|
|
1372
1454
|
return { history: [...messages, response], executionTime: res.executionTime };
|
|
1373
|
-
}), tap(() => this.notifyAudit(this.chatHistory, this.chatConfig$.value.
|
|
1455
|
+
}), tap(() => this.notifyAudit(this.chatHistory, this.chatConfig$.value.defaultValues.service_id)), finalize(() => this.streaming$.next(false)));
|
|
1374
1456
|
}
|
|
1375
1457
|
listSavedChat() {
|
|
1376
1458
|
const data = {
|
|
1377
1459
|
action: "SavedChatList",
|
|
1378
1460
|
instanceId: this.chatInstanceId,
|
|
1379
|
-
debug: this.chatConfig$.value.debug
|
|
1461
|
+
debug: this.chatConfig$.value.defaultValues.debug
|
|
1380
1462
|
};
|
|
1381
1463
|
this.jsonMethodWebService.get(this.REQUEST_URL, data).subscribe(res => this.savedChats$.next(res.savedChats), error => {
|
|
1382
1464
|
console.error('Error occurred while calling the SavedChatList API:', error);
|
|
@@ -1388,7 +1470,7 @@ class RestChatService extends ChatService {
|
|
|
1388
1470
|
action: "SavedChatGet",
|
|
1389
1471
|
instanceId: this.chatInstanceId,
|
|
1390
1472
|
savedChatId: id,
|
|
1391
|
-
debug: this.chatConfig$.value.debug
|
|
1473
|
+
debug: this.chatConfig$.value.defaultValues.debug
|
|
1392
1474
|
};
|
|
1393
1475
|
return this.jsonMethodWebService.get(this.REQUEST_URL, data).pipe(map(res => res.savedChat), catchError((error) => {
|
|
1394
1476
|
console.error('Error occurred while calling the SavedChatGet API:', error);
|
|
@@ -1396,12 +1478,26 @@ class RestChatService extends ChatService {
|
|
|
1396
1478
|
return throwError(() => error);
|
|
1397
1479
|
}));
|
|
1398
1480
|
}
|
|
1481
|
+
updateSavedChat(id, name) {
|
|
1482
|
+
const data = {
|
|
1483
|
+
action: "SavedChatUpdate",
|
|
1484
|
+
instanceId: this.chatInstanceId,
|
|
1485
|
+
savedChatId: id,
|
|
1486
|
+
title: name,
|
|
1487
|
+
debug: this.chatConfig$.value.defaultValues.debug
|
|
1488
|
+
};
|
|
1489
|
+
return this.jsonMethodWebService.get(this.REQUEST_URL, data).pipe(map(res => res.savedChat), catchError((error) => {
|
|
1490
|
+
console.error('Error occurred while calling the SavedChatUpdate API:', error);
|
|
1491
|
+
this.notificationsService.error('Error occurred while calling the SavedChatUpdate API');
|
|
1492
|
+
return throwError(() => error);
|
|
1493
|
+
}));
|
|
1494
|
+
}
|
|
1399
1495
|
deleteSavedChat(ids) {
|
|
1400
1496
|
const data = {
|
|
1401
1497
|
action: "SavedChatDelete",
|
|
1402
1498
|
instanceId: this.chatInstanceId,
|
|
1403
1499
|
savedChatIds: ids,
|
|
1404
|
-
debug: this.chatConfig$.value.debug
|
|
1500
|
+
debug: this.chatConfig$.value.defaultValues.debug
|
|
1405
1501
|
};
|
|
1406
1502
|
return this.jsonMethodWebService.post(this.REQUEST_URL, data).pipe(map(res => res.deletedCount), catchError((error) => {
|
|
1407
1503
|
console.error('Error occurred while calling the SavedChatDelete API:', error);
|
|
@@ -1419,14 +1515,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImpor
|
|
|
1419
1515
|
class ChatComponent extends AbstractFacet {
|
|
1420
1516
|
constructor() {
|
|
1421
1517
|
super();
|
|
1518
|
+
this.loginService = inject(LoginService);
|
|
1519
|
+
this.websocketService = inject(WebSocketChatService);
|
|
1520
|
+
this.restService = inject(RestChatService);
|
|
1521
|
+
this.instanceManagerService = inject(InstanceManagerService);
|
|
1522
|
+
this.searchService = inject(SearchService);
|
|
1523
|
+
this.principalService = inject(PrincipalWebService);
|
|
1524
|
+
this.cdr = inject(ChangeDetectorRef);
|
|
1525
|
+
/** Define the query to use to fetch answers */
|
|
1526
|
+
this.query = this.searchService.query;
|
|
1422
1527
|
/** Define the protocol to be used for this chat instance*/
|
|
1423
1528
|
this.protocol = "WEBSOCKET";
|
|
1424
1529
|
/** Map of listeners overriding default registered ones*/
|
|
1425
1530
|
this.messageHandlers = new Map();
|
|
1426
1531
|
/** When the assistant answer a user question, automatically scroll down to the bottom of the discussion */
|
|
1427
1532
|
this.automaticScrollToLastResponse = false;
|
|
1428
|
-
this.enableChat = true;
|
|
1429
|
-
this.showCredits = true;
|
|
1430
1533
|
this.customAssistantIcon = '';
|
|
1431
1534
|
this.data = new EventEmitter();
|
|
1432
1535
|
this.referenceClicked = new EventEmitter();
|
|
@@ -1439,16 +1542,10 @@ class ChatComponent extends AbstractFacet {
|
|
|
1439
1542
|
this._actions = [];
|
|
1440
1543
|
this.sub = new Subscription();
|
|
1441
1544
|
this.changes$ = new BehaviorSubject(undefined);
|
|
1442
|
-
this.
|
|
1545
|
+
this.firstChangesHandled = false;
|
|
1443
1546
|
this.isAtBottom = true;
|
|
1444
1547
|
this.initializationError = false;
|
|
1445
|
-
this.
|
|
1446
|
-
this.websocketService = inject(WebSocketChatService);
|
|
1447
|
-
this.restService = inject(RestChatService);
|
|
1448
|
-
this.instanceManagerService = inject(InstanceManagerService);
|
|
1449
|
-
this.searchService = inject(SearchService);
|
|
1450
|
-
this.principalService = inject(PrincipalWebService);
|
|
1451
|
-
this.cdr = inject(ChangeDetectorRef);
|
|
1548
|
+
this.enabledUserInput = false;
|
|
1452
1549
|
this._actions.push(new Action({
|
|
1453
1550
|
icon: 'fas fa-sync',
|
|
1454
1551
|
title: 'Reset chat',
|
|
@@ -1458,13 +1555,14 @@ class ChatComponent extends AbstractFacet {
|
|
|
1458
1555
|
ngOnInit() {
|
|
1459
1556
|
this.sub.add(this.loginService.events.pipe(filter(e => e.type === 'login-complete'), tap(_ => this.instantiateChatService()), map(_ => this.chatService.initChatConfig()), switchMap(() => this.chatService.initConfig$), filter(initConfig => !!initConfig), switchMap(_ => this.chatService.init()), filter(success => !!success), tap(_ => this.onLoadChat()), switchMap(_ => this.chatService.chatConfig$), tap(config => {
|
|
1460
1557
|
this.config = config;
|
|
1558
|
+
this.enabledUserInput = this.config.modeSettings.enabledUserInput;
|
|
1461
1559
|
this._config.emit(config);
|
|
1462
1560
|
try {
|
|
1463
1561
|
this.updateModelDescription();
|
|
1464
|
-
if (!this.
|
|
1562
|
+
if (!this.firstChangesHandled) {
|
|
1465
1563
|
this.handleChanges();
|
|
1466
1564
|
this.addScrollListener();
|
|
1467
|
-
this.
|
|
1565
|
+
this.firstChangesHandled = true;
|
|
1468
1566
|
}
|
|
1469
1567
|
}
|
|
1470
1568
|
catch (error) {
|
|
@@ -1500,12 +1598,35 @@ class ChatComponent extends AbstractFacet {
|
|
|
1500
1598
|
get actions() { return this._actions; }
|
|
1501
1599
|
handleChanges() {
|
|
1502
1600
|
const changes = this.changes$.value;
|
|
1601
|
+
// If the chat service is a WebSocketChatService, handle the override of the message handlers if exists
|
|
1503
1602
|
if (changes?.messageHandlers && this.messageHandlers && this.chatService instanceof WebSocketChatService) {
|
|
1504
1603
|
this.chatService.overrideMessageHandlers(this.messageHandlers);
|
|
1505
1604
|
}
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1605
|
+
// Initialize the chat with the provided chat messages if exists, otherwise load the default chat
|
|
1606
|
+
// Once the chat is initialized (firstChangesHandled is true), allow opening the chat with the new provided messages (if exists)
|
|
1607
|
+
if (!this.firstChangesHandled || changes?.chat) {
|
|
1608
|
+
const openChat = () => {
|
|
1609
|
+
if (this.messages$.value && this.config.savedChatSettings.enabled) {
|
|
1610
|
+
this.chatService.listSavedChat(); // Refresh the list of saved chats
|
|
1611
|
+
}
|
|
1612
|
+
this.openChat(this.chat.messages);
|
|
1613
|
+
};
|
|
1614
|
+
this.chat ? openChat() : this.loadDefaultChat();
|
|
1615
|
+
}
|
|
1616
|
+
// If the chat is initialized and the initialization event is "Query", then a fresh new chat should be started with the provided query
|
|
1617
|
+
if (this.firstChangesHandled && changes?.query && this.config.modeSettings.initialization.event === 'Query') {
|
|
1618
|
+
const systemMsg = { role: 'system', content: this.config.defaultValues.systemPrompt, additionalProperties: { display: false } };
|
|
1619
|
+
const userMsg = { role: 'user', content: ChatService.formatPrompt(this.config.defaultValues.userPrompt, { principal: this.principalService.principal }), additionalProperties: { display: this.config.modeSettings.displayUserPrompt } };
|
|
1620
|
+
// If the provided query text is not empty, then add the user query message to the chat history and invoke the assistant
|
|
1621
|
+
// Otherwise, just start a new chat with a warning message inviting the user to perform a full text search to retrieve some results
|
|
1622
|
+
if (!!this.query.text) {
|
|
1623
|
+
const userQueryMsg = { role: 'user', content: this.query.text, additionalProperties: { display: this.config.modeSettings.initialization.displayUserQuery, query: this.query, forcedWorkflow: this.config.modeSettings.initialization.forcedWorkflow, isUserInput: true } };
|
|
1624
|
+
this.openChat(this.config.modeSettings.sendUserPrompt ? [systemMsg, userMsg, userQueryMsg] : [systemMsg, userQueryMsg]);
|
|
1625
|
+
}
|
|
1626
|
+
else {
|
|
1627
|
+
const warningMsg = { role: 'assistant', content: "You must perform a full text search to retrieve some results", additionalProperties: { display: true } };
|
|
1628
|
+
this.openChat([warningMsg]);
|
|
1629
|
+
}
|
|
1509
1630
|
}
|
|
1510
1631
|
}
|
|
1511
1632
|
addScrollListener() {
|
|
@@ -1515,7 +1636,7 @@ class ChatComponent extends AbstractFacet {
|
|
|
1515
1636
|
}));
|
|
1516
1637
|
}
|
|
1517
1638
|
updateModelDescription() {
|
|
1518
|
-
this.modelDescription = this.chatService.getModel(this.config.
|
|
1639
|
+
this.modelDescription = this.chatService.getModel(this.config.defaultValues.service_id, this.config.defaultValues.model_id);
|
|
1519
1640
|
this.assistantIcon = !!this.customAssistantIcon ? this.customAssistantIcon : 'sq-sinequa';
|
|
1520
1641
|
switch (this.modelDescription?.provider) {
|
|
1521
1642
|
case 'Google':
|
|
@@ -1552,7 +1673,7 @@ class ChatComponent extends AbstractFacet {
|
|
|
1552
1673
|
}
|
|
1553
1674
|
}
|
|
1554
1675
|
fetchAnswer(question, conversation) {
|
|
1555
|
-
const userMsg = { role: 'user', content: question, additionalProperties: { display: true } };
|
|
1676
|
+
const userMsg = { role: 'user', content: question, additionalProperties: { display: true, isUserInput: true } };
|
|
1556
1677
|
const messages = [...conversation, userMsg];
|
|
1557
1678
|
this.messages$.next(messages);
|
|
1558
1679
|
this.fetch(messages);
|
|
@@ -1609,16 +1730,46 @@ class ChatComponent extends AbstractFacet {
|
|
|
1609
1730
|
}
|
|
1610
1731
|
}, 10);
|
|
1611
1732
|
}
|
|
1733
|
+
/**
|
|
1734
|
+
* Start a new chat with the defaultValues settings
|
|
1735
|
+
* If the savedChat feature is enabled, the list of saved chats will be refreshed
|
|
1736
|
+
*/
|
|
1612
1737
|
newChat() {
|
|
1613
|
-
this.
|
|
1738
|
+
if (this.config.savedChatSettings.enabled) {
|
|
1739
|
+
this.chatService.listSavedChat(); // Refresh the list of saved chats
|
|
1740
|
+
}
|
|
1614
1741
|
this.loadDefaultChat(); // Start a new chat
|
|
1615
1742
|
}
|
|
1743
|
+
/**
|
|
1744
|
+
* Start the default chat with the defaultValues settings
|
|
1745
|
+
* If the chat is meant to be initialized with event === "Query", the corresponding user query message will be added to the chat history
|
|
1746
|
+
*/
|
|
1616
1747
|
loadDefaultChat() {
|
|
1617
|
-
this.
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1748
|
+
const systemMsg = { role: 'system', content: this.config.defaultValues.systemPrompt, additionalProperties: { display: false } };
|
|
1749
|
+
const userMsg = { role: 'user', content: ChatService.formatPrompt(this.config.defaultValues.userPrompt, { principal: this.principalService.principal }), additionalProperties: { display: this.config.modeSettings.displayUserPrompt } };
|
|
1750
|
+
if (this.config.modeSettings.initialization.event === 'Query') {
|
|
1751
|
+
// If the provided query text is not empty, then add the user query message to the chat history and invoke the assistant
|
|
1752
|
+
// Otherwise, just start a new chat with a warning message inviting the user to perform a full text search to retrieve some results
|
|
1753
|
+
if (!!this.query.text) {
|
|
1754
|
+
const userQueryMsg = { role: 'user', content: this.query.text, additionalProperties: { display: this.config.modeSettings.initialization.displayUserQuery, query: this.query, forcedWorkflow: this.config.modeSettings.initialization.forcedWorkflow, isUserInput: true } };
|
|
1755
|
+
this.openChat(this.config.modeSettings.sendUserPrompt ? [systemMsg, userMsg, userQueryMsg] : [systemMsg, userQueryMsg]);
|
|
1756
|
+
}
|
|
1757
|
+
else {
|
|
1758
|
+
const warningMsg = { role: 'assistant', content: "You must perform a full text search to retrieve some results", additionalProperties: { display: true } };
|
|
1759
|
+
this.openChat([warningMsg]);
|
|
1760
|
+
}
|
|
1761
|
+
}
|
|
1762
|
+
else {
|
|
1763
|
+
this.openChat([systemMsg, userMsg]);
|
|
1764
|
+
}
|
|
1621
1765
|
}
|
|
1766
|
+
/**
|
|
1767
|
+
* Start/open a new chat with the provided messages and chatId
|
|
1768
|
+
* If the last message is from the user, a request to the assistant is made to get an answer
|
|
1769
|
+
* If the last message is from the assistant, the conversation is loaded right away
|
|
1770
|
+
* @param messages The list of messages of the chat
|
|
1771
|
+
* @param chatId The id of the chat. If not provided, a new id will be generated
|
|
1772
|
+
*/
|
|
1622
1773
|
openChat(messages, chatId) {
|
|
1623
1774
|
if (!messages || !Array.isArray(messages)) {
|
|
1624
1775
|
console.error('Error occurs while trying to load the chat discussion. Invalid messages received :', messages);
|
|
@@ -1637,6 +1788,11 @@ class ChatComponent extends AbstractFacet {
|
|
|
1637
1788
|
this.terminateFetch();
|
|
1638
1789
|
}
|
|
1639
1790
|
}
|
|
1791
|
+
/**
|
|
1792
|
+
* Reset the chat by clearing the messages and the chat history
|
|
1793
|
+
* The question input will be focused after the chat is reset
|
|
1794
|
+
* The fetch subscription will be terminated
|
|
1795
|
+
*/
|
|
1640
1796
|
resetChat() {
|
|
1641
1797
|
if (this.messages$.value) {
|
|
1642
1798
|
this.messages$.next(undefined); // Reset chat
|
|
@@ -1648,8 +1804,7 @@ class ChatComponent extends AbstractFacet {
|
|
|
1648
1804
|
onLoadChat() {
|
|
1649
1805
|
this.loading$.next(true);
|
|
1650
1806
|
this.sub.add(this.chatService.loadSavedChat$
|
|
1651
|
-
.pipe(filter(savedChat => !!savedChat), switchMap(savedChat => this.chatService.getSavedChat(savedChat.id)), filter(savedChatHistory => !!savedChatHistory), tap(savedChatHistory => this.openChat(savedChatHistory.
|
|
1652
|
-
).subscribe());
|
|
1807
|
+
.pipe(filter(savedChat => !!savedChat), switchMap(savedChat => this.chatService.getSavedChat(savedChat.id)), filter(savedChatHistory => !!savedChatHistory), tap(savedChatHistory => this.openChat(savedChatHistory.history, savedChatHistory.id))).subscribe());
|
|
1653
1808
|
}
|
|
1654
1809
|
terminateFetch() {
|
|
1655
1810
|
this.dataSubscription?.unsubscribe();
|
|
@@ -1715,16 +1870,16 @@ class ChatComponent extends AbstractFacet {
|
|
|
1715
1870
|
}
|
|
1716
1871
|
}
|
|
1717
1872
|
ChatComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ChatComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1718
|
-
ChatComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: ChatComponent, isStandalone: true, selector: "sq-chat-v3", inputs: { instanceId: "instanceId", query: "query", protocol: "protocol", messageHandlers: "messageHandlers", automaticScrollToLastResponse: "automaticScrollToLastResponse", chat: "chat",
|
|
1873
|
+
ChatComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: ChatComponent, isStandalone: true, selector: "sq-chat-v3", inputs: { instanceId: "instanceId", query: "query", protocol: "protocol", messageHandlers: "messageHandlers", automaticScrollToLastResponse: "automaticScrollToLastResponse", chat: "chat", customAssistantIcon: "customAssistantIcon" }, outputs: { data: "data", referenceClicked: "referenceClicked", openPreview: "openPreview", loading$: "loading", error: "error", _config: "config" }, providers: [
|
|
1719
1874
|
RestChatService,
|
|
1720
1875
|
WebSocketChatService
|
|
1721
|
-
], queries: [{ propertyName: "loadingTpl", first: true, predicate: ["loadingTpl"], descendants: true }], viewQueries: [{ propertyName: "messageList", first: true, predicate: ["messageList"], descendants: true }, { propertyName: "questionInput", first: true, predicate: ["questionInput"], descendants: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "\n<ng-container *ngIf=\"!initializationError\">\n <div *ngIf=\"messages$ | async as messages; else loadingTpl || loadingTplDefault\" class=\"h-100 d-flex flex-column\">\n\n <ul class=\"list-group list-group-flush overflow-auto
|
|
1876
|
+
], queries: [{ propertyName: "loadingTpl", first: true, predicate: ["loadingTpl"], descendants: true }], viewQueries: [{ propertyName: "messageList", first: true, predicate: ["messageList"], descendants: true }, { propertyName: "questionInput", first: true, predicate: ["questionInput"], descendants: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "\n<ng-container *ngIf=\"!initializationError\">\n <div *ngIf=\"messages$ | async as messages; else loadingTpl || loadingTplDefault\" class=\"h-100 d-flex flex-column\">\n\n <ul class=\"list-group list-group-flush overflow-auto pe-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\" *ngIf=\"message.additionalProperties.display\"\n [class.opacity-50]=\"messageToEdit && messageToEdit < index + 1\">\n <sq-chat-message\n [class.sq-user-message]=\"message.role !== 'assistant'\"\n [message]=\"message\"\n [conversation]=\"messages\"\n [assistantIcon]=\"customAssistantIcon || assistantIcon\"\n [streaming]=\"last && (chatService.streaming$ | async)\"\n [canEdit]=\"(loading$ | async) === false && (chatService.streaming$ | async) === false && messageToEdit === undefined && message.role !== 'assistant'\"\n [canRegenerate]=\"(loading$ | async) === false && (chatService.streaming$ | async) === false && messageToEdit === undefined && message.role === 'assistant' && last\"\n [canCopy]=\"!(last && (chatService.streaming$ | async)) && messageToEdit === undefined && message.role === 'assistant'\"\n (edit)=\"editMessage(index)\" (regenerate)=\"regenerateMessage(index)\"\n (referenceClicked)=\"referenceClicked.emit($event)\"\n (openPreview)=\"openPreview.emit($event)\">\n </sq-chat-message>\n </li>\n </ng-container>\n\n <li class=\"list-group-item\" *ngIf=\"(loading$ | async) === true\">\n <ng-container *ngTemplateOutlet=\"loadingTpl || loadingTplDefault\"></ng-container>\n </li>\n </ul>\n\n <div class=\"user-input mt-auto\" *ngIf=\"enabledUserInput\">\n <div class=\"py-2\">\n <ng-container *ngTemplateOutlet=\"inputTpl\"></ng-container>\n <div class=\"text-end small text-muted px-3\" *ngIf=\"!!config?.globalSettings?.disclaimer\">\n {{ config?.globalSettings?.disclaimer }}\n </div>\n </div>\n </div>\n </div>\n</ng-container>\n\n<!-- NG TEMPLATES-->\n\n<ng-template #loadingTplDefault>\n <div class=\"spinner-grow text-primary d-block mx-auto my-5\" role=\"status\">\n <span class=\"visually-hidden\">Loading...</span>\n </div>\n</ng-template>\n\n<ng-template #inputTpl>\n <div class=\"px-3 py-1\">\n <div class=\"ast-input-container\">\n <i class=\"fas fa-search\"></i>\n <input #questionInput\n type=\"text\" class=\"form-control\"\n placeholder=\"Ask something\" autofocus\n [(ngModel)]=\"question\"\n (keyup)=\"onKeyUp($event)\"\n [disabled]=\"(loading$ | async) || (chatService.streaming$ | async)\">\n <button\n *ngIf=\"!(chatService.streaming$ | async) && !(loading$ | async)\"\n type=\"button\"\n class=\"btn btn-light ms-2\"\n title=\"Send message\"\n (click)=\"submitQuestion()\">\n <i class=\"fas fa-paper-plane\"></i>\n </button>\n <!--<button\n *ngIf=\"(chatService.streaming$ | async)\"\n type=\"button\"\n class=\"btn btn-light ms-2\"\n title=\"Stop generating\"\n (click)=\"terminateFetch()\">\n <i class=\"fas fa-stop\"></i>\n </button>-->\n <button\n *ngIf=\"messageToEdit\"\n type=\"button\"\n class=\"btn btn-light ms-2\"\n title=\"Cancel edition\"\n (click)=\"messageToEdit = undefined; question = ''\">\n <i class=\"fas fa-undo-alt\"></i>\n </button>\n <div class=\"sq-floating-scroll\" *ngIf=\"!isAtBottom\">\n <button class=\"btn shadow\" (click)=\"scrollDown()\">\n <i class=\"fas fa-angle-double-down\"></i>\n </button>\n </div>\n </div>\n </div>\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-btn{border:0;text-align:left;padding-top:.5rem;padding-bottom:.5rem;display:flex;align-items:center}.dark{--ast-primary-bg: #0d0701;--ast-primary-color: #008cd1;--ast-secondary-bg: #00070e;--ast-secondary-color: #ffa258;--ast-input-bg: #070707;--ast-input-color: rgba(222, 218, 218, .75);--ast-muted-color: rgba(222, 218, 218, .75);--ast-saved-chat-hover-background: #262421;--ast-message-table-border-color: #333333;--ast-message-table-tr-bg: #070707;--ast-message-table-tr-border-color: #222222;--ast-reference-icon-color: white;--ast-reference-icon-active-color: black;--ast-reference-passages-color: white;--ast-reference-expanded-hover-bg: #262421;--ast-message-reference-color: black}:host ::ng-deep .reference,:host ::ng-deep .message-content .reference,:host ::ng-deep .attachment .reference{position:relative;bottom:var(--ast-reference-bottom, .3em);font-weight:var(--ast-reference-font-weight, bold);padding:var(--ast-reference-padding, 0 .2em);margin:var(--ast-reference-margin, 0 .1em);border-radius:var(--ast-reference-border-radius, .2em);background-color:var(--ast-reference-background-color, lightblue);color:var(--ast-reference-color, black)}:host ::ng-deep .reference,:host ::ng-deep .message-content .reference{font-size:var(--ast-reference-message-font-size, .7em)}:host ::ng-deep .attachment .reference{font-size:var(--ast-reference-attachment-font-size, 13px)}:host{font-size:.875rem}:host>div>.user-input>div:not(.progress),:host>div>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%;bottom:75px;text-align:center}.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 input{padding-left:var(--ast-size-3, .75rem);padding-right:var(--ast-size-3, .75rem)}.ast-input-container input,.ast-input-container button,.ast-input-container button:hover{background-color:transparent;border:0}.ast-input-container button:hover{color:var(--ast-primary-color, #005DA7)}.ast-input-container button:not(:hover){color:var(--ast-muted-color, rgba(33, 37, 41, .75))}sq-chat-message.sq-user-message{float:var(--ast-user-message-float, none)}\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: "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.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.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", "assistantIcon", "streaming", "canEdit", "canRegenerate", "canCopy"], outputs: ["referenceClicked", "edit", "regenerate", "openPreview"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1722
1877
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ChatComponent, decorators: [{
|
|
1723
1878
|
type: Component,
|
|
1724
1879
|
args: [{ selector: 'sq-chat-v3', providers: [
|
|
1725
1880
|
RestChatService,
|
|
1726
1881
|
WebSocketChatService
|
|
1727
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [CommonModule, FormsModule, ChatMessageComponent], template: "\n<ng-container *ngIf=\"!initializationError\">\n <div *ngIf=\"messages$ | async as messages; else loadingTpl || loadingTplDefault\" class=\"h-100 d-flex flex-column\">\n\n <ul class=\"list-group list-group-flush overflow-auto
|
|
1882
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [CommonModule, FormsModule, ChatMessageComponent], template: "\n<ng-container *ngIf=\"!initializationError\">\n <div *ngIf=\"messages$ | async as messages; else loadingTpl || loadingTplDefault\" class=\"h-100 d-flex flex-column\">\n\n <ul class=\"list-group list-group-flush overflow-auto pe-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\" *ngIf=\"message.additionalProperties.display\"\n [class.opacity-50]=\"messageToEdit && messageToEdit < index + 1\">\n <sq-chat-message\n [class.sq-user-message]=\"message.role !== 'assistant'\"\n [message]=\"message\"\n [conversation]=\"messages\"\n [assistantIcon]=\"customAssistantIcon || assistantIcon\"\n [streaming]=\"last && (chatService.streaming$ | async)\"\n [canEdit]=\"(loading$ | async) === false && (chatService.streaming$ | async) === false && messageToEdit === undefined && message.role !== 'assistant'\"\n [canRegenerate]=\"(loading$ | async) === false && (chatService.streaming$ | async) === false && messageToEdit === undefined && message.role === 'assistant' && last\"\n [canCopy]=\"!(last && (chatService.streaming$ | async)) && messageToEdit === undefined && message.role === 'assistant'\"\n (edit)=\"editMessage(index)\" (regenerate)=\"regenerateMessage(index)\"\n (referenceClicked)=\"referenceClicked.emit($event)\"\n (openPreview)=\"openPreview.emit($event)\">\n </sq-chat-message>\n </li>\n </ng-container>\n\n <li class=\"list-group-item\" *ngIf=\"(loading$ | async) === true\">\n <ng-container *ngTemplateOutlet=\"loadingTpl || loadingTplDefault\"></ng-container>\n </li>\n </ul>\n\n <div class=\"user-input mt-auto\" *ngIf=\"enabledUserInput\">\n <div class=\"py-2\">\n <ng-container *ngTemplateOutlet=\"inputTpl\"></ng-container>\n <div class=\"text-end small text-muted px-3\" *ngIf=\"!!config?.globalSettings?.disclaimer\">\n {{ config?.globalSettings?.disclaimer }}\n </div>\n </div>\n </div>\n </div>\n</ng-container>\n\n<!-- NG TEMPLATES-->\n\n<ng-template #loadingTplDefault>\n <div class=\"spinner-grow text-primary d-block mx-auto my-5\" role=\"status\">\n <span class=\"visually-hidden\">Loading...</span>\n </div>\n</ng-template>\n\n<ng-template #inputTpl>\n <div class=\"px-3 py-1\">\n <div class=\"ast-input-container\">\n <i class=\"fas fa-search\"></i>\n <input #questionInput\n type=\"text\" class=\"form-control\"\n placeholder=\"Ask something\" autofocus\n [(ngModel)]=\"question\"\n (keyup)=\"onKeyUp($event)\"\n [disabled]=\"(loading$ | async) || (chatService.streaming$ | async)\">\n <button\n *ngIf=\"!(chatService.streaming$ | async) && !(loading$ | async)\"\n type=\"button\"\n class=\"btn btn-light ms-2\"\n title=\"Send message\"\n (click)=\"submitQuestion()\">\n <i class=\"fas fa-paper-plane\"></i>\n </button>\n <!--<button\n *ngIf=\"(chatService.streaming$ | async)\"\n type=\"button\"\n class=\"btn btn-light ms-2\"\n title=\"Stop generating\"\n (click)=\"terminateFetch()\">\n <i class=\"fas fa-stop\"></i>\n </button>-->\n <button\n *ngIf=\"messageToEdit\"\n type=\"button\"\n class=\"btn btn-light ms-2\"\n title=\"Cancel edition\"\n (click)=\"messageToEdit = undefined; question = ''\">\n <i class=\"fas fa-undo-alt\"></i>\n </button>\n <div class=\"sq-floating-scroll\" *ngIf=\"!isAtBottom\">\n <button class=\"btn shadow\" (click)=\"scrollDown()\">\n <i class=\"fas fa-angle-double-down\"></i>\n </button>\n </div>\n </div>\n </div>\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-btn{border:0;text-align:left;padding-top:.5rem;padding-bottom:.5rem;display:flex;align-items:center}.dark{--ast-primary-bg: #0d0701;--ast-primary-color: #008cd1;--ast-secondary-bg: #00070e;--ast-secondary-color: #ffa258;--ast-input-bg: #070707;--ast-input-color: rgba(222, 218, 218, .75);--ast-muted-color: rgba(222, 218, 218, .75);--ast-saved-chat-hover-background: #262421;--ast-message-table-border-color: #333333;--ast-message-table-tr-bg: #070707;--ast-message-table-tr-border-color: #222222;--ast-reference-icon-color: white;--ast-reference-icon-active-color: black;--ast-reference-passages-color: white;--ast-reference-expanded-hover-bg: #262421;--ast-message-reference-color: black}:host ::ng-deep .reference,:host ::ng-deep .message-content .reference,:host ::ng-deep .attachment .reference{position:relative;bottom:var(--ast-reference-bottom, .3em);font-weight:var(--ast-reference-font-weight, bold);padding:var(--ast-reference-padding, 0 .2em);margin:var(--ast-reference-margin, 0 .1em);border-radius:var(--ast-reference-border-radius, .2em);background-color:var(--ast-reference-background-color, lightblue);color:var(--ast-reference-color, black)}:host ::ng-deep .reference,:host ::ng-deep .message-content .reference{font-size:var(--ast-reference-message-font-size, .7em)}:host ::ng-deep .attachment .reference{font-size:var(--ast-reference-attachment-font-size, 13px)}:host{font-size:.875rem}:host>div>.user-input>div:not(.progress),:host>div>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%;bottom:75px;text-align:center}.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 input{padding-left:var(--ast-size-3, .75rem);padding-right:var(--ast-size-3, .75rem)}.ast-input-container input,.ast-input-container button,.ast-input-container button:hover{background-color:transparent;border:0}.ast-input-container button:hover{color:var(--ast-primary-color, #005DA7)}.ast-input-container button:not(:hover){color:var(--ast-muted-color, rgba(33, 37, 41, .75))}sq-chat-message.sq-user-message{float:var(--ast-user-message-float, none)}\n"] }]
|
|
1728
1883
|
}], ctorParameters: function () { return []; }, propDecorators: { instanceId: [{
|
|
1729
1884
|
type: Input
|
|
1730
1885
|
}], query: [{
|
|
@@ -1737,10 +1892,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImpor
|
|
|
1737
1892
|
type: Input
|
|
1738
1893
|
}], chat: [{
|
|
1739
1894
|
type: Input
|
|
1740
|
-
}], enableChat: [{
|
|
1741
|
-
type: Input
|
|
1742
|
-
}], showCredits: [{
|
|
1743
|
-
type: Input
|
|
1744
1895
|
}], customAssistantIcon: [{
|
|
1745
1896
|
type: Input
|
|
1746
1897
|
}], data: [{
|
|
@@ -1793,12 +1944,42 @@ class SavedChatsComponent {
|
|
|
1793
1944
|
this.chatService = this.instanceManagerService.getInstance(this.instanceId);
|
|
1794
1945
|
}
|
|
1795
1946
|
onListSavedChat() {
|
|
1796
|
-
this.subscription.add(this.chatService.savedChats$.subscribe((savedChats) =>
|
|
1947
|
+
this.subscription.add(this.chatService.savedChats$.subscribe((savedChats) => {
|
|
1948
|
+
this.currentChatId = undefined;
|
|
1949
|
+
this.groupedSavedChats$.next(this._groupSavedChatsByDate(savedChats));
|
|
1950
|
+
}));
|
|
1797
1951
|
}
|
|
1798
1952
|
onLoad(savedChat) {
|
|
1953
|
+
this.currentChatId = savedChat.id;
|
|
1799
1954
|
this.chatService.loadSavedChat$.next(savedChat);
|
|
1955
|
+
this.chatService.listSavedChat();
|
|
1800
1956
|
this.load.emit(savedChat);
|
|
1801
1957
|
}
|
|
1958
|
+
onRename(savedChat) {
|
|
1959
|
+
const model = {
|
|
1960
|
+
title: 'Rename saved discussion',
|
|
1961
|
+
message: `Please enter a new name for the discussion "${savedChat.title}".`,
|
|
1962
|
+
buttons: [
|
|
1963
|
+
new ModalButton({ result: -2 /* ModalResult.Cancel */ }),
|
|
1964
|
+
new ModalButton({ result: -1 /* ModalResult.OK */, text: "Rename", primary: true })
|
|
1965
|
+
],
|
|
1966
|
+
output: savedChat.title,
|
|
1967
|
+
validators: [Validators.required]
|
|
1968
|
+
};
|
|
1969
|
+
this.modalService.prompt(model).then(res => {
|
|
1970
|
+
if (res === -1 /* ModalResult.OK */) {
|
|
1971
|
+
this.subscription.add(this.chatService.updateSavedChat(savedChat.id, model.output)
|
|
1972
|
+
.pipe(tap(() => {
|
|
1973
|
+
this.notificationsService.success(`The saved discussion "${savedChat.title}" has been successfully renamed to "${model.output}".`);
|
|
1974
|
+
this.chatService.listSavedChat();
|
|
1975
|
+
}), catchError((error) => {
|
|
1976
|
+
console.error('Error occurred while updating the saved chat:', error);
|
|
1977
|
+
this.notificationsService.error(`Error occurred while updating the saved discussion "${savedChat.title}"`);
|
|
1978
|
+
return throwError(() => error);
|
|
1979
|
+
})).subscribe());
|
|
1980
|
+
}
|
|
1981
|
+
});
|
|
1982
|
+
}
|
|
1802
1983
|
onDelete(savedChat) {
|
|
1803
1984
|
this.modalService
|
|
1804
1985
|
.confirm({
|
|
@@ -1875,10 +2056,10 @@ class SavedChatsComponent {
|
|
|
1875
2056
|
}
|
|
1876
2057
|
}
|
|
1877
2058
|
SavedChatsComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: SavedChatsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1878
|
-
SavedChatsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: SavedChatsComponent, isStandalone: true, selector: "sq-saved-chats-v3", inputs: { instanceId: "instanceId" }, outputs: { load: "load", delete: "delete" }, ngImport: i0, template: "<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\" class=\"saved-chat p-2\"
|
|
2059
|
+
SavedChatsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: SavedChatsComponent, isStandalone: true, selector: "sq-saved-chats-v3", inputs: { instanceId: "instanceId" }, outputs: { load: "load", delete: "delete" }, ngImport: i0, template: "<ng-container *ngIf=\"(chatService.chatConfig$ | async)?.savedChatSettings.display\">\n <div *ngFor=\"let group of (groupedSavedChats$ | async)\" class=\"saved-chats\">\n <div class=\"saved-chat-date\">{{group.key}}</div>\n <div *ngFor=\"let savedChat of group.value\" class=\"saved-chat p-2\" [class.active]=\"currentChatId === savedChat.id\"\n (click)=\"onLoad(savedChat)\">\n <span class=\"title me-1\">{{savedChat.title}}</span>\n <i class=\"saved-chat-actions fas fa-pen mx-1\" [sqTooltip]=\"'Rename'\"\n (click)=\"$event.stopPropagation(); onRename(savedChat)\"></i>\n <i class=\"saved-chat-actions fas fa-trash ms-1\" [sqTooltip]=\"'Delete'\"\n (click)=\"$event.stopPropagation(); onDelete(savedChat)\"></i>\n </div>\n </div>\n</ng-container>\n", styles: [".ast-primary{color:var(--ast-primary-color, #005DA7);background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover{background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover:hover{color:var(--ast-primary-color, #005DA7)}.ast-secondary{color:var(--ast-secondary-color, #FF732E);background-color:var(--ast-secondary-bg, #FFF8F1)}.ast-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}.saved-chats .saved-chat-date{font-weight:500;color:#a9a9a9;margin-top:.5rem}.saved-chats .saved-chat{display:flex;align-items:center;cursor:pointer;margin-left:.25rem}.saved-chats .saved-chat span{flex-grow:1;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.saved-chats .saved-chat .saved-chat-actions{display:none}.saved-chats .saved-chat:hover,.saved-chats .saved-chat.active{color:var(--ast-secondary-color, #FF732E);background-color:var(--ast-saved-chat-hover-background, #FFF8F1)}.saved-chats .saved-chat:hover .saved-chat-actions{display:block}.saved-chats .title{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: ModalModule }, { kind: "ngmodule", type: UtilsModule }, { kind: "directive", type: i2$1.TooltipDirective, selector: "[sqTooltip]", inputs: ["sqTooltip", "sqTooltipData", "sqTooltipTemplate", "placement", "fallbackPlacements", "delay", "hoverableTooltip", "tooltipClass"] }] });
|
|
1879
2060
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: SavedChatsComponent, decorators: [{
|
|
1880
2061
|
type: Component,
|
|
1881
|
-
args: [{ selector: 'sq-saved-chats-v3', standalone: true, imports: [CommonModule, ModalModule, UtilsModule], template: "<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\" class=\"saved-chat p-2\"
|
|
2062
|
+
args: [{ selector: 'sq-saved-chats-v3', standalone: true, imports: [CommonModule, ModalModule, UtilsModule], template: "<ng-container *ngIf=\"(chatService.chatConfig$ | async)?.savedChatSettings.display\">\n <div *ngFor=\"let group of (groupedSavedChats$ | async)\" class=\"saved-chats\">\n <div class=\"saved-chat-date\">{{group.key}}</div>\n <div *ngFor=\"let savedChat of group.value\" class=\"saved-chat p-2\" [class.active]=\"currentChatId === savedChat.id\"\n (click)=\"onLoad(savedChat)\">\n <span class=\"title me-1\">{{savedChat.title}}</span>\n <i class=\"saved-chat-actions fas fa-pen mx-1\" [sqTooltip]=\"'Rename'\"\n (click)=\"$event.stopPropagation(); onRename(savedChat)\"></i>\n <i class=\"saved-chat-actions fas fa-trash ms-1\" [sqTooltip]=\"'Delete'\"\n (click)=\"$event.stopPropagation(); onDelete(savedChat)\"></i>\n </div>\n </div>\n</ng-container>\n", styles: [".ast-primary{color:var(--ast-primary-color, #005DA7);background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover{background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover:hover{color:var(--ast-primary-color, #005DA7)}.ast-secondary{color:var(--ast-secondary-color, #FF732E);background-color:var(--ast-secondary-bg, #FFF8F1)}.ast-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}.saved-chats .saved-chat-date{font-weight:500;color:#a9a9a9;margin-top:.5rem}.saved-chats .saved-chat{display:flex;align-items:center;cursor:pointer;margin-left:.25rem}.saved-chats .saved-chat span{flex-grow:1;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.saved-chats .saved-chat .saved-chat-actions{display:none}.saved-chats .saved-chat:hover,.saved-chats .saved-chat.active{color:var(--ast-secondary-color, #FF732E);background-color:var(--ast-saved-chat-hover-background, #FFF8F1)}.saved-chats .saved-chat:hover .saved-chat-actions{display:block}.saved-chats .title{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n"] }]
|
|
1882
2063
|
}], propDecorators: { instanceId: [{
|
|
1883
2064
|
type: Input
|
|
1884
2065
|
}], load: [{
|
|
@@ -1903,9 +2084,81 @@ const enAssistant = Utils.merge({}, _enAssistant);
|
|
|
1903
2084
|
const frAssistant = Utils.merge({}, _frAssistant);
|
|
1904
2085
|
const deAssistant = Utils.merge({}, _deAssistant);
|
|
1905
2086
|
|
|
2087
|
+
class ChatPrompt {
|
|
2088
|
+
constructor(model, modalRef, formBuilder) {
|
|
2089
|
+
this.model = model;
|
|
2090
|
+
this.modalRef = modalRef;
|
|
2091
|
+
this.formBuilder = formBuilder;
|
|
2092
|
+
this.defaultButtons = [
|
|
2093
|
+
new ModalButton({
|
|
2094
|
+
result: -1 /* ModalResult.OK */,
|
|
2095
|
+
primary: true,
|
|
2096
|
+
validation: this.form
|
|
2097
|
+
}),
|
|
2098
|
+
new ModalButton({
|
|
2099
|
+
result: -2 /* ModalResult.Cancel */
|
|
2100
|
+
})
|
|
2101
|
+
];
|
|
2102
|
+
}
|
|
2103
|
+
ngOnInit() {
|
|
2104
|
+
this.inputControl = new UntypedFormControl(this.model.output, this.model.validators || Validators.required);
|
|
2105
|
+
this.form = this.formBuilder.group({
|
|
2106
|
+
input: this.inputControl
|
|
2107
|
+
});
|
|
2108
|
+
this.formChanges = Utils.subscribe(this.form.valueChanges, (value) => {
|
|
2109
|
+
this.model.output = this.inputControl.value;
|
|
2110
|
+
});
|
|
2111
|
+
}
|
|
2112
|
+
ngOnDestroy() {
|
|
2113
|
+
this.formChanges.unsubscribe();
|
|
2114
|
+
}
|
|
2115
|
+
get title() {
|
|
2116
|
+
return this.model.title ? this.model.title : "msg#modal.prompt.title";
|
|
2117
|
+
}
|
|
2118
|
+
get buttons() {
|
|
2119
|
+
return (this.model.buttons && this.model.buttons.length > 0) ? this.model.buttons : this.defaultButtons;
|
|
2120
|
+
}
|
|
2121
|
+
}
|
|
2122
|
+
ChatPrompt.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ChatPrompt, deps: [{ token: MODAL_MODEL }, { token: i1$2.ModalRef }, { token: i2.UntypedFormBuilder }], target: i0.ɵɵFactoryTarget.Component });
|
|
2123
|
+
ChatPrompt.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: ChatPrompt, isStandalone: true, selector: "sq-chat-prompt", ngImport: i0, template: `
|
|
2124
|
+
<form name="prompt" novalidate [formGroup]="form">
|
|
2125
|
+
<sq-modal [title]="title" [buttons]="buttons">
|
|
2126
|
+
<div class="mb-3 sq-form-group">
|
|
2127
|
+
<label class="form-label" for="input">{{model.message | sqMessage:model.messageParams}}</label>
|
|
2128
|
+
<input [sqValidation]="form" type="text" class="form-control" id="input" formControlName="input" spellcheck="off" sqAutofocus *ngIf="!model.rowCount">
|
|
2129
|
+
<textarea [sqValidation]="form" type="text" class="form-control" id="input" formControlName="input" spellcheck="on" rows="{{model.rowCount}}" sqAutofocus *ngIf="!!model.rowCount">
|
|
2130
|
+
</textarea>
|
|
2131
|
+
</div>
|
|
2132
|
+
</sq-modal>
|
|
2133
|
+
</form>
|
|
2134
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: BsModalModule }, { kind: "component", type: i4.BsModal, selector: "sq-modal", inputs: ["title", "buttons", "showHeader", "showFooter", "isProcessingState"] }, { kind: "ngmodule", type: ValidationModule }, { kind: "directive", type: i5$1.ValidationDirective, selector: "[sqValidation]", inputs: ["sqValidation"] }, { 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"] }, { kind: "ngmodule", type: IntlModule }, { kind: "pipe", type: i6$1.MessagePipe, name: "sqMessage" }] });
|
|
2135
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ChatPrompt, decorators: [{
|
|
2136
|
+
type: Component,
|
|
2137
|
+
args: [{
|
|
2138
|
+
selector: "sq-chat-prompt",
|
|
2139
|
+
template: `
|
|
2140
|
+
<form name="prompt" novalidate [formGroup]="form">
|
|
2141
|
+
<sq-modal [title]="title" [buttons]="buttons">
|
|
2142
|
+
<div class="mb-3 sq-form-group">
|
|
2143
|
+
<label class="form-label" for="input">{{model.message | sqMessage:model.messageParams}}</label>
|
|
2144
|
+
<input [sqValidation]="form" type="text" class="form-control" id="input" formControlName="input" spellcheck="off" sqAutofocus *ngIf="!model.rowCount">
|
|
2145
|
+
<textarea [sqValidation]="form" type="text" class="form-control" id="input" formControlName="input" spellcheck="on" rows="{{model.rowCount}}" sqAutofocus *ngIf="!!model.rowCount">
|
|
2146
|
+
</textarea>
|
|
2147
|
+
</div>
|
|
2148
|
+
</sq-modal>
|
|
2149
|
+
</form>
|
|
2150
|
+
`,
|
|
2151
|
+
standalone: true,
|
|
2152
|
+
imports: [CommonModule, BsModalModule, ValidationModule, ReactiveFormsModule, IntlModule],
|
|
2153
|
+
}]
|
|
2154
|
+
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
|
|
2155
|
+
type: Inject,
|
|
2156
|
+
args: [MODAL_MODEL]
|
|
2157
|
+
}] }, { type: i1$2.ModalRef }, { type: i2.UntypedFormBuilder }]; } });
|
|
2158
|
+
|
|
1906
2159
|
/**
|
|
1907
2160
|
* Generated bundle index. Do not edit.
|
|
1908
2161
|
*/
|
|
1909
2162
|
|
|
1910
|
-
export { ChatComponent, ChatService, ChatSettingsV3Component, FormatIconComponent, InitialsAvatarComponent, InstanceManagerService, RestChatService, SavedChatsComponent, WebSocketChatService, chatConfigSchema, deAssistant, enAssistant, frAssistant
|
|
2163
|
+
export { ChatComponent, ChatPrompt, ChatService, ChatSettingsV3Component, FormatIconComponent, InitialsAvatarComponent, InstanceManagerService, RestChatService, SavedChatsComponent, WebSocketChatService, chatConfigSchema, connectionSettingsSchema, deAssistant, enAssistant, frAssistant };
|
|
1911
2164
|
//# sourceMappingURL=sinequa-assistant-chat.mjs.map
|