@dataclouder/ngx-agent-cards 0.1.0 → 0.1.1

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.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, Injectable, inject, Pipe, input, output, Input, Component, signal, computed, ChangeDetectorRef, DestroyRef, effect, ChangeDetectionStrategy, ElementRef, ViewChild, ViewChildren } from '@angular/core';
2
+ import { InjectionToken, Injectable, inject, Pipe, input, output, Input, Component, signal, effect, computed, ChangeDetectorRef, DestroyRef, ChangeDetectionStrategy, ElementRef, ViewChild, ViewChildren } from '@angular/core';
3
3
  import * as i1$1 from '@angular/common';
4
4
  import { CommonModule, DatePipe, DecimalPipe, NgComponentOutlet } from '@angular/common';
5
5
  import { DynamicDialogRef, DialogService, DynamicDialogConfig, DynamicDialogModule } from 'primeng/dynamicdialog';
@@ -14,6 +14,7 @@ import * as i3 from 'primeng/textarea';
14
14
  import { TextareaModule } from 'primeng/textarea';
15
15
  import * as i2$1 from 'primeng/button';
16
16
  import { ButtonModule } from 'primeng/button';
17
+ import { nanoid } from 'nanoid';
17
18
  import { AudioSpeed as AudioSpeed$1, TOAST_ALERTS_TOKEN, PaginationBase, DCFilterBarComponent, QuickTableComponent } from '@dataclouder/ngx-core';
18
19
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
19
20
  import { Subject, fromEvent, filter } from 'rxjs';
@@ -534,12 +535,14 @@ class DCConversationPromptBuilderService {
534
535
  }
535
536
  // For chat conversation i need inital settings.
536
537
  buildConversationSettings(agentCard, parseDict = null) {
538
+ debugger;
537
539
  const converstionSettings = agentCard?.conversationSettings || {};
538
540
  converstionSettings.messages = this.buildConversationMessages(agentCard, parseDict);
539
541
  converstionSettings.last_prompt = this.getJailBrakePrompt(agentCard);
540
542
  return converstionSettings;
541
543
  }
542
544
  buildConversationMessages(agentCard, parseDict = null) {
545
+ debugger;
543
546
  const initialConversation = this.buildInitialConversation(agentCard.characterCard, agentCard?.conversationSettings?.conversationType);
544
547
  parseDict = this.getDefaultParseDict(parseDict, agentCard);
545
548
  // Si quiero agregar todo tipo de info, el parse dict es algo que debe hacer el cliente.
@@ -980,16 +983,22 @@ function removeAllEmojis(text) {
980
983
  }
981
984
 
982
985
  class MessageProcessingService {
983
- constructor() { }
984
986
  // Process message for display
985
- processMessage(message, conversationSettings) {
986
- const defaultVoice = this.getVoice(conversationSettings.voice);
987
- let processedMessage;
988
- processedMessage = {
989
- content: message.content,
990
- role: message.role,
991
- voice: defaultVoice,
992
- };
987
+ processMessage(message, conversationSettings, extraData = {}) {
988
+ let processedMessage = { ...message };
989
+ // Add ID if not present
990
+ if (!processedMessage.messageId) {
991
+ processedMessage.messageId = nanoid();
992
+ }
993
+ // Add images and default voice
994
+ if (message.role === ChatRole.User && extraData.userImg) {
995
+ processedMessage.imgUrl = extraData.userImg;
996
+ }
997
+ else if (message.role === ChatRole.Assistant && extraData.assistantImg) {
998
+ const defaultVoice = this.getVoice(conversationSettings.voice);
999
+ processedMessage.voice = defaultVoice;
1000
+ processedMessage.imgUrl = extraData.assistantImg;
1001
+ }
993
1002
  // Process based on text engine
994
1003
  if (conversationSettings.textEngine === TextEngines.MarkdownMultiMessages) {
995
1004
  this.processMultiMessages(processedMessage, conversationSettings);
@@ -1001,8 +1010,7 @@ class MessageProcessingService {
1001
1010
  const content = this.subsItalicsByTag(processedMessage.content, conversationSettings.secondaryVoice);
1002
1011
  processedMessage.ssml = '<speak>' + content + '</speak>';
1003
1012
  }
1004
- console.log(processedMessage);
1005
- return { ...message, ...processedMessage };
1013
+ return processedMessage;
1006
1014
  }
1007
1015
  // Process multi-messages from markdown
1008
1016
  processMultiMessages(message, settings) {
@@ -1063,7 +1071,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImpor
1063
1071
  args: [{
1064
1072
  providedIn: 'root',
1065
1073
  }]
1066
- }], ctorParameters: () => [] });
1074
+ }] });
1067
1075
 
