@sftech/ng-orchestrator 0.0.17 → 0.0.18
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/fesm2022/sftech-ng-orchestrator-agent-rag-upload.component-iqEbrzkb.mjs +189 -0
- package/fesm2022/sftech-ng-orchestrator-agent-rag-upload.component-iqEbrzkb.mjs.map +1 -0
- package/fesm2022/{sftech-ng-orchestrator-agents.routes-B9GSWOIz.mjs → sftech-ng-orchestrator-agents.routes-CVcxzNAE.mjs} +70 -13
- package/fesm2022/sftech-ng-orchestrator-agents.routes-CVcxzNAE.mjs.map +1 -0
- package/fesm2022/sftech-ng-orchestrator-chats.routes-BDe9JC4m.mjs +625 -0
- package/fesm2022/sftech-ng-orchestrator-chats.routes-BDe9JC4m.mjs.map +1 -0
- package/fesm2022/{sftech-ng-orchestrator-prompt-display.component-Cd6Ff3KE.mjs → sftech-ng-orchestrator-prompt-display.component-BkSLQgGU.mjs} +2 -2
- package/fesm2022/{sftech-ng-orchestrator-prompt-display.component-Cd6Ff3KE.mjs.map → sftech-ng-orchestrator-prompt-display.component-BkSLQgGU.mjs.map} +1 -1
- package/fesm2022/{sftech-ng-orchestrator-prompts.routes-DQZ_Hmjs.mjs → sftech-ng-orchestrator-prompts.routes-DeR6lppF.mjs} +2 -2
- package/fesm2022/{sftech-ng-orchestrator-prompts.routes-DQZ_Hmjs.mjs.map → sftech-ng-orchestrator-prompts.routes-DeR6lppF.mjs.map} +1 -1
- package/fesm2022/{sftech-ng-orchestrator-sftech-ng-orchestrator-CJMmRHC-.mjs → sftech-ng-orchestrator-sftech-ng-orchestrator-D9fLhC24.mjs} +66 -7
- package/fesm2022/sftech-ng-orchestrator-sftech-ng-orchestrator-D9fLhC24.mjs.map +1 -0
- package/fesm2022/sftech-ng-orchestrator.mjs +1 -1
- package/lib/ng-orchestrator/admin/agents/components/agent/agent-rag-upload/agent-rag-upload.component.d.ts +21 -0
- package/lib/ng-orchestrator/admin/agents/components/agent/agents-list/agents-list.component.d.ts +2 -0
- package/lib/ng-orchestrator/chats/agent-chat/agent-chat-message-human-input/agent-chat-message-human-input.component.d.ts +6 -5
- package/lib/ng-orchestrator/chats/agent-chat/agent-chat-message-human-input-initial/agent-chat-message-human-input-initial.component.d.ts +20 -0
- package/lib/ng-orchestrator/chats/agent-chat/agent-chat.component.d.ts +7 -1
- package/lib/ng-orchestrator/core/configuration/orchestrator-config.interface.d.ts +2 -0
- package/lib/ng-orchestrator/core/dtos/agent-create-request.dto.d.ts +2 -0
- package/lib/ng-orchestrator/core/dtos/agent-response.dto.d.ts +2 -0
- package/lib/ng-orchestrator/core/dtos/agent-update-request.dto.d.ts +2 -0
- package/lib/ng-orchestrator/core/dtos/rag-ingest-config.dto.d.ts +4 -0
- package/lib/ng-orchestrator/core/models/agent.model.d.ts +2 -0
- package/lib/ng-orchestrator/core/service/orchestrator.service.d.ts +3 -0
- package/lib/ng-orchestrator/core/validators/rag.validator.d.ts +2 -0
- package/package.json +1 -1
- package/fesm2022/sftech-ng-orchestrator-agent.service-DPJMw8a4.mjs +0 -106
- package/fesm2022/sftech-ng-orchestrator-agent.service-DPJMw8a4.mjs.map +0 -1
- package/fesm2022/sftech-ng-orchestrator-agents.routes-B9GSWOIz.mjs.map +0 -1
- package/fesm2022/sftech-ng-orchestrator-chats.routes-BLGhykMM.mjs +0 -556
- package/fesm2022/sftech-ng-orchestrator-chats.routes-BLGhykMM.mjs.map +0 -1
- package/fesm2022/sftech-ng-orchestrator-sftech-ng-orchestrator-CJMmRHC-.mjs.map +0 -1
|
@@ -1,556 +0,0 @@
|
|
|
1
|
-
import { AuthenticationGuard } from '@sftech/ng-auth';
|
|
2
|
-
import { NgClass, JsonPipe, DatePipe } from '@angular/common';
|
|
3
|
-
import * as i0 from '@angular/core';
|
|
4
|
-
import { Inject, Injectable, input, EventEmitter, inject, effect, Output, Component, signal, computed } from '@angular/core';
|
|
5
|
-
import { ActivatedRoute, Router, RouterLink, RouterOutlet } from '@angular/router';
|
|
6
|
-
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
|
7
|
-
import { BaseDbApiService, IconProvider, MappedApiError, FormErrorDisplayComponent, OData, OdataFilter, EFilterOperator, EFilterTypes, ESortDirection, BaseListComponent } from '@sftech/ng-shared';
|
|
8
|
-
import { MessageService } from 'primeng/api';
|
|
9
|
-
import { Button, ButtonDirective } from 'primeng/button';
|
|
10
|
-
import { Panel } from 'primeng/panel';
|
|
11
|
-
import { map, catchError } from 'rxjs';
|
|
12
|
-
import { A as AgentRun, O as ORCHESTRATOR_CONFIGURATION, C as Chat, a as OrchestratorService, b as ChatMessage } from './sftech-ng-orchestrator-sftech-ng-orchestrator-CJMmRHC-.mjs';
|
|
13
|
-
import * as i1 from '@angular/common/http';
|
|
14
|
-
import { A as AgentService } from './sftech-ng-orchestrator-agent.service-DPJMw8a4.mjs';
|
|
15
|
-
import { faNoteSticky, faCog, faCheck, faXmark, faSpinner, faClipboardCheck, faCircleQuestion, faBrain, faUser, faNetworkWired } from '@fortawesome/free-solid-svg-icons';
|
|
16
|
-
import * as i1$1 from '@angular/forms';
|
|
17
|
-
import { FormGroup, FormControl, Validators, ReactiveFormsModule } from '@angular/forms';
|
|
18
|
-
import { AgentRunIconTextDataprovider as AgentRunIconTextDataprovider$1 } from 'libs/ng-orchestrator/src/lib/ng-orchestrator/chats/core/dataprovider/agent-run-icon-text.dataprovider';
|
|
19
|
-
import { FloatLabel } from 'primeng/floatlabel';
|
|
20
|
-
import { InputText } from 'primeng/inputtext';
|
|
21
|
-
import { MarkdownComponent } from 'ngx-markdown';
|
|
22
|
-
import { Skeleton } from 'primeng/skeleton';
|
|
23
|
-
import { DialogService } from 'primeng/dynamicdialog';
|
|
24
|
-
|
|
25
|
-
var EAgentRunStatus;
|
|
26
|
-
(function (EAgentRunStatus) {
|
|
27
|
-
EAgentRunStatus["INIT"] = "init";
|
|
28
|
-
EAgentRunStatus["PRERUNNING"] = "pre_running";
|
|
29
|
-
EAgentRunStatus["RUNNING"] = "running";
|
|
30
|
-
EAgentRunStatus["POSTRUNNING"] = "post_running";
|
|
31
|
-
EAgentRunStatus["CLARIFICATION_NEEDED"] = "clarification_needed";
|
|
32
|
-
EAgentRunStatus["COMPLETED"] = "completed";
|
|
33
|
-
EAgentRunStatus["FAILED"] = "failed";
|
|
34
|
-
})(EAgentRunStatus || (EAgentRunStatus = {}));
|
|
35
|
-
|
|
36
|
-
class AgentRunService extends BaseDbApiService {
|
|
37
|
-
http;
|
|
38
|
-
config;
|
|
39
|
-
constructor(http, config) {
|
|
40
|
-
super(http, config);
|
|
41
|
-
this.http = http;
|
|
42
|
-
this.config = config;
|
|
43
|
-
this.url = `${this.config.orchestratorDbUrl}/agent-runs`;
|
|
44
|
-
}
|
|
45
|
-
// biome-ignore lint/correctness/noUnusedVariables: <explanation>
|
|
46
|
-
insert(dto) {
|
|
47
|
-
throw new Error('Method not implemented');
|
|
48
|
-
}
|
|
49
|
-
// biome-ignore lint/correctness/noUnusedVariables: <explanation>
|
|
50
|
-
update(id, dto) {
|
|
51
|
-
throw new Error('Method not implemented');
|
|
52
|
-
}
|
|
53
|
-
// biome-ignore lint/correctness/noUnusedVariables: <explanation>
|
|
54
|
-
delete(id) {
|
|
55
|
-
throw new Error('Method not implemented');
|
|
56
|
-
}
|
|
57
|
-
getNewModel() {
|
|
58
|
-
return new AgentRun();
|
|
59
|
-
}
|
|
60
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AgentRunService, deps: [{ token: i1.HttpClient }, { token: ORCHESTRATOR_CONFIGURATION }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
61
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AgentRunService, providedIn: 'root' });
|
|
62
|
-
}
|
|
63
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AgentRunService, decorators: [{
|
|
64
|
-
type: Injectable,
|
|
65
|
-
args: [{ providedIn: 'root' }]
|
|
66
|
-
}], ctorParameters: () => [{ type: i1.HttpClient }, { type: undefined, decorators: [{
|
|
67
|
-
type: Inject,
|
|
68
|
-
args: [ORCHESTRATOR_CONFIGURATION]
|
|
69
|
-
}] }] });
|
|
70
|
-
|
|
71
|
-
class ChatService extends BaseDbApiService {
|
|
72
|
-
http;
|
|
73
|
-
config;
|
|
74
|
-
constructor(http, config) {
|
|
75
|
-
super(http, config);
|
|
76
|
-
this.http = http;
|
|
77
|
-
this.config = config;
|
|
78
|
-
this.url = `${this.config.orchestratorDbUrl}/chats`;
|
|
79
|
-
}
|
|
80
|
-
odata(odataQuery) {
|
|
81
|
-
return this.http.get(`${this.url}/${odataQuery.toGetParameter()}`).pipe(map((response) => this.responseOdataMapping(response)), catchError((error) => {
|
|
82
|
-
return this.httpErrorToApiResponse(error);
|
|
83
|
-
}));
|
|
84
|
-
}
|
|
85
|
-
insert(dto) {
|
|
86
|
-
return this.http.post(this.url, dto).pipe(map((response) => this.responseMapping(response)), catchError((error) => {
|
|
87
|
-
return this.httpErrorToApiResponse(error);
|
|
88
|
-
}));
|
|
89
|
-
}
|
|
90
|
-
// biome-ignore lint/correctness/noUnusedVariables: <explanation>
|
|
91
|
-
update(id, dto) {
|
|
92
|
-
throw new Error('update of a chat is not allowed');
|
|
93
|
-
}
|
|
94
|
-
getNewModel() {
|
|
95
|
-
return new Chat();
|
|
96
|
-
}
|
|
97
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ChatService, deps: [{ token: i1.HttpClient }, { token: ORCHESTRATOR_CONFIGURATION }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
98
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ChatService, providedIn: 'root' });
|
|
99
|
-
}
|
|
100
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ChatService, decorators: [{
|
|
101
|
-
type: Injectable,
|
|
102
|
-
args: [{ providedIn: 'root' }]
|
|
103
|
-
}], ctorParameters: () => [{ type: i1.HttpClient }, { type: undefined, decorators: [{
|
|
104
|
-
type: Inject,
|
|
105
|
-
args: [ORCHESTRATOR_CONFIGURATION]
|
|
106
|
-
}] }] });
|
|
107
|
-
|
|
108
|
-
class OrchestratorIconProvider extends IconProvider {
|
|
109
|
-
static agentRunStatusInit = faNoteSticky;
|
|
110
|
-
static agentRunStatusRunning = faCog;
|
|
111
|
-
static agentRunStatusCompleted = faCheck;
|
|
112
|
-
static agentRunStatusFailed = faXmark;
|
|
113
|
-
static agentRunStatusPrerun = faSpinner;
|
|
114
|
-
static agentRunStatusPostrun = faClipboardCheck;
|
|
115
|
-
static agentRunStatusClarify = faCircleQuestion;
|
|
116
|
-
static messageTypeAI = faBrain;
|
|
117
|
-
static messageTypeHuman = faUser;
|
|
118
|
-
static messageTypeSystem = faNetworkWired;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// biome-ignore lint/complexity/noStaticOnlyClass: <explanation>
|
|
122
|
-
class AgentRunIconTextDataprovider {
|
|
123
|
-
static UNKNOWN_TEXT = 'Unbekannt';
|
|
124
|
-
static getTextForStatus(status) {
|
|
125
|
-
if (!status) {
|
|
126
|
-
return AgentRunIconTextDataprovider.UNKNOWN_TEXT;
|
|
127
|
-
}
|
|
128
|
-
switch (status) {
|
|
129
|
-
case EAgentRunStatus.INIT:
|
|
130
|
-
return 'Anlage';
|
|
131
|
-
case EAgentRunStatus.RUNNING:
|
|
132
|
-
return 'In Bearbeitung';
|
|
133
|
-
case EAgentRunStatus.COMPLETED:
|
|
134
|
-
return 'Abgeschlossen';
|
|
135
|
-
case EAgentRunStatus.FAILED:
|
|
136
|
-
return 'Fehlgeschlagen';
|
|
137
|
-
case EAgentRunStatus.CLARIFICATION_NEEDED:
|
|
138
|
-
return 'Rückfrage';
|
|
139
|
-
case EAgentRunStatus.PRERUNNING:
|
|
140
|
-
return 'Vorbereitung';
|
|
141
|
-
case EAgentRunStatus.POSTRUNNING:
|
|
142
|
-
return 'Nachbereitung';
|
|
143
|
-
default:
|
|
144
|
-
return AgentRunIconTextDataprovider.UNKNOWN_TEXT;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
static getIconForStatus(status) {
|
|
148
|
-
if (!status) {
|
|
149
|
-
return IconProvider.unknown;
|
|
150
|
-
}
|
|
151
|
-
switch (status) {
|
|
152
|
-
case EAgentRunStatus.INIT:
|
|
153
|
-
return OrchestratorIconProvider.agentRunStatusInit;
|
|
154
|
-
case EAgentRunStatus.RUNNING:
|
|
155
|
-
return OrchestratorIconProvider.agentRunStatusRunning;
|
|
156
|
-
case EAgentRunStatus.COMPLETED:
|
|
157
|
-
return OrchestratorIconProvider.agentRunStatusCompleted;
|
|
158
|
-
case EAgentRunStatus.FAILED:
|
|
159
|
-
return OrchestratorIconProvider.agentRunStatusFailed;
|
|
160
|
-
case EAgentRunStatus.CLARIFICATION_NEEDED:
|
|
161
|
-
return OrchestratorIconProvider.agentRunStatusClarify;
|
|
162
|
-
case EAgentRunStatus.PRERUNNING:
|
|
163
|
-
return OrchestratorIconProvider.agentRunStatusPrerun;
|
|
164
|
-
case EAgentRunStatus.POSTRUNNING:
|
|
165
|
-
return OrchestratorIconProvider.agentRunStatusPostrun;
|
|
166
|
-
default:
|
|
167
|
-
return IconProvider.unknown;
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
static getIconClassesForStatus(status) {
|
|
171
|
-
if (!status) {
|
|
172
|
-
return AgentRunIconTextDataprovider.UNKNOWN_TEXT;
|
|
173
|
-
}
|
|
174
|
-
switch (status) {
|
|
175
|
-
case EAgentRunStatus.INIT:
|
|
176
|
-
return '';
|
|
177
|
-
case EAgentRunStatus.RUNNING:
|
|
178
|
-
return 'text-primary-600';
|
|
179
|
-
case EAgentRunStatus.COMPLETED:
|
|
180
|
-
return 'text-green-600';
|
|
181
|
-
case EAgentRunStatus.FAILED:
|
|
182
|
-
return 'text-red-600';
|
|
183
|
-
case EAgentRunStatus.CLARIFICATION_NEEDED:
|
|
184
|
-
return '';
|
|
185
|
-
case EAgentRunStatus.PRERUNNING:
|
|
186
|
-
return '';
|
|
187
|
-
case EAgentRunStatus.POSTRUNNING:
|
|
188
|
-
return '';
|
|
189
|
-
default:
|
|
190
|
-
return '';
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
static getIconForMessageType(messageType) {
|
|
194
|
-
switch (messageType) {
|
|
195
|
-
case 'system':
|
|
196
|
-
return OrchestratorIconProvider.messageTypeSystem;
|
|
197
|
-
case 'human':
|
|
198
|
-
return OrchestratorIconProvider.messageTypeHuman;
|
|
199
|
-
case 'ai':
|
|
200
|
-
return OrchestratorIconProvider.messageTypeAI;
|
|
201
|
-
default:
|
|
202
|
-
return IconProvider.unknown;
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
class AgentChatMessageHumanInputComponent {
|
|
208
|
-
agent = input();
|
|
209
|
-
agentRunIdReceived = new EventEmitter();
|
|
210
|
-
messageService = inject(MessageService);
|
|
211
|
-
orchestratorService = inject(OrchestratorService);
|
|
212
|
-
form = new FormGroup({});
|
|
213
|
-
_agentChanged$ = effect(() => {
|
|
214
|
-
this.agent()
|
|
215
|
-
.llmUserPrompt?.template.match(/{{(.*?)}}/g)
|
|
216
|
-
?.forEach((m) => {
|
|
217
|
-
const key = m.slice(2, -2);
|
|
218
|
-
this.form.addControl(key, new FormControl('', [Validators.required]));
|
|
219
|
-
});
|
|
220
|
-
});
|
|
221
|
-
iconTextMapper = AgentRunIconTextDataprovider$1;
|
|
222
|
-
run() {
|
|
223
|
-
if (this.form.valid && this.form.valid) {
|
|
224
|
-
this.orchestratorService
|
|
225
|
-
.runAgent({
|
|
226
|
-
agentIdentifier: this.agent().identifier,
|
|
227
|
-
userInput: this.form.value,
|
|
228
|
-
})
|
|
229
|
-
.subscribe((res) => {
|
|
230
|
-
if (res instanceof MappedApiError) {
|
|
231
|
-
this.messageService.add({ severity: 'error', summary: 'Error', detail: res.messages.join('|') });
|
|
232
|
-
return;
|
|
233
|
-
}
|
|
234
|
-
this.agentRunIdReceived.emit(res);
|
|
235
|
-
});
|
|
236
|
-
}
|
|
237
|
-
else {
|
|
238
|
-
console.error('Form is invalid');
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
getInputFormControlNames() {
|
|
242
|
-
return Object.keys(this.form.controls);
|
|
243
|
-
}
|
|
244
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AgentChatMessageHumanInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
245
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: AgentChatMessageHumanInputComponent, isStandalone: true, selector: "sftech-agent-chat-message-human-input", inputs: { agent: { classPropertyName: "agent", publicName: "agent", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { agentRunIdReceived: "agentRunIdReceived" }, ngImport: i0, template: "<div class=\"my-2 p-4 rounded bg-white flex border-1 flex-row items-center text-right border-gray-600 flex-row-reverse\">\r\n <div class=\"me-4 ms-4 text-gray-600\">\r\n <fa-icon [icon]=\"iconTextMapper.getIconForMessageType('human')\" size=\"2x\"></fa-icon>\r\n </div>\r\n <div class=\"m-0 flex-grow\">\r\n <div class=\"template border-b-1 border-gray-600 p-3\">{{this.agent()!.llmUserPrompt?.template}}</div>\r\n <hr />\r\n <div class=\"inputs mt-2\">\r\n <form [formGroup]=\"form!\">\r\n <div class=\"flex justify-end\">\r\n @for (controlName of getInputFormControlNames(); track controlName) {\r\n <div>\r\n <p-floatlabel variant=\"in\" class=\"w-full\">\r\n <input type=\"text\" id=\"{{ controlName}}\" formControlName=\"{{ controlName }}\" pInputText\r\n class=\"w-full\"/>\r\n <label for=\"{{ controlName }}\">{{ controlName }}</label>\r\n </p-floatlabel>\r\n <sftech-form-error-display [control]=\"form!.get(controlName)!\"\r\n [label]=\"controlName\"></sftech-form-error-display>\r\n </div>\r\n }\r\n </div>\r\n <div class=\"mt-2\">\r\n <p-button type=\"submit\" label=\"Senden\" (onClick)=\"run()\" tabindex=\"1\"/>\r\n </div>\r\n </form>\r\n </div>\r\n </div>\r\n</div>", styles: [""], dependencies: [{ kind: "component", type: FaIconComponent, selector: "fa-icon", inputs: ["icon", "title", "animation", "mask", "flip", "size", "pull", "border", "inverse", "symbol", "rotate", "fixedWidth", "transform", "a11yRole"] }, { kind: "component", type: Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "fluid", "buttonProps"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: FloatLabel, selector: "p-floatlabel, p-floatLabel, p-float-label", inputs: ["variant"] }, { kind: "component", type: FormErrorDisplayComponent, selector: "sftech-form-error-display", inputs: ["control", "label"] }, { kind: "directive", type: InputText, selector: "[pInputText]", inputs: ["variant", "fluid", "pSize"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.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: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }] });
|
|
246
|
-
}
|
|
247
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AgentChatMessageHumanInputComponent, decorators: [{
|
|
248
|
-
type: Component,
|
|
249
|
-
args: [{ selector: 'sftech-agent-chat-message-human-input', imports: [FaIconComponent, Button, FloatLabel, FormErrorDisplayComponent, InputText, ReactiveFormsModule], template: "<div class=\"my-2 p-4 rounded bg-white flex border-1 flex-row items-center text-right border-gray-600 flex-row-reverse\">\r\n <div class=\"me-4 ms-4 text-gray-600\">\r\n <fa-icon [icon]=\"iconTextMapper.getIconForMessageType('human')\" size=\"2x\"></fa-icon>\r\n </div>\r\n <div class=\"m-0 flex-grow\">\r\n <div class=\"template border-b-1 border-gray-600 p-3\">{{this.agent()!.llmUserPrompt?.template}}</div>\r\n <hr />\r\n <div class=\"inputs mt-2\">\r\n <form [formGroup]=\"form!\">\r\n <div class=\"flex justify-end\">\r\n @for (controlName of getInputFormControlNames(); track controlName) {\r\n <div>\r\n <p-floatlabel variant=\"in\" class=\"w-full\">\r\n <input type=\"text\" id=\"{{ controlName}}\" formControlName=\"{{ controlName }}\" pInputText\r\n class=\"w-full\"/>\r\n <label for=\"{{ controlName }}\">{{ controlName }}</label>\r\n </p-floatlabel>\r\n <sftech-form-error-display [control]=\"form!.get(controlName)!\"\r\n [label]=\"controlName\"></sftech-form-error-display>\r\n </div>\r\n }\r\n </div>\r\n <div class=\"mt-2\">\r\n <p-button type=\"submit\" label=\"Senden\" (onClick)=\"run()\" tabindex=\"1\"/>\r\n </div>\r\n </form>\r\n </div>\r\n </div>\r\n</div>" }]
|
|
250
|
-
}], propDecorators: { agentRunIdReceived: [{
|
|
251
|
-
type: Output
|
|
252
|
-
}] } });
|
|
253
|
-
|
|
254
|
-
class AgentChatMessageComponent {
|
|
255
|
-
message = input('message');
|
|
256
|
-
type = input('type');
|
|
257
|
-
iconTextMapper = AgentRunIconTextDataprovider;
|
|
258
|
-
extractJson(message) {
|
|
259
|
-
const jsonMatch = message.match(/```json\s*([\s\S]*?)\s*```/);
|
|
260
|
-
if (jsonMatch && jsonMatch[1]) {
|
|
261
|
-
try {
|
|
262
|
-
const data = JSON.parse(jsonMatch[1]);
|
|
263
|
-
const md = this._toMarkdownFromJson(data);
|
|
264
|
-
return md;
|
|
265
|
-
}
|
|
266
|
-
catch (e) {
|
|
267
|
-
console.error('Failed to parse JSON:', e);
|
|
268
|
-
return 'Invalid JSON';
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
return 'No JSON found';
|
|
272
|
-
}
|
|
273
|
-
_toMarkdownFromJson(obj) {
|
|
274
|
-
let md = '';
|
|
275
|
-
for (const key of Object.keys(obj)) {
|
|
276
|
-
const value = obj[key];
|
|
277
|
-
// Überschrift für jede Kategorie
|
|
278
|
-
md += `\n### ${key}\n\n`;
|
|
279
|
-
if (Array.isArray(value) && value.length && typeof value[0] === 'object') {
|
|
280
|
-
// Tabellen-Header
|
|
281
|
-
const headers = Object.keys(value[0]);
|
|
282
|
-
md += `| ${headers.join(' | ')} |\n`;
|
|
283
|
-
md += `| ${headers.map(() => '---').join(' | ')} |\n`;
|
|
284
|
-
// Tabellen-Zeilen
|
|
285
|
-
for (const row of value) {
|
|
286
|
-
md += `| ${headers.map((h) => row[h]).join(' | ')} |\n`;
|
|
287
|
-
}
|
|
288
|
-
md += '\n';
|
|
289
|
-
}
|
|
290
|
-
else if (typeof value === 'object') {
|
|
291
|
-
// Rekursiver Aufruf bei verschachtelten Objekten
|
|
292
|
-
md += this._toMarkdownFromJson(value);
|
|
293
|
-
}
|
|
294
|
-
else {
|
|
295
|
-
// Einfaches Feld
|
|
296
|
-
md += `- **${key}:** ${value}\n`;
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
return md;
|
|
300
|
-
}
|
|
301
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AgentChatMessageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
302
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: AgentChatMessageComponent, isStandalone: true, selector: "sftech-agent-chat-message", inputs: { message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (type() === 'ai_loading') {\r\n <div class=\"p-4 rounded bg-white flex border-1 flex-row items-center\">\r\n <div class=\"me-4 ms-4 text-green-600\">\r\n <fa-icon [icon]=\"iconTextMapper.getIconForMessageType('ai')\" size=\"2x\"></fa-icon>\r\n </div>\r\n <div class=\"m-0 w-full\">\r\n <div class=\"flex space-x-2 justify-start items-center\">\r\n <div class=\"me-4\">Die Antwort wird ermittelt</div>\r\n <div class=\"w-3 h-3 bg-green-600 rounded-full animate-bounceDelay\"></div>\r\n <div class=\"w-3 h-3 bg-green-600 rounded-full animate-bounceDelay [animation-delay:-0.32s]\"></div>\r\n <div class=\"w-3 h-3 bg-green-600 rounded-full animate-bounceDelay [animation-delay:-0.16s]\"></div>\r\n </div>\r\n </div>\r\n\r\n </div>\r\n\r\n} @else if (type() === 'ai_failed') {\r\n <div class=\"p-4 rounded bg-red-100 flex border-1 flex-row items-center\">\r\n <div class=\"me-4 ms-4 text-green-600\">\r\n <fa-icon [icon]=\"iconTextMapper.getIconForMessageType('ai')\" size=\"2x\"></fa-icon>\r\n </div>\r\n <div class=\"m-0 w-full\">\r\n {{\r\n message()\r\n }}\r\n </div>\r\n\r\n </div>\r\n\r\n} @else {\r\n <div class=\"p-4 rounded bg-white flex border-1 flex-row items-center\" [ngClass]=\"{\r\n 'border-green-600 bg-green-200': type() === 'ai',\r\n 'text-right border-gray-600 flex-row-reverse': type() === 'human',\r\n 'border-yellow-600 bg-yellow-100': type() === 'system',\r\n }\">\r\n <div class=\"me-4 ms-4\" [ngClass]=\"{\r\n 'text-green-600': type() === 'ai',\r\n 'text-gray-600': type() === 'human',\r\n 'text-yellow-600': type() === 'system',\r\n }\">\r\n <fa-icon [icon]=\"iconTextMapper.getIconForMessageType(type())\" size=\"2x\"></fa-icon>\r\n </div>\r\n @if (message().includes('```json')) {\r\n <div class=\"m-0 prose prose-sm max-w-none\" markdown>{{ extractJson(message()) }}</div>\r\n } @else {\r\n <div class=\"m-0\" markdown>{{ message() }}</div>\r\n }\r\n </div>\r\n}\r\n\r\n\r\n\r\n", styles: ["@layer utilities{@keyframes bounceDelay{0%,80%,to{transform:scale(0)}40%{transform:scale(1)}}.animate-bounceDelay{animation:bounceDelay 1.4s infinite ease-in-out both}}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: FaIconComponent, selector: "fa-icon", inputs: ["icon", "title", "animation", "mask", "flip", "size", "pull", "border", "inverse", "symbol", "rotate", "fixedWidth", "transform", "a11yRole"] }, { kind: "component", type: MarkdownComponent, selector: "markdown, [markdown]", inputs: ["data", "src", "disableSanitizer", "inline", "clipboard", "clipboardButtonComponent", "clipboardButtonTemplate", "emoji", "katex", "katexOptions", "mermaid", "mermaidOptions", "lineHighlight", "line", "lineOffset", "lineNumbers", "start", "commandLine", "filterOutput", "host", "prompt", "output", "user"], outputs: ["error", "load", "ready"] }] });
|
|
303
|
-
}
|
|
304
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AgentChatMessageComponent, decorators: [{
|
|
305
|
-
type: Component,
|
|
306
|
-
args: [{ selector: 'sftech-agent-chat-message', imports: [NgClass, FaIconComponent, MarkdownComponent, JsonPipe, Skeleton], template: "@if (type() === 'ai_loading') {\r\n <div class=\"p-4 rounded bg-white flex border-1 flex-row items-center\">\r\n <div class=\"me-4 ms-4 text-green-600\">\r\n <fa-icon [icon]=\"iconTextMapper.getIconForMessageType('ai')\" size=\"2x\"></fa-icon>\r\n </div>\r\n <div class=\"m-0 w-full\">\r\n <div class=\"flex space-x-2 justify-start items-center\">\r\n <div class=\"me-4\">Die Antwort wird ermittelt</div>\r\n <div class=\"w-3 h-3 bg-green-600 rounded-full animate-bounceDelay\"></div>\r\n <div class=\"w-3 h-3 bg-green-600 rounded-full animate-bounceDelay [animation-delay:-0.32s]\"></div>\r\n <div class=\"w-3 h-3 bg-green-600 rounded-full animate-bounceDelay [animation-delay:-0.16s]\"></div>\r\n </div>\r\n </div>\r\n\r\n </div>\r\n\r\n} @else if (type() === 'ai_failed') {\r\n <div class=\"p-4 rounded bg-red-100 flex border-1 flex-row items-center\">\r\n <div class=\"me-4 ms-4 text-green-600\">\r\n <fa-icon [icon]=\"iconTextMapper.getIconForMessageType('ai')\" size=\"2x\"></fa-icon>\r\n </div>\r\n <div class=\"m-0 w-full\">\r\n {{\r\n message()\r\n }}\r\n </div>\r\n\r\n </div>\r\n\r\n} @else {\r\n <div class=\"p-4 rounded bg-white flex border-1 flex-row items-center\" [ngClass]=\"{\r\n 'border-green-600 bg-green-200': type() === 'ai',\r\n 'text-right border-gray-600 flex-row-reverse': type() === 'human',\r\n 'border-yellow-600 bg-yellow-100': type() === 'system',\r\n }\">\r\n <div class=\"me-4 ms-4\" [ngClass]=\"{\r\n 'text-green-600': type() === 'ai',\r\n 'text-gray-600': type() === 'human',\r\n 'text-yellow-600': type() === 'system',\r\n }\">\r\n <fa-icon [icon]=\"iconTextMapper.getIconForMessageType(type())\" size=\"2x\"></fa-icon>\r\n </div>\r\n @if (message().includes('```json')) {\r\n <div class=\"m-0 prose prose-sm max-w-none\" markdown>{{ extractJson(message()) }}</div>\r\n } @else {\r\n <div class=\"m-0\" markdown>{{ message() }}</div>\r\n }\r\n </div>\r\n}\r\n\r\n\r\n\r\n", styles: ["@layer utilities{@keyframes bounceDelay{0%,80%,to{transform:scale(0)}40%{transform:scale(1)}}.animate-bounceDelay{animation:bounceDelay 1.4s infinite ease-in-out both}}\n"] }]
|
|
307
|
-
}] });
|
|
308
|
-
|
|
309
|
-
class AgentChatComponent {
|
|
310
|
-
activeRoute = inject(ActivatedRoute);
|
|
311
|
-
router = inject(Router);
|
|
312
|
-
agentService = inject(AgentService);
|
|
313
|
-
agentRunService = inject(AgentRunService);
|
|
314
|
-
chatService = inject(ChatService);
|
|
315
|
-
orchestratorService = inject(OrchestratorService);
|
|
316
|
-
messageService = inject(MessageService);
|
|
317
|
-
agent;
|
|
318
|
-
agentRuns = signal(undefined);
|
|
319
|
-
selectedAgentRun = signal(undefined);
|
|
320
|
-
selectedAgent = signal(undefined);
|
|
321
|
-
iconProvider = IconProvider;
|
|
322
|
-
iconTextMapper = AgentRunIconTextDataprovider;
|
|
323
|
-
agentRunStatus = EAgentRunStatus;
|
|
324
|
-
subscriptions = [];
|
|
325
|
-
selectedAgentRunChanged$ = effect(() => {
|
|
326
|
-
if (!this.selectedAgentRun()) {
|
|
327
|
-
return;
|
|
328
|
-
}
|
|
329
|
-
});
|
|
330
|
-
loading = computed(() => {
|
|
331
|
-
if (!this.selectedAgentRun()?.status) {
|
|
332
|
-
return false;
|
|
333
|
-
}
|
|
334
|
-
return ![EAgentRunStatus.COMPLETED, EAgentRunStatus.CLARIFICATION_NEEDED, EAgentRunStatus.FAILED, EAgentRunStatus.INIT].includes(this.selectedAgentRun().status);
|
|
335
|
-
});
|
|
336
|
-
ngOnInit() {
|
|
337
|
-
console.log('ngOnInit');
|
|
338
|
-
const agentId = Number(this.activeRoute.snapshot.paramMap.get('agentId'));
|
|
339
|
-
const agentRunId = Number(this.activeRoute.snapshot.paramMap.get('agentRunId'));
|
|
340
|
-
if (agentId) {
|
|
341
|
-
const odata = new OData();
|
|
342
|
-
odata.filter.addAnd(new OdataFilter('agentId', agentId, EFilterOperator.EQUALS, EFilterTypes.NUMERIC));
|
|
343
|
-
odata.order.column = 'updatedAt';
|
|
344
|
-
odata.order.direction = ESortDirection.DESC;
|
|
345
|
-
this.agentRunService
|
|
346
|
-
.odata(odata)
|
|
347
|
-
.pipe(map((res) => {
|
|
348
|
-
if (res instanceof MappedApiError) {
|
|
349
|
-
this.messageService.add({
|
|
350
|
-
severity: 'error',
|
|
351
|
-
summary: 'Error',
|
|
352
|
-
detail: 'Fehler beim Laden der Chat-Daten',
|
|
353
|
-
});
|
|
354
|
-
throw new Error(res.messages.join('|'));
|
|
355
|
-
}
|
|
356
|
-
this.selectedAgentRun.set(res.data.items.find((ar) => agentRunId == ar.id));
|
|
357
|
-
this.agentRuns.set(res.data.items);
|
|
358
|
-
}))
|
|
359
|
-
.subscribe();
|
|
360
|
-
this.agentService.get(agentId, true).subscribe((res) => {
|
|
361
|
-
if (res instanceof MappedApiError) {
|
|
362
|
-
this.messageService.add({
|
|
363
|
-
severity: 'error',
|
|
364
|
-
summary: 'Error',
|
|
365
|
-
detail: 'Fehler beim Laden des Agenten-Daten',
|
|
366
|
-
});
|
|
367
|
-
throw new Error(res.messages.join('|'));
|
|
368
|
-
}
|
|
369
|
-
this.selectedAgent.set(res.data);
|
|
370
|
-
});
|
|
371
|
-
}
|
|
372
|
-
else {
|
|
373
|
-
this.messageService.add({ severity: 'error', summary: 'Error', detail: 'Fehler beim Laden des Agenten' });
|
|
374
|
-
// this.router.navigate(['../chats']);
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
ngOnDestroy() {
|
|
378
|
-
this.subscriptions.forEach((subscription) => subscription.unsubscribe());
|
|
379
|
-
}
|
|
380
|
-
startNewRun() {
|
|
381
|
-
if (!this.selectedAgent()) {
|
|
382
|
-
return;
|
|
383
|
-
}
|
|
384
|
-
const agentRun = new AgentRun();
|
|
385
|
-
agentRun.agentId = this.selectedAgent().id;
|
|
386
|
-
agentRun.agent = this.selectedAgent();
|
|
387
|
-
agentRun.status = EAgentRunStatus.INIT;
|
|
388
|
-
agentRun.createdAt = new Date();
|
|
389
|
-
agentRun.chat = new Chat();
|
|
390
|
-
const systemContextMessage = new ChatMessage();
|
|
391
|
-
systemContextMessage.messageType = 'system';
|
|
392
|
-
systemContextMessage.message = `${this.selectedAgent().llmSystemPrompt?.template}Antworte nach folgender Spezifikation:<br>${this.selectedAgent()?.answerSpecification}`;
|
|
393
|
-
agentRun.chat.messages = [systemContextMessage];
|
|
394
|
-
this.selectedAgentRun.set(agentRun);
|
|
395
|
-
}
|
|
396
|
-
selectAgentRun(agentRun) {
|
|
397
|
-
this.selectedAgentRun.set(agentRun);
|
|
398
|
-
this._loadChat();
|
|
399
|
-
if (this.selectedAgentRun().id) {
|
|
400
|
-
this._setRelativeUrl();
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
startObservingAgentRun(agentRunId) {
|
|
404
|
-
this.subscriptions.push(this.orchestratorService.observeAgentRun(agentRunId).subscribe({
|
|
405
|
-
next: (update) => {
|
|
406
|
-
if (update instanceof MappedApiError) {
|
|
407
|
-
this.messageService.add({ severity: 'error', summary: 'Error', detail: 'Fehler beim Beobachten des Agentenlaufs' });
|
|
408
|
-
return;
|
|
409
|
-
}
|
|
410
|
-
// biome-ignore lint/correctness/noUnusedVariables: <explanation>
|
|
411
|
-
this.selectedAgentRun.update((agentRun) => {
|
|
412
|
-
return this._mapUpdateOnAgentRun(agentRun, update);
|
|
413
|
-
});
|
|
414
|
-
if (update.id && this.agentRuns()?.filter((ars) => ars.id === update.id).length === 0) {
|
|
415
|
-
this.agentRuns.update((ars) => {
|
|
416
|
-
ars?.unshift(update);
|
|
417
|
-
return ars;
|
|
418
|
-
});
|
|
419
|
-
}
|
|
420
|
-
},
|
|
421
|
-
error: (err) => {
|
|
422
|
-
this.messageService.add({ severity: 'error', summary: 'Error', detail: 'Fehler beim Beobachten des Agentenlaufs' });
|
|
423
|
-
console.error('Error observing agent run:', err);
|
|
424
|
-
},
|
|
425
|
-
complete: () => {
|
|
426
|
-
console.log('Completed observing agent run');
|
|
427
|
-
},
|
|
428
|
-
}));
|
|
429
|
-
}
|
|
430
|
-
goBack() {
|
|
431
|
-
const index = this.router.url.indexOf('/agent/');
|
|
432
|
-
const result = this.router.url.substring(0, index);
|
|
433
|
-
this.router.navigateByUrl(result);
|
|
434
|
-
}
|
|
435
|
-
_loadChat() {
|
|
436
|
-
if (!this.selectedAgentRun() || !this.selectedAgentRun().chatId) {
|
|
437
|
-
return;
|
|
438
|
-
}
|
|
439
|
-
this.chatService.get(this.selectedAgentRun().chatId, true).subscribe((res) => {
|
|
440
|
-
if (res instanceof MappedApiError) {
|
|
441
|
-
this.messageService.add({
|
|
442
|
-
severity: 'error',
|
|
443
|
-
summary: 'Error',
|
|
444
|
-
detail: 'Fehler beim Laden der Chat-Daten',
|
|
445
|
-
});
|
|
446
|
-
}
|
|
447
|
-
this.selectedAgentRun.update((ar) => {
|
|
448
|
-
ar.chat = res.data;
|
|
449
|
-
return ar;
|
|
450
|
-
});
|
|
451
|
-
});
|
|
452
|
-
}
|
|
453
|
-
_setRelativeUrl() {
|
|
454
|
-
let relativeUrl;
|
|
455
|
-
if (this.router.url.includes('/r/')) {
|
|
456
|
-
const index = this.router.url.indexOf('/r/') + 3; // 3 = Länge von "/r/"
|
|
457
|
-
const result = this.router.url.substring(0, index);
|
|
458
|
-
relativeUrl = `${result}${this.selectedAgentRun().id}`;
|
|
459
|
-
}
|
|
460
|
-
else {
|
|
461
|
-
relativeUrl = `r/${this.selectedAgentRun().id}`;
|
|
462
|
-
}
|
|
463
|
-
this.router.navigate([relativeUrl], {
|
|
464
|
-
relativeTo: this.activeRoute,
|
|
465
|
-
replaceUrl: true, // überschreibt den Verlauf
|
|
466
|
-
skipLocationChange: false, // false = URL sichtbar, true = nur intern
|
|
467
|
-
});
|
|
468
|
-
}
|
|
469
|
-
_mapUpdateOnAgentRun(agentRun, update) {
|
|
470
|
-
if (!agentRun.chat?.messages && !update.chat?.messages) {
|
|
471
|
-
return update;
|
|
472
|
-
}
|
|
473
|
-
if (!update.chat && agentRun.chat) {
|
|
474
|
-
update.chat = agentRun.chat;
|
|
475
|
-
}
|
|
476
|
-
if (agentRun.chat?.messages && update.chat.messages.length <= agentRun.chat.messages.length) {
|
|
477
|
-
update.chat.messages = agentRun.chat.messages;
|
|
478
|
-
}
|
|
479
|
-
console.log('Mapped AgentRun:', update.chat.messages.length, agentRun.chat.messages.length);
|
|
480
|
-
return update;
|
|
481
|
-
}
|
|
482
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AgentChatComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
483
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: AgentChatComponent, isStandalone: true, selector: "sftech-agent-chat", ngImport: i0, template: "<div class=\"flex h-full shadow-lg\">\r\n <div class=\"chats-panel border-r-1 border-gray-300 p-2 w-[250px] flex-shrink-0 h-full\">\r\n <div class=\"flex justify-between\">\r\n <div (click)=\"goBack()\" tabindex=\"2\">\r\n <fa-icon [icon]=\"iconProvider.back\" class=\"me-3\"></fa-icon>\r\n </div>\r\n <h2 class=\"text-2xl font-bold mb-4\">{{ selectedAgent()?.name }}</h2>\r\n </div>\r\n @if (selectedAgent()) {\r\n <div class=\"mt-0 mb-2\">\r\n <button pButton type=\"button\" class=\"w-full mt-4\" (click)=\"startNewRun()\" tabindex=\"3\">\r\n <fa-icon [icon]=\"iconProvider.add\"></fa-icon>\r\n neu\r\n </button>\r\n </div>\r\n }\r\n <div class=\"p-1 m-2 border-1 border-gray-300 rounded-lg bg-white max-h-[calc(100%-120px)] overflow-y-auto\">\r\n\r\n\r\n @if (agentRuns() === undefined) {\r\n\r\n <p class=\"m-0\">\r\n Die Chats werden geladen...\r\n </p>\r\n } @else if (!agentRuns()?.length) {\r\n <p class=\"m-0\">\r\n Bisher noch keine Chats vorhanden\r\n </p>\r\n } @else {\r\n <div class=\"my-2 mx-2 flex flex-col gap-1 overflow-y-auto\">\r\n @for (agentRun of agentRuns(); track agentRun) {\r\n <div class=\"border border-gray-300 rounded-lg p-4 hover:shadow-lg transition cursor-pointer\"\r\n (click)=\"selectAgentRun(agentRun)\"\r\n [class.bg-blue-100]=\"selectedAgentRun()?.id === agentRun.id\">\r\n <div class=\"text-sm text-gray-500\">{{ agentRun.createdAt | date:'dd.MM.YY - hh:mm' }}</div>\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n <div class=\"chat bg-gray-50 flex-grow-1 p-3 overflow-y-auto m-1\">\r\n @if (selectedAgentRun() === undefined) {\r\n <p-panel [toggleable]=\"false\">\r\n <p class=\"m-0\">\r\n Bitte einen Chat aus der linken Liste ausw\u00E4hlen\r\n </p>\r\n </p-panel>\r\n } @else if (selectedAgent() === undefined) {\r\n <p-panel [toggleable]=\"false\">\r\n <p class=\"m-0\">\r\n Die Chat-Daten werden geladen...\r\n </p>\r\n </p-panel>\r\n } @else {\r\n <div class=\"flex flex-col h-full\">\r\n <div class=\"border-b border-gray-300 pb-2 mb-2 flex justify-between\">\r\n <h2 class=\"text-xl font-semibold\">\r\n Agent: {{ selectedAgent()?.name }}\r\n vom {{ (selectedAgentRun()?.createdAt ?? selectedAgentRun()?.startedAt | date:'dd.MM.yyyy - hh:mm') }}</h2>\r\n <p class=\"text-gray-600 font-bold\">Status:\r\n <fa-icon [icon]=\"iconTextMapper.getIconForStatus(selectedAgentRun()?.status)\" size=\"2x\"\r\n [classList]=\"iconTextMapper.getIconClassesForStatus(selectedAgentRun()?.status)\"\r\n [animation]=\"selectedAgentRun()?.status === 'running' ? 'spin' : undefined\"\r\n class=\"ms-2\"></fa-icon>\r\n </p>\r\n </div>\r\n @if (selectedAgentRun()!.chat) {\r\n @for (message of selectedAgentRun()!.chat!.messages; track message.id) {\r\n <div class=\"mb-2\">\r\n <sftech-agent-chat-message [message]=\"message.message\"\r\n [type]=\"message.messageType\"></sftech-agent-chat-message>\r\n </div>\r\n }\r\n }\r\n @if (selectedAgentRun()!.status === agentRunStatus.INIT) {\r\n <sftech-agent-chat-message-human-input [agent]=\"selectedAgent()\"\r\n (agentRunIdReceived)=\"startObservingAgentRun($event)\"></sftech-agent-chat-message-human-input>\r\n }\r\n @if (loading()) {\r\n <div class=\"mb-2\">\r\n <sftech-agent-chat-message [message]=\"'Am \u00DCberlegen'\"\r\n [type]=\"'ai_loading'\"></sftech-agent-chat-message>\r\n </div>\r\n }\r\n @if (selectedAgentRun()?.status === agentRunStatus.FAILED) {\r\n <div class=\"mb-2\">\r\n <sftech-agent-chat-message\r\n [message]=\"'Es ist ein Fehler aufgetreten! Bitte versuche es zu einem sp\u00E4teren Zeitpunkt erneut.'\"\r\n [type]=\"'ai_failed'\"></sftech-agent-chat-message>\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n</div>\r\n", styles: [""], dependencies: [{ kind: "component", type: Panel, selector: "p-panel", inputs: ["toggleable", "header", "collapsed", "style", "styleClass", "iconPos", "expandIcon", "collapseIcon", "showHeader", "toggler", "transitionOptions", "toggleButtonProps"], outputs: ["collapsedChange", "onBeforeToggle", "onAfterToggle"] }, { kind: "directive", type: ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "loading", "severity", "raised", "rounded", "text", "outlined", "size", "plain", "fluid", "label", "icon", "buttonProps"] }, { kind: "component", type: AgentChatMessageComponent, selector: "sftech-agent-chat-message", inputs: ["message", "type"] }, { kind: "pipe", type: DatePipe, name: "date" }, { kind: "component", type: FaIconComponent, selector: "fa-icon", inputs: ["icon", "title", "animation", "mask", "flip", "size", "pull", "border", "inverse", "symbol", "rotate", "fixedWidth", "transform", "a11yRole"] }, { kind: "component", type: AgentChatMessageHumanInputComponent, selector: "sftech-agent-chat-message-human-input", inputs: ["agent"], outputs: ["agentRunIdReceived"] }] });
|
|
484
|
-
}
|
|
485
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AgentChatComponent, decorators: [{
|
|
486
|
-
type: Component,
|
|
487
|
-
args: [{ selector: 'sftech-agent-chat', imports: [Panel, ButtonDirective, AgentChatMessageComponent, DatePipe, FaIconComponent, AgentChatMessageHumanInputComponent], template: "<div class=\"flex h-full shadow-lg\">\r\n <div class=\"chats-panel border-r-1 border-gray-300 p-2 w-[250px] flex-shrink-0 h-full\">\r\n <div class=\"flex justify-between\">\r\n <div (click)=\"goBack()\" tabindex=\"2\">\r\n <fa-icon [icon]=\"iconProvider.back\" class=\"me-3\"></fa-icon>\r\n </div>\r\n <h2 class=\"text-2xl font-bold mb-4\">{{ selectedAgent()?.name }}</h2>\r\n </div>\r\n @if (selectedAgent()) {\r\n <div class=\"mt-0 mb-2\">\r\n <button pButton type=\"button\" class=\"w-full mt-4\" (click)=\"startNewRun()\" tabindex=\"3\">\r\n <fa-icon [icon]=\"iconProvider.add\"></fa-icon>\r\n neu\r\n </button>\r\n </div>\r\n }\r\n <div class=\"p-1 m-2 border-1 border-gray-300 rounded-lg bg-white max-h-[calc(100%-120px)] overflow-y-auto\">\r\n\r\n\r\n @if (agentRuns() === undefined) {\r\n\r\n <p class=\"m-0\">\r\n Die Chats werden geladen...\r\n </p>\r\n } @else if (!agentRuns()?.length) {\r\n <p class=\"m-0\">\r\n Bisher noch keine Chats vorhanden\r\n </p>\r\n } @else {\r\n <div class=\"my-2 mx-2 flex flex-col gap-1 overflow-y-auto\">\r\n @for (agentRun of agentRuns(); track agentRun) {\r\n <div class=\"border border-gray-300 rounded-lg p-4 hover:shadow-lg transition cursor-pointer\"\r\n (click)=\"selectAgentRun(agentRun)\"\r\n [class.bg-blue-100]=\"selectedAgentRun()?.id === agentRun.id\">\r\n <div class=\"text-sm text-gray-500\">{{ agentRun.createdAt | date:'dd.MM.YY - hh:mm' }}</div>\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n <div class=\"chat bg-gray-50 flex-grow-1 p-3 overflow-y-auto m-1\">\r\n @if (selectedAgentRun() === undefined) {\r\n <p-panel [toggleable]=\"false\">\r\n <p class=\"m-0\">\r\n Bitte einen Chat aus der linken Liste ausw\u00E4hlen\r\n </p>\r\n </p-panel>\r\n } @else if (selectedAgent() === undefined) {\r\n <p-panel [toggleable]=\"false\">\r\n <p class=\"m-0\">\r\n Die Chat-Daten werden geladen...\r\n </p>\r\n </p-panel>\r\n } @else {\r\n <div class=\"flex flex-col h-full\">\r\n <div class=\"border-b border-gray-300 pb-2 mb-2 flex justify-between\">\r\n <h2 class=\"text-xl font-semibold\">\r\n Agent: {{ selectedAgent()?.name }}\r\n vom {{ (selectedAgentRun()?.createdAt ?? selectedAgentRun()?.startedAt | date:'dd.MM.yyyy - hh:mm') }}</h2>\r\n <p class=\"text-gray-600 font-bold\">Status:\r\n <fa-icon [icon]=\"iconTextMapper.getIconForStatus(selectedAgentRun()?.status)\" size=\"2x\"\r\n [classList]=\"iconTextMapper.getIconClassesForStatus(selectedAgentRun()?.status)\"\r\n [animation]=\"selectedAgentRun()?.status === 'running' ? 'spin' : undefined\"\r\n class=\"ms-2\"></fa-icon>\r\n </p>\r\n </div>\r\n @if (selectedAgentRun()!.chat) {\r\n @for (message of selectedAgentRun()!.chat!.messages; track message.id) {\r\n <div class=\"mb-2\">\r\n <sftech-agent-chat-message [message]=\"message.message\"\r\n [type]=\"message.messageType\"></sftech-agent-chat-message>\r\n </div>\r\n }\r\n }\r\n @if (selectedAgentRun()!.status === agentRunStatus.INIT) {\r\n <sftech-agent-chat-message-human-input [agent]=\"selectedAgent()\"\r\n (agentRunIdReceived)=\"startObservingAgentRun($event)\"></sftech-agent-chat-message-human-input>\r\n }\r\n @if (loading()) {\r\n <div class=\"mb-2\">\r\n <sftech-agent-chat-message [message]=\"'Am \u00DCberlegen'\"\r\n [type]=\"'ai_loading'\"></sftech-agent-chat-message>\r\n </div>\r\n }\r\n @if (selectedAgentRun()?.status === agentRunStatus.FAILED) {\r\n <div class=\"mb-2\">\r\n <sftech-agent-chat-message\r\n [message]=\"'Es ist ein Fehler aufgetreten! Bitte versuche es zu einem sp\u00E4teren Zeitpunkt erneut.'\"\r\n [type]=\"'ai_failed'\"></sftech-agent-chat-message>\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n</div>\r\n" }]
|
|
488
|
-
}] });
|
|
489
|
-
|
|
490
|
-
class AgentSelectionComponent extends BaseListComponent {
|
|
491
|
-
_repo = inject(AgentService);
|
|
492
|
-
_route = 'chats/agents';
|
|
493
|
-
orchestratorService = inject(OrchestratorService);
|
|
494
|
-
messageService = inject(MessageService);
|
|
495
|
-
iconProvider = IconProvider;
|
|
496
|
-
tools = signal(undefined);
|
|
497
|
-
ngOnInit() {
|
|
498
|
-
super.ngOnInit();
|
|
499
|
-
this.orchestratorService.getTools().subscribe((res) => {
|
|
500
|
-
if (res instanceof MappedApiError) {
|
|
501
|
-
this.messageService.add({ severity: 'error', summary: 'Fehler', detail: res.messages.join('|') });
|
|
502
|
-
return;
|
|
503
|
-
}
|
|
504
|
-
this.tools.set(res.data);
|
|
505
|
-
});
|
|
506
|
-
}
|
|
507
|
-
getToolNames(agent) {
|
|
508
|
-
if (!agent.tools || agent.tools.length === 0) {
|
|
509
|
-
return 'Keine Werkzeuge';
|
|
510
|
-
}
|
|
511
|
-
return agent.tools
|
|
512
|
-
.map((tool) => this.tools()?.find((t) => t.identifier === tool)?.name)
|
|
513
|
-
.filter((name) => !!name)
|
|
514
|
-
.join(' | ');
|
|
515
|
-
}
|
|
516
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AgentSelectionComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
517
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: AgentSelectionComponent, isStandalone: true, selector: "sftech-agent-selection", providers: [DialogService], usesInheritance: true, ngImport: i0, template: "<h2 class=\"mt-4 text-2xl font-bold mb-4\">Agenten Auswahl</h2>\r\n\r\n@if (data() === undefined) {\r\n <p-panel [toggleable]=\"false\">\r\n <p class=\"m-0\">\r\n Daten werden geladen...\r\n </p>\r\n </p-panel>\r\n} @else if (!data()?.length) {\r\n <p-panel [toggleable]=\"false\">\r\n <p class=\"m-0\">\r\n Keine Daten vorhanden\r\n </p>\r\n </p-panel>\r\n} @else {\r\n <div class=\"grid grid-cols-4 gap-4\">\r\n @for (agent of data(); track agent) {\r\n <div class=\"aspect-square flex justify-between flex-col border border-gray-300 rounded-lg p-4 hover:shadow-lg transition cursor-pointer shadow-xl hover:shadow-sm\" [routerLink]=\"['agent/' + agent.id]\">\r\n <div>\r\n <h2 class=\"text-lg font-semibold mb-6\">{{ agent.name }}</h2>\r\n <p class=\"text-gray-600\">{{ agent.description }}</p>\r\n </div>\r\n <div class=\"text-sm text-gray-500\">Tools: {{ getToolNames(agent) }}</div>\r\n </div>\r\n }\r\n </div>\r\n}", styles: [""], dependencies: [{ kind: "component", type: Panel, selector: "p-panel", inputs: ["toggleable", "header", "collapsed", "style", "styleClass", "iconPos", "expandIcon", "collapseIcon", "showHeader", "toggler", "transitionOptions", "toggleButtonProps"], outputs: ["collapsedChange", "onBeforeToggle", "onAfterToggle"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }] });
|
|
518
|
-
}
|
|
519
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AgentSelectionComponent, decorators: [{
|
|
520
|
-
type: Component,
|
|
521
|
-
args: [{ selector: 'sftech-agent-selection', imports: [Panel, RouterLink], providers: [DialogService], template: "<h2 class=\"mt-4 text-2xl font-bold mb-4\">Agenten Auswahl</h2>\r\n\r\n@if (data() === undefined) {\r\n <p-panel [toggleable]=\"false\">\r\n <p class=\"m-0\">\r\n Daten werden geladen...\r\n </p>\r\n </p-panel>\r\n} @else if (!data()?.length) {\r\n <p-panel [toggleable]=\"false\">\r\n <p class=\"m-0\">\r\n Keine Daten vorhanden\r\n </p>\r\n </p-panel>\r\n} @else {\r\n <div class=\"grid grid-cols-4 gap-4\">\r\n @for (agent of data(); track agent) {\r\n <div class=\"aspect-square flex justify-between flex-col border border-gray-300 rounded-lg p-4 hover:shadow-lg transition cursor-pointer shadow-xl hover:shadow-sm\" [routerLink]=\"['agent/' + agent.id]\">\r\n <div>\r\n <h2 class=\"text-lg font-semibold mb-6\">{{ agent.name }}</h2>\r\n <p class=\"text-gray-600\">{{ agent.description }}</p>\r\n </div>\r\n <div class=\"text-sm text-gray-500\">Tools: {{ getToolNames(agent) }}</div>\r\n </div>\r\n }\r\n </div>\r\n}" }]
|
|
522
|
-
}] });
|
|
523
|
-
|
|
524
|
-
class ChatsComponent {
|
|
525
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ChatsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
526
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: ChatsComponent, isStandalone: true, selector: "sftech-chats", ngImport: i0, template: '<router-outlet></router-outlet>', isInline: true, styles: [""], dependencies: [{ kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }] });
|
|
527
|
-
}
|
|
528
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ChatsComponent, decorators: [{
|
|
529
|
-
type: Component,
|
|
530
|
-
args: [{ selector: 'sftech-chats', imports: [RouterOutlet], template: '<router-outlet></router-outlet>' }]
|
|
531
|
-
}] });
|
|
532
|
-
|
|
533
|
-
const chatsRoutes = [
|
|
534
|
-
{
|
|
535
|
-
path: '',
|
|
536
|
-
component: ChatsComponent,
|
|
537
|
-
children: [
|
|
538
|
-
{
|
|
539
|
-
path: '',
|
|
540
|
-
component: AgentSelectionComponent,
|
|
541
|
-
},
|
|
542
|
-
{
|
|
543
|
-
path: 'agent/:agentId/r/:agentRunId',
|
|
544
|
-
component: AgentChatComponent,
|
|
545
|
-
},
|
|
546
|
-
{
|
|
547
|
-
path: 'agent/:agentId',
|
|
548
|
-
component: AgentChatComponent,
|
|
549
|
-
},
|
|
550
|
-
],
|
|
551
|
-
canActivate: [AuthenticationGuard],
|
|
552
|
-
},
|
|
553
|
-
];
|
|
554
|
-
|
|
555
|
-
export { chatsRoutes };
|
|
556
|
-
//# sourceMappingURL=sftech-ng-orchestrator-chats.routes-BLGhykMM.mjs.map
|