1068
1076
  function matchTranscription(originalText, transcription) {
1069
1077
  const result = [];
@@ -1132,19 +1140,42 @@ class ConversationService {
1132
1140
  this.messageProcessingService = inject(MessageProcessingService);
1133
1141
  this.conversationBuilder = inject(DCConversationPromptBuilderService);
1134
1142
  this.userDataExchange = inject(USER_DATA_EXCHANGE);
1135
- // Signals
1143
+ // State Signals
1136
1144
  this.messagesSignal = signal([]);
1137
1145
  this.isThinkingSignal = signal(false);
1138
1146
  this.conversationSettingsSignal = signal(null);
1139
1147
  this.isDestroyedSignal = signal(false);
1148
+ this.micStatusSignal = signal('ready');
1149
+ this.currentAudioStatus = signal(null);
1150
+ // Var State
1151
+ this.avatarImages = {
1152
+ userImg: 'assets/defaults/avatar_user.png',
1153
+ assistantImg: 'assets/defaults/avatar_ai.webp',
1154
+ };
1140
1155
  }
1141
- // Get messages as a signal
1142
1156
  getMessagesSignal() {
1143
1157
  return this.messagesSignal;
1144
1158
  }
1145
1159
  // Add message to conversation
1146
1160
  addMessage(message) {
1147
1161
  this.messagesSignal.update((messages) => [...messages, message]);
1162
+ console.log('Message added:', this.messagesSignal());
1163
+ return message.messageId;
1164
+ }
1165
+ // Update message by ID
1166
+ updateMessage(messageId, updatedMessage) {
1167
+ let found = false;
1168
+ this.messagesSignal.update((messages) => {
1169
+ return messages.map((message) => {
1170
+ if (message.messageId === messageId) {
1171
+ found = true;
1172
+ // Create a new message object with the updated properties
1173
+ return { ...message, ...updatedMessage };
1174
+ }
1175
+ return message;
1176
+ });
1177
+ });
1178
+ return found;
1148
1179
  }
1149
1180
  // Get thinking state as a signal
1150
1181
  isThinking() {
@@ -1154,8 +1185,10 @@ class ConversationService {
1154
1185
  setDestroyed(value) {
1155
1186
  this.isDestroyedSignal.set(value);
1156
1187
  }
1157
- setupConversationWithAgentCard(agentCard) {
1158
- const conversationSettings = this.conversationBuilder.buildConversationSettings(agentCard);
1188
+ setupConversationWithAgentCard(agentCard, parseDict = null) {
1189
+ // Set user AI avatar image
1190
+ this.avatarImages.assistantImg = agentCard?.assets.image?.url || this.avatarImages.assistantImg;
1191
+ const conversationSettings = this.conversationBuilder.buildConversationSettings(agentCard, parseDict);
1159
1192
  this.conversationSettingsSignal.set(conversationSettings);
1160
1193
  }
1161
1194
  async initConversationWithSettings(conversationSettings) {
@@ -1163,6 +1196,9 @@ class ConversationService {
1163
1196
  await this.initConversation();
1164
1197
  }
1165
1198
  async initConversation() {
1199
+ // Set user avatar images
1200
+ this.avatarImages.userImg = this.userDataExchange.getUserDataExchange().imgUrl;
1201
+ console.log(this.avatarImages);
1166
1202
  const conversationSettings = this.conversationSettingsSignal();
1167
1203
  for (const i in conversationSettings.messages) {
1168
1204
  conversationSettings.messages[i].messageId = 'msg_' + i;
@@ -1172,7 +1208,7 @@ class ConversationService {
1172
1208
  this.messagesSignal.set(conversationSettings?.messages || []);
1173
1209
  if (firstAssistantMsg) {
1174
1210
  // Process the first assistant message
1175
- const processedMessage = this.messageProcessingService.processMessage(firstAssistantMsg, this.conversationSettingsSignal());
1211
+ const processedMessage = this.messageProcessingService.processMessage(firstAssistantMsg, this.conversationSettingsSignal(), this.avatarImages);
1176
1212
  // Find the index of the message with the matching ID
1177
1213
  const messageIndex = conversationSettings.messages.findIndex((message) => message.messageId === firstAssistantMsg.messageId);
1178
1214
  // If found, replace the message at that index
@@ -1186,17 +1222,23 @@ class ConversationService {
1186
1222
  }
1187
1223
  }
1188
1224
  // Initialize conversation
1189
- async initConversationWithAgentCard(agentCard) {
1190
- this.setupConversationWithAgentCard(agentCard);
1225
+ async initConversationWithAgentCard(agentCard, parseDict = null) {
1226
+ this.setupConversationWithAgentCard(agentCard, parseDict);
1191
1227
  await this.initConversation();
1192
1228
  }
1193
1229
  // Send user message
1194
- async sendUserMessage(message) {
1230
+ async sendUserMessage(message, updateId = null) {
1195
1231
  if (this.isThinkingSignal()) {
1196
1232
  return;
1197
1233
  }
1198
- // Add message to conversation
1199
- this.addMessage(message);
1234
+ if (updateId) {
1235
+ this.updateMessage(updateId, message);
1236
+ }
1237
+ else {
1238
+ // Add message to conversation
1239
+ const processedMessage = this.messageProcessingService.processMessage(message, this.conversationSettingsSignal(), this.avatarImages);
1240
+ this.addMessage(processedMessage);
1241
+ }
1200
1242
  // Set thinking state
1201
1243
  this.isThinkingSignal.set(true);
1202
1244
  try {
@@ -1238,7 +1280,7 @@ class ConversationService {
1238
1280
  throw new Error('No message returned from AI');
1239
1281
  }
1240
1282
  // Process response
1241
- const newMessage = this.messageProcessingService.processMessage(response, conversationSettings);
1283
+ const newMessage = this.messageProcessingService.processMessage(response, conversationSettings, this.avatarImages);
1242
1284
  // Add to messages
1243
1285
  this.addMessage(newMessage);
1244
1286
  this.isThinkingSignal.set(false);
@@ -1278,8 +1320,11 @@ function extractJsonFromResponse(content) {
1278
1320
 
1279
1321
  class EvaluationService {
1280
1322
  constructor() {
1323
+ // Services
1281
1324
  this.agentCardService = inject(CONVERSATION_AI_TOKEN);
1282
- this.scoreSignal = signal(10);
1325
+ this.toastService = inject(TOAST_ALERTS_TOKEN);
1326
+ // Signals
1327
+ this.scoreSignal = signal(0);
1283
1328
  this.evaluationResultSignal = signal(null);
1284
1329
  }
1285
1330
  // Get score as a signal
@@ -1301,9 +1346,7 @@ class EvaluationService {
1301
1346
  return;
1302
1347
  }
1303
1348
  // Format conversation for evaluation
1304
- const conversationMessagesString = conversationMessages
1305
- .map((message) => `${message.role}: ${message.content}`)
1306
- .join('\n');
1349
+ const conversationMessagesString = conversationMessages.map((message) => `${message.role}: ${message.content}`).join('\n');
1307
1350
  // Create evaluation prompt
1308
1351
  const instructions = `
1309
1352
  Please replay to this task:
@@ -1315,20 +1358,26 @@ and give the response in next JSON format.
1315
1358
  `;
1316
1359
  // Send evaluation request
1317
1360
  const evaluationMessages = [{ content: instructions, role: ChatRole.User }];
1361
+ // Not sure what strategy use, if works types should be definied in definitions, generarally response will be score, and feedback.
1318
1362
  const response = await this.agentCardService.callChatCompletion({ messages: evaluationMessages });
1319
1363
  // Extract JSON from response
1320
1364
  const jsonData = extractJsonFromResponse(response.content);
1321
1365
  this.evaluationResultSignal.set(jsonData);
1366
+ this.toastService.info({
1367
+ title: 'Score ' + jsonData.score,
1368
+ subtitle: `Added ${jsonData.feedback} points`,
1369
+ });
1322
1370
  // Update score if available
1323
1371
  if (jsonData.score) {
1324
1372
  if (jsonData.score <= 3) {
1325
1373
  this.updateScore(jsonData.score * 10);
1326
1374
  }
1327
1375
  }
1376
+ return jsonData;
1328
1377
  }
1329
1378
  // Update score with limits
1330
1379
  updateScore(additionalScore) {
1331
- this.scoreSignal.update(currentScore => {
1380
+ this.scoreSignal.update((currentScore) => {
1332
1381
  const newScore = currentScore + additionalScore;
1333
1382
  return newScore > 100 ? 100 : newScore;
1334
1383
  });
@@ -1345,7 +1394,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImpor
1345
1394
  args: [{
1346
1395
  providedIn: 'root',
1347
1396
  }]
1348
- }], ctorParameters: () => [] });
1397
+ }] });
1349
1398
 
1350
1399
  class ChatFooterComponent {
1351
1400
  constructor() {
@@ -1363,9 +1412,31 @@ class ChatFooterComponent {
1363
1412
  // readonly micFinishedEvent = output<any>();
1364
1413
  this.isGettingTranscription = false;
1365
1414
  this.isUserTalking = false;
1415
+ this.micStatus = '';
1416
+ // Signal to control mic resumption
1417
+ this.shouldResumeMic = signal(false);
1366
1418
  this.chatInputControl = new FormControl();
1367
1419
  // Get score from evaluation service
1368
1420
  this.score = this.evaluationService.getScore();
1421
+ // Watch for audio completion and set the shouldResumeMic signal
1422
+ effect(() => {
1423
+ const audioStatus = this.conversationService.currentAudioStatus();
1424
+ // If audio has completed playing and mic is in paused state, resume recording
1425
+ if (audioStatus?.completed && this.micStatus === 'paused') {
1426
+ console.log('Audio playback completed, resuming mic recording');
1427
+ this.shouldResumeMic.set(true);
1428
+ // Reset after a short delay to avoid continuous triggering
1429
+ setTimeout(() => {
1430
+ this.shouldResumeMic.set(false);
1431
+ }, 100);
1432
+ }
1433
+ });
1434
+ }
1435
+ /**
1436
+ * Method used by the template to determine if the mic should continue listening
1437
+ */
1438
+ shouldContinueListening() {
1439
+ return this.shouldResumeMic();
1369
1440
  }
1370
1441
  /**
1371
1442
  * Sets the input text in the textarea
@@ -1382,6 +1453,7 @@ class ChatFooterComponent {
1382
1453
  micFinished(eventBlob) {
1383
1454
  // this.micFinishedEvent.emit(eventBlob);
1384
1455
  }
1456
+ // how to handle status audio finished? this.conversationService.currentAudioStatus.
1385
1457
  /**
1386
1458
  * Sends the user message
1387
1459
  */
@@ -1409,13 +1481,24 @@ class ChatFooterComponent {
1409
1481
  async evaluateConversation() {
1410
1482
  const messages = this.conversationService.getMessagesSignal()();
1411
1483
  if (this.evaluatorAgentCard()) {
1412
- await this.evaluationService.evaluateConversation(messages, this.evaluatorAgentCard());
1484
+ const data = await this.evaluationService.evaluateConversation(messages, this.evaluatorAgentCard());
1485
+ console.log(data);
1413
1486
  }
1414
1487
  }
1415
1488
  handleAudioRecorded(event) {
1416
1489
  console.log(event);
1417
1490
  this.onMicFinished(event.blob);
1418
1491
  }
1492
+ /**
1493
+ * Handles the mic status changed event
1494
+ * @param event The status event from the mic component
1495
+ */
1496
+ handleMicStatusChanged(event) {
1497
+ console.log('Mic status changed:', event);
1498
+ this.micStatus = event.status;
1499
+ // Update isUserTalking based on the status
1500
+ this.isUserTalking = event.status === 'recording';
1501
+ }
1419
1502
  async onMicFinished(eventBlob) {
1420
1503
  if (!(eventBlob instanceof Blob)) {
1421
1504
  return;
@@ -1423,32 +1506,37 @@ class ChatFooterComponent {
1423
1506
  this.isUserTalking = false;
1424
1507
  this.isGettingTranscription = true;
1425
1508
  try {
1426
- // Get transcription from audio
1427
- const transcription = await this.agentCardService.getAudioTranscriptions(eventBlob, null);
1428
1509
  const message = {
1429
1510
  content: '',
1430
1511
  role: ChatRole.User,
1431
1512
  audioUrl: URL.createObjectURL(eventBlob),
1513
+ isLoading: true,
1514
+ };
1515
+ const messageId = this.conversationService.addMessage(message);
1516
+ // Get transcription from audio
1517
+ const transcription = await this.agentCardService.getAudioTranscriptions(eventBlob, null);
1518
+ // Create updated message with transcription and isLoading set to false
1519
+ const updatedMessage = {
1520
+ ...message,
1521
+ content: transcription ? transcription.text : '',
1522
+ transcription: transcription || undefined,
1523
+ isLoading: false,
1432
1524
  };
1433
- if (transcription) {
1434
- message.content = transcription.text;
1435
- message.transcription = transcription;
1436
- }
1437
1525
  // Send message to conversation
1438
1526
  // The evaluation will happen automatically in the conversation service
1439
- await this.conversationService.sendUserMessage(message);
1527
+ await this.conversationService.sendUserMessage(updatedMessage, messageId);
1440
1528
  }
1441
1529
  finally {
1442
1530
  this.isGettingTranscription = false;
1443
1531
  }
1444
1532
  }
1445
1533
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: ChatFooterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1446
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.4", type: ChatFooterComponent, isStandalone: true, selector: "dc-chat-footer", inputs: { isAIThinking: { classPropertyName: "isAIThinking", publicName: "isAIThinking", isSignal: true, isRequired: false, transformFunction: null }, evaluatorAgentCard: { classPropertyName: "evaluatorAgentCard", publicName: "evaluatorAgentCard", isSignal: true, isRequired: false, transformFunction: null }, micSettings: { classPropertyName: "micSettings", publicName: "micSettings", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sendMessage: "sendMessage", textInputChanged: "textInputChanged" }, ngImport: i0, template: "<div class=\"progress-input\">\n <div class=\"input-container\">\n <app-mic-vad (audioRecorded)=\"handleAudioRecorded($event)\" />\n <!-- <dc-mic\n style=\"display: flex; align-items: center\"\n (onInterpretedText)=\"setInputText($event)\"\n (onFinished)=\"micFinished($event)\"\n [micSettings]=\"micSettings()\"></dc-mic> -->\n\n <textarea pTextarea [formControl]=\"chatInputControl\" (keyup.enter)=\"sendUserMessage()\" rows=\"1\"></textarea>\n\n <p-button (click)=\"sendUserMessage()\" [disabled]=\"isAIThinking() || !chatInputControl.value\" label=\"Enviar\" [rounded]=\"true\" />\n </div>\n\n <div>\n <p-progressbar showValue=\"false\" [value]=\"score()\" [style]=\"{ height: '6px' }\" />\n </div>\n</div>\n", styles: [".progress-input{padding:10px;background-color:#f5f5f545;border-top:1px solid #b1a8a8}.progress-input .input-container{display:flex;align-items:center;margin-bottom:5px}.progress-input .input-container textarea{flex:1;resize:none;margin:0 10px}.progress-input .input-container .send-button{background-color:#007bff;color:#fff;border:none;border-radius:4px;padding:8px 15px;cursor:pointer}.progress-input .input-container .send-button:disabled{background-color:#ccc;cursor:not-allowed}.progress-input .input-container .send-button:hover:not(:disabled){background-color:#0069d9}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: ProgressBarModule }, { kind: "component", type: i2.ProgressBar, selector: "p-progressBar, p-progressbar, p-progress-bar", inputs: ["value", "showValue", "styleClass", "valueStyleClass", "style", "unit", "mode", "color"] }, { kind: "ngmodule", type: TextareaModule }, { kind: "directive", type: i3.Textarea, selector: "[pTextarea]", inputs: ["autoResize", "variant", "fluid", "pSize"], outputs: ["onResize"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2$1.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: MicVadComponent, selector: "app-mic-vad", inputs: ["buttonLabel", "recordingLabel", "listeningLabel", "buttonIcon", "recordingIcon", "buttonClass"], outputs: ["recordingStarted", "recordingStopped", "speechDetected", "speechEnded", "audioRecorded", "error"] }] }); }
1534
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.4", type: ChatFooterComponent, isStandalone: true, selector: "dc-chat-footer", inputs: { isAIThinking: { classPropertyName: "isAIThinking", publicName: "isAIThinking", isSignal: true, isRequired: false, transformFunction: null }, evaluatorAgentCard: { classPropertyName: "evaluatorAgentCard", publicName: "evaluatorAgentCard", isSignal: true, isRequired: false, transformFunction: null }, micSettings: { classPropertyName: "micSettings", publicName: "micSettings", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sendMessage: "sendMessage", textInputChanged: "textInputChanged" }, ngImport: i0, template: "<div class=\"progress-input\">\n <div class=\"input-container\">\n <app-mic-vad\n (audioRecorded)=\"handleAudioRecorded($event)\"\n (statusChanged)=\"handleMicStatusChanged($event)\"\n [continueListening]=\"shouldContinueListening()\" />\n <!-- <dc-mic\n style=\"display: flex; align-items: center\"\n (onInterpretedText)=\"setInputText($event)\"\n (onFinished)=\"micFinished($event)\"\n [micSettings]=\"micSettings()\"></dc-mic> -->\n\n <textarea pTextarea [formControl]=\"chatInputControl\" (keyup.enter)=\"sendUserMessage()\" rows=\"1\"></textarea>\n\n <p-button (click)=\"sendUserMessage()\" [disabled]=\"isAIThinking() || !chatInputControl.value\" label=\"Enviar\" [rounded]=\"true\" />\n </div>\n\n @if(evaluatorAgentCard()) {\n <div>\n <p-progressbar showValue=\"false\" [value]=\"score()\" [style]=\"{ height: '6px' }\" />\n </div>\n }\n</div>\n", styles: [".progress-input{padding:10px;background-color:#f5f5f545;border-top:1px solid #b1a8a8}.progress-input .input-container{display:flex;align-items:center;margin-bottom:5px}.progress-input .input-container textarea{flex:1;resize:none;margin:0 10px}.progress-input .input-container .send-button{background-color:#007bff;color:#fff;border:none;border-radius:4px;padding:8px 15px;cursor:pointer}.progress-input .input-container .send-button:disabled{background-color:#ccc;cursor:not-allowed}.progress-input .input-container .send-button:hover:not(:disabled){background-color:#0069d9}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: ProgressBarModule }, { kind: "component", type: i2.ProgressBar, selector: "p-progressBar, p-progressbar, p-progress-bar", inputs: ["value", "showValue", "styleClass", "valueStyleClass", "style", "unit", "mode", "color"] }, { kind: "ngmodule", type: TextareaModule }, { kind: "directive", type: i3.Textarea, selector: "[pTextarea]", inputs: ["autoResize", "variant", "fluid", "pSize"], outputs: ["onResize"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2$1.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: MicVadComponent, selector: "app-mic-vad", inputs: ["continueListening"], outputs: ["statusChanged", "audioRecorded", "error"] }] }); }
1447
1535
  }
1448
1536
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: ChatFooterComponent, decorators: [{
1449
1537
  type: Component,
1450
- args: [{ selector: 'dc-chat-footer', standalone: true, imports: [ReactiveFormsModule, ProgressBarModule, TextareaModule, ButtonModule, MicVadComponent], template: "<div class=\"progress-input\">\n <div class=\"input-container\">\n <app-mic-vad (audioRecorded)=\"handleAudioRecorded($event)\" />\n <!-- <dc-mic\n style=\"display: flex; align-items: center\"\n (onInterpretedText)=\"setInputText($event)\"\n (onFinished)=\"micFinished($event)\"\n [micSettings]=\"micSettings()\"></dc-mic> -->\n\n <textarea pTextarea [formControl]=\"chatInputControl\" (keyup.enter)=\"sendUserMessage()\" rows=\"1\"></textarea>\n\n <p-button (click)=\"sendUserMessage()\" [disabled]=\"isAIThinking() || !chatInputControl.value\" label=\"Enviar\" [rounded]=\"true\" />\n </div>\n\n <div>\n <p-progressbar showValue=\"false\" [value]=\"score()\" [style]=\"{ height: '6px' }\" />\n </div>\n</div>\n", styles: [".progress-input{padding:10px;background-color:#f5f5f545;border-top:1px solid #b1a8a8}.progress-input .input-container{display:flex;align-items:center;margin-bottom:5px}.progress-input .input-container textarea{flex:1;resize:none;margin:0 10px}.progress-input .input-container .send-button{background-color:#007bff;color:#fff;border:none;border-radius:4px;padding:8px 15px;cursor:pointer}.progress-input .input-container .send-button:disabled{background-color:#ccc;cursor:not-allowed}.progress-input .input-container .send-button:hover:not(:disabled){background-color:#0069d9}\n"] }]
1451
- }] });
1538
+ args: [{ selector: 'dc-chat-footer', standalone: true, imports: [ReactiveFormsModule, ProgressBarModule, TextareaModule, ButtonModule, MicVadComponent], template: "<div class=\"progress-input\">\n <div class=\"input-container\">\n <app-mic-vad\n (audioRecorded)=\"handleAudioRecorded($event)\"\n (statusChanged)=\"handleMicStatusChanged($event)\"\n [continueListening]=\"shouldContinueListening()\" />\n <!-- <dc-mic\n style=\"display: flex; align-items: center\"\n (onInterpretedText)=\"setInputText($event)\"\n (onFinished)=\"micFinished($event)\"\n [micSettings]=\"micSettings()\"></dc-mic> -->\n\n <textarea pTextarea [formControl]=\"chatInputControl\" (keyup.enter)=\"sendUserMessage()\" rows=\"1\"></textarea>\n\n <p-button (click)=\"sendUserMessage()\" [disabled]=\"isAIThinking() || !chatInputControl.value\" label=\"Enviar\" [rounded]=\"true\" />\n </div>\n\n @if(evaluatorAgentCard()) {\n <div>\n <p-progressbar showValue=\"false\" [value]=\"score()\" [style]=\"{ height: '6px' }\" />\n </div>\n }\n</div>\n", styles: [".progress-input{padding:10px;background-color:#f5f5f545;border-top:1px solid #b1a8a8}.progress-input .input-container{display:flex;align-items:center;margin-bottom:5px}.progress-input .input-container textarea{flex:1;resize:none;margin:0 10px}.progress-input .input-container .send-button{background-color:#007bff;color:#fff;border:none;border-radius:4px;padding:8px 15px;cursor:pointer}.progress-input .input-container .send-button:disabled{background-color:#ccc;cursor:not-allowed}.progress-input .input-container .send-button:hover:not(:disabled){background-color:#0069d9}\n"] }]
1539
+ }], ctorParameters: () => [] });
1452
1540
 
1453
1541
  const ICONS = {
1454
1542
  chat: `<svg viewBox="0 0 24 24" fill="currentColor">
@@ -1775,11 +1863,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImpor
1775
1863
 
1776
1864
  class MessageOrchestratorComponent {
1777
1865
  constructor() {
1778
- this.agentCardService = inject(CONVERSATION_AI_TOKEN);
1779
1866
  this.conversationService = inject(ConversationService);
1780
1867
  this.messages = input.required();
1781
1868
  this.messageRole = input.required();
1782
1869
  this.messagesSignal = signal([]);
1870
+ // Effect to update messagesSignal when input messages change
1871
+ this.messagesEffect = effect(() => {
1872
+ // Get the latest messages from the input
1873
+ const currentMessages = this.messages();
1874
+ if (currentMessages && currentMessages.length > 0) {
1875
+ // Update our internal signal with a new array reference
1876
+ this.messagesSignal.set([...currentMessages]);
1877
+ }
1878
+ });
1783
1879
  this.playAudio = output();
1784
1880
  this.audioCompleted = output();
1785
1881
  // Audio queue management
@@ -1868,6 +1964,7 @@ class MessageOrchestratorComponent {
1868
1964
  onAudioCompleted(message) {
1869
1965
  // Forward the event
1870
1966
  this.audioCompleted.emit(message);
1967
+ this.conversationService.currentAudioStatus.set({ message, completed: true });
1871
1968
  // Reset current playing index
1872
1969
  this.currentPlayingIndex = null;
1873
1970
  // If there are more messages in the queue, process the next one
@@ -1902,8 +1999,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImpor
1902
1999
 
1903
2000
  class ChatMessageComponent {
1904
2001
  constructor() {
2002
+ // Inputs
1905
2003
  this.chatMessage = input.required();
1906
2004
  this.chatUserSettings = input(null);
2005
+ // Signal States
1907
2006
  this.audioMessage = signal(null);
1908
2007
  // Computed properties for easier access to signal values
1909
2008
  this.hasMultiMessages = computed(() => !!this.chatMessage()?.multiMessages);
@@ -1931,37 +2030,38 @@ class ChatMessageComponent {
1931
2030
  });
1932
2031
  }
1933
2032
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: ChatMessageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1934
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.4", type: ChatMessageComponent, isStandalone: true, selector: "dc-chat-message", inputs: { chatMessage: { classPropertyName: "chatMessage", publicName: "chatMessage", isSignal: true, isRequired: true, transformFunction: null }, chatUserSettings: { classPropertyName: "chatUserSettings", publicName: "chatUserSettings", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"message-wrapper\" [ngClass]=\"{ 'user-message': isUserMessage(), 'assistant-message': !isUserMessage() }\">\n <div class=\"message-container\">\n <!-- Avatar for assistant messages -->\n\n @if (!isUserMessage()) {\n <div class=\"avatar-container\">\n <div class=\"avatar\">\n <img src=\"assets/defaults/avatar.jpg\" alt=\"User\" class=\"avatar-image\" />\n </div>\n </div>\n }\n\n <!-- Message content -->\n <div class=\"message-bubble\">\n @if (hasMultiMessages()) {\n <dc-message-orchestrator [messages]=\"multiMessages()\" [messageRole]=\"chatMessage().role\"></dc-message-orchestrator>\n } @else {\n <dc-message-orchestrator [messages]=\"[audioMessage()]\" [messageRole]=\"chatMessage().role\"></dc-message-orchestrator>\n }\n\n <!-- Translation if available -->\n @if (messageTranslation()) {\n <div class=\"translation\">\n <hr class=\"divider\" />\n {{ messageTranslation() }}\n </div>\n }\n </div>\n\n <!-- Avatar for user messages -->\n @if (isUserMessage()) {\n <div class=\"avatar-container\">\n <div class=\"avatar user-avatar\">\n <img src=\"assets/defaults/avatar.jpg\" alt=\"User\" class=\"avatar-image\" />\n </div>\n </div>\n }\n </div>\n</div>\n", styles: [":host{display:block;margin-bottom:16px}.message-wrapper{display:flex;width:100%;margin-bottom:12px}.message-container{display:flex;max-width:85%;line-height:1.5}.user-message{justify-content:flex-end}.user-message .message-container{flex-direction:row}.user-message .message-bubble{background-color:#0d5878;color:#fff;border-radius:18px 18px 0;margin-left:8px}.assistant-message{justify-content:flex-start}.assistant-message .message-container{flex-direction:row}.assistant-message .message-bubble{background-color:#f0f0f0;color:#333;border-radius:18px 18px 18px 0;margin-left:8px}.message-bubble{padding:12px 16px;box-shadow:0 1px 2px #0000001a;max-width:calc(100% - 50px);word-wrap:break-word;overflow-wrap:break-word;word-break:break-word;hyphens:auto;min-width:0}.avatar-container{display:flex;align-items:flex-end}.avatar{width:36px;height:36px;border-radius:50%;background-color:#0d5878;display:flex;align-items:center;justify-content:center;color:#fff;font-weight:700;font-size:14px;overflow:hidden}.avatar-image{width:100%;height:100%;object-fit:cover}.user-avatar{background-color:#ffa77e}::ng-deep .em{color:inherit;font-style:italic}::ng-deep .strong{font-weight:700;color:inherit}::ng-deep .em_strong{font-weight:700;font-style:italic;color:inherit}.translation{margin-top:8px;font-size:small;line-height:1.6;color:#393744;font-style:italic}.divider{margin:.5rem 40px;border-top:1px solid #ffa77e}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: MessageOrchestratorComponent, selector: "dc-message-orchestrator", inputs: ["messages", "messageRole"], outputs: ["playAudio", "audioCompleted"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2033
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.4", type: ChatMessageComponent, isStandalone: true, selector: "dc-chat-message", inputs: { chatMessage: { classPropertyName: "chatMessage", publicName: "chatMessage", isSignal: true, isRequired: true, transformFunction: null }, chatUserSettings: { classPropertyName: "chatUserSettings", publicName: "chatUserSettings", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"message-wrapper\" [ngClass]=\"{ 'user-message': isUserMessage(), 'assistant-message': !isUserMessage() }\">\n <div class=\"message-container\">\n <!-- Avatar for assistant messages -->\n\n @if (!isUserMessage()) {\n <div class=\"avatar-container\">\n <div class=\"avatar\">\n <img [src]=\"chatMessage().imgUrl\" alt=\"AI\" class=\"avatar-image\" />\n </div>\n </div>\n }\n\n <!-- Message content -->\n <div class=\"message-bubble\">\n @if (hasMultiMessages()) {\n <dc-message-orchestrator [messages]=\"multiMessages()\" [messageRole]=\"chatMessage().role\"></dc-message-orchestrator>\n } @else {\n <dc-message-orchestrator [messages]=\"[audioMessage()]\" [messageRole]=\"chatMessage().role\"></dc-message-orchestrator>\n }\n\n <!-- Translation if available -->\n @if (messageTranslation()) {\n <div class=\"translation\">\n <hr class=\"divider\" />\n {{ messageTranslation() }}\n </div>\n }\n </div>\n\n <!-- Avatar for user messages -->\n @if (isUserMessage()) {\n <div class=\"avatar-container\">\n <div class=\"avatar user-avatar\">\n <img [src]=\"chatMessage().imgUrl\" alt=\"User\" class=\"avatar-image\" />\n </div>\n </div>\n }\n </div>\n</div>\n", styles: [":host{display:block;margin-bottom:16px}.message-wrapper{display:flex;width:100%;margin-bottom:12px}.message-container{display:flex;max-width:85%;line-height:1.5}.user-message{justify-content:flex-end}.user-message .message-container{flex-direction:row}.user-message .message-bubble{background-color:#0d5878;color:#fff;border-radius:18px 18px 0;margin-left:8px}.assistant-message{justify-content:flex-start}.assistant-message .message-container{flex-direction:row}.assistant-message .message-bubble{background-color:#f0f0f0;color:#333;border-radius:18px 18px 18px 0;margin-left:8px}.message-bubble{padding:12px 16px;box-shadow:0 1px 2px #0000001a;max-width:calc(100% - 50px);word-wrap:break-word;overflow-wrap:break-word;word-break:break-word;hyphens:auto;min-width:0}.avatar-container{display:flex;align-items:flex-end}.avatar{width:36px;height:36px;border-radius:50%;background-color:#0d5878;display:flex;align-items:center;justify-content:center;color:#fff;font-weight:700;font-size:14px;overflow:hidden}.avatar-image{width:100%;height:100%;object-fit:cover}.user-avatar{background-color:#ffa77e}::ng-deep .em{color:inherit;font-style:italic}::ng-deep .strong{font-weight:700;color:inherit}::ng-deep .em_strong{font-weight:700;font-style:italic;color:inherit}.translation{margin-top:8px;font-size:small;line-height:1.6;color:#393744;font-style:italic}.divider{margin:.5rem 40px;border-top:1px solid #ffa77e}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: MessageOrchestratorComponent, selector: "dc-message-orchestrator", inputs: ["messages", "messageRole"], outputs: ["playAudio", "audioCompleted"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1935
2034
  }
1936
2035
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: ChatMessageComponent, decorators: [{
1937
2036
  type: Component,
1938
- args: [{ selector: 'dc-chat-message', standalone: true, imports: [CommonModule, MessageOrchestratorComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"message-wrapper\" [ngClass]=\"{ 'user-message': isUserMessage(), 'assistant-message': !isUserMessage() }\">\n <div class=\"message-container\">\n <!-- Avatar for assistant messages -->\n\n @if (!isUserMessage()) {\n <div class=\"avatar-container\">\n <div class=\"avatar\">\n <img src=\"assets/defaults/avatar.jpg\" alt=\"User\" class=\"avatar-image\" />\n </div>\n </div>\n }\n\n <!-- Message content -->\n <div class=\"message-bubble\">\n @if (hasMultiMessages()) {\n <dc-message-orchestrator [messages]=\"multiMessages()\" [messageRole]=\"chatMessage().role\"></dc-message-orchestrator>\n } @else {\n <dc-message-orchestrator [messages]=\"[audioMessage()]\" [messageRole]=\"chatMessage().role\"></dc-message-orchestrator>\n }\n\n <!-- Translation if available -->\n @if (messageTranslation()) {\n <div class=\"translation\">\n <hr class=\"divider\" />\n {{ messageTranslation() }}\n </div>\n }\n </div>\n\n <!-- Avatar for user messages -->\n @if (isUserMessage()) {\n <div class=\"avatar-container\">\n <div class=\"avatar user-avatar\">\n <img src=\"assets/defaults/avatar.jpg\" alt=\"User\" class=\"avatar-image\" />\n </div>\n </div>\n }\n </div>\n</div>\n", styles: [":host{display:block;margin-bottom:16px}.message-wrapper{display:flex;width:100%;margin-bottom:12px}.message-container{display:flex;max-width:85%;line-height:1.5}.user-message{justify-content:flex-end}.user-message .message-container{flex-direction:row}.user-message .message-bubble{background-color:#0d5878;color:#fff;border-radius:18px 18px 0;margin-left:8px}.assistant-message{justify-content:flex-start}.assistant-message .message-container{flex-direction:row}.assistant-message .message-bubble{background-color:#f0f0f0;color:#333;border-radius:18px 18px 18px 0;margin-left:8px}.message-bubble{padding:12px 16px;box-shadow:0 1px 2px #0000001a;max-width:calc(100% - 50px);word-wrap:break-word;overflow-wrap:break-word;word-break:break-word;hyphens:auto;min-width:0}.avatar-container{display:flex;align-items:flex-end}.avatar{width:36px;height:36px;border-radius:50%;background-color:#0d5878;display:flex;align-items:center;justify-content:center;color:#fff;font-weight:700;font-size:14px;overflow:hidden}.avatar-image{width:100%;height:100%;object-fit:cover}.user-avatar{background-color:#ffa77e}::ng-deep .em{color:inherit;font-style:italic}::ng-deep .strong{font-weight:700;color:inherit}::ng-deep .em_strong{font-weight:700;font-style:italic;color:inherit}.translation{margin-top:8px;font-size:small;line-height:1.6;color:#393744;font-style:italic}.divider{margin:.5rem 40px;border-top:1px solid #ffa77e}\n"] }]
2037
+ args: [{ selector: 'dc-chat-message', standalone: true, imports: [CommonModule, MessageOrchestratorComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"message-wrapper\" [ngClass]=\"{ 'user-message': isUserMessage(), 'assistant-message': !isUserMessage() }\">\n <div class=\"message-container\">\n <!-- Avatar for assistant messages -->\n\n @if (!isUserMessage()) {\n <div class=\"avatar-container\">\n <div class=\"avatar\">\n <img [src]=\"chatMessage().imgUrl\" alt=\"AI\" class=\"avatar-image\" />\n </div>\n </div>\n }\n\n <!-- Message content -->\n <div class=\"message-bubble\">\n @if (hasMultiMessages()) {\n <dc-message-orchestrator [messages]=\"multiMessages()\" [messageRole]=\"chatMessage().role\"></dc-message-orchestrator>\n } @else {\n <dc-message-orchestrator [messages]=\"[audioMessage()]\" [messageRole]=\"chatMessage().role\"></dc-message-orchestrator>\n }\n\n <!-- Translation if available -->\n @if (messageTranslation()) {\n <div class=\"translation\">\n <hr class=\"divider\" />\n {{ messageTranslation() }}\n </div>\n }\n </div>\n\n <!-- Avatar for user messages -->\n @if (isUserMessage()) {\n <div class=\"avatar-container\">\n <div class=\"avatar user-avatar\">\n <img [src]=\"chatMessage().imgUrl\" alt=\"User\" class=\"avatar-image\" />\n </div>\n </div>\n }\n </div>\n</div>\n", styles: [":host{display:block;margin-bottom:16px}.message-wrapper{display:flex;width:100%;margin-bottom:12px}.message-container{display:flex;max-width:85%;line-height:1.5}.user-message{justify-content:flex-end}.user-message .message-container{flex-direction:row}.user-message .message-bubble{background-color:#0d5878;color:#fff;border-radius:18px 18px 0;margin-left:8px}.assistant-message{justify-content:flex-start}.assistant-message .message-container{flex-direction:row}.assistant-message .message-bubble{background-color:#f0f0f0;color:#333;border-radius:18px 18px 18px 0;margin-left:8px}.message-bubble{padding:12px 16px;box-shadow:0 1px 2px #0000001a;max-width:calc(100% - 50px);word-wrap:break-word;overflow-wrap:break-word;word-break:break-word;hyphens:auto;min-width:0}.avatar-container{display:flex;align-items:flex-end}.avatar{width:36px;height:36px;border-radius:50%;background-color:#0d5878;display:flex;align-items:center;justify-content:center;color:#fff;font-weight:700;font-size:14px;overflow:hidden}.avatar-image{width:100%;height:100%;object-fit:cover}.user-avatar{background-color:#ffa77e}::ng-deep .em{color:inherit;font-style:italic}::ng-deep .strong{font-weight:700;color:inherit}::ng-deep .em_strong{font-weight:700;font-style:italic;color:inherit}.translation{margin-top:8px;font-size:small;line-height:1.6;color:#393744;font-style:italic}.divider{margin:.5rem 40px;border-top:1px solid #ffa77e}\n"] }]
1939
2038
  }] });
1940
2039
 
1941
2040
  class ChatMessagesListComponent {
1942
2041
  constructor() {
2042
+ // Inputs
1943
2043
  this.chatUserSettings = input.required();
1944
- this.aiIcon = 'assets/default/ai.png';
1945
- this.conversationService = inject(ConversationService);
1946
2044
  this.inputMessages = input.required();
1947
- // Inject ElementRef to access the component's host element
1948
- this.elementRef = inject((ElementRef));
1949
- // Get messages and thinking state from the conversation service
2045
+ // Private services
2046
+ this.conversationService = inject(ConversationService);
2047
+ this.elementRef = inject(ElementRef);
2048
+ // State
2049
+ this.aiIcon = 'assets/default/ai.png';
2050
+ this.isThinking = this.conversationService.isThinking();
1950
2051
  this.messages = computed(() => {
1951
2052
  // Get the actual array of messages from the signal by calling it as a function
1952
2053
  const allMessages = this.conversationService.getMessagesSignal()();
1953
2054
  console.log('Getting messages', allMessages);
1954
2055
  return allMessages.filter((message) => message.role !== ChatRole.System);
1955
2056
  });
1956
- this.isThinking = this.conversationService.isThinking();
1957
- // Use effect to automatically scroll to bottom when messages change
1958
2057
  effect(() => {
1959
2058
  // Access the messages to create a dependency
1960
- const messages = this.messages();
2059
+ const messages = this.messages(); // just to subscribe
1961
2060
  // Schedule the scroll after the view has been updated
1962
2061
  setTimeout(() => this.scrollToBottom(), 0);
1963
2062
  });
1964
2063
  }
2064
+ // Note probably i don't need this.
1965
2065
  ngAfterViewInit() {
1966
2066
  // Initial scroll to bottom when view is initialized
1967
2067
  this.scrollToBottom();
@@ -1971,7 +2071,7 @@ class ChatMessagesListComponent {
1971
2071
  const element = this.elementRef.nativeElement;
1972
2072
  element.scrollTo({
1973
2073
  top: element.scrollHeight,
1974
- behavior: 'smooth'
2074
+ behavior: 'smooth',
1975
2075
  });
1976
2076
  }
1977
2077
  // Track messages by their content and role for efficient rendering
@@ -1979,11 +2079,11 @@ class ChatMessagesListComponent {
1979
2079
  return `${message.role}-${index}-${message.content.substring(0, 20)}`;
1980
2080
  }
1981
2081
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: ChatMessagesListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1982
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.4", type: ChatMessagesListComponent, isStandalone: true, selector: "dc-chat-messages-list", inputs: { chatUserSettings: { classPropertyName: "chatUserSettings", publicName: "chatUserSettings", isSignal: true, isRequired: true, transformFunction: null }, inputMessages: { classPropertyName: "inputMessages", publicName: "inputMessages", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"messages-container\">\n @for (message of messages(); track trackByMessage($index, message)) {\n <dc-chat-message [chatMessage]=\"message\" [chatUserSettings]=\"chatUserSettings()\"> </dc-chat-message>\n } @if (isThinking()) {\n <div class=\"thinking-container\">\n <div class=\"thinking-message\">\n <div class=\"thinking-avatar\">\n <img [src]=\"aiIcon\" alt=\"AI thinking\" class=\"avatar-img\" />\n </div>\n <div class=\"thinking-content\">\n <p-skeleton width=\"80%\" height=\"2rem\"></p-skeleton>\n <p-skeleton width=\"60%\" height=\"2rem\"></p-skeleton>\n </div>\n </div>\n </div>\n }\n</div>\n", styles: [".messages-container{display:flex;flex-direction:column;gap:1rem;padding:1rem;height:100%}.thinking-container{padding:.5rem 0}.thinking-message{display:flex;gap:1rem;align-items:flex-start}.thinking-avatar{width:40px;height:40px;border-radius:50%;overflow:hidden;flex-shrink:0}.avatar-img{width:100%;height:100%;object-fit:cover}.thinking-content{flex:1;display:flex;flex-direction:column;gap:.5rem}\n"], dependencies: [{ kind: "component", type: ChatMessageComponent, selector: "dc-chat-message", inputs: ["chatMessage", "chatUserSettings"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i1$2.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "style", "shape", "animation", "borderRadius", "size", "width", "height"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2082
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.4", type: ChatMessagesListComponent, isStandalone: true, selector: "dc-chat-messages-list", inputs: { chatUserSettings: { classPropertyName: "chatUserSettings", publicName: "chatUserSettings", isSignal: true, isRequired: true, transformFunction: null }, inputMessages: { classPropertyName: "inputMessages", publicName: "inputMessages", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"messages-container\">\n @for (message of messages(); track message.messageId) {\n <dc-chat-message [chatMessage]=\"message\" [chatUserSettings]=\"chatUserSettings()\"> </dc-chat-message>\n } @if (isThinking()) {\n <div class=\"thinking-container\">\n <div class=\"thinking-message\">\n <div class=\"thinking-avatar\">\n <img [src]=\"aiIcon\" alt=\"AI thinking\" class=\"avatar-img\" />\n </div>\n <div class=\"thinking-content\">\n <p-skeleton width=\"80%\" height=\"2rem\"></p-skeleton>\n <p-skeleton width=\"60%\" height=\"2rem\"></p-skeleton>\n </div>\n </div>\n </div>\n }\n</div>\n", styles: [".messages-container{display:flex;flex-direction:column;gap:1rem;padding:1rem;height:100%}.thinking-container{padding:.5rem 0}.thinking-message{display:flex;gap:1rem;align-items:flex-start}.thinking-avatar{width:40px;height:40px;border-radius:50%;overflow:hidden;flex-shrink:0}.avatar-img{width:100%;height:100%;object-fit:cover}.thinking-content{flex:1;display:flex;flex-direction:column;gap:.5rem}\n"], dependencies: [{ kind: "component", type: ChatMessageComponent, selector: "dc-chat-message", inputs: ["chatMessage", "chatUserSettings"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i1$2.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "style", "shape", "animation", "borderRadius", "size", "width", "height"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1983
2083
  }
1984
2084
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: ChatMessagesListComponent, decorators: [{
1985
2085
  type: Component,
1986
- args: [{ selector: 'dc-chat-messages-list', standalone: true, imports: [ChatMessageComponent, SkeletonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"messages-container\">\n @for (message of messages(); track trackByMessage($index, message)) {\n <dc-chat-message [chatMessage]=\"message\" [chatUserSettings]=\"chatUserSettings()\"> </dc-chat-message>\n } @if (isThinking()) {\n <div class=\"thinking-container\">\n <div class=\"thinking-message\">\n <div class=\"thinking-avatar\">\n <img [src]=\"aiIcon\" alt=\"AI thinking\" class=\"avatar-img\" />\n </div>\n <div class=\"thinking-content\">\n <p-skeleton width=\"80%\" height=\"2rem\"></p-skeleton>\n <p-skeleton width=\"60%\" height=\"2rem\"></p-skeleton>\n </div>\n </div>\n </div>\n }\n</div>\n", styles: [".messages-container{display:flex;flex-direction:column;gap:1rem;padding:1rem;height:100%}.thinking-container{padding:.5rem 0}.thinking-message{display:flex;gap:1rem;align-items:flex-start}.thinking-avatar{width:40px;height:40px;border-radius:50%;overflow:hidden;flex-shrink:0}.avatar-img{width:100%;height:100%;object-fit:cover}.thinking-content{flex:1;display:flex;flex-direction:column;gap:.5rem}\n"] }]
2086
+ args: [{ selector: 'dc-chat-messages-list', standalone: true, imports: [ChatMessageComponent, SkeletonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"messages-container\">\n @for (message of messages(); track message.messageId) {\n <dc-chat-message [chatMessage]=\"message\" [chatUserSettings]=\"chatUserSettings()\"> </dc-chat-message>\n } @if (isThinking()) {\n <div class=\"thinking-container\">\n <div class=\"thinking-message\">\n <div class=\"thinking-avatar\">\n <img [src]=\"aiIcon\" alt=\"AI thinking\" class=\"avatar-img\" />\n </div>\n <div class=\"thinking-content\">\n <p-skeleton width=\"80%\" height=\"2rem\"></p-skeleton>\n <p-skeleton width=\"60%\" height=\"2rem\"></p-skeleton>\n </div>\n </div>\n </div>\n }\n</div>\n", styles: [".messages-container{display:flex;flex-direction:column;gap:1rem;padding:1rem;height:100%}.thinking-container{padding:.5rem 0}.thinking-message{display:flex;gap:1rem;align-items:flex-start}.thinking-avatar{width:40px;height:40px;border-radius:50%;overflow:hidden;flex-shrink:0}.avatar-img{width:100%;height:100%;object-fit:cover}.thinking-content{flex:1;display:flex;flex-direction:column;gap:.5rem}\n"] }]
1987
2087
  }], ctorParameters: () => [] });
1988
2088
 
1989
2089
  const SpeedDescription = {
@@ -2171,28 +2271,41 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImpor
2171
2271
 
2172
2272
  class DCChatComponent {
2173
2273
  constructor() {
2174
- this.conversationBuilder = inject(DCConversationPromptBuilderService);
2274
+ // Services
2175
2275
  this.dialogService = inject(DialogService);
2176
2276
  this.conversationService = inject(ConversationService);
2277
+ this.evaluationService = inject(EvaluationService);
2177
2278
  this.userDataExchange = inject(USER_DATA_EXCHANGE);
2279
+ // Inputs
2178
2280
  this.chatUserSettings = this.userDataExchange.getUserChatSettings(); // Default to user data exchange
2179
- // TODO: those are optional think if i need them,
2281
+ // Signal Inputs
2180
2282
  this.evaluatorAgentCard = input();
2181
2283
  this.parseDict = input({});
2284
+ // Outputs
2182
2285
  this.sendMessage = output(); // notifies whatever happened inside the chat
2286
+ this.goalCompleted = output(); // notifies when user completes goal (score reaches 100)
2287
+ // Signals States
2288
+ this.messages = signal([]);
2289
+ // States
2183
2290
  this.micSettings = { useWhisper: true, lang: 'en' };
2184
2291
  this.isInfoVisible = false;
2185
2292
  this.isAdmin = true;
2186
- // Get reactive state from services
2187
- // public messages = this.conversationService.getMessages();
2188
- this.messages = signal([]);
2293
+ // Subscribe to score updates using effect
2294
+ effect(() => {
2295
+ const score = this.evaluationService.getScore()();
2296
+ if (score >= 100) {
2297
+ this.goalCompleted.emit();
2298
+ }
2299
+ });
2189
2300
  }
2190
2301
  async ngOnInit() {
2302
+ debugger;
2303
+ console.log(this.parseDict());
2191
2304
  if (this.conversationSettings) {
2192
2305
  await this.conversationService.initConversationWithSettings(this.conversationSettings);
2193
2306
  }
2194
2307
  else {
2195
- await this.conversationService.initConversationWithAgentCard(this.agentCard);
2308
+ await this.conversationService.initConversationWithAgentCard(this.agentCard, this.parseDict());
2196
2309
  }
2197
2310
  }
2198
2311
  ngOnDestroy() {
@@ -2231,12 +2344,12 @@ class DCChatComponent {
2231
2344
  await this.ngOnInit();
2232
2345
  }
2233
2346
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: DCChatComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2234
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.4", type: DCChatComponent, isStandalone: true, selector: "dc-chat", inputs: { chatUserSettings: { classPropertyName: "chatUserSettings", publicName: "chatUserSettings", isSignal: false, isRequired: false, transformFunction: null }, conversationSettings: { classPropertyName: "conversationSettings", publicName: "conversationSettings", isSignal: false, isRequired: false, transformFunction: null }, agentCard: { classPropertyName: "agentCard", publicName: "agentCard", isSignal: false, isRequired: false, transformFunction: null }, evaluatorAgentCard: { classPropertyName: "evaluatorAgentCard", publicName: "evaluatorAgentCard", isSignal: true, isRequired: false, transformFunction: null }, parseDict: { classPropertyName: "parseDict", publicName: "parseDict", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sendMessage: "sendMessage" }, providers: [DialogService], ngImport: i0, template: "<div class=\"chat-container\">\n <!-- Chat Header -->\n <dc-chat-header\n [agentCard]=\"agentCard\"\n [isAdmin]=\"isAdmin\"\n (showInfoEvent)=\"showInfo()\"\n (settingsClickEvent)=\"changeUserChatSettings()\"\n (restartConversationEvent)=\"restartConversation($event)\">\n </dc-chat-header>\n\n <!-- Messages List -->\n <dc-chat-messages-list [chatUserSettings]=\"chatUserSettings\" [inputMessages]=\"messages()\"> </dc-chat-messages-list>\n\n <!-- Chat Footer -->\n <dc-chat-footer [micSettings]=\"micSettings\" [evaluatorAgentCard]=\"evaluatorAgentCard()\"> </dc-chat-footer>\n\n <!-- Info Dialog -->\n <p-dialog [(visible)]=\"isInfoVisible\" [modal]=\"true\" [draggable]=\"false\" [resizable]=\"false\" header=\"Conversation Info\">\n <div class=\"info-content\">\n <h3>Agent Card</h3>\n <pre>{{ agentCard | safeJson }}</pre>\n\n <h3>User Settings</h3>\n <pre>{{ chatUserSettings | safeJson }}</pre>\n </div>\n </p-dialog>\n</div>\n", styles: ["::ng-deep .p-drawer-content{padding:0!important}.chat-container{display:flex;flex-direction:column;height:100%;max-height:100vh;overflow:hidden;background-color:transparent}dc-chat-messages-list{flex:1;overflow-y:auto;padding:.5rem}.score-container{padding:.5rem 1rem;background-color:var(--surface-card, #ffffff);border-top:1px solid var(--surface-border, #dee2e6)}.info-content{max-height:70vh;overflow-y:auto}.info-content h3{margin-top:1rem;margin-bottom:.5rem;font-size:1.2rem}.info-content pre{background-color:var(--surface-hover, #f1f1f1);padding:1rem;border-radius:4px;overflow-x:auto;font-size:.9rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: ChatHeaderComponent, selector: "dc-chat-header", inputs: ["isAdmin", "alternativeConversation", "agentCard"], outputs: ["restartConversationEvent", "showInfoEvent", "settingsClickEvent"] }, { kind: "component", type: ChatFooterComponent, selector: "dc-chat-footer", inputs: ["isAIThinking", "evaluatorAgentCard", "micSettings"], outputs: ["sendMessage", "textInputChanged"] }, { kind: "component", type: ChatMessagesListComponent, selector: "dc-chat-messages-list", inputs: ["chatUserSettings", "inputMessages"] }, { kind: "ngmodule", type: DialogModule }, { kind: "component", type: i1$3.Dialog, selector: "p-dialog", inputs: ["header", "draggable", "resizable", "positionLeft", "positionTop", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "responsive", "appendTo", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "breakpoint", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "ngmodule", type: ProgressBarModule }, { kind: "pipe", type: SafeJsonPipe, name: "safeJson" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2347
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.4", type: DCChatComponent, isStandalone: true, selector: "dc-chat", inputs: { chatUserSettings: { classPropertyName: "chatUserSettings", publicName: "chatUserSettings", isSignal: false, isRequired: false, transformFunction: null }, conversationSettings: { classPropertyName: "conversationSettings", publicName: "conversationSettings", isSignal: false, isRequired: false, transformFunction: null }, agentCard: { classPropertyName: "agentCard", publicName: "agentCard", isSignal: false, isRequired: false, transformFunction: null }, evaluatorAgentCard: { classPropertyName: "evaluatorAgentCard", publicName: "evaluatorAgentCard", isSignal: true, isRequired: false, transformFunction: null }, parseDict: { classPropertyName: "parseDict", publicName: "parseDict", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sendMessage: "sendMessage", goalCompleted: "goalCompleted" }, providers: [DialogService], ngImport: i0, template: "<div class=\"chat-container\">\n <!-- Chat Header -->\n <dc-chat-header\n [agentCard]=\"agentCard\"\n [isAdmin]=\"isAdmin\"\n (showInfoEvent)=\"showInfo()\"\n (settingsClickEvent)=\"changeUserChatSettings()\"\n (restartConversationEvent)=\"restartConversation($event)\">\n </dc-chat-header>\n\n <!-- Messages List -->\n <dc-chat-messages-list [chatUserSettings]=\"chatUserSettings\" [inputMessages]=\"messages()\"> </dc-chat-messages-list>\n\n <!-- Chat Footer -->\n <dc-chat-footer [micSettings]=\"micSettings\" [evaluatorAgentCard]=\"evaluatorAgentCard()\"> </dc-chat-footer>\n\n <!-- Info Dialog -->\n <p-dialog [(visible)]=\"isInfoVisible\" [modal]=\"true\" [draggable]=\"false\" [resizable]=\"false\" header=\"Conversation Info\">\n <div class=\"info-content\">\n <h3>Agent Card</h3>\n <pre>{{ agentCard | safeJson }}</pre>\n\n <h3>User Settings</h3>\n <pre>{{ chatUserSettings | safeJson }}</pre>\n </div>\n </p-dialog>\n</div>\n", styles: ["::ng-deep .p-drawer-content{padding:0!important}.chat-container{display:flex;flex-direction:column;height:100%;max-height:100vh;overflow:hidden;background-color:transparent}dc-chat-messages-list{flex:1;overflow-y:auto;padding:.5rem}.score-container{padding:.5rem 1rem;background-color:var(--surface-card, #ffffff);border-top:1px solid var(--surface-border, #dee2e6)}.info-content{max-height:70vh;overflow-y:auto}.info-content h3{margin-top:1rem;margin-bottom:.5rem;font-size:1.2rem}.info-content pre{background-color:var(--surface-hover, #f1f1f1);padding:1rem;border-radius:4px;overflow-x:auto;font-size:.9rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: ChatHeaderComponent, selector: "dc-chat-header", inputs: ["isAdmin", "alternativeConversation", "agentCard"], outputs: ["restartConversationEvent", "showInfoEvent", "settingsClickEvent"] }, { kind: "component", type: ChatFooterComponent, selector: "dc-chat-footer", inputs: ["isAIThinking", "evaluatorAgentCard", "micSettings"], outputs: ["sendMessage", "textInputChanged"] }, { kind: "component", type: ChatMessagesListComponent, selector: "dc-chat-messages-list", inputs: ["chatUserSettings", "inputMessages"] }, { kind: "ngmodule", type: DialogModule }, { kind: "component", type: i1$3.Dialog, selector: "p-dialog", inputs: ["header", "draggable", "resizable", "positionLeft", "positionTop", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "responsive", "appendTo", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "breakpoint", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "ngmodule", type: ProgressBarModule }, { kind: "pipe", type: SafeJsonPipe, name: "safeJson" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2235
2348
  }
2236
2349
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: DCChatComponent, decorators: [{
2237
2350
  type: Component,
2238
2351
  args: [{ selector: 'dc-chat', standalone: true, imports: [CommonModule, ChatHeaderComponent, ChatFooterComponent, ChatMessagesListComponent, DialogModule, ProgressBarModule, SafeJsonPipe], changeDetection: ChangeDetectionStrategy.OnPush, providers: [DialogService], template: "<div class=\"chat-container\">\n <!-- Chat Header -->\n <dc-chat-header\n [agentCard]=\"agentCard\"\n [isAdmin]=\"isAdmin\"\n (showInfoEvent)=\"showInfo()\"\n (settingsClickEvent)=\"changeUserChatSettings()\"\n (restartConversationEvent)=\"restartConversation($event)\">\n </dc-chat-header>\n\n <!-- Messages List -->\n <dc-chat-messages-list [chatUserSettings]=\"chatUserSettings\" [inputMessages]=\"messages()\"> </dc-chat-messages-list>\n\n <!-- Chat Footer -->\n <dc-chat-footer [micSettings]=\"micSettings\" [evaluatorAgentCard]=\"evaluatorAgentCard()\"> </dc-chat-footer>\n\n <!-- Info Dialog -->\n <p-dialog [(visible)]=\"isInfoVisible\" [modal]=\"true\" [draggable]=\"false\" [resizable]=\"false\" header=\"Conversation Info\">\n <div class=\"info-content\">\n <h3>Agent Card</h3>\n <pre>{{ agentCard | safeJson }}</pre>\n\n <h3>User Settings</h3>\n <pre>{{ chatUserSettings | safeJson }}</pre>\n </div>\n </p-dialog>\n</div>\n", styles: ["::ng-deep .p-drawer-content{padding:0!important}.chat-container{display:flex;flex-direction:column;height:100%;max-height:100vh;overflow:hidden;background-color:transparent}dc-chat-messages-list{flex:1;overflow-y:auto;padding:.5rem}.score-container{padding:.5rem 1rem;background-color:var(--surface-card, #ffffff);border-top:1px solid var(--surface-border, #dee2e6)}.info-content{max-height:70vh;overflow-y:auto}.info-content h3{margin-top:1rem;margin-bottom:.5rem;font-size:1.2rem}.info-content pre{background-color:var(--surface-hover, #f1f1f1);padding:1rem;border-radius:4px;overflow-x:auto;font-size:.9rem}\n"] }]
2239
- }], propDecorators: { chatUserSettings: [{
2352
+ }], ctorParameters: () => [], propDecorators: { chatUserSettings: [{
2240
2353
  type: Input
2241
2354
  }], conversationSettings: [{
2242
2355
  type: Input
@@ -3209,7 +3322,7 @@ class AgentCardListComponent extends PaginationBase {
3209
3322
  }
3210
3323
  }
3211
3324
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: AgentCardListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3212
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.4", type: AgentCardListComponent, isStandalone: true, selector: "dc-agent-card-lists", inputs: { viewMode: { classPropertyName: "viewMode", publicName: "viewMode", isSignal: false, isRequired: false, transformFunction: null }, customCardComponent: { classPropertyName: "customCardComponent", publicName: "customCardComponent", isSignal: true, isRequired: false, transformFunction: null }, showOptions: { classPropertyName: "showOptions", publicName: "showOptions", isSignal: true, isRequired: false, transformFunction: null }, gridLayout: { classPropertyName: "gridLayout", publicName: "gridLayout", isSignal: true, isRequired: false, transformFunction: null }, getCustomButtons: { classPropertyName: "getCustomButtons", publicName: "getCustomButtons", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "outlets", predicate: ["outlet"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<dc-filter-bar [isAdmin]=\"true\" (onFilterAction)=\"doFilterBarAction($event)\"></dc-filter-bar>\n\n@if(viewMode === 'table'){\n<app-quick-table [columns]=\"columns\" [tableData]=\"agentCards\" [actions]=\"actions()\" (onAction)=\"onCardAction($event)\"></app-quick-table>\n\n}@else{\n\n<div class=\"conversation-card-lists\">\n @if(!isLoading) {\n <div [ngClass]=\"{ 'cards-container': gridLayout() }\">\n @for (card of agentCards; track card) {\n <div style=\"position: relative\">\n <ng-container #outlet=\"ngComponentOutlet\" [ngComponentOutlet]=\"cardComponent\" [ngComponentOutletInputs]=\"{ card: card, showOptions: showOptions() }\">\n </ng-container>\n </div>\n }\n </div>\n }\n</div>\n\n@if(isLoading) {\n<div>\n <p-skeleton styleClass=\"mb-2\" />\n <p-skeleton width=\"10rem\" styleClass=\"mb-2\" />\n <p-skeleton width=\"5rem\" styleClass=\"mb-2\" />\n <p-skeleton height=\"2rem\" styleClass=\"mb-2\" />\n <p-skeleton width=\"10rem\" height=\"4rem\" />\n</div>\n} @if(agentCards.length === 0) {\n<div>\n <p>No conversations found or no connection with server</p>\n</div>\n} }\n\n<p-paginator\n currentPageReportTemplate=\"{{ totalRecords }} conversations\"\n [showCurrentPageReport]=\"true\"\n (onPageChange)=\"onPageChange($event)\"\n [first]=\"paginatorFirst\"\n [rows]=\"paginatorRows\"\n [totalRecords]=\"totalRecords\"\n [rowsPerPageOptions]=\"[10, 20, 30]\">\n</p-paginator>\n", styles: [":host{display:block;height:100%}.options-icon{cursor:pointer;position:absolute;top:2px;right:3px;font-size:1.2rem;color:#dde9e9;background-color:#4f486281;border-radius:50%;padding:5px;z-index:1000}.conversation-card-lists{padding:1.5rem;width:100%;height:100%;display:flex;flex-direction:column}.conversation-card-lists .cards-container{display:flex;flex-wrap:wrap;gap:2rem;width:100%;justify-content:center;flex:1;overflow-y:auto;min-height:0}.conversation-card-lists .cards-container>div{flex:0 0 240px}.conversation-card-lists .dc-card{position:relative;background:#fff;border-radius:8px;box-shadow:0 2px 4px #0000001a;padding:.5rem;transition:transform .2s ease,box-shadow .2s ease;display:flex;flex-direction:column;gap:2px}.conversation-card-lists .dc-card:hover{transform:translateY(-2px);box-shadow:0 4px 8px #00000026}.conversation-card-lists .dc-card .dc-card-header{position:absolute;top:10px;left:5px;border-radius:5px;padding:5px}.conversation-card-lists .dc-card .dc-card-header:before{content:\"\";position:absolute;inset:0;background-color:#4d30db81;filter:blur(2px);border-radius:5px;z-index:0}.conversation-card-lists .dc-card .dc-card-header h3{margin:0;font-size:1.25rem;font-weight:600;color:#ece7e7;position:relative;z-index:1}.conversation-card-lists .dc-card .dc-card-content{flex:1}.conversation-card-lists .dc-card .dc-card-content p{margin:0;color:#666;line-height:1.5}.conversation-card-lists .dc-card button{padding:.5rem 1rem;border:none;border-radius:4px;background-color:#007bff;color:#fff;cursor:pointer;font-weight:500;transition:background-color .2s ease}.conversation-card-lists .dc-card button:hover{background-color:#0056b3}.conversation-card-lists .dc-card button:active{transform:translateY(1px)}:host{display:flex;flex-direction:column;height:100%}p-paginator{margin-top:1rem;flex-shrink:0}\n"], dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "ngmodule", type: PaginatorModule }, { kind: "component", type: i1$4.Paginator, selector: "p-paginator", inputs: ["pageLinkSize", "style", "styleClass", "alwaysShow", "dropdownAppendTo", "templateLeft", "templateRight", "appendTo", "dropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showFirstLastIcon", "totalRecords", "rows", "rowsPerPageOptions", "showJumpToPageDropdown", "showJumpToPageInput", "jumpToPageItemTemplate", "showPageLinks", "locale", "dropdownItemTemplate", "first"], outputs: ["onPageChange"] }, { kind: "component", type: DCFilterBarComponent, selector: "dc-filter-bar", inputs: ["isAdmin", "customFilters", "items"], outputs: ["onFilterAction", "onChangeSort"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i1$2.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "style", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "ngmodule", type: SpeedDialModule }, { kind: "component", type: QuickTableComponent, selector: "app-quick-table", inputs: ["onlyView", "columns", "tableData", "actions"], outputs: ["onAction"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] }); }
3325
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.4", type: AgentCardListComponent, isStandalone: true, selector: "dc-agent-card-lists", inputs: { viewMode: { classPropertyName: "viewMode", publicName: "viewMode", isSignal: false, isRequired: false, transformFunction: null }, customCardComponent: { classPropertyName: "customCardComponent", publicName: "customCardComponent", isSignal: true, isRequired: false, transformFunction: null }, showOptions: { classPropertyName: "showOptions", publicName: "showOptions", isSignal: true, isRequired: false, transformFunction: null }, gridLayout: { classPropertyName: "gridLayout", publicName: "gridLayout", isSignal: true, isRequired: false, transformFunction: null }, getCustomButtons: { classPropertyName: "getCustomButtons", publicName: "getCustomButtons", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "outlets", predicate: ["outlet"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<dc-filter-bar [isAdmin]=\"true\" (onFilterAction)=\"doFilterBarAction($event)\"></dc-filter-bar>\n\n@if(viewMode === 'table'){\n<app-quick-table [columns]=\"columns\" [tableData]=\"agentCards\" [actions]=\"actions()\" (onAction)=\"onCardAction($event)\"></app-quick-table>\n\n}@else{\n\n<div class=\"conversation-card-lists\">\n @if(!isLoading) {\n <div [ngClass]=\"{ 'cards-container': gridLayout() }\">\n @for (card of agentCards; track card) {\n <div style=\"position: relative\">\n <ng-container #outlet=\"ngComponentOutlet\" [ngComponentOutlet]=\"cardComponent\" [ngComponentOutletInputs]=\"{ card: card, showOptions: showOptions() }\">\n </ng-container>\n </div>\n }\n </div>\n }\n</div>\n\n@if(isLoading) {\n<div>\n <p-skeleton styleClass=\"mb-2\" />\n <p-skeleton width=\"10rem\" styleClass=\"mb-2\" />\n <p-skeleton width=\"5rem\" styleClass=\"mb-2\" />\n <p-skeleton height=\"2rem\" styleClass=\"mb-2\" />\n <p-skeleton width=\"10rem\" height=\"4rem\" />\n</div>\n} @if(agentCards.length === 0) {\n<div>\n <p>No conversations found or no connection with server</p>\n</div>\n} }\n\n<p-paginator\n currentPageReportTemplate=\"{{ totalRecords }} conversations\"\n [showCurrentPageReport]=\"true\"\n (onPageChange)=\"onPageChange($event)\"\n [first]=\"paginatorFirst\"\n [rows]=\"paginatorRows\"\n [totalRecords]=\"totalRecords\"\n [rowsPerPageOptions]=\"[10, 20, 30]\">\n</p-paginator>\n", styles: [":host{display:block;height:100%}.options-icon{cursor:pointer;position:absolute;top:2px;right:3px;font-size:1.2rem;color:#dde9e9;background-color:#4f486281;border-radius:50%;padding:5px;z-index:1000}.conversation-card-lists{padding:1.5rem;width:100%;height:100%;display:flex;flex-direction:column}.conversation-card-lists .cards-container{display:flex;flex-wrap:wrap;gap:2rem;width:100%;justify-content:center;flex:1;overflow-y:auto;min-height:0}.conversation-card-lists .cards-container>div{flex:0 0 240px}.conversation-card-lists .dc-card{position:relative;background:#fff;border-radius:8px;box-shadow:0 2px 4px #0000001a;padding:.5rem;transition:transform .2s ease,box-shadow .2s ease;display:flex;flex-direction:column;gap:2px}.conversation-card-lists .dc-card:hover{transform:translateY(-2px);box-shadow:0 4px 8px #00000026}.conversation-card-lists .dc-card .dc-card-header{position:absolute;top:10px;left:5px;border-radius:5px;padding:5px}.conversation-card-lists .dc-card .dc-card-header:before{content:\"\";position:absolute;inset:0;background-color:#4d30db81;filter:blur(2px);border-radius:5px;z-index:0}.conversation-card-lists .dc-card .dc-card-header h3{margin:0;font-size:1.25rem;font-weight:600;color:#ece7e7;position:relative;z-index:1}.conversation-card-lists .dc-card .dc-card-content{flex:1}.conversation-card-lists .dc-card .dc-card-content p{margin:0;color:#666;line-height:1.5}.conversation-card-lists .dc-card button{padding:.5rem 1rem;border:none;border-radius:4px;background-color:#007bff;color:#fff;cursor:pointer;font-weight:500;transition:background-color .2s ease}.conversation-card-lists .dc-card button:hover{background-color:#0056b3}.conversation-card-lists .dc-card button:active{transform:translateY(1px)}:host{display:flex;flex-direction:column;height:100%}p-paginator{margin-top:1rem;flex-shrink:0}\n"], dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "ngmodule", type: PaginatorModule }, { kind: "component", type: i1$4.Paginator, selector: "p-paginator", inputs: ["pageLinkSize", "style", "styleClass", "alwaysShow", "dropdownAppendTo", "templateLeft", "templateRight", "appendTo", "dropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showFirstLastIcon", "totalRecords", "rows", "rowsPerPageOptions", "showJumpToPageDropdown", "showJumpToPageInput", "jumpToPageItemTemplate", "showPageLinks", "locale", "dropdownItemTemplate", "first"], outputs: ["onPageChange"] }, { kind: "component", type: DCFilterBarComponent, selector: "dc-filter-bar", inputs: ["isAdmin", "items", "customFilters"], outputs: ["onFilterAction", "onChangeSort", "onNew"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i1$2.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "style", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "ngmodule", type: SpeedDialModule }, { kind: "component", type: QuickTableComponent, selector: "app-quick-table", inputs: ["columns", "tableData", "actions"], outputs: ["onAction"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] }); }
3213
3326
  }
3214
3327
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: AgentCardListComponent, decorators: [{
3215
3328
  type: Component,
@@ -3308,7 +3421,7 @@ const DefaultEvaluatorAgentCard = {
3308
3421
  task: 'Evaluate the user understanding of the lesson',
3309
3422
  messages: [],
3310
3423
  expectedResponseType: EvalResultStringDefinition,
3311
- model: { id: 'gpt-4o-mini', provider: 'openai' },
3424
+ model: { id: '', provider: 'google' },
3312
3425
  sources: [],
3313
3426
  };
3314
3427