@dataclouder/ngx-agent-cards 0.2.2 → 0.2.4

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,13 +1,14 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { InjectionToken, Injectable, inject, signal, computed, RendererFactory2, ApplicationRef, Injector, EnvironmentInjector, createComponent, ChangeDetectionStrategy, Component, output, Input, input, effect, ViewChild, DestroyRef, HostBinding, untracked, ElementRef, Pipe, ChangeDetectorRef, EventEmitter, Output, viewChild } from '@angular/core';
3
3
  import * as i1 from '@dataclouder/ngx-core';
4
- import { MoodStateOptions, LANGUAGES, EntityCommunicationService, TOAST_ALERTS_TOKEN, APP_CONFIG, MoodState, AudioSpeed as AudioSpeed$1, LoadingBarService, EModelQuality, getLangDesc, AudioSpeedReverse, formatCamelCaseString, EntityBaseDetailComponent, AudioNotificationService, SUPPORTED_LANGUAGES, FormUtilsService, DcTagsFormComponent, EntityBaseFormComponent, getSupportedLanguageOptions, DcManageableFormComponent, DcLearnableFormComponent, EntityBaseListV2Component, DCFilterBarComponent, QuickTableComponent, EmptyStateComponent, EntityBaseListComponent, EntityBaseSignalFormComponent } from '@dataclouder/ngx-core';
4
+ import { MoodStateOptions, LANGUAGES, EntityCommunicationService, TOAST_ALERTS_TOKEN, APP_CONFIG, MoodState, AudioSpeed as AudioSpeed$1, LoadingBarService, EModelQuality, getLangDesc, AudioSpeedReverse, formatCamelCaseString, EntityBaseDetailComponent, AudioNotificationService, SUPPORTED_LANGUAGES, FormUtilsService, LangDescTranslation, FlagPipe, FlagImgPipe, DcTagsFormComponent, EntityBaseFormComponent, getSupportedLanguageOptions, DcManageableFormComponent, DcLearnableFormComponent, EntityBaseListV2Component, DCFilterBarComponent, QuickTableComponent, EmptyStateComponent, EntityBaseSignalFormComponent } from '@dataclouder/ngx-core';
5
5
  import { UserService } from '@dataclouder/ngx-users';
6
6
  import { AiWhisperService, TtsService, NgxAiServicesService, GeneratedAssetsService, VoiceSelectorComponent } from '@dataclouder/ngx-ai-services';
7
+ import { FirebaseAuthService } from '@dataclouder/ngx-auth';
8
+ import { firstValueFrom, Subject, fromEvent, filter, BehaviorSubject, Subscription } from 'rxjs';
7
9
  import * as i2$1 from '@angular/common';
8
10
  import { DOCUMENT, CommonModule, KeyValuePipe, NgTemplateOutlet, DatePipe, SlicePipe, JsonPipe } from '@angular/common';
9
11
  import { nanoid } from 'nanoid';
10
- import { Subject, fromEvent, filter, BehaviorSubject } from 'rxjs';
11
12
  import { DynamicDialogRef, DynamicDialogConfig, DialogService, DynamicDialogModule } from 'primeng/dynamicdialog';
12
13
  import * as i2 from 'primeng/button';
13
14
  import { ButtonModule } from 'primeng/button';
@@ -30,25 +31,25 @@ import * as i1$2 from 'primeng/skeleton';
30
31
  import { SkeletonModule, Skeleton } from 'primeng/skeleton';
31
32
  import * as i4 from 'primeng/checkbox';
32
33
  import { CheckboxModule } from 'primeng/checkbox';
33
- import * as i1$6 from 'primeng/slider';
34
+ import * as i4$1 from 'primeng/slider';
34
35
  import { SliderModule } from 'primeng/slider';
35
36
  import * as i3$2 from 'primeng/radiobutton';
36
37
  import { RadioButtonModule } from 'primeng/radiobutton';
37
38
  import { RatingModule } from 'primeng/rating';
38
- import * as i1$5 from 'primeng/table';
39
+ import * as i1$4 from 'primeng/table';
39
40
  import { TableModule } from 'primeng/table';
40
41
  import { BadgeModule } from 'primeng/badge';
41
42
  import * as i5 from 'primeng/select';
42
43
  import { SelectModule } from 'primeng/select';
43
- import * as i1$3 from 'primeng/divider';
44
+ import * as i2$4 from 'primeng/divider';
44
45
  import { DividerModule } from 'primeng/divider';
45
- import * as i2$5 from 'primeng/tabs';
46
+ import * as i2$6 from 'primeng/tabs';
46
47
  import { TabsModule } from 'primeng/tabs';
47
48
  import { ChipModule } from 'primeng/chip';
48
- import * as i1$4 from 'primeng/tag';
49
+ import * as i1$3 from 'primeng/tag';
49
50
  import { TagModule } from 'primeng/tag';
50
- import * as i2$4 from 'primeng/api';
51
- import * as i2$6 from 'primeng/card';
51
+ import * as i2$5 from 'primeng/api';
52
+ import * as i2$7 from 'primeng/card';
52
53
  import { CardModule } from 'primeng/card';
53
54
  import * as i3$3 from 'primeng/progressspinner';
54
55
  import { ProgressSpinnerModule } from 'primeng/progressspinner';
@@ -61,18 +62,18 @@ import { MessageModule } from 'primeng/message';
61
62
  import * as i7 from 'primeng/accordion';
62
63
  import { AccordionModule } from 'primeng/accordion';
63
64
  import { AspectRatioOptions, SafeHtmlPipe, AssetsLoaderComponent, SimpleUploaderComponent, ResolutionType, AspectType, CropperComponentModal } from '@dataclouder/ngx-cloud-storage';
64
- import * as i1$7 from '@angular/router';
65
+ import * as i1$5 from '@angular/router';
65
66
  import { ActivatedRoute, Router, RouterModule } from '@angular/router';
66
- import * as i4$1 from 'primeng/toggleswitch';
67
+ import * as i4$2 from 'primeng/toggleswitch';
67
68
  import { ToggleSwitchModule } from 'primeng/toggleswitch';
68
69
  import * as i5$2 from 'primeng/inputnumber';
69
70
  import { InputNumberModule } from 'primeng/inputnumber';
70
71
  import { ToggleButtonModule } from 'primeng/togglebutton';
71
72
  import * as i3$6 from 'primeng/inputgroup';
72
73
  import { InputGroupModule } from 'primeng/inputgroup';
73
- import * as i4$2 from 'primeng/inputgroupaddon';
74
+ import * as i4$3 from 'primeng/inputgroupaddon';
74
75
  import { InputGroupAddonModule } from 'primeng/inputgroupaddon';
75
- import * as i4$3 from 'primeng/paginator';
76
+ import * as i4$4 from 'primeng/paginator';
76
77
  import { PaginatorModule } from 'primeng/paginator';
77
78
  import * as i3$7 from 'primeng/speeddial';
78
79
  import { SpeedDialModule } from 'primeng/speeddial';
@@ -1310,9 +1311,6 @@ class ConversationPromptBuilderService {
1310
1311
  // New field for all greetings.
1311
1312
  gretting = this.sampleSize(characterCard.data.greetings, 1)[0];
1312
1313
  }
1313
- else {
1314
- gretting = this.selectOneRandomGreeting(characterCard.data.first_mes, characterCard.data.greetings);
1315
- }
1316
1314
  chat.push({ role: ChatRole.System, content: '[Start a new Chat]' });
1317
1315
  if (gretting) {
1318
1316
  chat.push({ role: ChatRole.Assistant, content: gretting });
@@ -1462,6 +1460,7 @@ class DefaultAgentCardsService extends EntityCommunicationService {
1462
1460
  this.toastService = inject(TOAST_ALERTS_TOKEN);
1463
1461
  this.appConfig = inject(APP_CONFIG);
1464
1462
  this.whisperService = inject(AiWhisperService);
1463
+ this.fbAuthService = inject(FirebaseAuthService, { optional: true });
1465
1464
  this.randomSeed = Math.floor(Math.random() * 100000);
1466
1465
  }
1467
1466
  partialUpdateAgentCard(agentCard) {
@@ -1494,6 +1493,66 @@ class DefaultAgentCardsService extends EntityCommunicationService {
1494
1493
  }
1495
1494
  return response;
1496
1495
  }
1496
+ async *callChatCompletionStream(conversation) {
1497
+ let messages = conversation.messages.map((m) => ({ content: m.content, role: m.role }));
1498
+ const conversationFiltered = { ...conversation, messages };
1499
+ const host = this.appConfig?.aiServicesUrl || this.appConfig?.backendNodeUrl || '';
1500
+ const baseUrl = host.endsWith('/') ? host.slice(0, -1) : host;
1501
+ const service = `api/ai-services/gemini/chat/stream`;
1502
+ const url = `${baseUrl}/${service}`;
1503
+ let token = null;
1504
+ if (this.fbAuthService) {
1505
+ try {
1506
+ token = (await firstValueFrom(this.fbAuthService.tokenId$));
1507
+ }
1508
+ catch (err) {
1509
+ console.warn('Failed to retrieve Firebase ID token:', err);
1510
+ }
1511
+ }
1512
+ const response = await fetch(url, {
1513
+ method: 'POST',
1514
+ headers: {
1515
+ 'Content-Type': 'application/json',
1516
+ ...(token ? { Authorization: `Bearer ${token}` } : {}),
1517
+ },
1518
+ body: JSON.stringify(conversationFiltered),
1519
+ });
1520
+ if (!response.ok || !response.body) {
1521
+ throw new Error(`HTTP error: ${response.status} ${response.statusText}`);
1522
+ }
1523
+ const reader = response.body.getReader();
1524
+ const decoder = new TextDecoder();
1525
+ let buffer = '';
1526
+ try {
1527
+ while (true) {
1528
+ const { done, value } = await reader.read();
1529
+ if (done)
1530
+ break;
1531
+ buffer += decoder.decode(value, { stream: true });
1532
+ const lines = buffer.split('\n');
1533
+ buffer = lines.pop() ?? '';
1534
+ for (const line of lines) {
1535
+ if (!line.startsWith('data: '))
1536
+ continue;
1537
+ const data = line.slice(6).trim();
1538
+ if (data === '[DONE]')
1539
+ return;
1540
+ try {
1541
+ const parsed = JSON.parse(data);
1542
+ if (parsed.content) {
1543
+ yield parsed.content;
1544
+ }
1545
+ }
1546
+ catch {
1547
+ // ignore malformed lines
1548
+ }
1549
+ }
1550
+ }
1551
+ }
1552
+ finally {
1553
+ reader.cancel();
1554
+ }
1555
+ }
1497
1556
  async filterConversationCards(filters) {
1498
1557
  return this.httpService.post(`api/${this.serviceName}/query`, filters, 'primary');
1499
1558
  }
@@ -1812,6 +1871,8 @@ class ConversationFlowStateService {
1812
1871
  this.currentMood = computed(() => this.flowState().moodState.value, ...(ngDevMode ? [{ debugName: "currentMood" }] : /* istanbul ignore next */ []));
1813
1872
  this.moodUpdated = new Subject();
1814
1873
  this.moodUpdated$ = this.moodUpdated.asObservable();
1874
+ this.goalEvaluationUpdated = new Subject();
1875
+ this.goalEvaluationUpdated$ = this.goalEvaluationUpdated.asObservable();
1815
1876
  }
1816
1877
  /**
1817
1878
  * @description
@@ -1831,6 +1892,12 @@ class ConversationFlowStateService {
1831
1892
  if (newState.moodState?.value) {
1832
1893
  this.moodUpdated.next(newState.moodState.value);
1833
1894
  }
1895
+ if (newState.goal && newState.goal.deltaPoints !== undefined && newState.goal.deltaPoints !== 0) {
1896
+ this.goalEvaluationUpdated.next({
1897
+ deltaPoints: newState.goal.deltaPoints,
1898
+ feedback: newState.goal.feedback,
1899
+ });
1900
+ }
1834
1901
  }
1835
1902
  /**
1836
1903
  * @description
@@ -1931,6 +1998,7 @@ class DynamicFlowService {
1931
1998
  this.messagesStateService = inject(MessagesStateService);
1932
1999
  this.conversationFlowStateService = inject(ConversationFlowStateService);
1933
2000
  this.agentCardStateService = inject(AgentCardStateService);
2001
+ this.userService = inject(UserService);
1934
2002
  /** Derived from AgentCardStateService — single source of truth for the conversation flow config. */
1935
2003
  this.conversationFlowConfig = this.agentCardStateService.conversationFlow$;
1936
2004
  /**
@@ -1988,11 +2056,15 @@ class DynamicFlowService {
1988
2056
  updateStateFromAI(aiResponse) {
1989
2057
  const currentState = this.flowState();
1990
2058
  const updatedState = { ...aiResponse };
2059
+ let previousGoalValue;
2060
+ let newGoalValueComputed;
1991
2061
  // Goal: Add deltaPoints to current value
1992
2062
  if (aiResponse.goal && typeof aiResponse.goal.deltaPoints === 'number') {
1993
2063
  const currentGoalValue = currentState.goal?.value || 0;
1994
2064
  const deltaPoints = aiResponse.goal.deltaPoints;
1995
2065
  const newGoalValue = Math.min(100, Math.max(0, currentGoalValue + deltaPoints));
2066
+ previousGoalValue = currentGoalValue;
2067
+ newGoalValueComputed = newGoalValue;
1996
2068
  updatedState.goal = {
1997
2069
  ...currentState.goal,
1998
2070
  value: newGoalValue,
@@ -2015,8 +2087,33 @@ class DynamicFlowService {
2015
2087
  updatedState.challenges = mergedChallenges;
2016
2088
  }
2017
2089
  this.conversationFlowStateService.updateState(updatedState);
2090
+ this.attachFlowEvaluationToLastUserMessage(aiResponse, previousGoalValue, newGoalValueComputed);
2018
2091
  this.syncMoodToLatestMessage();
2019
2092
  }
2093
+ attachFlowEvaluationToLastUserMessage(aiResponse, previousGoalValue, newGoalValue) {
2094
+ const messages = this.messagesStateService.getMessagesSignal()();
2095
+ const lastUserMessage = messages.slice().reverse().find((m) => m.role === ChatRole.User);
2096
+ if (!lastUserMessage?.messageId)
2097
+ return;
2098
+ const flowEvaluation = { evaluatedAt: new Date().toISOString() };
2099
+ if (aiResponse.goal) {
2100
+ flowEvaluation['goal'] = {
2101
+ deltaPoints: aiResponse.goal.deltaPoints,
2102
+ feedback: aiResponse.goal.feedback,
2103
+ previousValue: previousGoalValue,
2104
+ newValue: newGoalValue,
2105
+ };
2106
+ }
2107
+ if (aiResponse.challenges?.length) {
2108
+ flowEvaluation['challenges'] = aiResponse.challenges;
2109
+ }
2110
+ if (aiResponse.moodState) {
2111
+ flowEvaluation['moodState'] = aiResponse.moodState;
2112
+ }
2113
+ this.messagesStateService.updateMessage(lastUserMessage.messageId, {
2114
+ evaluation: { ...(lastUserMessage.evaluation || {}), flow: flowEvaluation },
2115
+ });
2116
+ }
2020
2117
  syncMoodToLatestMessage(messageId) {
2021
2118
  const currentState = this.flowState();
2022
2119
  if (!currentState?.moodState?.value)
@@ -2058,9 +2155,21 @@ class DynamicFlowService {
2058
2155
  */
2059
2156
  generateSystemPromptForFlow(messages) {
2060
2157
  const config = this.agentCardStateService.conversationFlow$();
2061
- const currentState = this.flowState();
2062
2158
  if (!config)
2063
2159
  return '';
2160
+ debugger;
2161
+ const hasGoal = config.goal?.enabled && !config.goal.disableFeature;
2162
+ const currentState = this.flowState();
2163
+ const completedChallengeNames = new Set((currentState.challenges || []).filter((c) => c.value === true).map((c) => c.name));
2164
+ const activeChallenges = (config.challenges || []).filter((c) => c.enabled && !completedChallengeNames.has(c.name));
2165
+ const hasChallenges = activeChallenges.length > 0;
2166
+ const hasMood = config.moodState?.enabled;
2167
+ if (!hasGoal && !hasChallenges && !hasMood) {
2168
+ return '';
2169
+ }
2170
+ // I do this as test, lets see how it goes. so ai is not influenced by previous delta points value.
2171
+ currentState.goal.deltaPoints = 0;
2172
+ // debugger;
2064
2173
  let prompt = `You are an AI managing the conversation flow. Your task is to update the current state based on the conversation context.
2065
2174
 
2066
2175
  Current State:
@@ -2071,7 +2180,7 @@ Instructions per Component:
2071
2180
  if (config.goal?.enabled) {
2072
2181
  prompt += `
2073
2182
  - Goal: ${config.goal.task}
2074
- Evaluate the interaction and provide an integer value for "deltaPoints" representing points to ADD or SUBTRACT from the current goal value (usually 1-15 points), and "feedback" explaining why.
2183
+ Evaluate the interaction and provide an integer value for "deltaPoints" representing points to ADD or SUBTRACT from the current goal value (don't Subtract more than 10 points), and "feedback" explaining why you took this decision.
2075
2184
  `;
2076
2185
  }
2077
2186
  if (config.challenges && config.challenges.length > 0) {
@@ -2110,6 +2219,14 @@ Mark challenges as completed (true) ONLY if the user has satisfied the condition
2110
2219
  - Mood: Detect the agent's mood based on the conversation.
2111
2220
  Stricly use one of these Detectable states: ${detectableStates.join(', ')}
2112
2221
  If really not posible to fit into one then use neutral.
2222
+ `;
2223
+ }
2224
+ const userContext = this.userService.getUserDataInformation();
2225
+ if (userContext) {
2226
+ prompt += `
2227
+ - User Context: Take into consideration the user profile when evaluating.
2228
+ ${userContext}
2229
+ IMPORTANT: If the user level is basic or beginner, be extremely generous and encouraging when assigning deltaPoints. Do not demotivate them with negative points for minor mistakes. Focus on positive reinforcement.
2113
2230
  `;
2114
2231
  }
2115
2232
  const lastMessages = messages.slice(-4);
@@ -2119,10 +2236,10 @@ Context (Last Messages):
2119
2236
  ${lastMessages.map((m) => `${m.role}: ${m.content}`).join('\n')}
2120
2237
 
2121
2238
  Instructions:
2122
- 1. Analyze the context, that is a partial conversation, evaluate the last user interaction only.
2123
- 2. Update the goal state: provide "deltaPoints" and "feedback" (less than 80 words) inside the goal object.
2239
+ 1. Analyze the context, that is a partial conversation, last 4 dialogs (2 user, 2 agent).
2240
+ 2. Update the goal state: focous on last user message, provide "deltaPoints" and "feedback" (less than 80 words) inside the goal object.
2124
2241
  3. Mark challenges as completed if met.
2125
- 4. Update the mood state.
2242
+ 4. Update the mood state according to last agent message.
2126
2243
  5. Return ONLY a valid JSON object matching the IConversationFlowState structure with updated values.
2127
2244
  Do not return markdown formatting.
2128
2245
  `;
@@ -3112,6 +3229,110 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
3112
3229
  }]
3113
3230
  }], ctorParameters: () => [] });
3114
3231
 
3232
+ class SentenceStreamParser {
3233
+ constructor() {
3234
+ this.buffer = '';
3235
+ this.currentTag = 'p';
3236
+ }
3237
+ append(chunk) {
3238
+ this.buffer += chunk;
3239
+ return this.parse(false);
3240
+ }
3241
+ finish() {
3242
+ return this.parse(true);
3243
+ }
3244
+ parse(isFinished) {
3245
+ const completed = [];
3246
+ let i = 0;
3247
+ while (i < this.buffer.length) {
3248
+ // Check for code tag `
3249
+ if (this.buffer[i] === '`') {
3250
+ this.currentTag = this.currentTag === 'code' ? 'p' : 'code';
3251
+ this.buffer = this.buffer.substring(i + 1);
3252
+ i = 0;
3253
+ continue;
3254
+ }
3255
+ // Check for asterisks
3256
+ if (this.buffer[i] === '*') {
3257
+ let count = 0;
3258
+ while (i + count < this.buffer.length && this.buffer[i + count] === '*') {
3259
+ count++;
3260
+ }
3261
+ if (count === 3) {
3262
+ this.currentTag = this.currentTag === 'em_strong' ? 'p' : 'em_strong';
3263
+ }
3264
+ else if (count === 2) {
3265
+ this.currentTag = this.currentTag === 'strong' ? 'p' : 'strong';
3266
+ }
3267
+ else if (count === 1) {
3268
+ this.currentTag = this.currentTag === 'em' ? 'p' : 'em';
3269
+ }
3270
+ this.buffer = this.buffer.substring(i + count);
3271
+ i = 0;
3272
+ continue;
3273
+ }
3274
+ // Find next sentence boundary or tag token or end
3275
+ let boundaryIndex = -1;
3276
+ let nextTagIndex = -1;
3277
+ for (let j = i; j < this.buffer.length; j++) {
3278
+ const char = this.buffer[j];
3279
+ if (char === '*' || char === '`') {
3280
+ nextTagIndex = j;
3281
+ break;
3282
+ }
3283
+ if (char === '.' || char === '?' || char === '!' || char === '\n') {
3284
+ const nextChar = j + 1 < this.buffer.length ? this.buffer[j + 1] : '';
3285
+ const isFollowedByWhitespace = !nextChar || nextChar === ' ' || nextChar === '\n' || nextChar === '\r';
3286
+ let isAbbreviation = false;
3287
+ if (char === '.') {
3288
+ const wordStart = this.buffer.substring(0, j).lastIndexOf(' ') + 1;
3289
+ const word = this.buffer.substring(wordStart, j).toLowerCase();
3290
+ const abbreviations = ['mr', 'mrs', 'ms', 'dr', 'sr', 'sra', 'srta', 'etc', 'eg', 'ie'];
3291
+ if (abbreviations.includes(word)) {
3292
+ isAbbreviation = true;
3293
+ }
3294
+ }
3295
+ if (isFollowedByWhitespace && !isAbbreviation) {
3296
+ boundaryIndex = j;
3297
+ break;
3298
+ }
3299
+ }
3300
+ }
3301
+ if (boundaryIndex !== -1) {
3302
+ const sentenceText = this.buffer.substring(i, boundaryIndex + 1);
3303
+ completed.push({
3304
+ text: sentenceText,
3305
+ tag: this.currentTag
3306
+ });
3307
+ this.buffer = this.buffer.substring(boundaryIndex + 1);
3308
+ i = 0;
3309
+ }
3310
+ else if (nextTagIndex !== -1) {
3311
+ const segmentText = this.buffer.substring(i, nextTagIndex);
3312
+ if (segmentText) {
3313
+ completed.push({
3314
+ text: segmentText,
3315
+ tag: this.currentTag
3316
+ });
3317
+ }
3318
+ this.buffer = this.buffer.substring(nextTagIndex);
3319
+ i = 0;
3320
+ }
3321
+ else {
3322
+ break;
3323
+ }
3324
+ }
3325
+ if (isFinished && this.buffer) {
3326
+ completed.push({
3327
+ text: this.buffer,
3328
+ tag: this.currentTag
3329
+ });
3330
+ this.buffer = '';
3331
+ }
3332
+ return completed.filter(c => c.text !== '');
3333
+ }
3334
+ }
3335
+
3115
3336
  const DEFUALT_USER_AVATAR = 'defaults/avatar_user.jpg';
3116
3337
  const DEFUALT_ASSISTANT_AVATAR = 'defaults/avatar_ai.webp';
3117
3338
  class ConversationService {
@@ -3189,7 +3410,14 @@ class ConversationService {
3189
3410
  return agentFlow;
3190
3411
  }
3191
3412
  const mergedFlow = { ...agentFlow };
3192
- mergedFlow.goal = agentFlow?.goal?.task ? agentFlow.goal : defaultFlow.goal;
3413
+ debugger;
3414
+ if (agentFlow?.goal?.disableFeature ||
3415
+ (agentFlow?.goal?.task && agentFlow?.goal?.enabled === false)) {
3416
+ mergedFlow.goal = agentFlow.goal;
3417
+ }
3418
+ else {
3419
+ mergedFlow.goal = agentFlow?.goal?.task ? agentFlow.goal : defaultFlow.goal;
3420
+ }
3193
3421
  mergedFlow.dynamicConditions = agentFlow?.dynamicConditions?.length > 0 ? agentFlow.dynamicConditions : defaultFlow.dynamicConditions;
3194
3422
  mergedFlow.challenges = agentFlow?.challenges?.length > 0 ? agentFlow.challenges : defaultFlow.challenges;
3195
3423
  mergedFlow.tools = agentFlow?.tools?.length > 0 ? agentFlow.tools : defaultFlow.tools;
@@ -3204,7 +3432,8 @@ class ConversationService {
3204
3432
  if (!mergedFlow.triggerTasks) {
3205
3433
  mergedFlow.triggerTasks = {};
3206
3434
  }
3207
- if (agentFlow?.triggerTasks?.onUserMessage?.disableFeature) {
3435
+ if (agentFlow?.triggerTasks?.onUserMessage?.disableFeature ||
3436
+ (agentFlow?.triggerTasks?.onUserMessage?.task && agentFlow?.triggerTasks?.onUserMessage?.enabled === false)) {
3208
3437
  // just setting to null disables de feature, this is is card demands.
3209
3438
  mergedFlow.triggerTasks.onUserMessage = null;
3210
3439
  }
@@ -3213,7 +3442,8 @@ class ConversationService {
3213
3442
  ? agentFlow.triggerTasks.onUserMessage
3214
3443
  : defaultFlow.triggerTasks?.onUserMessage;
3215
3444
  }
3216
- if (agentFlow?.triggerTasks?.onAssistantMessage?.disableFeature) {
3445
+ if (agentFlow?.triggerTasks?.onAssistantMessage?.disableFeature ||
3446
+ (agentFlow?.triggerTasks?.onAssistantMessage?.task && agentFlow?.triggerTasks?.onAssistantMessage?.enabled === false)) {
3217
3447
  mergedFlow.triggerTasks.onAssistantMessage = null;
3218
3448
  }
3219
3449
  else {
@@ -3361,6 +3591,14 @@ class ConversationService {
3361
3591
  type: 'rp-conversation',
3362
3592
  };
3363
3593
  this.isThinkingSignal.set(true);
3594
+ if (conversationSettings.streamResponses) {
3595
+ return this.handleStreamingResponse(conversation, conversationSettings);
3596
+ }
3597
+ else {
3598
+ return this.handleBlockingResponse(conversation, conversationSettings);
3599
+ }
3600
+ }
3601
+ async handleBlockingResponse(conversation, conversationSettings) {
3364
3602
  const response = await this.defaultAgentCardService.callChatCompletion(conversation);
3365
3603
  if (!response) {
3366
3604
  console.error('No message returned from AI, is your service working?');
@@ -3372,10 +3610,116 @@ class ConversationService {
3372
3610
  this.isThinkingSignal.set(false);
3373
3611
  // Run Dynamic Flow Evaluations
3374
3612
  this.dynamicFlowTaskService.triggerAfterAssistantMessage(newMessage); // Not waiting should be parallel.
3375
- // Persist conversation Not for now, only when conversation is finish.
3376
- // this.persistCurrentSession();
3377
3613
  return newMessage.messageId;
3378
3614
  }
3615
+ async handleStreamingResponse(conversation, conversationSettings) {
3616
+ const messageId = nanoid();
3617
+ const mainVoice = conversationSettings?.mainVoice?.voice || conversationSettings?.tts?.voice;
3618
+ const assistantVoice = this.messageProcessingService.getVoice(mainVoice);
3619
+ const secondaryVoice = conversationSettings?.secondaryVoice?.voice || conversationSettings?.tts?.secondaryVoice || 'en-US-News-L';
3620
+ let assistantMessage = {
3621
+ messageId,
3622
+ role: ChatRole.Assistant,
3623
+ content: '',
3624
+ text: '',
3625
+ voice: assistantVoice,
3626
+ imgUrl: conversationSettings.avatarImages?.assistant || undefined,
3627
+ multiMessages: [],
3628
+ isLoading: true,
3629
+ };
3630
+ this.messagesStateService.addMessage(assistantMessage);
3631
+ let stream;
3632
+ try {
3633
+ stream = this.defaultAgentCardService.callChatCompletionStream(conversation);
3634
+ }
3635
+ catch (error) {
3636
+ this.isThinkingSignal.set(false);
3637
+ this.messagesStateService.updateMessage(messageId, {
3638
+ isLoading: false,
3639
+ content: 'Error: Failed to initiate stream connection.',
3640
+ });
3641
+ throw error;
3642
+ }
3643
+ const parser = new SentenceStreamParser();
3644
+ let accumulatedText = '';
3645
+ let isFirstChunk = true;
3646
+ try {
3647
+ for await (const chunk of stream) {
3648
+ if (isFirstChunk) {
3649
+ isFirstChunk = false;
3650
+ this.isThinkingSignal.set(false);
3651
+ assistantMessage = {
3652
+ ...assistantMessage,
3653
+ isLoading: false,
3654
+ };
3655
+ }
3656
+ accumulatedText += chunk;
3657
+ // Feed the chunk into the sentence parser
3658
+ const parsedChunks = parser.append(chunk);
3659
+ if (parsedChunks.length > 0) {
3660
+ const newSegments = parsedChunks.map((c) => {
3661
+ const isItalics = c.tag === 'em';
3662
+ const voice = isItalics ? secondaryVoice : assistantVoice;
3663
+ return {
3664
+ voice,
3665
+ content: this.messageProcessingService.wrapContentWithTag(c.text, c.tag),
3666
+ text: c.text,
3667
+ audioUrl: null,
3668
+ audioPromise: null,
3669
+ audioStatus: 'pending',
3670
+ tag: c.tag,
3671
+ messageId,
3672
+ };
3673
+ });
3674
+ assistantMessage.multiMessages = [
3675
+ ...(assistantMessage.multiMessages || []),
3676
+ ...newSegments,
3677
+ ];
3678
+ }
3679
+ assistantMessage.content = accumulatedText;
3680
+ assistantMessage.text = accumulatedText;
3681
+ this.messagesStateService.updateMessage(messageId, { ...assistantMessage });
3682
+ }
3683
+ // Finish the parser stream
3684
+ const finalParsedChunks = parser.finish();
3685
+ if (finalParsedChunks.length > 0) {
3686
+ const newSegments = finalParsedChunks.map((c) => {
3687
+ const isItalics = c.tag === 'em';
3688
+ const voice = isItalics ? secondaryVoice : assistantVoice;
3689
+ return {
3690
+ voice,
3691
+ content: this.messageProcessingService.wrapContentWithTag(c.text, c.tag),
3692
+ text: c.text,
3693
+ audioUrl: null,
3694
+ audioPromise: null,
3695
+ audioStatus: 'pending',
3696
+ tag: c.tag,
3697
+ messageId,
3698
+ };
3699
+ });
3700
+ assistantMessage.multiMessages = [
3701
+ ...(assistantMessage.multiMessages || []),
3702
+ ...newSegments,
3703
+ ];
3704
+ }
3705
+ assistantMessage.content = accumulatedText;
3706
+ assistantMessage.text = accumulatedText;
3707
+ assistantMessage.isLoading = false;
3708
+ this.messagesStateService.updateMessage(messageId, { ...assistantMessage });
3709
+ }
3710
+ catch (err) {
3711
+ console.error('Error during chat completion stream:', err);
3712
+ this.isThinkingSignal.set(false);
3713
+ this.messagesStateService.updateMessage(messageId, {
3714
+ isLoading: false,
3715
+ content: 'Error: Connection lost during stream generation.',
3716
+ });
3717
+ throw err;
3718
+ }
3719
+ // Run Dynamic Flow Evaluations
3720
+ this.dynamicFlowTaskService.triggerAfterAssistantMessage(assistantMessage);
3721
+ return messageId;
3722
+ }
3379
3723
  /**
3380
3724
  * Persists the current conversation session to the database.
3381
3725
  * @param status The status of the session.
@@ -4025,11 +4369,11 @@ class ChatHeaderComponent {
4025
4369
  this.viewModeChanged.emit(newMode);
4026
4370
  }
4027
4371
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ChatHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4028
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: ChatHeaderComponent, isStandalone: true, selector: "dc-chat-header", inputs: { alternativeConversation: "alternativeConversation", agentCard: "agentCard", viewMode: "viewMode" }, outputs: { restartConversationEvent: "restartConversationEvent", showInfoEvent: "showInfoEvent", settingsClickEvent: "settingsClickEvent", viewModeChanged: "viewModeChanged" }, ngImport: i0, template: "<div class=\"chat-header\">\n <span class=\"pointer\" (click)=\"restartConversation()\">\n @if (agentCard?.name) {\n {{ agentCard.name }}\n } @else { Reiniciar conversaci\u00F3n }\n </span>\n\n @for (conversation of alternativeConversation; track conversation._id) {\n <span class=\"pointer\" (click)=\"restartConversation(conversation)\"> {{ conversation.name }} </span>\n }\n\n <div class=\"header-controls\">\n @if (userService.isAdmin()){\n <div class=\"admin-controls\">\n <i style=\"color: rgb(255, 149, 0)\" class=\"pi pi-key\"></i>\n\n <p-button variant=\"text\" [raised]=\"true\" icon=\"pi pi-id-card\" (click)=\"showInfo()\"></p-button>\n </div>\n\n }\n\n <div>\n <p-button\n variant=\"text\"\n [raised]=\"true\"\n [icon]=\"viewMode === 'chat' ? 'pi pi-tablet' : 'pi pi-comments'\"\n (click)=\"toggleViewMode()\"\n [pTooltip]=\"viewMode === 'chat' ? 'Modo Inmersivo' : 'Modo Chat'\"\n tooltipPosition=\"bottom\">\n </p-button>\n </div>\n\n <div>\n <span class=\"pointer\" (click)=\"settingsClick()\"> \u2699\uFE0F </span>\n </div>\n </div>\n</div>\n", styles: [".chat-header{display:flex;justify-content:space-between;align-items:center;width:100%}.pointer{cursor:pointer}.header-controls{font-size:large;display:flex;justify-content:space-between;gap:10px}.admin-controls{background-color:bisque;padding:2px 5px;border-radius:4px}\n"], dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i3.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }] }); }
4372
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: ChatHeaderComponent, isStandalone: true, selector: "dc-chat-header", inputs: { alternativeConversation: "alternativeConversation", agentCard: "agentCard", viewMode: "viewMode" }, outputs: { restartConversationEvent: "restartConversationEvent", showInfoEvent: "showInfoEvent", settingsClickEvent: "settingsClickEvent", viewModeChanged: "viewModeChanged" }, ngImport: i0, template: "<div class=\"chat-header\">\n <span class=\"pointer\" (click)=\"restartConversation()\">\n @if (agentCard?.name) {\n {{ agentCard.name }}\n } @else { Reiniciar conversaci\u00F3n }\n </span>\n\n @for (conversation of alternativeConversation; track conversation._id) {\n <span class=\"pointer\" (click)=\"restartConversation(conversation)\"> {{ conversation.name }} </span>\n }\n\n <div class=\"header-controls\">\n @if (userService.isAdmin()){\n <div>\n <p-button variant=\"text\" [style]=\"{'color': 'rgb(255, 149, 0)'}\" [raised]=\"true\" icon=\"pi pi-key\" (click)=\"showInfo()\" pTooltip=\"Debug Info\" tooltipPosition=\"left\"></p-button>\n </div>\n }\n\n <div>\n <p-button\n variant=\"text\"\n [raised]=\"true\"\n [icon]=\"viewMode === 'chat' ? 'pi pi-tablet' : 'pi pi-comments'\"\n (click)=\"toggleViewMode()\"\n [pTooltip]=\"viewMode === 'chat' ? 'Modo Inmersivo' : 'Modo Chat'\"\n tooltipPosition=\"left\">\n </p-button>\n </div>\n\n <div>\n <p-button variant=\"text\" [raised]=\"true\" icon=\"pi pi-cog\" (click)=\"settingsClick()\" pTooltip=\"Ajustes\" tooltipPosition=\"left\"></p-button>\n </div>\n </div>\n</div>\n", styles: [".chat-header{display:flex;justify-content:space-between;align-items:center;width:100%}.pointer{cursor:pointer}.header-controls{font-size:large;display:flex;justify-content:space-between;gap:10px}\n"], dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i3.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }] }); }
4029
4373
  }
4030
4374
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ChatHeaderComponent, decorators: [{
4031
4375
  type: Component,
4032
- args: [{ selector: 'dc-chat-header', standalone: true, imports: [ButtonModule, TooltipModule], template: "<div class=\"chat-header\">\n <span class=\"pointer\" (click)=\"restartConversation()\">\n @if (agentCard?.name) {\n {{ agentCard.name }}\n } @else { Reiniciar conversaci\u00F3n }\n </span>\n\n @for (conversation of alternativeConversation; track conversation._id) {\n <span class=\"pointer\" (click)=\"restartConversation(conversation)\"> {{ conversation.name }} </span>\n }\n\n <div class=\"header-controls\">\n @if (userService.isAdmin()){\n <div class=\"admin-controls\">\n <i style=\"color: rgb(255, 149, 0)\" class=\"pi pi-key\"></i>\n\n <p-button variant=\"text\" [raised]=\"true\" icon=\"pi pi-id-card\" (click)=\"showInfo()\"></p-button>\n </div>\n\n }\n\n <div>\n <p-button\n variant=\"text\"\n [raised]=\"true\"\n [icon]=\"viewMode === 'chat' ? 'pi pi-tablet' : 'pi pi-comments'\"\n (click)=\"toggleViewMode()\"\n [pTooltip]=\"viewMode === 'chat' ? 'Modo Inmersivo' : 'Modo Chat'\"\n tooltipPosition=\"bottom\">\n </p-button>\n </div>\n\n <div>\n <span class=\"pointer\" (click)=\"settingsClick()\"> \u2699\uFE0F </span>\n </div>\n </div>\n</div>\n", styles: [".chat-header{display:flex;justify-content:space-between;align-items:center;width:100%}.pointer{cursor:pointer}.header-controls{font-size:large;display:flex;justify-content:space-between;gap:10px}.admin-controls{background-color:bisque;padding:2px 5px;border-radius:4px}\n"] }]
4376
+ args: [{ selector: 'dc-chat-header', standalone: true, imports: [ButtonModule, TooltipModule], template: "<div class=\"chat-header\">\n <span class=\"pointer\" (click)=\"restartConversation()\">\n @if (agentCard?.name) {\n {{ agentCard.name }}\n } @else { Reiniciar conversaci\u00F3n }\n </span>\n\n @for (conversation of alternativeConversation; track conversation._id) {\n <span class=\"pointer\" (click)=\"restartConversation(conversation)\"> {{ conversation.name }} </span>\n }\n\n <div class=\"header-controls\">\n @if (userService.isAdmin()){\n <div>\n <p-button variant=\"text\" [style]=\"{'color': 'rgb(255, 149, 0)'}\" [raised]=\"true\" icon=\"pi pi-key\" (click)=\"showInfo()\" pTooltip=\"Debug Info\" tooltipPosition=\"left\"></p-button>\n </div>\n }\n\n <div>\n <p-button\n variant=\"text\"\n [raised]=\"true\"\n [icon]=\"viewMode === 'chat' ? 'pi pi-tablet' : 'pi pi-comments'\"\n (click)=\"toggleViewMode()\"\n [pTooltip]=\"viewMode === 'chat' ? 'Modo Inmersivo' : 'Modo Chat'\"\n tooltipPosition=\"left\">\n </p-button>\n </div>\n\n <div>\n <p-button variant=\"text\" [raised]=\"true\" icon=\"pi pi-cog\" (click)=\"settingsClick()\" pTooltip=\"Ajustes\" tooltipPosition=\"left\"></p-button>\n </div>\n </div>\n</div>\n", styles: [".chat-header{display:flex;justify-content:space-between;align-items:center;width:100%}.pointer{cursor:pointer}.header-controls{font-size:large;display:flex;justify-content:space-between;gap:10px}\n"] }]
4033
4377
  }], propDecorators: { alternativeConversation: [{
4034
4378
  type: Input
4035
4379
  }], agentCard: [{
@@ -4867,11 +5211,11 @@ class ChatMessageComponent {
4867
5211
  console.log(res);
4868
5212
  }
4869
5213
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ChatMessageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4870
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", 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 -->\n @if (!isUserMessage()) {\n <div class=\"avatar-container\">\n <div class=\"avatar\" (click)=\"printData()\">\n <img [src]=\"chatMessage().imgUrl\" alt=\"AI\" class=\"avatar-image\" />\n </div>\n </div>\n } @if (isUserMessage()) {\n <div class=\"avatar-container-right\" (click)=\"printData()\">\n <div class=\"avatar user-avatar\">\n <img [src]=\"chatMessage()?.imgUrl || '/defaults/avatar_user.jpg'\" alt=\"User\" class=\"avatar-image\" />\n </div>\n </div>\n }\n\n <!-- Message Bubble -->\n <div class=\"message-bubble\">\n @if (chatMessage().generatedImg) {\n <img class=\"generated-img\" [src]=\"chatMessage().generatedImg\" alt=\"Generated Image\" />\n } @if (hasMultiMessages()) {\n <dc-message-orchestrator [messages]=\"multiMessages()\" [messageRole]=\"chatMessage().role\"></dc-message-orchestrator>\n } @else {\n <dc-message-orchestrator [messages]=\"messageContentArray()\" [messageRole]=\"chatMessage().role\"></dc-message-orchestrator>\n }\n\n <!-- Translation -->\n @if (isAssistantMessage() && chatMessage().evaluation?.['text']) {\n <div class=\"translation\">\n <hr class=\"divider\" />\n\n {{ chatMessage().evaluation?.['text'] }}\n </div>\n } @if (isUserMessage() && chatMessage().evaluation) {\n <div class=\"translation\" style=\"color: white\">\n <hr class=\"divider\" />\n {{ chatMessage().evaluation?.['text'] }}\n </div>\n <div class=\"evaluation-footer\">\n <span>{{ evaluationEmoji() }}</span>\n <span class=\"pointer\" (click)=\"showEvaluation()\"> \uD83E\uDDD0 </span>\n </div>\n } @if (userService.isAdmin()) {\n <div class=\"options-footer\">\n <i #popoverTarget class=\"pi pi-ellipsis-h\" style=\"font-size: 1rem\" (click)=\"op.toggle($event)\"></i>\n <p-popover #op>\n <ul class=\"list-none p-0 m-0 flex flex-col\">\n <li class=\"flex items-center gap-2 px-2 py-3 hover:bg-emphasis cursor-pointer rounded-border\" (click)=\"generateImage()\">\n <span>Generate image</span>\n </li>\n </ul>\n </p-popover>\n </div>\n }\n </div>\n\n <!-- Tags -->\n @if (chatMessage().tags?.length) {\n <div class=\"tags\">\n @for (tag of chatMessage().tags; track tag) {\n <span class=\"tag\" [pTooltip]=\"getMoodLabel(tag)\" tooltipPosition=\"top\">{{ tag }}</span>\n }\n </div>\n }\n </div>\n</div>\n", styles: [":host{--user-message-bg: var(--chat-user-message-bg);--assistant-message-bg: var(--chat-assistant-message-bg);--user-text-color: white;--assistant-text-color: #ffffff;--avatar-user-bg: #ffa77e;--divider-color: #ffa77e;--border-radius: 18px;--avatar-size: 36px;--shadow: 0 2px 8px rgba(0, 0, 0, .15);display:block;margin-bottom:16px}.message-wrapper{display:flex;width:100%;margin-bottom:12px}.message-container{display:flex;max-width:98%;line-height:1.5;position:relative}.user-message{justify-content:flex-end}.user-message .message-bubble{background-color:var(--user-message-bg);color:var(--user-text-color);border-radius:var(--border-radius) var(--border-radius) 0 var(--border-radius);margin-left:8px;min-width:150px}.user-message dc-message-orchestrator{margin-right:19px}.assistant-message{justify-content:flex-start}.assistant-message .message-bubble{background-color:var(--assistant-message-bg);color:var(--assistant-text-color);border-radius:var(--border-radius) var(--border-radius) var(--border-radius) 0;margin-left:8px}.message-bubble{padding:9px;box-shadow:var(--shadow);max-width:98%;min-width:0;position:relative;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px)}.avatar-container,.avatar-container-right{position:absolute;bottom:-20px}.avatar-container{left:-7px;z-index:1}.avatar-container-right{right:-5px;z-index:1}.avatar{width:var(--avatar-size);height:var(--avatar-size);border-radius:50%;background-color:var(--user-message-bg);display:flex;align-items:center;justify-content:center;color:var(--user-text-color);font-weight:700;font-size:14px;overflow:hidden}.avatar-image{width:100%;height:100%;object-fit:cover}.user-avatar{background-color:var(--avatar-user-bg)}::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:#d8d8d8;font-style:italic}.divider{margin:.5rem 40px;border-top:1px solid var(--divider-color)}.evaluation-footer{position:absolute;bottom:-10px;left:20px;display:flex;align-items:center;gap:8px}.options-footer{position:absolute;bottom:5px;right:20px;display:flex;align-items:center;gap:8px}.pointer{cursor:pointer}.tags{position:absolute;top:-10px;right:15px;display:flex;gap:5px;z-index:1}.tag{font-size:16px;transition:transform .3s ease-in-out;animation:float 6s ease-in-out infinite;cursor:default}.tag:hover{transform:scale(1.2)}@keyframes float{0%{transform:translateY(0)}50%{transform:translateY(-2px)}to{transform:translateY(0)}}.generated-img{width:100%;border-radius:var(--border-radius)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: ChatMessageOrchestratorComponent, selector: "dc-message-orchestrator", inputs: ["messages", "messageRole"], outputs: ["audioCompleted"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: i2$3.Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions", "motionOptions"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i3.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
5214
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", 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 -->\n @if (!isUserMessage()) {\n <div class=\"avatar-container\">\n <div class=\"avatar\" (click)=\"printData()\">\n <img [src]=\"chatMessage().imgUrl\" alt=\"AI\" class=\"avatar-image\" />\n </div>\n </div>\n } @if (isUserMessage()) {\n <div class=\"avatar-container-right\" (click)=\"printData()\">\n <div class=\"avatar user-avatar\">\n <img [src]=\"chatMessage()?.imgUrl || '/defaults/avatar_user.jpg'\" alt=\"User\" class=\"avatar-image\" />\n </div>\n </div>\n }\n\n <!-- Message Bubble -->\n <div class=\"message-bubble\">\n @if (chatMessage().generatedImg) {\n <img class=\"generated-img\" [src]=\"chatMessage().generatedImg\" alt=\"Generated Image\" />\n } @if (hasMultiMessages()) {\n <dc-message-orchestrator [messages]=\"multiMessages()\" [messageRole]=\"chatMessage().role\"></dc-message-orchestrator>\n } @else {\n <dc-message-orchestrator [messages]=\"messageContentArray()\" [messageRole]=\"chatMessage().role\"></dc-message-orchestrator>\n }\n\n <!-- Translation -->\n @if (isAssistantMessage() && chatMessage().evaluation?.['text']) {\n <div class=\"translation\">\n <hr class=\"divider\" />\n\n {{ chatMessage().evaluation?.['text'] }}\n </div>\n } @if (isUserMessage() && chatMessage().evaluation) {\n <div class=\"translation\" style=\"color: white\">\n <hr class=\"divider\" />\n {{ chatMessage().evaluation?.['text'] }}\n </div>\n <div class=\"evaluation-footer\">\n <span>{{ evaluationEmoji() }}</span>\n <span class=\"pointer\" (click)=\"showEvaluation()\"> \uD83E\uDDD0 </span>\n </div>\n } @if (userService.isAdmin()) {\n <div class=\"options-footer\">\n <i #popoverTarget class=\"pi pi-ellipsis-h\" style=\"font-size: 1rem\" (click)=\"op.toggle($event)\"></i>\n <p-popover #op>\n <ul class=\"list-none p-0 m-0 flex flex-col\">\n <li class=\"flex items-center gap-2 px-2 py-3 hover:bg-emphasis cursor-pointer rounded-border\" (click)=\"generateImage()\">\n <span>Generate image</span>\n </li>\n </ul>\n </p-popover>\n </div>\n }\n </div>\n\n <!-- Tags -->\n @if (chatMessage().tags?.length) {\n <div class=\"tags\">\n @for (tag of chatMessage().tags; track tag) {\n <span class=\"tag\" [pTooltip]=\"getMoodLabel(tag)\" tooltipPosition=\"top\">{{ tag }}</span>\n }\n </div>\n }\n </div>\n</div>\n", styles: [":host{--user-message-bg: var(--chat-user-message-bg);--assistant-message-bg: var(--chat-assistant-message-bg);--user-text-color: white;--assistant-text-color: #ffffff;--avatar-user-bg: #ffa77e;--divider-color: #ffa77e;--border-radius: 18px;--avatar-size: 36px;--shadow: 0 2px 8px rgba(0, 0, 0, .15);display:block;margin-bottom:16px}.message-wrapper{display:flex;width:100%;margin-bottom:12px}.message-container{display:flex;max-width:98%;line-height:1.5;position:relative}.user-message{justify-content:flex-end}.user-message .message-bubble{background-color:var(--user-message-bg);color:var(--user-text-color);border-radius:var(--border-radius) var(--border-radius) 0 var(--border-radius);margin-left:8px;min-width:150px}.user-message dc-message-orchestrator{margin-right:19px}.assistant-message{justify-content:flex-start}.assistant-message .message-bubble{background-color:var(--assistant-message-bg);color:var(--assistant-text-color);border-radius:var(--border-radius) var(--border-radius) var(--border-radius) 0;margin-left:8px}.message-bubble{padding:9px;box-shadow:var(--shadow);max-width:98%;min-width:0;position:relative;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.avatar-container,.avatar-container-right{position:absolute;bottom:-20px}.avatar-container{left:-7px;z-index:1}.avatar-container-right{right:-5px;z-index:1}.avatar{width:var(--avatar-size);height:var(--avatar-size);border-radius:50%;background-color:var(--user-message-bg);display:flex;align-items:center;justify-content:center;color:var(--user-text-color);font-weight:700;font-size:14px;overflow:hidden}.avatar-image{width:100%;height:100%;object-fit:cover}.user-avatar{background-color:var(--avatar-user-bg)}::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:#d8d8d8;font-style:italic}.divider{margin:.5rem 40px;border-top:1px solid var(--divider-color)}.evaluation-footer{position:absolute;bottom:-10px;left:20px;display:flex;align-items:center;gap:8px}.options-footer{position:absolute;bottom:5px;right:20px;display:flex;align-items:center;gap:8px}.pointer{cursor:pointer}.tags{position:absolute;top:-10px;right:15px;display:flex;gap:5px;z-index:1}.tag{font-size:16px;transition:transform .3s ease-in-out;animation:float 6s ease-in-out infinite;cursor:default}.tag:hover{transform:scale(1.2)}@keyframes float{0%{transform:translateY(0)}50%{transform:translateY(-2px)}to{transform:translateY(0)}}.generated-img{width:100%;border-radius:var(--border-radius)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: ChatMessageOrchestratorComponent, selector: "dc-message-orchestrator", inputs: ["messages", "messageRole"], outputs: ["audioCompleted"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: i2$3.Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions", "motionOptions"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i3.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4871
5215
  }
4872
5216
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ChatMessageComponent, decorators: [{
4873
5217
  type: Component,
4874
- args: [{ selector: 'dc-chat-message', standalone: true, imports: [CommonModule, ChatMessageOrchestratorComponent, PopoverModule, TooltipModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"message-wrapper\" [ngClass]=\"{ 'user-message': isUserMessage(), 'assistant-message': !isUserMessage() }\">\n <div class=\"message-container\">\n <!-- Avatar -->\n @if (!isUserMessage()) {\n <div class=\"avatar-container\">\n <div class=\"avatar\" (click)=\"printData()\">\n <img [src]=\"chatMessage().imgUrl\" alt=\"AI\" class=\"avatar-image\" />\n </div>\n </div>\n } @if (isUserMessage()) {\n <div class=\"avatar-container-right\" (click)=\"printData()\">\n <div class=\"avatar user-avatar\">\n <img [src]=\"chatMessage()?.imgUrl || '/defaults/avatar_user.jpg'\" alt=\"User\" class=\"avatar-image\" />\n </div>\n </div>\n }\n\n <!-- Message Bubble -->\n <div class=\"message-bubble\">\n @if (chatMessage().generatedImg) {\n <img class=\"generated-img\" [src]=\"chatMessage().generatedImg\" alt=\"Generated Image\" />\n } @if (hasMultiMessages()) {\n <dc-message-orchestrator [messages]=\"multiMessages()\" [messageRole]=\"chatMessage().role\"></dc-message-orchestrator>\n } @else {\n <dc-message-orchestrator [messages]=\"messageContentArray()\" [messageRole]=\"chatMessage().role\"></dc-message-orchestrator>\n }\n\n <!-- Translation -->\n @if (isAssistantMessage() && chatMessage().evaluation?.['text']) {\n <div class=\"translation\">\n <hr class=\"divider\" />\n\n {{ chatMessage().evaluation?.['text'] }}\n </div>\n } @if (isUserMessage() && chatMessage().evaluation) {\n <div class=\"translation\" style=\"color: white\">\n <hr class=\"divider\" />\n {{ chatMessage().evaluation?.['text'] }}\n </div>\n <div class=\"evaluation-footer\">\n <span>{{ evaluationEmoji() }}</span>\n <span class=\"pointer\" (click)=\"showEvaluation()\"> \uD83E\uDDD0 </span>\n </div>\n } @if (userService.isAdmin()) {\n <div class=\"options-footer\">\n <i #popoverTarget class=\"pi pi-ellipsis-h\" style=\"font-size: 1rem\" (click)=\"op.toggle($event)\"></i>\n <p-popover #op>\n <ul class=\"list-none p-0 m-0 flex flex-col\">\n <li class=\"flex items-center gap-2 px-2 py-3 hover:bg-emphasis cursor-pointer rounded-border\" (click)=\"generateImage()\">\n <span>Generate image</span>\n </li>\n </ul>\n </p-popover>\n </div>\n }\n </div>\n\n <!-- Tags -->\n @if (chatMessage().tags?.length) {\n <div class=\"tags\">\n @for (tag of chatMessage().tags; track tag) {\n <span class=\"tag\" [pTooltip]=\"getMoodLabel(tag)\" tooltipPosition=\"top\">{{ tag }}</span>\n }\n </div>\n }\n </div>\n</div>\n", styles: [":host{--user-message-bg: var(--chat-user-message-bg);--assistant-message-bg: var(--chat-assistant-message-bg);--user-text-color: white;--assistant-text-color: #ffffff;--avatar-user-bg: #ffa77e;--divider-color: #ffa77e;--border-radius: 18px;--avatar-size: 36px;--shadow: 0 2px 8px rgba(0, 0, 0, .15);display:block;margin-bottom:16px}.message-wrapper{display:flex;width:100%;margin-bottom:12px}.message-container{display:flex;max-width:98%;line-height:1.5;position:relative}.user-message{justify-content:flex-end}.user-message .message-bubble{background-color:var(--user-message-bg);color:var(--user-text-color);border-radius:var(--border-radius) var(--border-radius) 0 var(--border-radius);margin-left:8px;min-width:150px}.user-message dc-message-orchestrator{margin-right:19px}.assistant-message{justify-content:flex-start}.assistant-message .message-bubble{background-color:var(--assistant-message-bg);color:var(--assistant-text-color);border-radius:var(--border-radius) var(--border-radius) var(--border-radius) 0;margin-left:8px}.message-bubble{padding:9px;box-shadow:var(--shadow);max-width:98%;min-width:0;position:relative;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px)}.avatar-container,.avatar-container-right{position:absolute;bottom:-20px}.avatar-container{left:-7px;z-index:1}.avatar-container-right{right:-5px;z-index:1}.avatar{width:var(--avatar-size);height:var(--avatar-size);border-radius:50%;background-color:var(--user-message-bg);display:flex;align-items:center;justify-content:center;color:var(--user-text-color);font-weight:700;font-size:14px;overflow:hidden}.avatar-image{width:100%;height:100%;object-fit:cover}.user-avatar{background-color:var(--avatar-user-bg)}::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:#d8d8d8;font-style:italic}.divider{margin:.5rem 40px;border-top:1px solid var(--divider-color)}.evaluation-footer{position:absolute;bottom:-10px;left:20px;display:flex;align-items:center;gap:8px}.options-footer{position:absolute;bottom:5px;right:20px;display:flex;align-items:center;gap:8px}.pointer{cursor:pointer}.tags{position:absolute;top:-10px;right:15px;display:flex;gap:5px;z-index:1}.tag{font-size:16px;transition:transform .3s ease-in-out;animation:float 6s ease-in-out infinite;cursor:default}.tag:hover{transform:scale(1.2)}@keyframes float{0%{transform:translateY(0)}50%{transform:translateY(-2px)}to{transform:translateY(0)}}.generated-img{width:100%;border-radius:var(--border-radius)}\n"] }]
5218
+ args: [{ selector: 'dc-chat-message', standalone: true, imports: [CommonModule, ChatMessageOrchestratorComponent, PopoverModule, TooltipModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"message-wrapper\" [ngClass]=\"{ 'user-message': isUserMessage(), 'assistant-message': !isUserMessage() }\">\n <div class=\"message-container\">\n <!-- Avatar -->\n @if (!isUserMessage()) {\n <div class=\"avatar-container\">\n <div class=\"avatar\" (click)=\"printData()\">\n <img [src]=\"chatMessage().imgUrl\" alt=\"AI\" class=\"avatar-image\" />\n </div>\n </div>\n } @if (isUserMessage()) {\n <div class=\"avatar-container-right\" (click)=\"printData()\">\n <div class=\"avatar user-avatar\">\n <img [src]=\"chatMessage()?.imgUrl || '/defaults/avatar_user.jpg'\" alt=\"User\" class=\"avatar-image\" />\n </div>\n </div>\n }\n\n <!-- Message Bubble -->\n <div class=\"message-bubble\">\n @if (chatMessage().generatedImg) {\n <img class=\"generated-img\" [src]=\"chatMessage().generatedImg\" alt=\"Generated Image\" />\n } @if (hasMultiMessages()) {\n <dc-message-orchestrator [messages]=\"multiMessages()\" [messageRole]=\"chatMessage().role\"></dc-message-orchestrator>\n } @else {\n <dc-message-orchestrator [messages]=\"messageContentArray()\" [messageRole]=\"chatMessage().role\"></dc-message-orchestrator>\n }\n\n <!-- Translation -->\n @if (isAssistantMessage() && chatMessage().evaluation?.['text']) {\n <div class=\"translation\">\n <hr class=\"divider\" />\n\n {{ chatMessage().evaluation?.['text'] }}\n </div>\n } @if (isUserMessage() && chatMessage().evaluation) {\n <div class=\"translation\" style=\"color: white\">\n <hr class=\"divider\" />\n {{ chatMessage().evaluation?.['text'] }}\n </div>\n <div class=\"evaluation-footer\">\n <span>{{ evaluationEmoji() }}</span>\n <span class=\"pointer\" (click)=\"showEvaluation()\"> \uD83E\uDDD0 </span>\n </div>\n } @if (userService.isAdmin()) {\n <div class=\"options-footer\">\n <i #popoverTarget class=\"pi pi-ellipsis-h\" style=\"font-size: 1rem\" (click)=\"op.toggle($event)\"></i>\n <p-popover #op>\n <ul class=\"list-none p-0 m-0 flex flex-col\">\n <li class=\"flex items-center gap-2 px-2 py-3 hover:bg-emphasis cursor-pointer rounded-border\" (click)=\"generateImage()\">\n <span>Generate image</span>\n </li>\n </ul>\n </p-popover>\n </div>\n }\n </div>\n\n <!-- Tags -->\n @if (chatMessage().tags?.length) {\n <div class=\"tags\">\n @for (tag of chatMessage().tags; track tag) {\n <span class=\"tag\" [pTooltip]=\"getMoodLabel(tag)\" tooltipPosition=\"top\">{{ tag }}</span>\n }\n </div>\n }\n </div>\n</div>\n", styles: [":host{--user-message-bg: var(--chat-user-message-bg);--assistant-message-bg: var(--chat-assistant-message-bg);--user-text-color: white;--assistant-text-color: #ffffff;--avatar-user-bg: #ffa77e;--divider-color: #ffa77e;--border-radius: 18px;--avatar-size: 36px;--shadow: 0 2px 8px rgba(0, 0, 0, .15);display:block;margin-bottom:16px}.message-wrapper{display:flex;width:100%;margin-bottom:12px}.message-container{display:flex;max-width:98%;line-height:1.5;position:relative}.user-message{justify-content:flex-end}.user-message .message-bubble{background-color:var(--user-message-bg);color:var(--user-text-color);border-radius:var(--border-radius) var(--border-radius) 0 var(--border-radius);margin-left:8px;min-width:150px}.user-message dc-message-orchestrator{margin-right:19px}.assistant-message{justify-content:flex-start}.assistant-message .message-bubble{background-color:var(--assistant-message-bg);color:var(--assistant-text-color);border-radius:var(--border-radius) var(--border-radius) var(--border-radius) 0;margin-left:8px}.message-bubble{padding:9px;box-shadow:var(--shadow);max-width:98%;min-width:0;position:relative;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.avatar-container,.avatar-container-right{position:absolute;bottom:-20px}.avatar-container{left:-7px;z-index:1}.avatar-container-right{right:-5px;z-index:1}.avatar{width:var(--avatar-size);height:var(--avatar-size);border-radius:50%;background-color:var(--user-message-bg);display:flex;align-items:center;justify-content:center;color:var(--user-text-color);font-weight:700;font-size:14px;overflow:hidden}.avatar-image{width:100%;height:100%;object-fit:cover}.user-avatar{background-color:var(--avatar-user-bg)}::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:#d8d8d8;font-style:italic}.divider{margin:.5rem 40px;border-top:1px solid var(--divider-color)}.evaluation-footer{position:absolute;bottom:-10px;left:20px;display:flex;align-items:center;gap:8px}.options-footer{position:absolute;bottom:5px;right:20px;display:flex;align-items:center;gap:8px}.pointer{cursor:pointer}.tags{position:absolute;top:-10px;right:15px;display:flex;gap:5px;z-index:1}.tag{font-size:16px;transition:transform .3s ease-in-out;animation:float 6s ease-in-out infinite;cursor:default}.tag:hover{transform:scale(1.2)}@keyframes float{0%{transform:translateY(0)}50%{transform:translateY(-2px)}to{transform:translateY(0)}}.generated-img{width:100%;border-radius:var(--border-radius)}\n"] }]
4875
5219
  }], propDecorators: { chatMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "chatMessage", required: true }] }], chatUserSettings: [{ type: i0.Input, args: [{ isSignal: true, alias: "chatUserSettings", required: false }] }] } });
4876
5220
 
4877
5221
  class ChatMessagesListComponent {
@@ -5300,17 +5644,25 @@ class DcImmersiveChatComponent {
5300
5644
  }, ...(ngDevMode ? [{ debugName: "lastMessage" }] : /* istanbul ignore next */ []));
5301
5645
  this.isThinking = this.conversationService.isThinking();
5302
5646
  this.orchestratedMessageId = null;
5647
+ this.orchestratedSegmentsCount = 0;
5303
5648
  // Effect to start orchestration for new assistant messages
5304
5649
  effect(() => {
5305
5650
  const messages = this.messagesStateService.getMessagesSignal()();
5306
5651
  if (messages.length > 0) {
5307
5652
  const lastMsg = messages[messages.length - 1];
5308
- if (lastMsg.role === ChatRole.Assistant && lastMsg.messageId !== this.orchestratedMessageId) {
5309
- this.orchestratedMessageId = lastMsg.messageId || null;
5310
- if (lastMsg.multiMessages && lastMsg.multiMessages.length > 0) {
5311
- // If the last message is assistant and has multiMessages, start orchestration
5312
- // Note: MessageOrchestrationService handles sequential playback and prevents redundant starts
5313
- this.orchestration.startOrchestration(lastMsg.multiMessages, lastMsg.role);
5653
+ if (lastMsg.role === ChatRole.Assistant) {
5654
+ const isNewMessage = lastMsg.messageId !== this.orchestratedMessageId;
5655
+ const segmentCount = lastMsg.multiMessages?.length || 0;
5656
+ const hasNewSegments = segmentCount > this.orchestratedSegmentsCount;
5657
+ if (isNewMessage || hasNewSegments) {
5658
+ if (isNewMessage) {
5659
+ this.orchestratedMessageId = lastMsg.messageId || null;
5660
+ this.orchestratedSegmentsCount = 0;
5661
+ }
5662
+ if (lastMsg.multiMessages && lastMsg.multiMessages.length > 0) {
5663
+ this.orchestratedSegmentsCount = lastMsg.multiMessages.length;
5664
+ this.orchestration.startOrchestration(lastMsg.multiMessages, lastMsg.role);
5665
+ }
5314
5666
  }
5315
5667
  }
5316
5668
  }
@@ -5419,6 +5771,76 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
5419
5771
  `, styles: [":host{height:100%}.immersive-container{display:flex;flex-direction:column;height:100%;width:100%;background:radial-gradient(circle at center,#1e1e2d33,#0a0a0f1a);padding:2rem;box-sizing:border-box;overflow:hidden}.hud-section{flex:1;display:flex;flex-direction:column;align-items:center;width:100%;overflow-y:auto;min-height:0;padding:1rem 1.5rem;scrollbar-width:none}.hud-section::-webkit-scrollbar{display:none}.hud-section>div{margin:auto 0;width:100%;display:flex;flex-direction:column}.mic-section{flex-shrink:0;position:relative;height:180px;display:flex;align-items:center;justify-content:center;margin-top:1rem;padding-bottom:2rem}.mic-ripple-glow{position:absolute;width:140px;height:140px;border-radius:50%;background:radial-gradient(circle,rgba(64,156,255,.2) 0%,transparent 70%);animation:breathe 4s ease-in-out infinite;z-index:0}.mic-section.is-talking .mic-ripple-glow{background:radial-gradient(circle,rgba(64,255,156,.3) 0%,transparent 70%);animation:pulse-active 1.5s ease-in-out infinite}.mic-section dc-mic{z-index:1;transform:scale(1.5);transition:transform .3s cubic-bezier(.175,.885,.32,1.275)}.mic-section dc-mic:hover{transform:scale(1.6)}.active-sentence-hud{max-width:1000px;width:100%;transition:all .5s cubic-bezier(.4,0,.2,1);text-shadow:0 10px 30px rgba(0,0,0,.5);animation:fadeIn .8s ease-out}.active-sentence-hud ::ng-deep .audio-text-sync-container{background:transparent!important;padding:0!important;justify-content:center}.active-sentence-hud ::ng-deep .play-button{display:none!important}.active-sentence-hud ::ng-deep .text-content{font-size:clamp(1.8rem,6vw,3.5rem);font-weight:700;text-align:center;line-height:1.2;color:#ffffffe6;margin:0;letter-spacing:-.02em}.active-sentence-hud ::ng-deep .highlight{background:transparent!important;color:#fff;text-shadow:0 0 20px rgba(255,255,255,.8),0 0 40px rgba(64,156,255,.4);filter:brightness(1.2)}.user-talking-indicator,.idle-indicator,.last-message-hud,.thinking-indicator{font-size:1.8rem;color:#fff;opacity:.7;font-weight:300;text-align:center;max-width:800px;line-height:1.4}.thinking-indicator{animation:pulse-thinking 2s infinite ease-in-out}@keyframes pulse-thinking{0%,to{opacity:.5;transform:scale(.98)}50%{opacity:.9;transform:scale(1.02)}}.idle-indicator p{background:linear-gradient(90deg,transparent,rgba(255,255,255,.1),transparent);padding:1rem 2rem;border-radius:50px}@keyframes breathe{0%,to{transform:scale(1);opacity:.2}50%{transform:scale(1.2);opacity:.4}}@keyframes pulse-active{0%{transform:scale(1);opacity:.5;box-shadow:0 0 #40ff9c66}70%{transform:scale(1.5);opacity:0;box-shadow:0 0 0 40px transparent}to{transform:scale(1);opacity:0}}@keyframes fadeIn{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}\n"] }]
5420
5772
  }], ctorParameters: () => [], propDecorators: { micSettings: [{ type: i0.Input, args: [{ isSignal: true, alias: "micSettings", required: false }] }] } });
5421
5773
 
5774
+ class PolitoNotificationComponent {
5775
+ constructor() {
5776
+ this.flowStateService = inject(ConversationFlowStateService);
5777
+ this.agentCardStateService = inject(AgentCardStateService);
5778
+ this.notification = signal(null, ...(ngDevMode ? [{ debugName: "notification" }] : /* istanbul ignore next */ []));
5779
+ this.isHiding = signal(false, ...(ngDevMode ? [{ debugName: "isHiding" }] : /* istanbul ignore next */ []));
5780
+ this.subscription = new Subscription();
5781
+ }
5782
+ ngOnInit() {
5783
+ this.subscription.add(this.flowStateService.goalEvaluationUpdated$.subscribe((evalData) => {
5784
+ if (evalData.deltaPoints !== undefined && evalData.deltaPoints !== 0) {
5785
+ this.showNotification(evalData.deltaPoints, evalData.feedback || '');
5786
+ }
5787
+ }));
5788
+ }
5789
+ ngOnDestroy() {
5790
+ this.subscription.unsubscribe();
5791
+ this.clearTimeouts();
5792
+ }
5793
+ showNotification(points, feedback) {
5794
+ // Clear any pending timeouts to restart timing on new updates
5795
+ this.clearTimeouts();
5796
+ this.isHiding.set(false);
5797
+ this.notification.set({ points, feedback });
5798
+ // Transition out starts after 4.5 seconds
5799
+ this.hideTimeout = setTimeout(() => {
5800
+ this.isHiding.set(true);
5801
+ // Wait for CSS fade-out animation (400ms) to complete before removing element
5802
+ this.animTimeout = setTimeout(() => {
5803
+ this.notification.set(null);
5804
+ this.isHiding.set(false);
5805
+ }, 400);
5806
+ }, 4500);
5807
+ }
5808
+ clearTimeouts() {
5809
+ if (this.hideTimeout) {
5810
+ clearTimeout(this.hideTimeout);
5811
+ this.hideTimeout = null;
5812
+ }
5813
+ if (this.animTimeout) {
5814
+ clearTimeout(this.animTimeout);
5815
+ this.animTimeout = null;
5816
+ }
5817
+ }
5818
+ getPointsText(points) {
5819
+ const lang = this.agentCardStateService.agentCard$()?.lang || 'en';
5820
+ const isEs = lang.toLowerCase().startsWith('es');
5821
+ if (points >= 0) {
5822
+ return `+${points} ${isEs ? 'Puntos' : 'Points'}!`;
5823
+ }
5824
+ else {
5825
+ return `${points} ${isEs ? 'Puntos' : 'Points'}`;
5826
+ }
5827
+ }
5828
+ getFeatherPointsText(points) {
5829
+ if (points >= 0) {
5830
+ return `+${points}`;
5831
+ }
5832
+ else {
5833
+ return `${points}`;
5834
+ }
5835
+ }
5836
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: PolitoNotificationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5837
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: PolitoNotificationComponent, isStandalone: true, selector: "dc-polito-notification", ngImport: i0, template: "@if (notification()) {\n <div class=\"polito-notification-wrapper\" [class.hiding]=\"isHiding()\">\n <div class=\"polito-card\">\n <!-- Polito Avatar (Salmon Flamingo) -->\n <div class=\"polito-avatar-container\">\n <svg viewBox=\"0 0 100 100\" class=\"polito-avatar-svg\" xmlns=\"http://www.w3.org/2000/svg\">\n <!-- Background circle soft glow -->\n <circle cx=\"50\" cy=\"50\" r=\"46\" fill=\"url(#bgGrad)\" />\n \n <!-- Flamingo Neck & Head -->\n <path d=\"M 42,82 C 42,57 52,47 62,42 C 72,37 77,27 72,17 C 67,7 52,10 47,22 C 44,28 45,34 42,37 C 39,40 32,37 27,40 C 22,42 20,47 24,50 C 28,52 34,47 40,47\" \n fill=\"none\" \n stroke=\"url(#flamingoGrad)\" \n stroke-width=\"12\" \n stroke-linecap=\"round\" \n stroke-linejoin=\"round\"/>\n \n <!-- Beak -->\n <path d=\"M 24,40 C 21,42 19,45 21,48 C 23,50 26,49 28,47 Z\" fill=\"#1C1917\"/>\n <path d=\"M 28,47 C 30,45 33,44 33,42 C 31,42 29,43 28,44\" fill=\"#FFFFFF\"/>\n \n <!-- Eye -->\n <circle cx=\"59\" cy=\"18\" r=\"2.5\" fill=\"#1C1917\"/>\n \n <!-- Cheek Blush -->\n <circle cx=\"63\" cy=\"24\" r=\"4.5\" fill=\"#FF5252\" opacity=\"0.45\"/>\n \n <defs>\n <linearGradient id=\"bgGrad\" x1=\"0%\" y1=\"0%\" x2=\"100%\" y2=\"100%\">\n <stop offset=\"0%\" stop-color=\"#FFE4E6\" />\n <stop offset=\"100%\" stop-color=\"#FECDD3\" />\n </linearGradient>\n <linearGradient id=\"flamingoGrad\" x1=\"0%\" y1=\"100%\" x2=\"100%\" y2=\"0%\">\n <stop offset=\"0%\" stop-color=\"#F43F5E\" />\n <stop offset=\"50%\" stop-color=\"#FDA4AF\" />\n <stop offset=\"100%\" stop-color=\"#FFE4E6\" />\n </linearGradient>\n </defs>\n </svg>\n </div>\n\n <!-- Content Area -->\n <div class=\"polito-content\">\n <div class=\"polito-header\">\n <span class=\"polito-name\">Polito</span>\n \n <!-- Points Badge -->\n <div class=\"polito-badge\" [class.negative]=\"notification()!.points < 0\">\n <!-- Salmon Feather Icon -->\n <svg viewBox=\"0 0 24 24\" class=\"feather-svg\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M19.5 4.5C18.5 3.5 16 3 13 4.5C10 6 7.5 9 6.5 11C5.5 13 4.5 16 4 19.5C5.5 19 8.5 18 10.5 17C12.5 16 15.5 13.5 17 10.5C18.5 7.5 18 5 19.5 4.5Z\" \n fill=\"url(#featherBadgeGrad)\" />\n <path d=\"M4 19.5C5.5 18.5 8.5 14.5 13 10.5\" \n stroke=\"url(#featherLineGrad)\" \n stroke-width=\"1.5\" \n stroke-linecap=\"round\" />\n <defs>\n <linearGradient id=\"featherBadgeGrad\" x1=\"4\" y1=\"19.5\" x2=\"19.5\" y2=\"4.5\" gradientUnits=\"userSpaceOnUse\">\n <stop offset=\"0%\" stop-color=\"#FDA4AF\" />\n <stop offset=\"100%\" stop-color=\"#E11D48\" />\n </linearGradient>\n <linearGradient id=\"featherLineGrad\" x1=\"4\" y1=\"19.5\" x2=\"13\" y2=\"10.5\" gradientUnits=\"userSpaceOnUse\">\n <stop offset=\"0%\" stop-color=\"#FFE4E6\" />\n <stop offset=\"100%\" stop-color=\"#F43F5E\" />\n </linearGradient>\n </defs>\n </svg>\n <span class=\"points-text\">{{ getPointsText(notification()!.points) }}</span>\n </div>\n </div>\n\n <!-- Speech bubble/feedback -->\n @if (notification()!.feedback) {\n <div class=\"polito-speech-bubble\">\n <p>{{ notification()!.feedback }}</p>\n </div>\n }\n </div>\n </div>\n </div>\n\n <!-- Falling Feather Animation Overlay -->\n <div class=\"polito-falling-feather-container\" [class.negative]=\"notification()!.points < 0\">\n <div class=\"feather-wrapper-sway\">\n <svg class=\"falling-feather-svg\" viewBox=\"0 0 100 100\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <defs>\n <!-- Positive gradient: beautiful pink-rose -->\n <linearGradient id=\"featherGradPos\" x1=\"0%\" y1=\"100%\" x2=\"100%\" y2=\"0%\">\n <stop offset=\"0%\" stop-color=\"#F43F5E\" stop-opacity=\"0.85\" />\n <stop offset=\"50%\" stop-color=\"#FDA4AF\" stop-opacity=\"0.9\" />\n <stop offset=\"100%\" stop-color=\"#FFE4E6\" stop-opacity=\"0.95\" />\n </linearGradient>\n <!-- Negative gradient: cool grey/blue -->\n <linearGradient id=\"featherGradNeg\" x1=\"0%\" y1=\"100%\" x2=\"100%\" y2=\"0%\">\n <stop offset=\"0%\" stop-color=\"#6B7280\" stop-opacity=\"0.85\" />\n <stop offset=\"50%\" stop-color=\"#9CA3AF\" stop-opacity=\"0.9\" />\n <stop offset=\"100%\" stop-color=\"#E5E7EB\" stop-opacity=\"0.95\" />\n </linearGradient>\n <!-- Rachis/spine line gradient -->\n <linearGradient id=\"rachisGrad\" x1=\"0%\" y1=\"100%\" x2=\"100%\" y2=\"0%\">\n <stop offset=\"0%\" stop-color=\"#ffffff\" stop-opacity=\"0.8\" />\n <stop offset=\"100%\" stop-color=\"#ffffff\" stop-opacity=\"0.2\" />\n </linearGradient>\n </defs>\n\n <!-- Main feather shape (Vane) -->\n <path d=\"M 50 90 C 40 85, 20 75, 20 50 C 20 30, 42 20, 50 10 C 50 10, 47 30, 45 45 C 43 60, 46 75, 50 90 Z\" \n fill=\"url(#featherGradPos)\" class=\"feather-vane-pos\" />\n <path d=\"M 50 90 C 60 85, 80 75, 80 50 C 80 30, 58 20, 50 10 C 50 10, 53 30, 55 45 C 57 60, 54 75, 50 90 Z\" \n fill=\"url(#featherGradPos)\" class=\"feather-vane-pos\" />\n\n <path d=\"M 50 90 C 40 85, 20 75, 20 50 C 20 30, 42 20, 50 10 C 50 10, 47 30, 45 45 C 43 60, 46 75, 50 90 Z\" \n fill=\"url(#featherGradNeg)\" class=\"feather-vane-neg\" />\n <path d=\"M 50 90 C 60 85, 80 75, 80 50 C 80 30, 58 20, 50 10 C 50 10, 53 30, 55 45 C 57 60, 54 75, 50 90 Z\" \n fill=\"url(#featherGradNeg)\" class=\"feather-vane-neg\" />\n\n <!-- Rachis/spine (the middle stem) -->\n <path d=\"M 50 92 L 50 10\" stroke=\"url(#rachisGrad)\" stroke-width=\"2.5\" stroke-linecap=\"round\" />\n\n <!-- Fine barb lines for feather texture -->\n <path d=\"M 50 75 Q 35 70, 25 65\" stroke=\"#ffffff\" stroke-width=\"1.2\" opacity=\"0.35\" stroke-linecap=\"round\" />\n <path d=\"M 50 60 Q 32 55, 22 45\" stroke=\"#ffffff\" stroke-width=\"1.2\" opacity=\"0.35\" stroke-linecap=\"round\" />\n <path d=\"M 50 45 Q 35 38, 28 28\" stroke=\"#ffffff\" stroke-width=\"1.2\" opacity=\"0.35\" stroke-linecap=\"round\" />\n \n <path d=\"M 50 75 Q 65 70, 75 65\" stroke=\"#ffffff\" stroke-width=\"1.2\" opacity=\"0.35\" stroke-linecap=\"round\" />\n <path d=\"M 50 60 Q 68 55, 78 45\" stroke=\"#ffffff\" stroke-width=\"1.2\" opacity=\"0.35\" stroke-linecap=\"round\" />\n <path d=\"M 50 45 Q 65 38, 72 28\" stroke=\"#ffffff\" stroke-width=\"1.2\" opacity=\"0.35\" stroke-linecap=\"round\" />\n </svg>\n <div class=\"falling-feather-points\">\n {{ getFeatherPointsText(notification()!.points) }}\n </div>\n </div>\n </div>\n}\n", styles: ["@keyframes bomp-in{0%{transform:scale(.4) translateY(40px);opacity:0}50%{transform:scale(1.08) translateY(-8px)}75%{transform:scale(.96) translateY(3px)}to{transform:scale(1) translateY(0);opacity:1}}@keyframes bomp-out{0%{transform:scale(1) translateY(0);opacity:1}to{transform:scale(.85) translateY(20px);opacity:0}}.polito-notification-wrapper{position:absolute;bottom:80px;right:16px;z-index:999;max-width:320px;width:calc(100% - 32px);pointer-events:none;display:flex;flex-direction:column;animation:bomp-in .45s cubic-bezier(.34,1.56,.64,1) forwards}.polito-notification-wrapper.hiding{animation:bomp-out .35s cubic-bezier(.25,1,.5,1) forwards}.polito-card{pointer-events:auto;display:flex;gap:12px;padding:14px 16px;border-radius:20px;background:#ffffffd9;backdrop-filter:blur(16px) saturate(180%);-webkit-backdrop-filter:blur(16px) saturate(180%);border:1px solid rgba(255,255,255,.45);box-shadow:0 10px 30px -5px #f43f5e1a,0 20px 40px -10px #00000014,0 1px 3px #0000000a;transition:transform .2s ease,box-shadow .2s ease}.polito-card:hover{transform:translateY(-2px);box-shadow:0 12px 35px -5px #f43f5e26,0 22px 45px -10px #0000001a,0 1px 4px #0000000a}.polito-avatar-container{flex-shrink:0;width:44px;height:44px;border-radius:50%;overflow:hidden;box-shadow:0 4px 12px #f43f5e33;border:2px solid #ffffff}.polito-avatar-svg{width:100%;height:100%;display:block}.polito-content{flex:1;display:flex;flex-direction:column}.polito-header{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:4px}.polito-name{font-weight:700;font-size:.95rem;color:#1c1917;letter-spacing:-.2px}.polito-badge{display:inline-flex;align-items:center;gap:4px;padding:4px 8px;border-radius:12px;background:#fee4e6b3;border:1px solid rgba(251,113,133,.3);color:#e11d48;font-size:.78rem;font-weight:700}.polito-badge .feather-svg{width:14px;height:14px;flex-shrink:0}.polito-badge.negative{background:#f5f5f7b3;border-color:#0000001a;color:#4b5563}.polito-speech-bubble{position:relative;margin-top:6px;padding:8px 12px;border-radius:12px;background:#fff;border:1px solid rgba(229,231,235,.8);box-shadow:0 4px 12px #00000008}.polito-speech-bubble p{margin:0;font-size:.82rem;line-height:1.35;color:#4b5563;font-weight:450}.polito-speech-bubble:before{content:\"\";position:absolute;top:12px;left:-6px;width:10px;height:10px;background:#fff;border-left:1px solid rgba(229,231,235,.8);border-bottom:1px solid rgba(229,231,235,.8);transform:rotate(45deg)}@media(prefers-color-scheme:dark){.polito-card{background:#1e1e24d9;border-color:#ffffff1a;box-shadow:0 10px 30px -5px #f43f5e26,0 20px 40px -10px #0006,0 1px 3px #0000004d}.polito-card:hover{box-shadow:0 12px 35px -5px #f43f5e33,0 22px 45px -10px #00000080,0 1px 4px #0000004d}.polito-name{color:#f5f5f7}.polito-badge{background:#f43f5e26;border-color:#f43f5e4d;color:#fda4af}.polito-badge.negative{background:#ffffff0d;border-color:#ffffff1a;color:#9ca3af}.polito-speech-bubble{background:#27272a;border-color:#ffffff0f;box-shadow:0 4px 12px #0003}.polito-speech-bubble p{color:#d1d5db}.polito-speech-bubble:before{background:#27272a;border-left-color:#ffffff0f;border-bottom-color:#ffffff0f}.polito-avatar-container{border-color:#27272a}}@media(max-width:480px){.polito-notification-wrapper{right:8px;bottom:72px;width:calc(100% - 16px);max-width:none}}@keyframes feather-fall{0%{transform:translateY(-100px);opacity:0}12%{opacity:1}85%{opacity:1}to{transform:translateY(75vh);opacity:0}}@keyframes feather-sway{0%,to{transform:translate(-35px) rotate(-16deg)}50%{transform:translate(35px) rotate(16deg)}}.polito-falling-feather-container{position:absolute;top:0;right:120px;width:90px;height:90px;pointer-events:none;z-index:1000;animation:feather-fall 4.2s cubic-bezier(.33,1,.68,1) forwards}.polito-falling-feather-container .falling-feather-svg{width:100%;height:100%;filter:drop-shadow(0 6px 12px rgba(244,63,94,.25))}.polito-falling-feather-container .feather-vane-pos{display:block}.polito-falling-feather-container .feather-vane-neg{display:none}.polito-falling-feather-container .feather-wrapper-sway{position:relative;width:100%;height:100%;animation:feather-sway 2.2s ease-in-out infinite}.polito-falling-feather-container .falling-feather-points{position:absolute;top:48%;left:50%;transform:translate(-50%,-50%);font-size:1.4rem;font-weight:900;color:#fff;letter-spacing:-.5px;text-shadow:0 2px 5px rgba(0,0,0,.3),-2px -2px 0 #e11d48,2px -2px 0 #e11d48,-2px 2px 0 #e11d48,2px 2px 0 #e11d48;white-space:nowrap;-webkit-user-select:none;user-select:none}.polito-falling-feather-container.negative .falling-feather-svg{filter:drop-shadow(0 6px 12px rgba(107,114,128,.25))}.polito-falling-feather-container.negative .feather-vane-pos{display:none}.polito-falling-feather-container.negative .feather-vane-neg{display:block}.polito-falling-feather-container.negative .falling-feather-points{text-shadow:0 2px 5px rgba(0,0,0,.3),-2px -2px 0 #4b5563,2px -2px 0 #4b5563,-2px 2px 0 #4b5563,2px 2px 0 #4b5563}@media(prefers-color-scheme:dark){.polito-falling-feather-container .falling-feather-svg{filter:drop-shadow(0 8px 16px rgba(244,63,94,.35))}.polito-falling-feather-container.negative .falling-feather-svg{filter:drop-shadow(0 8px 16px rgba(0,0,0,.4))}}@media(max-width:480px){.polito-falling-feather-container{right:auto;left:calc(50% - 45px)}@keyframes mobile-feather-sway{0%,to{transform:translate(-25px) rotate(-12deg)}50%{transform:translate(25px) rotate(12deg)}}.polito-falling-feather-container .feather-wrapper-sway{animation-name:mobile-feather-sway}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
5838
+ }
5839
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: PolitoNotificationComponent, decorators: [{
5840
+ type: Component,
5841
+ args: [{ selector: 'dc-polito-notification', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (notification()) {\n <div class=\"polito-notification-wrapper\" [class.hiding]=\"isHiding()\">\n <div class=\"polito-card\">\n <!-- Polito Avatar (Salmon Flamingo) -->\n <div class=\"polito-avatar-container\">\n <svg viewBox=\"0 0 100 100\" class=\"polito-avatar-svg\" xmlns=\"http://www.w3.org/2000/svg\">\n <!-- Background circle soft glow -->\n <circle cx=\"50\" cy=\"50\" r=\"46\" fill=\"url(#bgGrad)\" />\n \n <!-- Flamingo Neck & Head -->\n <path d=\"M 42,82 C 42,57 52,47 62,42 C 72,37 77,27 72,17 C 67,7 52,10 47,22 C 44,28 45,34 42,37 C 39,40 32,37 27,40 C 22,42 20,47 24,50 C 28,52 34,47 40,47\" \n fill=\"none\" \n stroke=\"url(#flamingoGrad)\" \n stroke-width=\"12\" \n stroke-linecap=\"round\" \n stroke-linejoin=\"round\"/>\n \n <!-- Beak -->\n <path d=\"M 24,40 C 21,42 19,45 21,48 C 23,50 26,49 28,47 Z\" fill=\"#1C1917\"/>\n <path d=\"M 28,47 C 30,45 33,44 33,42 C 31,42 29,43 28,44\" fill=\"#FFFFFF\"/>\n \n <!-- Eye -->\n <circle cx=\"59\" cy=\"18\" r=\"2.5\" fill=\"#1C1917\"/>\n \n <!-- Cheek Blush -->\n <circle cx=\"63\" cy=\"24\" r=\"4.5\" fill=\"#FF5252\" opacity=\"0.45\"/>\n \n <defs>\n <linearGradient id=\"bgGrad\" x1=\"0%\" y1=\"0%\" x2=\"100%\" y2=\"100%\">\n <stop offset=\"0%\" stop-color=\"#FFE4E6\" />\n <stop offset=\"100%\" stop-color=\"#FECDD3\" />\n </linearGradient>\n <linearGradient id=\"flamingoGrad\" x1=\"0%\" y1=\"100%\" x2=\"100%\" y2=\"0%\">\n <stop offset=\"0%\" stop-color=\"#F43F5E\" />\n <stop offset=\"50%\" stop-color=\"#FDA4AF\" />\n <stop offset=\"100%\" stop-color=\"#FFE4E6\" />\n </linearGradient>\n </defs>\n </svg>\n </div>\n\n <!-- Content Area -->\n <div class=\"polito-content\">\n <div class=\"polito-header\">\n <span class=\"polito-name\">Polito</span>\n \n <!-- Points Badge -->\n <div class=\"polito-badge\" [class.negative]=\"notification()!.points < 0\">\n <!-- Salmon Feather Icon -->\n <svg viewBox=\"0 0 24 24\" class=\"feather-svg\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M19.5 4.5C18.5 3.5 16 3 13 4.5C10 6 7.5 9 6.5 11C5.5 13 4.5 16 4 19.5C5.5 19 8.5 18 10.5 17C12.5 16 15.5 13.5 17 10.5C18.5 7.5 18 5 19.5 4.5Z\" \n fill=\"url(#featherBadgeGrad)\" />\n <path d=\"M4 19.5C5.5 18.5 8.5 14.5 13 10.5\" \n stroke=\"url(#featherLineGrad)\" \n stroke-width=\"1.5\" \n stroke-linecap=\"round\" />\n <defs>\n <linearGradient id=\"featherBadgeGrad\" x1=\"4\" y1=\"19.5\" x2=\"19.5\" y2=\"4.5\" gradientUnits=\"userSpaceOnUse\">\n <stop offset=\"0%\" stop-color=\"#FDA4AF\" />\n <stop offset=\"100%\" stop-color=\"#E11D48\" />\n </linearGradient>\n <linearGradient id=\"featherLineGrad\" x1=\"4\" y1=\"19.5\" x2=\"13\" y2=\"10.5\" gradientUnits=\"userSpaceOnUse\">\n <stop offset=\"0%\" stop-color=\"#FFE4E6\" />\n <stop offset=\"100%\" stop-color=\"#F43F5E\" />\n </linearGradient>\n </defs>\n </svg>\n <span class=\"points-text\">{{ getPointsText(notification()!.points) }}</span>\n </div>\n </div>\n\n <!-- Speech bubble/feedback -->\n @if (notification()!.feedback) {\n <div class=\"polito-speech-bubble\">\n <p>{{ notification()!.feedback }}</p>\n </div>\n }\n </div>\n </div>\n </div>\n\n <!-- Falling Feather Animation Overlay -->\n <div class=\"polito-falling-feather-container\" [class.negative]=\"notification()!.points < 0\">\n <div class=\"feather-wrapper-sway\">\n <svg class=\"falling-feather-svg\" viewBox=\"0 0 100 100\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <defs>\n <!-- Positive gradient: beautiful pink-rose -->\n <linearGradient id=\"featherGradPos\" x1=\"0%\" y1=\"100%\" x2=\"100%\" y2=\"0%\">\n <stop offset=\"0%\" stop-color=\"#F43F5E\" stop-opacity=\"0.85\" />\n <stop offset=\"50%\" stop-color=\"#FDA4AF\" stop-opacity=\"0.9\" />\n <stop offset=\"100%\" stop-color=\"#FFE4E6\" stop-opacity=\"0.95\" />\n </linearGradient>\n <!-- Negative gradient: cool grey/blue -->\n <linearGradient id=\"featherGradNeg\" x1=\"0%\" y1=\"100%\" x2=\"100%\" y2=\"0%\">\n <stop offset=\"0%\" stop-color=\"#6B7280\" stop-opacity=\"0.85\" />\n <stop offset=\"50%\" stop-color=\"#9CA3AF\" stop-opacity=\"0.9\" />\n <stop offset=\"100%\" stop-color=\"#E5E7EB\" stop-opacity=\"0.95\" />\n </linearGradient>\n <!-- Rachis/spine line gradient -->\n <linearGradient id=\"rachisGrad\" x1=\"0%\" y1=\"100%\" x2=\"100%\" y2=\"0%\">\n <stop offset=\"0%\" stop-color=\"#ffffff\" stop-opacity=\"0.8\" />\n <stop offset=\"100%\" stop-color=\"#ffffff\" stop-opacity=\"0.2\" />\n </linearGradient>\n </defs>\n\n <!-- Main feather shape (Vane) -->\n <path d=\"M 50 90 C 40 85, 20 75, 20 50 C 20 30, 42 20, 50 10 C 50 10, 47 30, 45 45 C 43 60, 46 75, 50 90 Z\" \n fill=\"url(#featherGradPos)\" class=\"feather-vane-pos\" />\n <path d=\"M 50 90 C 60 85, 80 75, 80 50 C 80 30, 58 20, 50 10 C 50 10, 53 30, 55 45 C 57 60, 54 75, 50 90 Z\" \n fill=\"url(#featherGradPos)\" class=\"feather-vane-pos\" />\n\n <path d=\"M 50 90 C 40 85, 20 75, 20 50 C 20 30, 42 20, 50 10 C 50 10, 47 30, 45 45 C 43 60, 46 75, 50 90 Z\" \n fill=\"url(#featherGradNeg)\" class=\"feather-vane-neg\" />\n <path d=\"M 50 90 C 60 85, 80 75, 80 50 C 80 30, 58 20, 50 10 C 50 10, 53 30, 55 45 C 57 60, 54 75, 50 90 Z\" \n fill=\"url(#featherGradNeg)\" class=\"feather-vane-neg\" />\n\n <!-- Rachis/spine (the middle stem) -->\n <path d=\"M 50 92 L 50 10\" stroke=\"url(#rachisGrad)\" stroke-width=\"2.5\" stroke-linecap=\"round\" />\n\n <!-- Fine barb lines for feather texture -->\n <path d=\"M 50 75 Q 35 70, 25 65\" stroke=\"#ffffff\" stroke-width=\"1.2\" opacity=\"0.35\" stroke-linecap=\"round\" />\n <path d=\"M 50 60 Q 32 55, 22 45\" stroke=\"#ffffff\" stroke-width=\"1.2\" opacity=\"0.35\" stroke-linecap=\"round\" />\n <path d=\"M 50 45 Q 35 38, 28 28\" stroke=\"#ffffff\" stroke-width=\"1.2\" opacity=\"0.35\" stroke-linecap=\"round\" />\n \n <path d=\"M 50 75 Q 65 70, 75 65\" stroke=\"#ffffff\" stroke-width=\"1.2\" opacity=\"0.35\" stroke-linecap=\"round\" />\n <path d=\"M 50 60 Q 68 55, 78 45\" stroke=\"#ffffff\" stroke-width=\"1.2\" opacity=\"0.35\" stroke-linecap=\"round\" />\n <path d=\"M 50 45 Q 65 38, 72 28\" stroke=\"#ffffff\" stroke-width=\"1.2\" opacity=\"0.35\" stroke-linecap=\"round\" />\n </svg>\n <div class=\"falling-feather-points\">\n {{ getFeatherPointsText(notification()!.points) }}\n </div>\n </div>\n </div>\n}\n", styles: ["@keyframes bomp-in{0%{transform:scale(.4) translateY(40px);opacity:0}50%{transform:scale(1.08) translateY(-8px)}75%{transform:scale(.96) translateY(3px)}to{transform:scale(1) translateY(0);opacity:1}}@keyframes bomp-out{0%{transform:scale(1) translateY(0);opacity:1}to{transform:scale(.85) translateY(20px);opacity:0}}.polito-notification-wrapper{position:absolute;bottom:80px;right:16px;z-index:999;max-width:320px;width:calc(100% - 32px);pointer-events:none;display:flex;flex-direction:column;animation:bomp-in .45s cubic-bezier(.34,1.56,.64,1) forwards}.polito-notification-wrapper.hiding{animation:bomp-out .35s cubic-bezier(.25,1,.5,1) forwards}.polito-card{pointer-events:auto;display:flex;gap:12px;padding:14px 16px;border-radius:20px;background:#ffffffd9;backdrop-filter:blur(16px) saturate(180%);-webkit-backdrop-filter:blur(16px) saturate(180%);border:1px solid rgba(255,255,255,.45);box-shadow:0 10px 30px -5px #f43f5e1a,0 20px 40px -10px #00000014,0 1px 3px #0000000a;transition:transform .2s ease,box-shadow .2s ease}.polito-card:hover{transform:translateY(-2px);box-shadow:0 12px 35px -5px #f43f5e26,0 22px 45px -10px #0000001a,0 1px 4px #0000000a}.polito-avatar-container{flex-shrink:0;width:44px;height:44px;border-radius:50%;overflow:hidden;box-shadow:0 4px 12px #f43f5e33;border:2px solid #ffffff}.polito-avatar-svg{width:100%;height:100%;display:block}.polito-content{flex:1;display:flex;flex-direction:column}.polito-header{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:4px}.polito-name{font-weight:700;font-size:.95rem;color:#1c1917;letter-spacing:-.2px}.polito-badge{display:inline-flex;align-items:center;gap:4px;padding:4px 8px;border-radius:12px;background:#fee4e6b3;border:1px solid rgba(251,113,133,.3);color:#e11d48;font-size:.78rem;font-weight:700}.polito-badge .feather-svg{width:14px;height:14px;flex-shrink:0}.polito-badge.negative{background:#f5f5f7b3;border-color:#0000001a;color:#4b5563}.polito-speech-bubble{position:relative;margin-top:6px;padding:8px 12px;border-radius:12px;background:#fff;border:1px solid rgba(229,231,235,.8);box-shadow:0 4px 12px #00000008}.polito-speech-bubble p{margin:0;font-size:.82rem;line-height:1.35;color:#4b5563;font-weight:450}.polito-speech-bubble:before{content:\"\";position:absolute;top:12px;left:-6px;width:10px;height:10px;background:#fff;border-left:1px solid rgba(229,231,235,.8);border-bottom:1px solid rgba(229,231,235,.8);transform:rotate(45deg)}@media(prefers-color-scheme:dark){.polito-card{background:#1e1e24d9;border-color:#ffffff1a;box-shadow:0 10px 30px -5px #f43f5e26,0 20px 40px -10px #0006,0 1px 3px #0000004d}.polito-card:hover{box-shadow:0 12px 35px -5px #f43f5e33,0 22px 45px -10px #00000080,0 1px 4px #0000004d}.polito-name{color:#f5f5f7}.polito-badge{background:#f43f5e26;border-color:#f43f5e4d;color:#fda4af}.polito-badge.negative{background:#ffffff0d;border-color:#ffffff1a;color:#9ca3af}.polito-speech-bubble{background:#27272a;border-color:#ffffff0f;box-shadow:0 4px 12px #0003}.polito-speech-bubble p{color:#d1d5db}.polito-speech-bubble:before{background:#27272a;border-left-color:#ffffff0f;border-bottom-color:#ffffff0f}.polito-avatar-container{border-color:#27272a}}@media(max-width:480px){.polito-notification-wrapper{right:8px;bottom:72px;width:calc(100% - 16px);max-width:none}}@keyframes feather-fall{0%{transform:translateY(-100px);opacity:0}12%{opacity:1}85%{opacity:1}to{transform:translateY(75vh);opacity:0}}@keyframes feather-sway{0%,to{transform:translate(-35px) rotate(-16deg)}50%{transform:translate(35px) rotate(16deg)}}.polito-falling-feather-container{position:absolute;top:0;right:120px;width:90px;height:90px;pointer-events:none;z-index:1000;animation:feather-fall 4.2s cubic-bezier(.33,1,.68,1) forwards}.polito-falling-feather-container .falling-feather-svg{width:100%;height:100%;filter:drop-shadow(0 6px 12px rgba(244,63,94,.25))}.polito-falling-feather-container .feather-vane-pos{display:block}.polito-falling-feather-container .feather-vane-neg{display:none}.polito-falling-feather-container .feather-wrapper-sway{position:relative;width:100%;height:100%;animation:feather-sway 2.2s ease-in-out infinite}.polito-falling-feather-container .falling-feather-points{position:absolute;top:48%;left:50%;transform:translate(-50%,-50%);font-size:1.4rem;font-weight:900;color:#fff;letter-spacing:-.5px;text-shadow:0 2px 5px rgba(0,0,0,.3),-2px -2px 0 #e11d48,2px -2px 0 #e11d48,-2px 2px 0 #e11d48,2px 2px 0 #e11d48;white-space:nowrap;-webkit-user-select:none;user-select:none}.polito-falling-feather-container.negative .falling-feather-svg{filter:drop-shadow(0 6px 12px rgba(107,114,128,.25))}.polito-falling-feather-container.negative .feather-vane-pos{display:none}.polito-falling-feather-container.negative .feather-vane-neg{display:block}.polito-falling-feather-container.negative .falling-feather-points{text-shadow:0 2px 5px rgba(0,0,0,.3),-2px -2px 0 #4b5563,2px -2px 0 #4b5563,-2px 2px 0 #4b5563,2px 2px 0 #4b5563}@media(prefers-color-scheme:dark){.polito-falling-feather-container .falling-feather-svg{filter:drop-shadow(0 8px 16px rgba(244,63,94,.35))}.polito-falling-feather-container.negative .falling-feather-svg{filter:drop-shadow(0 8px 16px rgba(0,0,0,.4))}}@media(max-width:480px){.polito-falling-feather-container{right:auto;left:calc(50% - 45px)}@keyframes mobile-feather-sway{0%,to{transform:translate(-25px) rotate(-12deg)}50%{transform:translate(25px) rotate(12deg)}}.polito-falling-feather-container .feather-wrapper-sway{animation-name:mobile-feather-sway}}\n"] }]
5842
+ }] });
5843
+
5422
5844
  /**
5423
5845
  * SafeJsonPipe - A pipe that safely stringifies objects with circular references
5424
5846
  * This pipe handles circular references and DOM objects that can't be serialized
@@ -5516,7 +5938,7 @@ class PromptPreviewComponent {
5516
5938
  }
5517
5939
  ngOnInit() { }
5518
5940
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: PromptPreviewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5519
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: PromptPreviewComponent, isStandalone: true, selector: "dc-prompt-preview", inputs: { messages: { classPropertyName: "messages", publicName: "messages", isSignal: true, isRequired: true, transformFunction: null }, jailBrake: { classPropertyName: "jailBrake", publicName: "jailBrake", isSignal: true, isRequired: false, transformFunction: null }, view: { classPropertyName: "view", publicName: "view", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<h3\n >Total Tokens: <b class=\"text-green-700\">{{ totalTokens }}</b></h3\n>\n@if (view() === 'regular') {\n<div>\n @for (section of sectionsOrder; track section) { @if (getMessagesBySection(section).length > 0) {\n <p-divider align=\"left\" type=\"dotted\">\n <p-tag severity=\"secondary\" [value]=\"formatCamelCaseString(section)\" />\n </p-divider>\n @for (message of getMessagesBySection(section); track message) {\n <div>\n <h5>\n <b style=\"margin: 3px\" class=\"text-blue-700\">{{ formatCamelCaseString(message.role) }}</b>\n <b style=\"margin: 3px\" class=\"text-red-700\">{{ formatCamelCaseString(message.messageId) }}</b>\n <b style=\"margin: 3px\" class=\"text-green-700\">({{ estimateTokens(message.content || '') }} tokens)</b>\n </h5>\n <markdown [data]=\"message.content\"></markdown>\n </div>\n } } } @if (messagesWithNoSection.length > 0) {\n <p-divider align=\"left\" type=\"dotted\">\n <p-tag severity=\"secondary\" value=\"Others\" />\n </p-divider>\n @for (message of messagesWithNoSection; track message) {\n <div>\n <h5>\n <b style=\"margin: 3px\" class=\"text-blue-700\">{{ formatCamelCaseString(message.role) }}</b>\n <b style=\"margin: 3px\" class=\"text-red-700\">{{ formatCamelCaseString(message.messageId) }}</b>\n <b style=\"margin: 3px\" class=\"text-green-700\">({{ estimateTokens(message.content || '') }} tokens)</b>\n </h5>\n <markdown [data]=\"message.content\"></markdown>\n </div>\n } } @if (jailBrake()) {\n <!-- JailBrake Instructions Will be DEPRECATED -->\n <p-divider align=\"left\" type=\"dotted\">\n <p-tag severity=\"secondary\" value=\"JailBrake Instructions\" />\n </p-divider>\n <div>\n <h5>\n <b class=\"text-green-700\">({{ estimateTokens(jailBrake()!) }} tokens)</b>\n </h5>\n <p>{{ jailBrake() }}</p>\n </div>\n }\n</div>\n} @else {\n<div>\n <markdown [data]=\"markdownContent()\"></markdown>\n</div>\n}\n", styles: [":host{display:block;font-family:sans-serif;padding:1rem}h3,h5{margin-top:0}p{white-space:pre-wrap;word-break:break-word;margin-bottom:1rem;padding:.5rem;background-color:#f5f5f5;border-radius:4px}.text-blue-700{color:#1d4ed8}.text-red-700{color:#b91c1c}.text-green-700{color:#15803d}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ChipModule }, { 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"] }, { kind: "ngmodule", type: DividerModule }, { kind: "component", type: i1$3.Divider, selector: "p-divider", inputs: ["styleClass", "layout", "type", "align"] }, { kind: "ngmodule", type: TagModule }, { kind: "component", type: i1$4.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }] }); }
5941
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: PromptPreviewComponent, isStandalone: true, selector: "dc-prompt-preview", inputs: { messages: { classPropertyName: "messages", publicName: "messages", isSignal: true, isRequired: true, transformFunction: null }, jailBrake: { classPropertyName: "jailBrake", publicName: "jailBrake", isSignal: true, isRequired: false, transformFunction: null }, view: { classPropertyName: "view", publicName: "view", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<h3\n >Total Tokens: <b class=\"text-green-700\">{{ totalTokens }}</b></h3\n>\n@if (view() === 'regular') {\n<div>\n @for (section of sectionsOrder; track section) { @if (getMessagesBySection(section).length > 0) {\n <p-divider align=\"left\" type=\"dotted\">\n <p-tag severity=\"secondary\" [value]=\"formatCamelCaseString(section)\" />\n </p-divider>\n @for (message of getMessagesBySection(section); track message) {\n <div>\n <h5>\n <b style=\"margin: 3px\" class=\"text-blue-700\">{{ formatCamelCaseString(message.role) }}</b>\n <b style=\"margin: 3px\" class=\"text-red-700\">{{ formatCamelCaseString(message.messageId) }}</b>\n <b style=\"margin: 3px\" class=\"text-green-700\">({{ estimateTokens(message.content || '') }} tokens)</b>\n </h5>\n <markdown [data]=\"message.content\"></markdown>\n </div>\n } } } @if (messagesWithNoSection.length > 0) {\n <p-divider align=\"left\" type=\"dotted\">\n <p-tag severity=\"secondary\" value=\"Others\" />\n </p-divider>\n @for (message of messagesWithNoSection; track message) {\n <div>\n <h5>\n <b style=\"margin: 3px\" class=\"text-blue-700\">{{ formatCamelCaseString(message.role) }}</b>\n <b style=\"margin: 3px\" class=\"text-red-700\">{{ formatCamelCaseString(message.messageId) }}</b>\n <b style=\"margin: 3px\" class=\"text-green-700\">({{ estimateTokens(message.content || '') }} tokens)</b>\n </h5>\n <markdown [data]=\"message.content\"></markdown>\n </div>\n } } @if (jailBrake()) {\n <!-- JailBrake Instructions Will be DEPRECATED -->\n <p-divider align=\"left\" type=\"dotted\">\n <p-tag severity=\"secondary\" value=\"JailBrake Instructions\" />\n </p-divider>\n <div>\n <h5>\n <b class=\"text-green-700\">({{ estimateTokens(jailBrake()!) }} tokens)</b>\n </h5>\n <p>{{ jailBrake() }}</p>\n </div>\n }\n</div>\n} @else {\n<div>\n <markdown [data]=\"markdownContent()\"></markdown>\n</div>\n}\n", styles: [":host{display:block;font-family:sans-serif;padding:1rem}h3,h5{margin-top:0}p{white-space:pre-wrap;word-break:break-word;margin-bottom:1rem;padding:.5rem;background-color:#f5f5f5;border-radius:4px}.text-blue-700{color:#1d4ed8}.text-red-700{color:#b91c1c}.text-green-700{color:#15803d}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ChipModule }, { 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"] }, { kind: "ngmodule", type: DividerModule }, { kind: "component", type: i2$4.Divider, selector: "p-divider", inputs: ["styleClass", "layout", "type", "align"] }, { kind: "ngmodule", type: TagModule }, { kind: "component", type: i1$3.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }] }); }
5520
5942
  }
5521
5943
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: PromptPreviewComponent, decorators: [{
5522
5944
  type: Component,
@@ -5539,7 +5961,7 @@ class CostDetailsComponent {
5539
5961
  }));
5540
5962
  }
5541
5963
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CostDetailsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5542
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: CostDetailsComponent, isStandalone: true, selector: "dc-cost-details", ngImport: i0, template: "<div class=\"cost-details-container\">\n <h3>Cost Details</h3>\n @if (conversationCostService.totalTokens() > 0) {\n <div class=\"token-counter\">\n <span>\n \uD83D\uDCE5 {{ conversationCostService.totalInputTokens() }}\n <span style=\"font-size: small; color: rgb(74, 74, 74)\">${{ conversationCostService.totalInputCost() | number : '1.4-4' }}</span>\n </span>\n <span>\n \uD83D\uDCE4 {{ conversationCostService.totalOutputTokens() }}\n <span style=\"font-size: small; color: rgb(74, 74, 74)\">${{ conversationCostService.totalOutputCost() | number : '1.4-4' }}</span>\n </span>\n <span>\n \uD83E\uDDEE {{ conversationCostService.totalTokens() }}\n <span style=\"font-size: small; color: rgb(74, 74, 74)\">${{ conversationCostService.totalCost() | number : '1.4-4' }}</span>\n </span>\n <span> <i class=\"pi pi-cloud-upload\"></i> {{ conversationCostService.totalApiCalls() }} </span>\n </div>\n }\n <p-table [value]=\"usageArray\" [tableStyle]=\"{ 'min-width': '50rem' }\">\n <ng-template pTemplate=\"header\">\n <tr>\n <th>Tag</th>\n <th>Input Tokens</th>\n <th>Output Tokens</th>\n <th>Total Tokens</th>\n <th>Input Cost</th>\n <th>Output Cost</th>\n <th>Total Cost</th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\" let-item>\n <tr>\n <td>{{ item.tag }}</td>\n <td>{{ item.tokenUsage.input }}</td>\n <td>{{ item.tokenUsage.output }}</td>\n <td>{{ item.tokenUsage.total }}</td>\n <td>{{ item.inputCost | number : '1.4-4' }}</td>\n <td>{{ item.outputCost | number : '1.4-4' }}</td>\n <td>{{ item.totalCost | number : '1.4-4' }}</td>\n </tr>\n </ng-template>\n </p-table>\n</div>\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: i1$5.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i2$4.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "pipe", type: i2$1.DecimalPipe, name: "number" }] }); }
5964
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: CostDetailsComponent, isStandalone: true, selector: "dc-cost-details", ngImport: i0, template: "<div class=\"cost-details-container\">\n <h3>Cost Details</h3>\n @if (conversationCostService.totalTokens() > 0) {\n <div class=\"token-counter\">\n <span>\n \uD83D\uDCE5 {{ conversationCostService.totalInputTokens() }}\n <span style=\"font-size: small; color: rgb(74, 74, 74)\">${{ conversationCostService.totalInputCost() | number : '1.4-4' }}</span>\n </span>\n <span>\n \uD83D\uDCE4 {{ conversationCostService.totalOutputTokens() }}\n <span style=\"font-size: small; color: rgb(74, 74, 74)\">${{ conversationCostService.totalOutputCost() | number : '1.4-4' }}</span>\n </span>\n <span>\n \uD83E\uDDEE {{ conversationCostService.totalTokens() }}\n <span style=\"font-size: small; color: rgb(74, 74, 74)\">${{ conversationCostService.totalCost() | number : '1.4-4' }}</span>\n </span>\n <span> <i class=\"pi pi-cloud-upload\"></i> {{ conversationCostService.totalApiCalls() }} </span>\n </div>\n }\n <p-table [value]=\"usageArray\" [tableStyle]=\"{ 'min-width': '50rem' }\">\n <ng-template pTemplate=\"header\">\n <tr>\n <th>Tag</th>\n <th>Input Tokens</th>\n <th>Output Tokens</th>\n <th>Total Tokens</th>\n <th>Input Cost</th>\n <th>Output Cost</th>\n <th>Total Cost</th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\" let-item>\n <tr>\n <td>{{ item.tag }}</td>\n <td>{{ item.tokenUsage.input }}</td>\n <td>{{ item.tokenUsage.output }}</td>\n <td>{{ item.tokenUsage.total }}</td>\n <td>{{ item.inputCost | number : '1.4-4' }}</td>\n <td>{{ item.outputCost | number : '1.4-4' }}</td>\n <td>{{ item.totalCost | number : '1.4-4' }}</td>\n </tr>\n </ng-template>\n </p-table>\n</div>\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: i1$4.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i2$5.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "pipe", type: i2$1.DecimalPipe, name: "number" }] }); }
5543
5965
  }
5544
5966
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CostDetailsComponent, decorators: [{
5545
5967
  type: Component,
@@ -5552,11 +5974,11 @@ class MessagesStateInspectorComponent {
5552
5974
  this.messages = this.messagesStateService.getMessagesSignal();
5553
5975
  }
5554
5976
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MessagesStateInspectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5555
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: MessagesStateInspectorComponent, isStandalone: true, selector: "dc-messages-state-inspector", ngImport: i0, template: "<div class=\"messages-state-inspector\">\n @for (msg of messages(); track msg.messageId; let i = $index) {\n <details class=\"message-group mb-2 border rounded p-2\">\n <summary class=\"cursor-pointer font-bold p-1 hover:bg-gray-100 flex justify-between items-center\">\n <span>\n <span class=\"text-xs text-gray-400 mr-2\">#{{ i + 1 }}</span>\n <span [class]=\"'role-badge ' + msg.role\">{{ msg.role }}</span>\n <span class=\"ml-2 text-sm truncate max-w-xs\">{{ msg.content | slice:0:50 }}{{ msg.content.length > 50 ? '...' : '' }}</span>\n </span>\n <span class=\"text-xs text-gray-400\">{{ msg.messageId }}</span>\n </summary>\n\n <div class=\"message-details mt-2 pl-4 border-l-2 border-primary\">\n <!-- Standard Properties -->\n <div class=\"grid grid-cols-2 gap-2 text-sm\">\n <div><strong>Role:</strong> {{ msg.role }}</div>\n <div><strong>Section:</strong> {{ msg.section || 'N/A' }}</div>\n <div><strong>Message ID:</strong> {{ msg.messageId }}</div>\n <div class=\"col-span-2\"><strong>Content:</strong> <pre class=\"whitespace-pre-wrap text-xs bg-gray-50 p-2 mt-1\">{{ msg.content }}</pre></div>\n @if (msg.translation) {\n <div class=\"col-span-2 text-blue-600\"><strong>Translation:</strong> {{ msg.translation }}</div>\n }\n </div>\n\n <!-- JSON Preview of other props -->\n <details class=\"mt-2\">\n <summary class=\"text-xs text-gray-500 cursor-pointer\">All Metadata</summary>\n <pre class=\"text-[10px] bg-slate-800 text-white p-2 rounded mt-1 overflow-auto max-h-64\">{{ msg | safeJson }}</pre>\n </details>\n\n <!-- MultiMessages recursive check -->\n @if (msg.multiMessages && msg.multiMessages.length > 0) {\n <div class=\"mt-3\">\n <strong class=\"text-xs uppercase text-gray-500\">Multi Messages ({{ msg.multiMessages.length }})</strong>\n <div class=\"pl-4 border-l-2 border-dashed border-gray-300\">\n @for (subMsg of msg.multiMessages; track $index) {\n <details class=\"mt-1 border rounded p-1 bg-gray-50\">\n <summary class=\"text-xs cursor-pointer truncate\">Sub: {{ subMsg.text | slice:0:30 }}...</summary>\n <pre class=\"text-[10px] mt-1 p-1 bg-white border overflow-auto\">{{ subMsg | safeJson }}</pre>\n </details>\n }\n </div>\n </div>\n }\n\n <!-- Evaluation -->\n @if (msg.evaluation) {\n <div class=\"mt-2 p-2 bg-yellow-50 rounded text-xs\">\n <strong>Evaluation:</strong>\n <pre>{{ msg.evaluation | safeJson }}</pre>\n </div>\n }\n\n <!-- Tags -->\n @if (msg.tags && msg.tags.length > 0) {\n <div class=\"mt-2 flex flex-wrap gap-1\">\n <strong>Tags:</strong>\n @for (tag of msg.tags; track tag) {\n <span class=\"bg-gray-200 px-1 rounded text-[10px]\">{{ tag }}</span>\n }\n </div>\n }\n </div>\n </details>\n } @empty {\n <div class=\"p-4 text-center text-gray-400\">No messages in state.</div>\n }\n</div>\n\n<style>\n .role-badge {\n padding: 2px 6px;\n border-radius: 4px;\n font-size: 0.7rem;\n text-transform: uppercase;\n font-weight: bold;\n }\n .role-badge.user { background: #e0f2fe; color: #0369a1; }\n .role-badge.assistant { background: #f0fdf4; color: #15803d; }\n .role-badge.assistantHelper { background: #faf5ff; color: #7e22ce; }\n .role-badge.system { background: #f1f5f9; color: #475569; }\n .border-primary { border-color: var(--p-primary-color, #3b82f6); }\n</style>\n", styles: [".role-badge{padding:2px 6px;border-radius:4px;font-size:.7rem;text-transform:uppercase;font-weight:700}.role-badge.user{background:#e0f2fe;color:#0369a1}.role-badge.assistant{background:#f0fdf4;color:#15803d}.role-badge.assistantHelper{background:#faf5ff;color:#7e22ce}.role-badge.system{background:#f1f5f9;color:#475569}.border-primary{border-color:var(--p-primary-color, #3b82f6)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i2$1.SlicePipe, name: "slice" }, { kind: "pipe", type: SafeJsonPipe, name: "safeJson" }] }); }
5977
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: MessagesStateInspectorComponent, isStandalone: true, selector: "dc-messages-state-inspector", ngImport: i0, template: "<div class=\"messages-state-inspector\">\n @for (msg of messages(); track msg.messageId; let i = $index) {\n <details class=\"message-group mb-2 border rounded p-2\">\n <summary class=\"cursor-pointer font-bold p-1 hover:bg-gray-100 flex justify-between items-center\">\n <span>\n <span class=\"text-xs text-gray-400 mr-2\">#{{ i + 1 }}</span>\n <span [class]=\"'role-badge ' + msg.role\">{{ msg.role }}</span>\n <span class=\"ml-2 text-sm truncate max-w-xs\">{{ msg.content | slice:0:50 }}{{ msg.content.length > 50 ? '...' : '' }}</span>\n </span>\n <span class=\"text-xs text-gray-400\">{{ msg.messageId }}</span>\n </summary>\n\n <div class=\"message-details mt-2 pl-4 border-l-2 border-primary\">\n <!-- Standard Properties -->\n <div class=\"grid grid-cols-2 gap-2 text-sm\">\n <div><strong>Role:</strong> {{ msg.role }}</div>\n <div><strong>Section:</strong> {{ msg.section || 'N/A' }}</div>\n <div><strong>Message ID:</strong> {{ msg.messageId }}</div>\n <div class=\"col-span-2\"><strong>Content:</strong> <pre class=\"whitespace-pre-wrap text-xs bg-gray-50 p-2 mt-1\">{{ msg.content }}</pre></div>\n @if (msg.translation) {\n <div class=\"col-span-2 text-blue-600\"><strong>Translation:</strong> {{ msg.translation }}</div>\n }\n </div>\n\n <!-- JSON Preview of other props -->\n <details class=\"mt-2\">\n <summary class=\"text-xs text-gray-500 cursor-pointer\">All Metadata</summary>\n <pre class=\"text-[10px] bg-slate-800 text-white p-2 rounded mt-1 overflow-auto max-h-64\">{{ msg | safeJson }}</pre>\n </details>\n\n <!-- MultiMessages recursive check -->\n @if (msg.multiMessages && msg.multiMessages.length > 0) {\n <div class=\"mt-3\">\n <strong class=\"text-xs uppercase text-gray-500\">Multi Messages ({{ msg.multiMessages.length }})</strong>\n <div class=\"pl-4 border-l-2 border-dashed border-gray-300\">\n @for (subMsg of msg.multiMessages; track $index) {\n <details class=\"mt-1 border rounded p-1 bg-gray-50\">\n <summary class=\"text-xs cursor-pointer truncate\">Sub: {{ subMsg.text | slice:0:30 }}...</summary>\n <pre class=\"text-[10px] mt-1 p-1 bg-white border overflow-auto\">{{ subMsg | safeJson }}</pre>\n </details>\n }\n </div>\n </div>\n }\n\n <!-- Evaluation -->\n @if (msg.evaluation) {\n <div class=\"mt-2 p-2 bg-yellow-50 rounded text-xs space-y-2\">\n <strong>Evaluation</strong>\n\n @if (msg.evaluation['flow']; as flow) {\n <div class=\"flow-eval space-y-2\">\n @if (flow.goal) {\n <div class=\"p-2 bg-white rounded border\">\n <div class=\"flex items-center justify-between\">\n <strong class=\"text-[11px] uppercase text-gray-600\">Goal</strong>\n @if (flow.goal.deltaPoints != null) {\n <span\n class=\"px-1.5 rounded text-[11px] font-bold\"\n [class.bg-green-100]=\"flow.goal.deltaPoints > 0\"\n [class.text-green-700]=\"flow.goal.deltaPoints > 0\"\n [class.bg-red-100]=\"flow.goal.deltaPoints < 0\"\n [class.text-red-700]=\"flow.goal.deltaPoints < 0\"\n [class.bg-gray-100]=\"flow.goal.deltaPoints === 0\"\n [class.text-gray-600]=\"flow.goal.deltaPoints === 0\">\n {{ flow.goal.deltaPoints > 0 ? '+' : '' }}{{ flow.goal.deltaPoints }} pts\n </span>\n }\n </div>\n @if (flow.goal.previousValue != null && flow.goal.newValue != null) {\n <div class=\"mt-1 text-[11px] text-gray-600\">\n <span>{{ flow.goal.previousValue }}</span>\n <span class=\"mx-1\">\u2192</span>\n <span class=\"font-bold text-gray-900\">{{ flow.goal.newValue }}</span>\n <span class=\"text-gray-400\"> / 100</span>\n </div>\n <div class=\"w-full bg-gray-200 rounded h-1 mt-1 overflow-hidden\">\n <div class=\"bg-primary h-1\" [style.width.%]=\"flow.goal.newValue\" [style.background-color]=\"'#3b82f6'\"></div>\n </div>\n }\n @if (flow.goal.feedback) {\n <div class=\"mt-1 text-[11px] italic text-gray-700\">\"{{ flow.goal.feedback }}\"</div>\n }\n </div>\n }\n\n @if (flow.challenges?.length) {\n <div class=\"p-2 bg-white rounded border\">\n <strong class=\"text-[11px] uppercase text-gray-600\">Challenges</strong>\n <ul class=\"mt-1 space-y-0.5\">\n @for (ch of flow.challenges; track ch.name) {\n <li class=\"flex items-center gap-1 text-[11px]\">\n <span [class.text-green-600]=\"ch.value\" [class.text-gray-400]=\"!ch.value\">\n {{ ch.value ? '\u2713' : '\u25CB' }}\n </span>\n <span [class.font-semibold]=\"ch.value\">{{ ch.name }}</span>\n </li>\n }\n </ul>\n </div>\n }\n\n @if (flow.moodState?.value) {\n <div class=\"p-2 bg-white rounded border flex items-center justify-between\">\n <strong class=\"text-[11px] uppercase text-gray-600\">Mood</strong>\n <span class=\"text-[11px] font-semibold\">{{ flow.moodState.value }}</span>\n </div>\n }\n\n @if (flow.evaluatedAt) {\n <div class=\"text-[10px] text-gray-400 text-right\">{{ flow.evaluatedAt }}</div>\n }\n </div>\n }\n\n <details class=\"mt-1\">\n <summary class=\"text-[10px] text-gray-500 cursor-pointer\">Raw evaluation</summary>\n <pre class=\"text-[10px]\">{{ msg.evaluation | safeJson }}</pre>\n </details>\n </div>\n }\n\n <!-- Tags -->\n @if (msg.tags && msg.tags.length > 0) {\n <div class=\"mt-2 flex flex-wrap gap-1\">\n <strong>Tags:</strong>\n @for (tag of msg.tags; track tag) {\n <span class=\"bg-gray-200 px-1 rounded text-[10px]\">{{ tag }}</span>\n }\n </div>\n }\n </div>\n </details>\n } @empty {\n <div class=\"p-4 text-center text-gray-400\">No messages in state.</div>\n }\n</div>\n\n<style>\n .role-badge {\n padding: 2px 6px;\n border-radius: 4px;\n font-size: 0.7rem;\n text-transform: uppercase;\n font-weight: bold;\n }\n .role-badge.user { background: #e0f2fe; color: #0369a1; }\n .role-badge.assistant { background: #f0fdf4; color: #15803d; }\n .role-badge.assistantHelper { background: #faf5ff; color: #7e22ce; }\n .role-badge.system { background: #f1f5f9; color: #475569; }\n .border-primary { border-color: var(--p-primary-color, #3b82f6); }\n</style>\n", styles: [".role-badge{padding:2px 6px;border-radius:4px;font-size:.7rem;text-transform:uppercase;font-weight:700}.role-badge.user{background:#e0f2fe;color:#0369a1}.role-badge.assistant{background:#f0fdf4;color:#15803d}.role-badge.assistantHelper{background:#faf5ff;color:#7e22ce}.role-badge.system{background:#f1f5f9;color:#475569}.border-primary{border-color:var(--p-primary-color, #3b82f6)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i2$1.SlicePipe, name: "slice" }, { kind: "pipe", type: SafeJsonPipe, name: "safeJson" }] }); }
5556
5978
  }
5557
5979
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MessagesStateInspectorComponent, decorators: [{
5558
5980
  type: Component,
5559
- args: [{ selector: 'dc-messages-state-inspector', standalone: true, imports: [CommonModule, SafeJsonPipe], template: "<div class=\"messages-state-inspector\">\n @for (msg of messages(); track msg.messageId; let i = $index) {\n <details class=\"message-group mb-2 border rounded p-2\">\n <summary class=\"cursor-pointer font-bold p-1 hover:bg-gray-100 flex justify-between items-center\">\n <span>\n <span class=\"text-xs text-gray-400 mr-2\">#{{ i + 1 }}</span>\n <span [class]=\"'role-badge ' + msg.role\">{{ msg.role }}</span>\n <span class=\"ml-2 text-sm truncate max-w-xs\">{{ msg.content | slice:0:50 }}{{ msg.content.length > 50 ? '...' : '' }}</span>\n </span>\n <span class=\"text-xs text-gray-400\">{{ msg.messageId }}</span>\n </summary>\n\n <div class=\"message-details mt-2 pl-4 border-l-2 border-primary\">\n <!-- Standard Properties -->\n <div class=\"grid grid-cols-2 gap-2 text-sm\">\n <div><strong>Role:</strong> {{ msg.role }}</div>\n <div><strong>Section:</strong> {{ msg.section || 'N/A' }}</div>\n <div><strong>Message ID:</strong> {{ msg.messageId }}</div>\n <div class=\"col-span-2\"><strong>Content:</strong> <pre class=\"whitespace-pre-wrap text-xs bg-gray-50 p-2 mt-1\">{{ msg.content }}</pre></div>\n @if (msg.translation) {\n <div class=\"col-span-2 text-blue-600\"><strong>Translation:</strong> {{ msg.translation }}</div>\n }\n </div>\n\n <!-- JSON Preview of other props -->\n <details class=\"mt-2\">\n <summary class=\"text-xs text-gray-500 cursor-pointer\">All Metadata</summary>\n <pre class=\"text-[10px] bg-slate-800 text-white p-2 rounded mt-1 overflow-auto max-h-64\">{{ msg | safeJson }}</pre>\n </details>\n\n <!-- MultiMessages recursive check -->\n @if (msg.multiMessages && msg.multiMessages.length > 0) {\n <div class=\"mt-3\">\n <strong class=\"text-xs uppercase text-gray-500\">Multi Messages ({{ msg.multiMessages.length }})</strong>\n <div class=\"pl-4 border-l-2 border-dashed border-gray-300\">\n @for (subMsg of msg.multiMessages; track $index) {\n <details class=\"mt-1 border rounded p-1 bg-gray-50\">\n <summary class=\"text-xs cursor-pointer truncate\">Sub: {{ subMsg.text | slice:0:30 }}...</summary>\n <pre class=\"text-[10px] mt-1 p-1 bg-white border overflow-auto\">{{ subMsg | safeJson }}</pre>\n </details>\n }\n </div>\n </div>\n }\n\n <!-- Evaluation -->\n @if (msg.evaluation) {\n <div class=\"mt-2 p-2 bg-yellow-50 rounded text-xs\">\n <strong>Evaluation:</strong>\n <pre>{{ msg.evaluation | safeJson }}</pre>\n </div>\n }\n\n <!-- Tags -->\n @if (msg.tags && msg.tags.length > 0) {\n <div class=\"mt-2 flex flex-wrap gap-1\">\n <strong>Tags:</strong>\n @for (tag of msg.tags; track tag) {\n <span class=\"bg-gray-200 px-1 rounded text-[10px]\">{{ tag }}</span>\n }\n </div>\n }\n </div>\n </details>\n } @empty {\n <div class=\"p-4 text-center text-gray-400\">No messages in state.</div>\n }\n</div>\n\n<style>\n .role-badge {\n padding: 2px 6px;\n border-radius: 4px;\n font-size: 0.7rem;\n text-transform: uppercase;\n font-weight: bold;\n }\n .role-badge.user { background: #e0f2fe; color: #0369a1; }\n .role-badge.assistant { background: #f0fdf4; color: #15803d; }\n .role-badge.assistantHelper { background: #faf5ff; color: #7e22ce; }\n .role-badge.system { background: #f1f5f9; color: #475569; }\n .border-primary { border-color: var(--p-primary-color, #3b82f6); }\n</style>\n" }]
5981
+ args: [{ selector: 'dc-messages-state-inspector', standalone: true, imports: [CommonModule, SafeJsonPipe], template: "<div class=\"messages-state-inspector\">\n @for (msg of messages(); track msg.messageId; let i = $index) {\n <details class=\"message-group mb-2 border rounded p-2\">\n <summary class=\"cursor-pointer font-bold p-1 hover:bg-gray-100 flex justify-between items-center\">\n <span>\n <span class=\"text-xs text-gray-400 mr-2\">#{{ i + 1 }}</span>\n <span [class]=\"'role-badge ' + msg.role\">{{ msg.role }}</span>\n <span class=\"ml-2 text-sm truncate max-w-xs\">{{ msg.content | slice:0:50 }}{{ msg.content.length > 50 ? '...' : '' }}</span>\n </span>\n <span class=\"text-xs text-gray-400\">{{ msg.messageId }}</span>\n </summary>\n\n <div class=\"message-details mt-2 pl-4 border-l-2 border-primary\">\n <!-- Standard Properties -->\n <div class=\"grid grid-cols-2 gap-2 text-sm\">\n <div><strong>Role:</strong> {{ msg.role }}</div>\n <div><strong>Section:</strong> {{ msg.section || 'N/A' }}</div>\n <div><strong>Message ID:</strong> {{ msg.messageId }}</div>\n <div class=\"col-span-2\"><strong>Content:</strong> <pre class=\"whitespace-pre-wrap text-xs bg-gray-50 p-2 mt-1\">{{ msg.content }}</pre></div>\n @if (msg.translation) {\n <div class=\"col-span-2 text-blue-600\"><strong>Translation:</strong> {{ msg.translation }}</div>\n }\n </div>\n\n <!-- JSON Preview of other props -->\n <details class=\"mt-2\">\n <summary class=\"text-xs text-gray-500 cursor-pointer\">All Metadata</summary>\n <pre class=\"text-[10px] bg-slate-800 text-white p-2 rounded mt-1 overflow-auto max-h-64\">{{ msg | safeJson }}</pre>\n </details>\n\n <!-- MultiMessages recursive check -->\n @if (msg.multiMessages && msg.multiMessages.length > 0) {\n <div class=\"mt-3\">\n <strong class=\"text-xs uppercase text-gray-500\">Multi Messages ({{ msg.multiMessages.length }})</strong>\n <div class=\"pl-4 border-l-2 border-dashed border-gray-300\">\n @for (subMsg of msg.multiMessages; track $index) {\n <details class=\"mt-1 border rounded p-1 bg-gray-50\">\n <summary class=\"text-xs cursor-pointer truncate\">Sub: {{ subMsg.text | slice:0:30 }}...</summary>\n <pre class=\"text-[10px] mt-1 p-1 bg-white border overflow-auto\">{{ subMsg | safeJson }}</pre>\n </details>\n }\n </div>\n </div>\n }\n\n <!-- Evaluation -->\n @if (msg.evaluation) {\n <div class=\"mt-2 p-2 bg-yellow-50 rounded text-xs space-y-2\">\n <strong>Evaluation</strong>\n\n @if (msg.evaluation['flow']; as flow) {\n <div class=\"flow-eval space-y-2\">\n @if (flow.goal) {\n <div class=\"p-2 bg-white rounded border\">\n <div class=\"flex items-center justify-between\">\n <strong class=\"text-[11px] uppercase text-gray-600\">Goal</strong>\n @if (flow.goal.deltaPoints != null) {\n <span\n class=\"px-1.5 rounded text-[11px] font-bold\"\n [class.bg-green-100]=\"flow.goal.deltaPoints > 0\"\n [class.text-green-700]=\"flow.goal.deltaPoints > 0\"\n [class.bg-red-100]=\"flow.goal.deltaPoints < 0\"\n [class.text-red-700]=\"flow.goal.deltaPoints < 0\"\n [class.bg-gray-100]=\"flow.goal.deltaPoints === 0\"\n [class.text-gray-600]=\"flow.goal.deltaPoints === 0\">\n {{ flow.goal.deltaPoints > 0 ? '+' : '' }}{{ flow.goal.deltaPoints }} pts\n </span>\n }\n </div>\n @if (flow.goal.previousValue != null && flow.goal.newValue != null) {\n <div class=\"mt-1 text-[11px] text-gray-600\">\n <span>{{ flow.goal.previousValue }}</span>\n <span class=\"mx-1\">\u2192</span>\n <span class=\"font-bold text-gray-900\">{{ flow.goal.newValue }}</span>\n <span class=\"text-gray-400\"> / 100</span>\n </div>\n <div class=\"w-full bg-gray-200 rounded h-1 mt-1 overflow-hidden\">\n <div class=\"bg-primary h-1\" [style.width.%]=\"flow.goal.newValue\" [style.background-color]=\"'#3b82f6'\"></div>\n </div>\n }\n @if (flow.goal.feedback) {\n <div class=\"mt-1 text-[11px] italic text-gray-700\">\"{{ flow.goal.feedback }}\"</div>\n }\n </div>\n }\n\n @if (flow.challenges?.length) {\n <div class=\"p-2 bg-white rounded border\">\n <strong class=\"text-[11px] uppercase text-gray-600\">Challenges</strong>\n <ul class=\"mt-1 space-y-0.5\">\n @for (ch of flow.challenges; track ch.name) {\n <li class=\"flex items-center gap-1 text-[11px]\">\n <span [class.text-green-600]=\"ch.value\" [class.text-gray-400]=\"!ch.value\">\n {{ ch.value ? '\u2713' : '\u25CB' }}\n </span>\n <span [class.font-semibold]=\"ch.value\">{{ ch.name }}</span>\n </li>\n }\n </ul>\n </div>\n }\n\n @if (flow.moodState?.value) {\n <div class=\"p-2 bg-white rounded border flex items-center justify-between\">\n <strong class=\"text-[11px] uppercase text-gray-600\">Mood</strong>\n <span class=\"text-[11px] font-semibold\">{{ flow.moodState.value }}</span>\n </div>\n }\n\n @if (flow.evaluatedAt) {\n <div class=\"text-[10px] text-gray-400 text-right\">{{ flow.evaluatedAt }}</div>\n }\n </div>\n }\n\n <details class=\"mt-1\">\n <summary class=\"text-[10px] text-gray-500 cursor-pointer\">Raw evaluation</summary>\n <pre class=\"text-[10px]\">{{ msg.evaluation | safeJson }}</pre>\n </details>\n </div>\n }\n\n <!-- Tags -->\n @if (msg.tags && msg.tags.length > 0) {\n <div class=\"mt-2 flex flex-wrap gap-1\">\n <strong>Tags:</strong>\n @for (tag of msg.tags; track tag) {\n <span class=\"bg-gray-200 px-1 rounded text-[10px]\">{{ tag }}</span>\n }\n </div>\n }\n </div>\n </details>\n } @empty {\n <div class=\"p-4 text-center text-gray-400\">No messages in state.</div>\n }\n</div>\n\n<style>\n .role-badge {\n padding: 2px 6px;\n border-radius: 4px;\n font-size: 0.7rem;\n text-transform: uppercase;\n font-weight: bold;\n }\n .role-badge.user { background: #e0f2fe; color: #0369a1; }\n .role-badge.assistant { background: #f0fdf4; color: #15803d; }\n .role-badge.assistantHelper { background: #faf5ff; color: #7e22ce; }\n .role-badge.system { background: #f1f5f9; color: #475569; }\n .border-primary { border-color: var(--p-primary-color, #3b82f6); }\n</style>\n" }]
5560
5982
  }] });
5561
5983
 
5562
5984
  class DcAgentCardDetailComponent extends EntityBaseDetailComponent {
@@ -5597,13 +6019,61 @@ class DcAgentCardDetailComponent extends EntityBaseDetailComponent {
5597
6019
  this.selectedMotion.set(null);
5598
6020
  }
5599
6021
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DcAgentCardDetailComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5600
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: DcAgentCardDetailComponent, isStandalone: true, selector: "dc-agent-card-detail", inputs: { entityData: { classPropertyName: "entityData", publicName: "entityData", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: "@if (isLoading()) {\n<div class=\"loading-state\">\n <p-progressSpinner strokeWidth=\"4\" />\n</div>\n} @else if (entity()) {\n<div class=\"preview-container\">\n\n <!-- Banner -->\n @if (bannerUrl) {\n <div class=\"preview-banner\">\n <img class=\"banner-image\" [src]=\"bannerUrl\" alt=\"banner\" />\n </div>\n }\n\n <!-- Header: image + name + meta -->\n <div class=\"preview-header\" [class.has-banner]=\"bannerUrl\">\n @if (entity()?.assets?.image?.url) {\n <img class=\"preview-image\" [src]=\"entity()!.assets!.image!.url\" [alt]=\"characterData?.name || entity()?.name\" />\n }\n <div class=\"preview-header-info\">\n <h2 class=\"preview-name\">{{ characterData?.name || entity()?.name }}</h2>\n\n <div class=\"preview-meta-tags\">\n @if (entity()?.lang) {\n <p-tag [value]=\"entity()!.lang!\" severity=\"secondary\" icon=\"pi pi-flag\" />\n }\n @if (entity()?.manageable?.status) {\n <p-tag [value]=\"entity()!.manageable!.status!\" severity=\"info\" icon=\"pi pi-circle-fill\" />\n }\n @if (characterData?.gender) {\n <p-tag [value]=\"characterData!.gender\" severity=\"secondary\" icon=\"pi pi-user\" />\n }\n @if (entity()?.metaApp?.takenCount) {\n <p-tag [value]=\"'Taken: ' + entity()!.metaApp!.takenCount\" severity=\"success\" icon=\"pi pi-users\" />\n }\n @if (learnableInfo?.level) {\n <p-tag [value]=\"'Level ' + learnableInfo.level\" severity=\"warn\" icon=\"pi pi-star\" />\n }\n @if (learnableInfo?.takenCount) {\n <p-tag [value]=\"'Played: ' + learnableInfo.takenCount\" severity=\"secondary\" icon=\"pi pi-play\" />\n }\n </div>\n\n @if (characterData?.tags?.length) {\n <div class=\"preview-tags\">\n @for (tag of characterData!.tags; track tag) {\n <p-tag [value]=\"tag\" severity=\"secondary\" />\n }\n </div>\n }\n </div>\n </div>\n\n <!-- Entity-level description -->\n @if (entity()?.description) {\n <div class=\"preview-entity-description\">\n <p>{{ entity()!.description }}</p>\n </div>\n }\n\n <!-- Motion Videos -->\n @if (motions.length) {\n <div class=\"preview-section motions-top-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-video\"></i> Motion Videos ({{ motions.length }})</h4>\n <div class=\"motions-grid\">\n @for (motion of motions; track $index) {\n @if (motion.metadata?.moodState || motion.metadata?.event) {\n <button class=\"motion-chip\" (click)=\"openMotionVideo(motion)\">\n <i class=\"pi pi-play-circle\"></i>\n <span>{{ motion.metadata?.moodState || motion.metadata?.event }}</span>\n </button>\n }\n }\n </div>\n </div>\n }\n\n <p-divider />\n\n @if (characterData?.hook) {\n <div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-bookmark\"></i> Hook</h4>\n <p>{{ characterData!.hook }}</p>\n </div>\n }\n\n @if (characterData?.instructions) {\n <div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-info-circle\"></i> Instructions</h4>\n <p>{{ characterData!.instructions }}</p>\n </div>\n }\n\n @if (characterData?.scenario) {\n <div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-map\"></i> Scenario</h4>\n <p>{{ characterData!.scenario }}</p>\n </div>\n }\n\n @if (characterData?.creator_notes) {\n <div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-file\"></i> Creator Notes</h4>\n <p>{{ characterData!.creator_notes }}</p>\n </div>\n }\n\n @if (characterData?.description) {\n <div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-align-left\"></i> Description</h4>\n <p>{{ characterData!.description }}</p>\n </div>\n }\n\n @if (characterData?.greetings?.length) {\n <div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-comments\"></i> Greetings</h4>\n @for (greeting of characterData!.greetings; track $index) {\n <p class=\"greeting-item\"><i class=\"pi pi-chevron-right\"></i> {{ greeting }}</p>\n }\n </div>\n }\n\n @if (characterData?.first_mes) {\n <div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-comment\"></i> First Message</h4>\n <p class=\"first-message\">{{ characterData!.first_mes }}</p>\n </div>\n }\n\n @if (persona) {\n <p-divider />\n <div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-id-card\"></i> Persona</h4>\n <div class=\"persona-grid\">\n @if (persona.identity) {\n <div class=\"persona-field\">\n <span class=\"field-label\">Identity</span>\n <span>{{ persona.identity }}</span>\n </div>\n }\n @if (persona.physical) {\n <div class=\"persona-field\">\n <span class=\"field-label\">Physical</span>\n <span>{{ persona.physical }}</span>\n </div>\n }\n @if (persona.personality) {\n <div class=\"persona-field\">\n <span class=\"field-label\">Personality</span>\n <span>{{ persona.personality }}</span>\n </div>\n }\n @if (persona.communication) {\n <div class=\"persona-field\">\n <span class=\"field-label\">Communication</span>\n <span>{{ persona.communication }}</span>\n </div>\n }\n @if (persona.background) {\n <div class=\"persona-field\">\n <span class=\"field-label\">Background</span>\n <span>{{ persona.background }}</span>\n </div>\n }\n @if (persona.psychology) {\n <div class=\"persona-field\">\n <span class=\"field-label\">Psychology</span>\n <span>{{ persona.psychology }}</span>\n </div>\n }\n @if (persona.capabilities) {\n <div class=\"persona-field\">\n <span class=\"field-label\">Capabilities</span>\n <span>{{ persona.capabilities }}</span>\n </div>\n }\n @if (persona.social) {\n <div class=\"persona-field\">\n <span class=\"field-label\">Social</span>\n <span>{{ persona.social }}</span>\n </div>\n }\n @if (persona.preferences) {\n <div class=\"persona-field\">\n <span class=\"field-label\">Preferences</span>\n <span>{{ persona.preferences }}</span>\n </div>\n }\n @if (persona.situation) {\n <div class=\"persona-field\">\n <span class=\"field-label\">Situation</span>\n <span>{{ persona.situation }}</span>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Conversation Settings -->\n @if (entity()?.conversationSettings) {\n <p-divider />\n <div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-sliders-h\"></i> Conversation Settings</h4>\n <div class=\"settings-chips\">\n @if (entity()?.conversationSettings?.conversationType) {\n <p-tag [value]=\"entity()!.conversationSettings!.conversationType!\" severity=\"info\" icon=\"pi pi-comments\" />\n }\n @if (entity()?.conversationSettings?.textEngine) {\n <p-tag [value]=\"entity()!.conversationSettings!.textEngine!\" severity=\"secondary\" icon=\"pi pi-code\" />\n }\n @if (entity()?.conversationSettings?.autoStart) {\n <p-tag value=\"Auto Start\" severity=\"success\" icon=\"pi pi-play\" />\n }\n @if (entity()?.conversationSettings?.userMustStart) {\n <p-tag value=\"User Starts\" severity=\"warn\" icon=\"pi pi-user\" />\n }\n </div>\n </div>\n }\n\n <!-- Voices -->\n @if (entity()?.conversationSettings?.mainVoice?.voice) {\n <div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-volume-up\"></i> Voices</h4>\n <div class=\"voice-info\">\n <p><span class=\"field-label\">Main:</span> {{ entity()!.conversationSettings!.mainVoice!.voice }}</p>\n @if (entity()?.conversationSettings?.secondaryVoice?.voice) {\n <p><span class=\"field-label\">Secondary:</span> {{ entity()!.conversationSettings!.secondaryVoice!.voice }}</p>\n }\n </div>\n </div>\n }\n\n</div>\n}\n\n@if (entity()?.manageable) {\n<p-divider />\n<div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-sliders-h\"></i> Manageable</h4>\n <div class=\"settings-chips\">\n @if (entity()?.manageable?.status) {\n <p-tag [value]=\"entity()!.manageable!.status!\" severity=\"info\" icon=\"pi pi-comments\" />\n }\n @if (entity()?.manageable?.isPublic) {\n <p-tag [value]=\"'Public'\" severity=\"secondary\" icon=\"pi pi-code\" />\n }\n </div>\n</div>\n}\n\n@if (entity()?.learnable) {\n<p-divider />\n<div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-sliders-h\"></i> Learnable</h4>\n <div class=\"settings-chips\">\n @if (entity()?.learnable?.level) {\n <p-tag [value]=\"'Level ' + entity()!.learnable!.level!\" severity=\"info\" icon=\"pi pi-comments\" />\n }\n @if (entity()?.learnable?.tags) {\n <p-tag [value]=\"'Public'\" severity=\"secondary\" icon=\"pi pi-code\" />\n }\n </div>\n</div>\n}\n\n@if(entity()?.conversationFlow) {\n<p-divider />\n<div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-tags\"></i> Conversation Flow</h4>\n\n @if (entity()?.conversationFlow?.moodState) {\n <div class=\"preview-section\">\n <h5 class=\"section-title\"><i class=\"pi pi-face-smile\"></i> Mood State</h5>\n <div class=\"settings-chips\">\n @if (entity()!.conversationFlow!.moodState!.enabled) {\n <p-tag value=\"Enabled\" severity=\"success\" icon=\"pi pi-check\" />\n } @else {\n <p-tag value=\"Disabled\" severity=\"danger\" icon=\"pi pi-times\" />\n }\n @if (entity()!.conversationFlow!.moodState!.useAssetStatesOnly) {\n <p-tag value=\"Asset States Only\" severity=\"warn\" icon=\"pi pi-images\" />\n }\n </div>\n @if (entity()!.conversationFlow!.moodState!.detectableStates?.length) {\n <div class=\"settings-chips\" style=\"margin-top: 0.5rem;\">\n @for (state of entity()!.conversationFlow!.moodState!.detectableStates; track $index) {\n <p-tag [value]=\"state\" severity=\"info\" icon=\"pi pi-tag\" />\n }\n </div>\n }\n </div>\n }\n\n @if (entity()?.conversationFlow?.dynamicConditions?.length) {\n <div class=\"preview-section\">\n <h5 class=\"section-title\"><i class=\"pi pi-sliders-v\"></i> Dynamic Conditions</h5>\n @for (condition of entity()!.conversationFlow!.dynamicConditions!; track $index) {\n <div class=\"persona-field\" style=\"margin-bottom: 0.5rem;\">\n <div class=\"settings-chips\">\n <p-tag [value]=\"condition.what\" severity=\"info\" icon=\"pi pi-filter\" />\n <p-tag [value]=\"condition.when\" severity=\"secondary\" />\n <p-tag [value]=\"condition.value + ''\" severity=\"warn\" />\n </div>\n @if (condition.do?.length) {\n <div class=\"settings-chips\" style=\"margin-top: 0.25rem;\">\n @for (action of condition.do!; track $index) {\n <p-tag [value]=\"action.actionType\" severity=\"contrast\" icon=\"pi pi-bolt\" />\n @if (action.prompt) {\n <span class=\"field-label\" style=\"font-size: 0.75rem;\">{{ action.prompt | slice:0:60 }}\u2026</span>\n }\n }\n </div>\n }\n </div>\n }\n </div>\n }\n\n @if (entity()?.conversationFlow?.triggerTasks) {\n <div class=\"preview-section\">\n <h5 class=\"section-title\"><i class=\"pi pi-bolt\"></i> Trigger Tasks</h5>\n @for (entry of objectEntries(entity()!.conversationFlow!.triggerTasks!); track $index) {\n <div class=\"persona-field\" style=\"margin-bottom: 0.5rem;\">\n <span class=\"field-label\">{{ entry[0] }}</span>\n <div class=\"settings-chips\" style=\"margin-top: 0.25rem;\">\n @if (entry[1].enabled) {\n <p-tag value=\"Enabled\" severity=\"success\" icon=\"pi pi-check\" />\n } @else {\n <p-tag value=\"Disabled\" severity=\"secondary\" icon=\"pi pi-times\" />\n }\n @if (entry[1].disableFeature) {\n <p-tag value=\"Feature Disabled\" severity=\"danger\" icon=\"pi pi-ban\" />\n }\n </div>\n @if (entry[1].task) {\n <p style=\"font-size: 0.8rem; margin: 0.25rem 0 0;\">{{ entry[1].task | slice:0:120 }}\u2026</p>\n }\n </div>\n }\n </div>\n }\n</div>\n}\n\n<!-- Video Dialog -->\n<p-dialog\n [visible]=\"videoDialogVisible()\"\n (visibleChange)=\"$event ? null : closeMotionVideo()\"\n [header]=\"selectedMotion()?.metadata?.moodState || selectedMotion()?.metadata?.event || 'Video'\"\n [modal]=\"true\"\n [dismissableMask]=\"true\"\n [closable]=\"true\"\n styleClass=\"video-dialog\"\n [style]=\"{ width: '560px' }\">\n\n @if (selectedMotion()?.url) {\n <video\n class=\"motion-video\"\n [src]=\"selectedMotion().url\"\n controls\n autoplay>\n </video>\n }\n</p-dialog>\n", styles: [".preview-container{padding:.5rem}.preview-banner{width:100%;height:210px;overflow:hidden;border-radius:8px;margin-bottom:0}.banner-image{width:100%;height:100%;object-fit:cover;display:block}.preview-header{display:flex;gap:1.5rem;align-items:flex-start;padding:1rem 0 .5rem}.preview-header.has-banner{padding-top:.75rem}.preview-image{width:120px;height:170px;object-fit:cover;border-radius:8px;flex-shrink:0;box-shadow:0 2px 8px #00000026}.preview-header-info{display:flex;flex-direction:column;gap:.5rem}.preview-name{margin:0 0 .25rem;font-size:1.5rem;font-weight:700}.preview-meta-tags{display:flex;flex-wrap:wrap;gap:.35rem}.preview-tags{display:flex;flex-wrap:wrap;gap:.25rem;margin-top:.25rem}.preview-entity-description{color:var(--p-text-muted-color);font-size:.9rem;margin:.5rem 0}.preview-entity-description p{margin:0}.preview-section{margin-bottom:1rem}.section-title{margin:0 0 .5rem;font-size:.95rem;font-weight:600;color:var(--p-text-muted-color);display:flex;align-items:center;gap:.4rem}.greeting-item{margin:.25rem 0;padding-left:.5rem;border-left:2px solid var(--p-primary-color)}.first-message{background:var(--p-surface-100);border-radius:6px;padding:.75rem;font-style:italic}.persona-grid{display:flex;flex-direction:column;gap:.5rem}.persona-field{display:flex;flex-direction:column;gap:.15rem}.field-label{font-size:.8rem;font-weight:600;color:var(--p-text-muted-color);text-transform:uppercase;letter-spacing:.05em}.motions-top-section{margin-top:.75rem;margin-bottom:0}.motions-grid{display:flex;flex-wrap:wrap;gap:.4rem}.motion-chip{display:inline-flex;align-items:center;gap:.35rem;padding:.3rem .65rem;border-radius:20px;border:1px solid var(--p-surface-300);background:var(--p-surface-100);color:var(--p-text-color);font-size:.8rem;font-weight:500;cursor:pointer;transition:background .15s,border-color .15s,transform .1s;text-transform:capitalize}.motion-chip i{font-size:.85rem;color:var(--p-primary-color)}.motion-chip:hover{background:var(--p-primary-50, #f0f4ff);border-color:var(--p-primary-color);transform:translateY(-1px)}.motion-chip:active{transform:translateY(0)}.motion-video{width:100%;border-radius:6px;display:block}.settings-chips{display:flex;flex-wrap:wrap;gap:.4rem}.voice-info{display:flex;flex-direction:column;gap:.25rem}.loading-state{display:flex;justify-content:center;padding:2rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: CardModule }, { kind: "ngmodule", type: TagModule }, { kind: "component", type: i1$4.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "ngmodule", type: DividerModule }, { kind: "component", type: i1$3.Divider, selector: "p-divider", inputs: ["styleClass", "layout", "type", "align"] }, { kind: "ngmodule", type: ProgressSpinnerModule }, { kind: "component", type: i3$3.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "ngmodule", type: DialogModule }, { kind: "component", type: i5$1.Dialog, selector: "p-dialog", inputs: ["hostName", "header", "draggable", "resizable", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "maskMotionOptions", "motionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "appendTo", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "pipe", type: i2$1.SlicePipe, name: "slice" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
6022
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: DcAgentCardDetailComponent, isStandalone: true, selector: "dc-agent-card-detail", inputs: { entityData: { classPropertyName: "entityData", publicName: "entityData", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: "@if (isLoading()) {\n<div class=\"loading-state\">\n <p-progressSpinner strokeWidth=\"4\" />\n</div>\n} @else if (entity()) {\n<div class=\"preview-container\">\n\n <!-- Banner -->\n @if (bannerUrl) {\n <div class=\"preview-banner\">\n <img class=\"banner-image\" [src]=\"bannerUrl\" alt=\"banner\" />\n </div>\n }\n\n <!-- Header: image + name + meta -->\n <div class=\"preview-header\" [class.has-banner]=\"bannerUrl\">\n @if (entity()?.assets?.image?.url) {\n <img class=\"preview-image\" [src]=\"entity()!.assets!.image!.url\" [alt]=\"characterData?.name || entity()?.name\" />\n }\n <div class=\"preview-header-info\">\n <h2 class=\"preview-name\">{{ characterData?.name || entity()?.name }}</h2>\n\n <div class=\"preview-meta-tags\">\n @if (entity()?.lang) {\n <p-tag [value]=\"entity()!.lang!\" severity=\"secondary\" icon=\"pi pi-flag\" />\n }\n @if (entity()?.manageable?.status) {\n <p-tag [value]=\"entity()!.manageable!.status!\" severity=\"info\" icon=\"pi pi-circle-fill\" />\n }\n @if (characterData?.gender) {\n <p-tag [value]=\"characterData!.gender\" severity=\"secondary\" icon=\"pi pi-user\" />\n }\n @if (entity()?.metaApp?.takenCount) {\n <p-tag [value]=\"'Taken: ' + entity()!.metaApp!.takenCount\" severity=\"success\" icon=\"pi pi-users\" />\n }\n @if (learnableInfo?.level) {\n <p-tag [value]=\"'Level ' + learnableInfo.level\" severity=\"warn\" icon=\"pi pi-star\" />\n }\n @if (learnableInfo?.takenCount) {\n <p-tag [value]=\"'Played: ' + learnableInfo.takenCount\" severity=\"secondary\" icon=\"pi pi-play\" />\n }\n </div>\n\n @if (characterData?.tags?.length) {\n <div class=\"preview-tags\">\n @for (tag of characterData!.tags; track tag) {\n <p-tag [value]=\"tag\" severity=\"secondary\" />\n }\n </div>\n }\n </div>\n </div>\n\n <!-- Entity-level description -->\n @if (entity()?.description) {\n <div class=\"preview-entity-description\">\n <p>{{ entity()!.description }}</p>\n </div>\n }\n\n <!-- Motion Videos -->\n @if (motions.length) {\n <div class=\"preview-section motions-top-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-video\"></i> Motion Videos ({{ motions.length }})</h4>\n <div class=\"motions-grid\">\n @for (motion of motions; track $index) {\n @if (motion.metadata?.moodState || motion.metadata?.event) {\n <button class=\"motion-chip\" (click)=\"openMotionVideo(motion)\">\n <i class=\"pi pi-play-circle\"></i>\n <span>{{ motion.metadata?.moodState || motion.metadata?.event }}</span>\n </button>\n }\n }\n </div>\n </div>\n }\n\n <p-divider />\n\n @if (characterData?.hook) {\n <div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-bookmark\"></i> Hook</h4>\n <p>{{ characterData!.hook }}</p>\n </div>\n }\n\n @if (characterData?.instructions) {\n <div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-info-circle\"></i> Instructions</h4>\n <p>{{ characterData!.instructions }}</p>\n </div>\n }\n\n @if (characterData?.scenario) {\n <div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-map\"></i> Scenario</h4>\n <p>{{ characterData!.scenario }}</p>\n </div>\n }\n\n @if (characterData?.creator_notes) {\n <div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-file\"></i> Creator Notes</h4>\n <p>{{ characterData!.creator_notes }}</p>\n </div>\n }\n\n @if (characterData?.description) {\n <div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-align-left\"></i> Description</h4>\n <p>{{ characterData!.description }}</p>\n </div>\n }\n\n @if (characterData?.greetings?.length) {\n <div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-comments\"></i> Greetings</h4>\n @for (greeting of characterData!.greetings; track $index) {\n <p class=\"greeting-item\"><i class=\"pi pi-chevron-right\"></i> {{ greeting }}</p>\n }\n </div>\n }\n\n\n @if (persona) {\n <p-divider />\n <div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-id-card\"></i> Persona</h4>\n <div class=\"persona-grid\">\n @if (persona.identity) {\n <div class=\"persona-field\">\n <span class=\"field-label\">Identity</span>\n <span>{{ persona.identity }}</span>\n </div>\n }\n @if (persona.physical) {\n <div class=\"persona-field\">\n <span class=\"field-label\">Physical</span>\n <span>{{ persona.physical }}</span>\n </div>\n }\n @if (persona.personality) {\n <div class=\"persona-field\">\n <span class=\"field-label\">Personality</span>\n <span>{{ persona.personality }}</span>\n </div>\n }\n @if (persona.communication) {\n <div class=\"persona-field\">\n <span class=\"field-label\">Communication</span>\n <span>{{ persona.communication }}</span>\n </div>\n }\n @if (persona.background) {\n <div class=\"persona-field\">\n <span class=\"field-label\">Background</span>\n <span>{{ persona.background }}</span>\n </div>\n }\n @if (persona.psychology) {\n <div class=\"persona-field\">\n <span class=\"field-label\">Psychology</span>\n <span>{{ persona.psychology }}</span>\n </div>\n }\n @if (persona.capabilities) {\n <div class=\"persona-field\">\n <span class=\"field-label\">Capabilities</span>\n <span>{{ persona.capabilities }}</span>\n </div>\n }\n @if (persona.social) {\n <div class=\"persona-field\">\n <span class=\"field-label\">Social</span>\n <span>{{ persona.social }}</span>\n </div>\n }\n @if (persona.preferences) {\n <div class=\"persona-field\">\n <span class=\"field-label\">Preferences</span>\n <span>{{ persona.preferences }}</span>\n </div>\n }\n @if (persona.situation) {\n <div class=\"persona-field\">\n <span class=\"field-label\">Situation</span>\n <span>{{ persona.situation }}</span>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Conversation Settings -->\n @if (entity()?.conversationSettings) {\n <p-divider />\n <div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-sliders-h\"></i> Conversation Settings</h4>\n <div class=\"settings-chips\">\n @if (entity()?.conversationSettings?.conversationType) {\n <p-tag [value]=\"entity()!.conversationSettings!.conversationType!\" severity=\"info\" icon=\"pi pi-comments\" />\n }\n @if (entity()?.conversationSettings?.textEngine) {\n <p-tag [value]=\"entity()!.conversationSettings!.textEngine!\" severity=\"secondary\" icon=\"pi pi-code\" />\n }\n @if (entity()?.conversationSettings?.autoStart) {\n <p-tag value=\"Auto Start\" severity=\"success\" icon=\"pi pi-play\" />\n }\n @if (entity()?.conversationSettings?.userMustStart) {\n <p-tag value=\"User Starts\" severity=\"warn\" icon=\"pi pi-user\" />\n }\n </div>\n </div>\n }\n\n <!-- Voices -->\n @if (entity()?.conversationSettings?.mainVoice?.voice) {\n <div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-volume-up\"></i> Voices</h4>\n <div class=\"voice-info\">\n <p><span class=\"field-label\">Main:</span> {{ entity()!.conversationSettings!.mainVoice!.voice }}</p>\n @if (entity()?.conversationSettings?.secondaryVoice?.voice) {\n <p><span class=\"field-label\">Secondary:</span> {{ entity()!.conversationSettings!.secondaryVoice!.voice }}</p>\n }\n </div>\n </div>\n }\n\n</div>\n}\n\n@if (entity()?.manageable) {\n<p-divider />\n<div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-sliders-h\"></i> Manageable</h4>\n <div class=\"settings-chips\">\n @if (entity()?.manageable?.status) {\n <p-tag [value]=\"entity()!.manageable!.status!\" severity=\"info\" icon=\"pi pi-comments\" />\n }\n @if (entity()?.manageable?.isPublic) {\n <p-tag [value]=\"'Public'\" severity=\"secondary\" icon=\"pi pi-code\" />\n }\n </div>\n</div>\n}\n\n@if (entity()?.learnable) {\n<p-divider />\n<div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-sliders-h\"></i> Learnable</h4>\n <div class=\"settings-chips\">\n @if (entity()?.learnable?.level) {\n <p-tag [value]=\"'Level ' + entity()!.learnable!.level!\" severity=\"info\" icon=\"pi pi-comments\" />\n }\n @if (entity()?.learnable?.tags) {\n <p-tag [value]=\"'Public'\" severity=\"secondary\" icon=\"pi pi-code\" />\n }\n </div>\n</div>\n}\n\n@if(entity()?.conversationFlow) {\n<p-divider />\n<div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-tags\"></i> Conversation Flow</h4>\n\n @if (entity()?.conversationFlow?.moodState) {\n <div class=\"preview-section\">\n <h5 class=\"section-title\"><i class=\"pi pi-face-smile\"></i> Mood State</h5>\n <div class=\"settings-chips\">\n @if (entity()!.conversationFlow!.moodState!.enabled) {\n <p-tag value=\"Enabled\" severity=\"success\" icon=\"pi pi-check\" />\n } @else {\n <p-tag value=\"Disabled\" severity=\"danger\" icon=\"pi pi-times\" />\n }\n @if (entity()!.conversationFlow!.moodState!.useAssetStatesOnly) {\n <p-tag value=\"Asset States Only\" severity=\"warn\" icon=\"pi pi-images\" />\n }\n </div>\n @if (entity()!.conversationFlow!.moodState!.detectableStates?.length) {\n <div class=\"settings-chips\" style=\"margin-top: 0.5rem;\">\n @for (state of entity()!.conversationFlow!.moodState!.detectableStates; track $index) {\n <p-tag [value]=\"state\" severity=\"info\" icon=\"pi pi-tag\" />\n }\n </div>\n }\n </div>\n }\n\n @if (entity()?.conversationFlow?.dynamicConditions?.length) {\n <div class=\"preview-section\">\n <h5 class=\"section-title\"><i class=\"pi pi-sliders-v\"></i> Dynamic Conditions</h5>\n @for (condition of entity()!.conversationFlow!.dynamicConditions!; track $index) {\n <div class=\"persona-field\" style=\"margin-bottom: 0.5rem;\">\n <div class=\"settings-chips\">\n <p-tag [value]=\"condition.what\" severity=\"info\" icon=\"pi pi-filter\" />\n <p-tag [value]=\"condition.when\" severity=\"secondary\" />\n <p-tag [value]=\"condition.value + ''\" severity=\"warn\" />\n </div>\n @if (condition.do?.length) {\n <div class=\"settings-chips\" style=\"margin-top: 0.25rem;\">\n @for (action of condition.do!; track $index) {\n <p-tag [value]=\"action.actionType\" severity=\"contrast\" icon=\"pi pi-bolt\" />\n @if (action.prompt) {\n <span class=\"field-label\" style=\"font-size: 0.75rem;\">{{ action.prompt | slice:0:60 }}\u2026</span>\n }\n }\n </div>\n }\n </div>\n }\n </div>\n }\n\n @if (entity()?.conversationFlow?.triggerTasks) {\n <div class=\"preview-section\">\n <h5 class=\"section-title\"><i class=\"pi pi-bolt\"></i> Trigger Tasks</h5>\n @for (entry of objectEntries(entity()!.conversationFlow!.triggerTasks!); track $index) {\n <div class=\"persona-field\" style=\"margin-bottom: 0.5rem;\">\n <span class=\"field-label\">{{ entry[0] }}</span>\n <div class=\"settings-chips\" style=\"margin-top: 0.25rem;\">\n @if (entry[1].enabled) {\n <p-tag value=\"Enabled\" severity=\"success\" icon=\"pi pi-check\" />\n } @else {\n <p-tag value=\"Disabled\" severity=\"secondary\" icon=\"pi pi-times\" />\n }\n @if (entry[1].disableFeature) {\n <p-tag value=\"Feature Disabled\" severity=\"danger\" icon=\"pi pi-ban\" />\n }\n </div>\n @if (entry[1].task) {\n <p style=\"font-size: 0.8rem; margin: 0.25rem 0 0;\">{{ entry[1].task | slice:0:120 }}\u2026</p>\n }\n </div>\n }\n </div>\n }\n</div>\n}\n\n<!-- Video Dialog -->\n<p-dialog\n [visible]=\"videoDialogVisible()\"\n (visibleChange)=\"$event ? null : closeMotionVideo()\"\n [header]=\"selectedMotion()?.metadata?.moodState || selectedMotion()?.metadata?.event || 'Video'\"\n [modal]=\"true\"\n [dismissableMask]=\"true\"\n [closable]=\"true\"\n styleClass=\"video-dialog\"\n [style]=\"{ width: '560px' }\">\n\n @if (selectedMotion()?.url) {\n <video\n class=\"motion-video\"\n [src]=\"selectedMotion().url\"\n controls\n autoplay>\n </video>\n }\n</p-dialog>\n", styles: [".preview-container{padding:.5rem}.preview-banner{width:100%;height:210px;overflow:hidden;border-radius:8px;margin-bottom:0}.banner-image{width:100%;height:100%;object-fit:cover;display:block}.preview-header{display:flex;gap:1.5rem;align-items:flex-start;padding:1rem 0 .5rem}.preview-header.has-banner{padding-top:.75rem}.preview-image{width:120px;height:170px;object-fit:cover;border-radius:8px;flex-shrink:0;box-shadow:0 2px 8px #00000026}.preview-header-info{display:flex;flex-direction:column;gap:.5rem}.preview-name{margin:0 0 .25rem;font-size:1.5rem;font-weight:700}.preview-meta-tags{display:flex;flex-wrap:wrap;gap:.35rem}.preview-tags{display:flex;flex-wrap:wrap;gap:.25rem;margin-top:.25rem}.preview-entity-description{color:var(--p-text-muted-color);font-size:.9rem;margin:.5rem 0}.preview-entity-description p{margin:0}.preview-section{margin-bottom:1rem}.section-title{margin:0 0 .5rem;font-size:.95rem;font-weight:600;color:var(--p-text-muted-color);display:flex;align-items:center;gap:.4rem}.greeting-item{margin:.25rem 0;padding-left:.5rem;border-left:2px solid var(--p-primary-color)}.first-message{background:var(--p-surface-100);border-radius:6px;padding:.75rem;font-style:italic}.persona-grid{display:flex;flex-direction:column;gap:.5rem}.persona-field{display:flex;flex-direction:column;gap:.15rem}.field-label{font-size:.8rem;font-weight:600;color:var(--p-text-muted-color);text-transform:uppercase;letter-spacing:.05em}.motions-top-section{margin-top:.75rem;margin-bottom:0}.motions-grid{display:flex;flex-wrap:wrap;gap:.4rem}.motion-chip{display:inline-flex;align-items:center;gap:.35rem;padding:.3rem .65rem;border-radius:20px;border:1px solid var(--p-surface-300);background:var(--p-surface-100);color:var(--p-text-color);font-size:.8rem;font-weight:500;cursor:pointer;transition:background .15s,border-color .15s,transform .1s;text-transform:capitalize}.motion-chip i{font-size:.85rem;color:var(--p-primary-color)}.motion-chip:hover{background:var(--p-primary-50, #f0f4ff);border-color:var(--p-primary-color);transform:translateY(-1px)}.motion-chip:active{transform:translateY(0)}.motion-video{width:100%;border-radius:6px;display:block}.settings-chips{display:flex;flex-wrap:wrap;gap:.4rem}.voice-info{display:flex;flex-direction:column;gap:.25rem}.loading-state{display:flex;justify-content:center;padding:2rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: CardModule }, { kind: "ngmodule", type: TagModule }, { kind: "component", type: i1$3.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "ngmodule", type: DividerModule }, { kind: "component", type: i2$4.Divider, selector: "p-divider", inputs: ["styleClass", "layout", "type", "align"] }, { kind: "ngmodule", type: ProgressSpinnerModule }, { kind: "component", type: i3$3.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "ngmodule", type: DialogModule }, { kind: "component", type: i5$1.Dialog, selector: "p-dialog", inputs: ["hostName", "header", "draggable", "resizable", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "maskMotionOptions", "motionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "appendTo", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "pipe", type: i2$1.SlicePipe, name: "slice" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
5601
6023
  }
5602
6024
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DcAgentCardDetailComponent, decorators: [{
5603
6025
  type: Component,
5604
- args: [{ selector: 'dc-agent-card-detail', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule, CardModule, TagModule, DividerModule, ProgressSpinnerModule, DialogModule, ButtonModule], template: "@if (isLoading()) {\n<div class=\"loading-state\">\n <p-progressSpinner strokeWidth=\"4\" />\n</div>\n} @else if (entity()) {\n<div class=\"preview-container\">\n\n <!-- Banner -->\n @if (bannerUrl) {\n <div class=\"preview-banner\">\n <img class=\"banner-image\" [src]=\"bannerUrl\" alt=\"banner\" />\n </div>\n }\n\n <!-- Header: image + name + meta -->\n <div class=\"preview-header\" [class.has-banner]=\"bannerUrl\">\n @if (entity()?.assets?.image?.url) {\n <img class=\"preview-image\" [src]=\"entity()!.assets!.image!.url\" [alt]=\"characterData?.name || entity()?.name\" />\n }\n <div class=\"preview-header-info\">\n <h2 class=\"preview-name\">{{ characterData?.name || entity()?.name }}</h2>\n\n <div class=\"preview-meta-tags\">\n @if (entity()?.lang) {\n <p-tag [value]=\"entity()!.lang!\" severity=\"secondary\" icon=\"pi pi-flag\" />\n }\n @if (entity()?.manageable?.status) {\n <p-tag [value]=\"entity()!.manageable!.status!\" severity=\"info\" icon=\"pi pi-circle-fill\" />\n }\n @if (characterData?.gender) {\n <p-tag [value]=\"characterData!.gender\" severity=\"secondary\" icon=\"pi pi-user\" />\n }\n @if (entity()?.metaApp?.takenCount) {\n <p-tag [value]=\"'Taken: ' + entity()!.metaApp!.takenCount\" severity=\"success\" icon=\"pi pi-users\" />\n }\n @if (learnableInfo?.level) {\n <p-tag [value]=\"'Level ' + learnableInfo.level\" severity=\"warn\" icon=\"pi pi-star\" />\n }\n @if (learnableInfo?.takenCount) {\n <p-tag [value]=\"'Played: ' + learnableInfo.takenCount\" severity=\"secondary\" icon=\"pi pi-play\" />\n }\n </div>\n\n @if (characterData?.tags?.length) {\n <div class=\"preview-tags\">\n @for (tag of characterData!.tags; track tag) {\n <p-tag [value]=\"tag\" severity=\"secondary\" />\n }\n </div>\n }\n </div>\n </div>\n\n <!-- Entity-level description -->\n @if (entity()?.description) {\n <div class=\"preview-entity-description\">\n <p>{{ entity()!.description }}</p>\n </div>\n }\n\n <!-- Motion Videos -->\n @if (motions.length) {\n <div class=\"preview-section motions-top-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-video\"></i> Motion Videos ({{ motions.length }})</h4>\n <div class=\"motions-grid\">\n @for (motion of motions; track $index) {\n @if (motion.metadata?.moodState || motion.metadata?.event) {\n <button class=\"motion-chip\" (click)=\"openMotionVideo(motion)\">\n <i class=\"pi pi-play-circle\"></i>\n <span>{{ motion.metadata?.moodState || motion.metadata?.event }}</span>\n </button>\n }\n }\n </div>\n </div>\n }\n\n <p-divider />\n\n @if (characterData?.hook) {\n <div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-bookmark\"></i> Hook</h4>\n <p>{{ characterData!.hook }}</p>\n </div>\n }\n\n @if (characterData?.instructions) {\n <div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-info-circle\"></i> Instructions</h4>\n <p>{{ characterData!.instructions }}</p>\n </div>\n }\n\n @if (characterData?.scenario) {\n <div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-map\"></i> Scenario</h4>\n <p>{{ characterData!.scenario }}</p>\n </div>\n }\n\n @if (characterData?.creator_notes) {\n <div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-file\"></i> Creator Notes</h4>\n <p>{{ characterData!.creator_notes }}</p>\n </div>\n }\n\n @if (characterData?.description) {\n <div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-align-left\"></i> Description</h4>\n <p>{{ characterData!.description }}</p>\n </div>\n }\n\n @if (characterData?.greetings?.length) {\n <div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-comments\"></i> Greetings</h4>\n @for (greeting of characterData!.greetings; track $index) {\n <p class=\"greeting-item\"><i class=\"pi pi-chevron-right\"></i> {{ greeting }}</p>\n }\n </div>\n }\n\n @if (characterData?.first_mes) {\n <div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-comment\"></i> First Message</h4>\n <p class=\"first-message\">{{ characterData!.first_mes }}</p>\n </div>\n }\n\n @if (persona) {\n <p-divider />\n <div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-id-card\"></i> Persona</h4>\n <div class=\"persona-grid\">\n @if (persona.identity) {\n <div class=\"persona-field\">\n <span class=\"field-label\">Identity</span>\n <span>{{ persona.identity }}</span>\n </div>\n }\n @if (persona.physical) {\n <div class=\"persona-field\">\n <span class=\"field-label\">Physical</span>\n <span>{{ persona.physical }}</span>\n </div>\n }\n @if (persona.personality) {\n <div class=\"persona-field\">\n <span class=\"field-label\">Personality</span>\n <span>{{ persona.personality }}</span>\n </div>\n }\n @if (persona.communication) {\n <div class=\"persona-field\">\n <span class=\"field-label\">Communication</span>\n <span>{{ persona.communication }}</span>\n </div>\n }\n @if (persona.background) {\n <div class=\"persona-field\">\n <span class=\"field-label\">Background</span>\n <span>{{ persona.background }}</span>\n </div>\n }\n @if (persona.psychology) {\n <div class=\"persona-field\">\n <span class=\"field-label\">Psychology</span>\n <span>{{ persona.psychology }}</span>\n </div>\n }\n @if (persona.capabilities) {\n <div class=\"persona-field\">\n <span class=\"field-label\">Capabilities</span>\n <span>{{ persona.capabilities }}</span>\n </div>\n }\n @if (persona.social) {\n <div class=\"persona-field\">\n <span class=\"field-label\">Social</span>\n <span>{{ persona.social }}</span>\n </div>\n }\n @if (persona.preferences) {\n <div class=\"persona-field\">\n <span class=\"field-label\">Preferences</span>\n <span>{{ persona.preferences }}</span>\n </div>\n }\n @if (persona.situation) {\n <div class=\"persona-field\">\n <span class=\"field-label\">Situation</span>\n <span>{{ persona.situation }}</span>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Conversation Settings -->\n @if (entity()?.conversationSettings) {\n <p-divider />\n <div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-sliders-h\"></i> Conversation Settings</h4>\n <div class=\"settings-chips\">\n @if (entity()?.conversationSettings?.conversationType) {\n <p-tag [value]=\"entity()!.conversationSettings!.conversationType!\" severity=\"info\" icon=\"pi pi-comments\" />\n }\n @if (entity()?.conversationSettings?.textEngine) {\n <p-tag [value]=\"entity()!.conversationSettings!.textEngine!\" severity=\"secondary\" icon=\"pi pi-code\" />\n }\n @if (entity()?.conversationSettings?.autoStart) {\n <p-tag value=\"Auto Start\" severity=\"success\" icon=\"pi pi-play\" />\n }\n @if (entity()?.conversationSettings?.userMustStart) {\n <p-tag value=\"User Starts\" severity=\"warn\" icon=\"pi pi-user\" />\n }\n </div>\n </div>\n }\n\n <!-- Voices -->\n @if (entity()?.conversationSettings?.mainVoice?.voice) {\n <div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-volume-up\"></i> Voices</h4>\n <div class=\"voice-info\">\n <p><span class=\"field-label\">Main:</span> {{ entity()!.conversationSettings!.mainVoice!.voice }}</p>\n @if (entity()?.conversationSettings?.secondaryVoice?.voice) {\n <p><span class=\"field-label\">Secondary:</span> {{ entity()!.conversationSettings!.secondaryVoice!.voice }}</p>\n }\n </div>\n </div>\n }\n\n</div>\n}\n\n@if (entity()?.manageable) {\n<p-divider />\n<div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-sliders-h\"></i> Manageable</h4>\n <div class=\"settings-chips\">\n @if (entity()?.manageable?.status) {\n <p-tag [value]=\"entity()!.manageable!.status!\" severity=\"info\" icon=\"pi pi-comments\" />\n }\n @if (entity()?.manageable?.isPublic) {\n <p-tag [value]=\"'Public'\" severity=\"secondary\" icon=\"pi pi-code\" />\n }\n </div>\n</div>\n}\n\n@if (entity()?.learnable) {\n<p-divider />\n<div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-sliders-h\"></i> Learnable</h4>\n <div class=\"settings-chips\">\n @if (entity()?.learnable?.level) {\n <p-tag [value]=\"'Level ' + entity()!.learnable!.level!\" severity=\"info\" icon=\"pi pi-comments\" />\n }\n @if (entity()?.learnable?.tags) {\n <p-tag [value]=\"'Public'\" severity=\"secondary\" icon=\"pi pi-code\" />\n }\n </div>\n</div>\n}\n\n@if(entity()?.conversationFlow) {\n<p-divider />\n<div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-tags\"></i> Conversation Flow</h4>\n\n @if (entity()?.conversationFlow?.moodState) {\n <div class=\"preview-section\">\n <h5 class=\"section-title\"><i class=\"pi pi-face-smile\"></i> Mood State</h5>\n <div class=\"settings-chips\">\n @if (entity()!.conversationFlow!.moodState!.enabled) {\n <p-tag value=\"Enabled\" severity=\"success\" icon=\"pi pi-check\" />\n } @else {\n <p-tag value=\"Disabled\" severity=\"danger\" icon=\"pi pi-times\" />\n }\n @if (entity()!.conversationFlow!.moodState!.useAssetStatesOnly) {\n <p-tag value=\"Asset States Only\" severity=\"warn\" icon=\"pi pi-images\" />\n }\n </div>\n @if (entity()!.conversationFlow!.moodState!.detectableStates?.length) {\n <div class=\"settings-chips\" style=\"margin-top: 0.5rem;\">\n @for (state of entity()!.conversationFlow!.moodState!.detectableStates; track $index) {\n <p-tag [value]=\"state\" severity=\"info\" icon=\"pi pi-tag\" />\n }\n </div>\n }\n </div>\n }\n\n @if (entity()?.conversationFlow?.dynamicConditions?.length) {\n <div class=\"preview-section\">\n <h5 class=\"section-title\"><i class=\"pi pi-sliders-v\"></i> Dynamic Conditions</h5>\n @for (condition of entity()!.conversationFlow!.dynamicConditions!; track $index) {\n <div class=\"persona-field\" style=\"margin-bottom: 0.5rem;\">\n <div class=\"settings-chips\">\n <p-tag [value]=\"condition.what\" severity=\"info\" icon=\"pi pi-filter\" />\n <p-tag [value]=\"condition.when\" severity=\"secondary\" />\n <p-tag [value]=\"condition.value + ''\" severity=\"warn\" />\n </div>\n @if (condition.do?.length) {\n <div class=\"settings-chips\" style=\"margin-top: 0.25rem;\">\n @for (action of condition.do!; track $index) {\n <p-tag [value]=\"action.actionType\" severity=\"contrast\" icon=\"pi pi-bolt\" />\n @if (action.prompt) {\n <span class=\"field-label\" style=\"font-size: 0.75rem;\">{{ action.prompt | slice:0:60 }}\u2026</span>\n }\n }\n </div>\n }\n </div>\n }\n </div>\n }\n\n @if (entity()?.conversationFlow?.triggerTasks) {\n <div class=\"preview-section\">\n <h5 class=\"section-title\"><i class=\"pi pi-bolt\"></i> Trigger Tasks</h5>\n @for (entry of objectEntries(entity()!.conversationFlow!.triggerTasks!); track $index) {\n <div class=\"persona-field\" style=\"margin-bottom: 0.5rem;\">\n <span class=\"field-label\">{{ entry[0] }}</span>\n <div class=\"settings-chips\" style=\"margin-top: 0.25rem;\">\n @if (entry[1].enabled) {\n <p-tag value=\"Enabled\" severity=\"success\" icon=\"pi pi-check\" />\n } @else {\n <p-tag value=\"Disabled\" severity=\"secondary\" icon=\"pi pi-times\" />\n }\n @if (entry[1].disableFeature) {\n <p-tag value=\"Feature Disabled\" severity=\"danger\" icon=\"pi pi-ban\" />\n }\n </div>\n @if (entry[1].task) {\n <p style=\"font-size: 0.8rem; margin: 0.25rem 0 0;\">{{ entry[1].task | slice:0:120 }}\u2026</p>\n }\n </div>\n }\n </div>\n }\n</div>\n}\n\n<!-- Video Dialog -->\n<p-dialog\n [visible]=\"videoDialogVisible()\"\n (visibleChange)=\"$event ? null : closeMotionVideo()\"\n [header]=\"selectedMotion()?.metadata?.moodState || selectedMotion()?.metadata?.event || 'Video'\"\n [modal]=\"true\"\n [dismissableMask]=\"true\"\n [closable]=\"true\"\n styleClass=\"video-dialog\"\n [style]=\"{ width: '560px' }\">\n\n @if (selectedMotion()?.url) {\n <video\n class=\"motion-video\"\n [src]=\"selectedMotion().url\"\n controls\n autoplay>\n </video>\n }\n</p-dialog>\n", styles: [".preview-container{padding:.5rem}.preview-banner{width:100%;height:210px;overflow:hidden;border-radius:8px;margin-bottom:0}.banner-image{width:100%;height:100%;object-fit:cover;display:block}.preview-header{display:flex;gap:1.5rem;align-items:flex-start;padding:1rem 0 .5rem}.preview-header.has-banner{padding-top:.75rem}.preview-image{width:120px;height:170px;object-fit:cover;border-radius:8px;flex-shrink:0;box-shadow:0 2px 8px #00000026}.preview-header-info{display:flex;flex-direction:column;gap:.5rem}.preview-name{margin:0 0 .25rem;font-size:1.5rem;font-weight:700}.preview-meta-tags{display:flex;flex-wrap:wrap;gap:.35rem}.preview-tags{display:flex;flex-wrap:wrap;gap:.25rem;margin-top:.25rem}.preview-entity-description{color:var(--p-text-muted-color);font-size:.9rem;margin:.5rem 0}.preview-entity-description p{margin:0}.preview-section{margin-bottom:1rem}.section-title{margin:0 0 .5rem;font-size:.95rem;font-weight:600;color:var(--p-text-muted-color);display:flex;align-items:center;gap:.4rem}.greeting-item{margin:.25rem 0;padding-left:.5rem;border-left:2px solid var(--p-primary-color)}.first-message{background:var(--p-surface-100);border-radius:6px;padding:.75rem;font-style:italic}.persona-grid{display:flex;flex-direction:column;gap:.5rem}.persona-field{display:flex;flex-direction:column;gap:.15rem}.field-label{font-size:.8rem;font-weight:600;color:var(--p-text-muted-color);text-transform:uppercase;letter-spacing:.05em}.motions-top-section{margin-top:.75rem;margin-bottom:0}.motions-grid{display:flex;flex-wrap:wrap;gap:.4rem}.motion-chip{display:inline-flex;align-items:center;gap:.35rem;padding:.3rem .65rem;border-radius:20px;border:1px solid var(--p-surface-300);background:var(--p-surface-100);color:var(--p-text-color);font-size:.8rem;font-weight:500;cursor:pointer;transition:background .15s,border-color .15s,transform .1s;text-transform:capitalize}.motion-chip i{font-size:.85rem;color:var(--p-primary-color)}.motion-chip:hover{background:var(--p-primary-50, #f0f4ff);border-color:var(--p-primary-color);transform:translateY(-1px)}.motion-chip:active{transform:translateY(0)}.motion-video{width:100%;border-radius:6px;display:block}.settings-chips{display:flex;flex-wrap:wrap;gap:.4rem}.voice-info{display:flex;flex-direction:column;gap:.25rem}.loading-state{display:flex;justify-content:center;padding:2rem}\n"] }]
6026
+ args: [{ selector: 'dc-agent-card-detail', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule, CardModule, TagModule, DividerModule, ProgressSpinnerModule, DialogModule, ButtonModule], template: "@if (isLoading()) {\n<div class=\"loading-state\">\n <p-progressSpinner strokeWidth=\"4\" />\n</div>\n} @else if (entity()) {\n<div class=\"preview-container\">\n\n <!-- Banner -->\n @if (bannerUrl) {\n <div class=\"preview-banner\">\n <img class=\"banner-image\" [src]=\"bannerUrl\" alt=\"banner\" />\n </div>\n }\n\n <!-- Header: image + name + meta -->\n <div class=\"preview-header\" [class.has-banner]=\"bannerUrl\">\n @if (entity()?.assets?.image?.url) {\n <img class=\"preview-image\" [src]=\"entity()!.assets!.image!.url\" [alt]=\"characterData?.name || entity()?.name\" />\n }\n <div class=\"preview-header-info\">\n <h2 class=\"preview-name\">{{ characterData?.name || entity()?.name }}</h2>\n\n <div class=\"preview-meta-tags\">\n @if (entity()?.lang) {\n <p-tag [value]=\"entity()!.lang!\" severity=\"secondary\" icon=\"pi pi-flag\" />\n }\n @if (entity()?.manageable?.status) {\n <p-tag [value]=\"entity()!.manageable!.status!\" severity=\"info\" icon=\"pi pi-circle-fill\" />\n }\n @if (characterData?.gender) {\n <p-tag [value]=\"characterData!.gender\" severity=\"secondary\" icon=\"pi pi-user\" />\n }\n @if (entity()?.metaApp?.takenCount) {\n <p-tag [value]=\"'Taken: ' + entity()!.metaApp!.takenCount\" severity=\"success\" icon=\"pi pi-users\" />\n }\n @if (learnableInfo?.level) {\n <p-tag [value]=\"'Level ' + learnableInfo.level\" severity=\"warn\" icon=\"pi pi-star\" />\n }\n @if (learnableInfo?.takenCount) {\n <p-tag [value]=\"'Played: ' + learnableInfo.takenCount\" severity=\"secondary\" icon=\"pi pi-play\" />\n }\n </div>\n\n @if (characterData?.tags?.length) {\n <div class=\"preview-tags\">\n @for (tag of characterData!.tags; track tag) {\n <p-tag [value]=\"tag\" severity=\"secondary\" />\n }\n </div>\n }\n </div>\n </div>\n\n <!-- Entity-level description -->\n @if (entity()?.description) {\n <div class=\"preview-entity-description\">\n <p>{{ entity()!.description }}</p>\n </div>\n }\n\n <!-- Motion Videos -->\n @if (motions.length) {\n <div class=\"preview-section motions-top-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-video\"></i> Motion Videos ({{ motions.length }})</h4>\n <div class=\"motions-grid\">\n @for (motion of motions; track $index) {\n @if (motion.metadata?.moodState || motion.metadata?.event) {\n <button class=\"motion-chip\" (click)=\"openMotionVideo(motion)\">\n <i class=\"pi pi-play-circle\"></i>\n <span>{{ motion.metadata?.moodState || motion.metadata?.event }}</span>\n </button>\n }\n }\n </div>\n </div>\n }\n\n <p-divider />\n\n @if (characterData?.hook) {\n <div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-bookmark\"></i> Hook</h4>\n <p>{{ characterData!.hook }}</p>\n </div>\n }\n\n @if (characterData?.instructions) {\n <div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-info-circle\"></i> Instructions</h4>\n <p>{{ characterData!.instructions }}</p>\n </div>\n }\n\n @if (characterData?.scenario) {\n <div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-map\"></i> Scenario</h4>\n <p>{{ characterData!.scenario }}</p>\n </div>\n }\n\n @if (characterData?.creator_notes) {\n <div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-file\"></i> Creator Notes</h4>\n <p>{{ characterData!.creator_notes }}</p>\n </div>\n }\n\n @if (characterData?.description) {\n <div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-align-left\"></i> Description</h4>\n <p>{{ characterData!.description }}</p>\n </div>\n }\n\n @if (characterData?.greetings?.length) {\n <div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-comments\"></i> Greetings</h4>\n @for (greeting of characterData!.greetings; track $index) {\n <p class=\"greeting-item\"><i class=\"pi pi-chevron-right\"></i> {{ greeting }}</p>\n }\n </div>\n }\n\n\n @if (persona) {\n <p-divider />\n <div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-id-card\"></i> Persona</h4>\n <div class=\"persona-grid\">\n @if (persona.identity) {\n <div class=\"persona-field\">\n <span class=\"field-label\">Identity</span>\n <span>{{ persona.identity }}</span>\n </div>\n }\n @if (persona.physical) {\n <div class=\"persona-field\">\n <span class=\"field-label\">Physical</span>\n <span>{{ persona.physical }}</span>\n </div>\n }\n @if (persona.personality) {\n <div class=\"persona-field\">\n <span class=\"field-label\">Personality</span>\n <span>{{ persona.personality }}</span>\n </div>\n }\n @if (persona.communication) {\n <div class=\"persona-field\">\n <span class=\"field-label\">Communication</span>\n <span>{{ persona.communication }}</span>\n </div>\n }\n @if (persona.background) {\n <div class=\"persona-field\">\n <span class=\"field-label\">Background</span>\n <span>{{ persona.background }}</span>\n </div>\n }\n @if (persona.psychology) {\n <div class=\"persona-field\">\n <span class=\"field-label\">Psychology</span>\n <span>{{ persona.psychology }}</span>\n </div>\n }\n @if (persona.capabilities) {\n <div class=\"persona-field\">\n <span class=\"field-label\">Capabilities</span>\n <span>{{ persona.capabilities }}</span>\n </div>\n }\n @if (persona.social) {\n <div class=\"persona-field\">\n <span class=\"field-label\">Social</span>\n <span>{{ persona.social }}</span>\n </div>\n }\n @if (persona.preferences) {\n <div class=\"persona-field\">\n <span class=\"field-label\">Preferences</span>\n <span>{{ persona.preferences }}</span>\n </div>\n }\n @if (persona.situation) {\n <div class=\"persona-field\">\n <span class=\"field-label\">Situation</span>\n <span>{{ persona.situation }}</span>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Conversation Settings -->\n @if (entity()?.conversationSettings) {\n <p-divider />\n <div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-sliders-h\"></i> Conversation Settings</h4>\n <div class=\"settings-chips\">\n @if (entity()?.conversationSettings?.conversationType) {\n <p-tag [value]=\"entity()!.conversationSettings!.conversationType!\" severity=\"info\" icon=\"pi pi-comments\" />\n }\n @if (entity()?.conversationSettings?.textEngine) {\n <p-tag [value]=\"entity()!.conversationSettings!.textEngine!\" severity=\"secondary\" icon=\"pi pi-code\" />\n }\n @if (entity()?.conversationSettings?.autoStart) {\n <p-tag value=\"Auto Start\" severity=\"success\" icon=\"pi pi-play\" />\n }\n @if (entity()?.conversationSettings?.userMustStart) {\n <p-tag value=\"User Starts\" severity=\"warn\" icon=\"pi pi-user\" />\n }\n </div>\n </div>\n }\n\n <!-- Voices -->\n @if (entity()?.conversationSettings?.mainVoice?.voice) {\n <div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-volume-up\"></i> Voices</h4>\n <div class=\"voice-info\">\n <p><span class=\"field-label\">Main:</span> {{ entity()!.conversationSettings!.mainVoice!.voice }}</p>\n @if (entity()?.conversationSettings?.secondaryVoice?.voice) {\n <p><span class=\"field-label\">Secondary:</span> {{ entity()!.conversationSettings!.secondaryVoice!.voice }}</p>\n }\n </div>\n </div>\n }\n\n</div>\n}\n\n@if (entity()?.manageable) {\n<p-divider />\n<div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-sliders-h\"></i> Manageable</h4>\n <div class=\"settings-chips\">\n @if (entity()?.manageable?.status) {\n <p-tag [value]=\"entity()!.manageable!.status!\" severity=\"info\" icon=\"pi pi-comments\" />\n }\n @if (entity()?.manageable?.isPublic) {\n <p-tag [value]=\"'Public'\" severity=\"secondary\" icon=\"pi pi-code\" />\n }\n </div>\n</div>\n}\n\n@if (entity()?.learnable) {\n<p-divider />\n<div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-sliders-h\"></i> Learnable</h4>\n <div class=\"settings-chips\">\n @if (entity()?.learnable?.level) {\n <p-tag [value]=\"'Level ' + entity()!.learnable!.level!\" severity=\"info\" icon=\"pi pi-comments\" />\n }\n @if (entity()?.learnable?.tags) {\n <p-tag [value]=\"'Public'\" severity=\"secondary\" icon=\"pi pi-code\" />\n }\n </div>\n</div>\n}\n\n@if(entity()?.conversationFlow) {\n<p-divider />\n<div class=\"preview-section\">\n <h4 class=\"section-title\"><i class=\"pi pi-tags\"></i> Conversation Flow</h4>\n\n @if (entity()?.conversationFlow?.moodState) {\n <div class=\"preview-section\">\n <h5 class=\"section-title\"><i class=\"pi pi-face-smile\"></i> Mood State</h5>\n <div class=\"settings-chips\">\n @if (entity()!.conversationFlow!.moodState!.enabled) {\n <p-tag value=\"Enabled\" severity=\"success\" icon=\"pi pi-check\" />\n } @else {\n <p-tag value=\"Disabled\" severity=\"danger\" icon=\"pi pi-times\" />\n }\n @if (entity()!.conversationFlow!.moodState!.useAssetStatesOnly) {\n <p-tag value=\"Asset States Only\" severity=\"warn\" icon=\"pi pi-images\" />\n }\n </div>\n @if (entity()!.conversationFlow!.moodState!.detectableStates?.length) {\n <div class=\"settings-chips\" style=\"margin-top: 0.5rem;\">\n @for (state of entity()!.conversationFlow!.moodState!.detectableStates; track $index) {\n <p-tag [value]=\"state\" severity=\"info\" icon=\"pi pi-tag\" />\n }\n </div>\n }\n </div>\n }\n\n @if (entity()?.conversationFlow?.dynamicConditions?.length) {\n <div class=\"preview-section\">\n <h5 class=\"section-title\"><i class=\"pi pi-sliders-v\"></i> Dynamic Conditions</h5>\n @for (condition of entity()!.conversationFlow!.dynamicConditions!; track $index) {\n <div class=\"persona-field\" style=\"margin-bottom: 0.5rem;\">\n <div class=\"settings-chips\">\n <p-tag [value]=\"condition.what\" severity=\"info\" icon=\"pi pi-filter\" />\n <p-tag [value]=\"condition.when\" severity=\"secondary\" />\n <p-tag [value]=\"condition.value + ''\" severity=\"warn\" />\n </div>\n @if (condition.do?.length) {\n <div class=\"settings-chips\" style=\"margin-top: 0.25rem;\">\n @for (action of condition.do!; track $index) {\n <p-tag [value]=\"action.actionType\" severity=\"contrast\" icon=\"pi pi-bolt\" />\n @if (action.prompt) {\n <span class=\"field-label\" style=\"font-size: 0.75rem;\">{{ action.prompt | slice:0:60 }}\u2026</span>\n }\n }\n </div>\n }\n </div>\n }\n </div>\n }\n\n @if (entity()?.conversationFlow?.triggerTasks) {\n <div class=\"preview-section\">\n <h5 class=\"section-title\"><i class=\"pi pi-bolt\"></i> Trigger Tasks</h5>\n @for (entry of objectEntries(entity()!.conversationFlow!.triggerTasks!); track $index) {\n <div class=\"persona-field\" style=\"margin-bottom: 0.5rem;\">\n <span class=\"field-label\">{{ entry[0] }}</span>\n <div class=\"settings-chips\" style=\"margin-top: 0.25rem;\">\n @if (entry[1].enabled) {\n <p-tag value=\"Enabled\" severity=\"success\" icon=\"pi pi-check\" />\n } @else {\n <p-tag value=\"Disabled\" severity=\"secondary\" icon=\"pi pi-times\" />\n }\n @if (entry[1].disableFeature) {\n <p-tag value=\"Feature Disabled\" severity=\"danger\" icon=\"pi pi-ban\" />\n }\n </div>\n @if (entry[1].task) {\n <p style=\"font-size: 0.8rem; margin: 0.25rem 0 0;\">{{ entry[1].task | slice:0:120 }}\u2026</p>\n }\n </div>\n }\n </div>\n }\n</div>\n}\n\n<!-- Video Dialog -->\n<p-dialog\n [visible]=\"videoDialogVisible()\"\n (visibleChange)=\"$event ? null : closeMotionVideo()\"\n [header]=\"selectedMotion()?.metadata?.moodState || selectedMotion()?.metadata?.event || 'Video'\"\n [modal]=\"true\"\n [dismissableMask]=\"true\"\n [closable]=\"true\"\n styleClass=\"video-dialog\"\n [style]=\"{ width: '560px' }\">\n\n @if (selectedMotion()?.url) {\n <video\n class=\"motion-video\"\n [src]=\"selectedMotion().url\"\n controls\n autoplay>\n </video>\n }\n</p-dialog>\n", styles: [".preview-container{padding:.5rem}.preview-banner{width:100%;height:210px;overflow:hidden;border-radius:8px;margin-bottom:0}.banner-image{width:100%;height:100%;object-fit:cover;display:block}.preview-header{display:flex;gap:1.5rem;align-items:flex-start;padding:1rem 0 .5rem}.preview-header.has-banner{padding-top:.75rem}.preview-image{width:120px;height:170px;object-fit:cover;border-radius:8px;flex-shrink:0;box-shadow:0 2px 8px #00000026}.preview-header-info{display:flex;flex-direction:column;gap:.5rem}.preview-name{margin:0 0 .25rem;font-size:1.5rem;font-weight:700}.preview-meta-tags{display:flex;flex-wrap:wrap;gap:.35rem}.preview-tags{display:flex;flex-wrap:wrap;gap:.25rem;margin-top:.25rem}.preview-entity-description{color:var(--p-text-muted-color);font-size:.9rem;margin:.5rem 0}.preview-entity-description p{margin:0}.preview-section{margin-bottom:1rem}.section-title{margin:0 0 .5rem;font-size:.95rem;font-weight:600;color:var(--p-text-muted-color);display:flex;align-items:center;gap:.4rem}.greeting-item{margin:.25rem 0;padding-left:.5rem;border-left:2px solid var(--p-primary-color)}.first-message{background:var(--p-surface-100);border-radius:6px;padding:.75rem;font-style:italic}.persona-grid{display:flex;flex-direction:column;gap:.5rem}.persona-field{display:flex;flex-direction:column;gap:.15rem}.field-label{font-size:.8rem;font-weight:600;color:var(--p-text-muted-color);text-transform:uppercase;letter-spacing:.05em}.motions-top-section{margin-top:.75rem;margin-bottom:0}.motions-grid{display:flex;flex-wrap:wrap;gap:.4rem}.motion-chip{display:inline-flex;align-items:center;gap:.35rem;padding:.3rem .65rem;border-radius:20px;border:1px solid var(--p-surface-300);background:var(--p-surface-100);color:var(--p-text-color);font-size:.8rem;font-weight:500;cursor:pointer;transition:background .15s,border-color .15s,transform .1s;text-transform:capitalize}.motion-chip i{font-size:.85rem;color:var(--p-primary-color)}.motion-chip:hover{background:var(--p-primary-50, #f0f4ff);border-color:var(--p-primary-color);transform:translateY(-1px)}.motion-chip:active{transform:translateY(0)}.motion-video{width:100%;border-radius:6px;display:block}.settings-chips{display:flex;flex-wrap:wrap;gap:.4rem}.voice-info{display:flex;flex-direction:column;gap:.25rem}.loading-state{display:flex;justify-content:center;padding:2rem}\n"] }]
5605
6027
  }], ctorParameters: () => [], propDecorators: { entityData: [{ type: i0.Input, args: [{ isSignal: true, alias: "entityData", required: false }] }] } });
5606
6028
 
6029
+ class ConversationSummaryComponent {
6030
+ constructor() {
6031
+ this.agentCard = input.required(...(ngDevMode ? [{ debugName: "agentCard" }] : /* istanbul ignore next */ []));
6032
+ this.parentInjector = input.required(...(ngDevMode ? [{ debugName: "parentInjector" }] : /* istanbul ignore next */ []));
6033
+ this.completeEvent = output();
6034
+ this.value = 0;
6035
+ this.totalMessages = computed(() => this.messageStateService.getMessagesSignal()().length, ...(ngDevMode ? [{ debugName: "totalMessages" }] : /* istanbul ignore next */ []));
6036
+ this.userMessagesCount = computed(() => this.messageStateService.getMessagesSignal()().filter((m) => m.role === 'user').length, ...(ngDevMode ? [{ debugName: "userMessagesCount" }] : /* istanbul ignore next */ []));
6037
+ this.assistantMessagesCount = computed(() => this.messageStateService.getMessagesSignal()().filter((m) => m.role === 'assistant').length, ...(ngDevMode ? [{ debugName: "assistantMessagesCount" }] : /* istanbul ignore next */ []));
6038
+ this.activeChallengesCount = computed(() => {
6039
+ const challenges = this.dynamicFlowService.conversationFlowConfig()?.challenges || [];
6040
+ return challenges.filter(c => c.enabled).length;
6041
+ }, ...(ngDevMode ? [{ debugName: "activeChallengesCount" }] : /* istanbul ignore next */ []));
6042
+ this.totalTokensUsed = computed(() => {
6043
+ const usage = this.conversationCostService.usageByTag();
6044
+ let total = 0;
6045
+ for (const tag in usage) {
6046
+ total += usage[tag].tokenUsage.input + usage[tag].tokenUsage.output;
6047
+ }
6048
+ return total;
6049
+ }, ...(ngDevMode ? [{ debugName: "totalTokensUsed" }] : /* istanbul ignore next */ []));
6050
+ }
6051
+ get messageStateService() { return this.parentInjector().get(MessagesStateService); }
6052
+ get dynamicFlowService() { return this.parentInjector().get(DynamicFlowService); }
6053
+ get conversationFlowStateService() { return this.parentInjector().get(ConversationFlowStateService); }
6054
+ get conversationCostService() { return this.parentInjector().get(ConversationCostService); }
6055
+ get evaluationService() { return this.parentInjector().get(EvaluationService); }
6056
+ get globalToolsService() { return this.parentInjector().get(GlobalToolsService); }
6057
+ setScore() {
6058
+ this.evaluationService.setScore(this.value);
6059
+ }
6060
+ callAgent() {
6061
+ this.globalToolsService.useTool('closeChatDrawer');
6062
+ }
6063
+ openFeedback() {
6064
+ this.evaluationService.openFeedbackEvaluation();
6065
+ }
6066
+ complete() {
6067
+ this.completeEvent.emit();
6068
+ }
6069
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ConversationSummaryComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6070
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: ConversationSummaryComponent, isStandalone: true, selector: "dc-conversation-summary", inputs: { agentCard: { classPropertyName: "agentCard", publicName: "agentCard", isSignal: true, isRequired: true, transformFunction: null }, parentInjector: { classPropertyName: "parentInjector", publicName: "parentInjector", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { completeEvent: "completeEvent" }, ngImport: i0, template: "<div class=\"flex flex-wrap gap-2 mb-2\">\n <p-button label=\"Call Agent\" (click)=\"callAgent()\" />\n <p-button label=\"Feedback\" icon=\"pi pi-pencil\" (click)=\"openFeedback()\" />\n <p-button label=\"Complete\" icon=\"pi pi-check\" (click)=\"complete()\" />\n</div>\n\n<p-divider>Session Stats</p-divider>\n<div class=\"grid grid-cols-2 gap-4 mb-4\">\n <div>\n <p class=\"font-semibold text-sm text-gray-500\">Messages</p>\n <p>Total: {{ totalMessages() }}</p>\n <p class=\"text-sm\">User: {{ userMessagesCount() }} | Assistant: {{ assistantMessagesCount() }}</p>\n </div>\n <div>\n <p class=\"font-semibold text-sm text-gray-500\">Agent Identity</p>\n <p>{{ agentCard().name }}</p>\n <p class=\"text-sm text-gray-600\">{{ agentCard().agentType || 'Agent' }} ({{ agentCard().lang || 'N/A' }})</p>\n </div>\n</div>\n\n<p-divider>Flow & Usage</p-divider>\n<div class=\"grid grid-cols-2 gap-4 mb-4\">\n <div>\n <p class=\"font-semibold text-sm text-gray-500\">Goal Status</p>\n <div class=\"flex items-center gap-2 mt-1\">\n @if (dynamicFlowService.conversationFlowConfig()?.goal?.enabled) {\n <div class=\"w-3 h-3 bg-green-500 rounded-full\" pTooltip=\"Active\"></div>\n <span>In Progress</span>\n } @else {\n <div class=\"w-3 h-3 bg-red-500 rounded-full\" pTooltip=\"Inactive\"></div>\n <span>Inactive / Completed</span>\n }\n </div>\n </div>\n <div>\n <p class=\"font-semibold text-sm text-gray-500\">Quick Stats</p>\n <p>Active Challenges: {{ activeChallengesCount() }}</p>\n <p>Total Tokens: {{ totalTokensUsed() }}</p>\n </div>\n</div>\n\n<!-- Summary -->\n<p-divider>Score</p-divider>\n\n<label for=\"slider\">Current Score : {{ conversationFlowStateService.flowState().goal.value }}</label>\n\n<div class=\"flex flex gap-3\">\n <p-slider [(ngModel)]=\"value\" [step]=\"10\" class=\"w-56\" />\n <p-button label=\"Set Score to {{ value }}\" (onClick)=\"setScore()\" />\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: DividerModule }, { kind: "component", type: i2$4.Divider, selector: "p-divider", inputs: ["styleClass", "layout", "type", "align"] }, { kind: "ngmodule", type: SliderModule }, { kind: "component", type: i4$1.Slider, selector: "p-slider", inputs: ["animate", "min", "max", "orientation", "step", "range", "styleClass", "ariaLabel", "ariaLabelledBy", "tabindex", "autofocus"], outputs: ["onChange", "onSlideEnd"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i3.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }] }); }
6071
+ }
6072
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ConversationSummaryComponent, decorators: [{
6073
+ type: Component,
6074
+ args: [{ selector: 'dc-conversation-summary', standalone: true, imports: [CommonModule, FormsModule, ButtonModule, DividerModule, SliderModule, TooltipModule], template: "<div class=\"flex flex-wrap gap-2 mb-2\">\n <p-button label=\"Call Agent\" (click)=\"callAgent()\" />\n <p-button label=\"Feedback\" icon=\"pi pi-pencil\" (click)=\"openFeedback()\" />\n <p-button label=\"Complete\" icon=\"pi pi-check\" (click)=\"complete()\" />\n</div>\n\n<p-divider>Session Stats</p-divider>\n<div class=\"grid grid-cols-2 gap-4 mb-4\">\n <div>\n <p class=\"font-semibold text-sm text-gray-500\">Messages</p>\n <p>Total: {{ totalMessages() }}</p>\n <p class=\"text-sm\">User: {{ userMessagesCount() }} | Assistant: {{ assistantMessagesCount() }}</p>\n </div>\n <div>\n <p class=\"font-semibold text-sm text-gray-500\">Agent Identity</p>\n <p>{{ agentCard().name }}</p>\n <p class=\"text-sm text-gray-600\">{{ agentCard().agentType || 'Agent' }} ({{ agentCard().lang || 'N/A' }})</p>\n </div>\n</div>\n\n<p-divider>Flow & Usage</p-divider>\n<div class=\"grid grid-cols-2 gap-4 mb-4\">\n <div>\n <p class=\"font-semibold text-sm text-gray-500\">Goal Status</p>\n <div class=\"flex items-center gap-2 mt-1\">\n @if (dynamicFlowService.conversationFlowConfig()?.goal?.enabled) {\n <div class=\"w-3 h-3 bg-green-500 rounded-full\" pTooltip=\"Active\"></div>\n <span>In Progress</span>\n } @else {\n <div class=\"w-3 h-3 bg-red-500 rounded-full\" pTooltip=\"Inactive\"></div>\n <span>Inactive / Completed</span>\n }\n </div>\n </div>\n <div>\n <p class=\"font-semibold text-sm text-gray-500\">Quick Stats</p>\n <p>Active Challenges: {{ activeChallengesCount() }}</p>\n <p>Total Tokens: {{ totalTokensUsed() }}</p>\n </div>\n</div>\n\n<!-- Summary -->\n<p-divider>Score</p-divider>\n\n<label for=\"slider\">Current Score : {{ conversationFlowStateService.flowState().goal.value }}</label>\n\n<div class=\"flex flex gap-3\">\n <p-slider [(ngModel)]=\"value\" [step]=\"10\" class=\"w-56\" />\n <p-button label=\"Set Score to {{ value }}\" (onClick)=\"setScore()\" />\n</div>\n" }]
6075
+ }], propDecorators: { agentCard: [{ type: i0.Input, args: [{ isSignal: true, alias: "agentCard", required: true }] }], parentInjector: [{ type: i0.Input, args: [{ isSignal: true, alias: "parentInjector", required: true }] }], completeEvent: [{ type: i0.Output, args: ["completeEvent"] }] } });
6076
+
5607
6077
  class ConversationInspector {
5608
6078
  constructor() {
5609
6079
  this.config = inject(DynamicDialogConfig);
@@ -5620,6 +6090,7 @@ class ConversationInspector {
5620
6090
  this.conversationFlowStateService = parentInjector.get(ConversationFlowStateService);
5621
6091
  this.conversationService = parentInjector.get(ConversationService);
5622
6092
  this.agentCardStateService = parentInjector.get(AgentCardStateService);
6093
+ this.conversationCostService = parentInjector.get(ConversationCostService);
5623
6094
  console.log('ConversationInspector data assigned', this.agentCard, this.chatUserSettings);
5624
6095
  }
5625
6096
  setScore() {
@@ -5650,11 +6121,11 @@ class ConversationInspector {
5650
6121
  this.viewMode.set(this.viewMode() === 'markdown' ? 'regular' : 'markdown');
5651
6122
  }
5652
6123
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ConversationInspector, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5653
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: ConversationInspector, isStandalone: true, selector: "dc-conversation-info", outputs: { completeEvent: "completeEvent" }, ngImport: i0, template: "<div class=\"info-content\">\n <p-tabs value=\"0\">\n <p-tablist>\n <p-tab value=\"0\">Summary</p-tab>\n <p-tab value=\"1\">Dynamic Flow</p-tab>\n <p-tab value=\"5\">Conversation State</p-tab>\n <p-tab value=\"2\">Conversation Messages</p-tab>\n <p-tab value=\"6\">Messages State</p-tab>\n <p-tab value=\"3\">Pricing</p-tab>\n <p-tab value=\"4\">More</p-tab>\n <p-tab value=\"7\">Preview</p-tab>\n </p-tablist>\n <p-tabpanels>\n <p-tabpanel value=\"0\">\n <ng-template #content>\n <div class=\"flex flex-wrap gap-2 mb-2\">\n <p-button label=\"Call Agent\" (click)=\"callAgent()\" />\n <p-button label=\"Feedback\" icon=\"pi pi-pencil\" (click)=\"openFeedback()\" />\n <p-button label=\"Complete\" icon=\"pi pi-check\" (click)=\"complete()\" />\n </div>\n\n <!-- Summary -->\n <p-divider>Score</p-divider>\n\n <label for=\"slider\">Current Score : {{ conversationFlowStateService.flowState().goal.value }}</label>\n\n <div class=\"flex flex gap-3\">\n <p-slider [(ngModel)]=\"value\" [step]=\"10\" class=\"w-56\" />\n <p-button label=\"Set Score to {{ value }}\" (onClick)=\"setScore()\" />\n </div>\n <!-- Summary ends Here -->\n </ng-template>\n </p-tabpanel>\n <p-tabpanel value=\"1\">\n <ng-template #content>\n <!-- Dynamic Flow -->\n\n <p-divider>Conversation Flow</p-divider>\n <div class=\"mb-2\">\n <div class=\"flex items-center gap-2\">\n @if (dynamicFlowService.conversationFlowConfig()?.goal?.enabled) {\n <div class=\"w-3 h-3 bg-green-500 rounded-full\" pTooltip=\"Active\"></div>\n } @else {\n <div class=\"w-3 h-3 bg-red-500 rounded-full\" pTooltip=\"Inactive\"></div>\n }\n <p class=\"font-semibold\">Goal</p>\n </div>\n @if(dynamicFlowService.conversationFlowConfig()?.goal?.task; as task) {\n <div class=\"pl-5 mt-1 text-sm text-gray-600 italic\"> {{ task }} </div>\n }\n </div>\n\n <div class=\"mb-2\">\n <div class=\"flex items-center gap-2\">\n @if (agentCardStateService.conversationFlow$()?.triggerTasks?.onUserMessage?.enabled) {\n <div class=\"w-3 h-3 bg-green-500 rounded-full\" pTooltip=\"Active\"></div>\n } @else {\n <div class=\"w-3 h-3 bg-red-500 rounded-full\" pTooltip=\"Inactive\"></div>\n }\n <p class=\"font-semibold\">Trigger User Message</p>\n </div>\n @if(agentCardStateService.conversationFlow$()?.triggerTasks?.onUserMessage?.task; as task) {\n <div class=\"pl-5 mt-1 text-sm text-gray-600 italic\"> {{ task }} </div>\n }\n </div>\n\n <div class=\"mb-2\">\n <div class=\"flex items-center gap-2\">\n @if (agentCardStateService.conversationFlow$()?.triggerTasks?.onAssistantMessage?.enabled) {\n <div class=\"w-3 h-3 bg-green-500 rounded-full\" pTooltip=\"Active\"></div>\n } @else {\n <div class=\"w-3 h-3 bg-red-500 rounded-full\" pTooltip=\"Inactive\"></div>\n }\n <p class=\"font-semibold\">Trigger Assistant Message</p>\n </div>\n @if(agentCardStateService.conversationFlow$()?.triggerTasks?.onAssistantMessage?.task; as task) {\n <div class=\"pl-5 mt-1 text-sm text-gray-600 italic\"> {{ task }} </div>\n }\n </div>\n\n <h3>Herramientas</h3>\n @for (tool of agentCardStateService.conversationFlow$()?.tools; track tool.name) {\n <div class=\"mb-2\">\n <div class=\"flex items-center gap-2\">\n @if (tool.enabled) {\n <div class=\"w-3 h-3 bg-green-500 rounded-full\" pTooltip=\"Active\"></div>\n } @else {\n <div class=\"w-3 h-3 bg-red-500 rounded-full\" pTooltip=\"Inactive\"></div>\n }\n <p class=\"font-semibold\">{{ tool.name }}</p>\n </div>\n @if(tool.description) {\n <div class=\"pl-5 mt-1 text-sm text-gray-600 italic\"> {{ tool.description }} </div>\n }\n </div>\n }\n\n <h3>Challenges Retos</h3>\n @for (challenge of dynamicFlowService.conversationFlowConfig()?.challenges; track challenge.name) {\n <div class=\"mb-2\">\n <div class=\"flex items-center gap-2\">\n @if (challenge.enabled) {\n <div class=\"w-3 h-3 bg-green-500 rounded-full\" pTooltip=\"Active\"></div>\n } @else {\n <div class=\"w-3 h-3 bg-red-500 rounded-full\" pTooltip=\"Inactive\"></div>\n }\n\n <p class=\"font-semibold\"> {{ challenge.emoji }} {{ challenge.name }}</p>\n </div>\n @if(challenge.description) {\n <div class=\"pl-5 mt-1 text-sm text-gray-600 italic\"> {{ challenge.description }} </div>\n }\n </div>\n }\n <h5>Conditions</h5>\n\n @for (condition of dynamicFlowService.conversationFlowConfig()?.dynamicConditions; track $index) {\n <div class=\"pl-2 mt-1 text-sm text-gray-600 italic\"> When the {{ condition.what }} is {{ condition.when }} than {{ condition.value }} Do </div>\n <ol>\n @for (doAction of condition.do; track $index) {\n <li class=\"pl-5 mt-1 text-sm text-gray-600 italic\">\n {{ $index }})\n <span style=\"color: brown\"> {{ doAction.actionType }}</span>\n <span style=\"color: green\"> {{ doAction.systemPromptType }}</span>\n <span style=\"color: green\"> {{ doAction.dynamicFlowTaskType }}</span>\n\n to\n <span style=\"color: rgb(49, 23, 177)\"> {{ doAction.enabled }}</span>\n \"{{ doAction.prompt }}\"\n </li>\n }\n </ol>\n }\n\n <p>Challenges</p>\n <pre>{{ agentCardStateService.conversationFlow$()?.challenges | safeJson }}</pre>\n\n <p-divider>Performance Evaluation</p-divider>\n <div class=\"mb-2\">\n <div class=\"flex items-center gap-2\">\n @if (agentCardStateService.conversationFlow$()?.enablePerformanceAnalysis !== false) {\n <div class=\"w-3 h-3 bg-green-500 rounded-full\" pTooltip=\"Active\"></div>\n } @else {\n <div class=\"w-3 h-3 bg-red-500 rounded-full\" pTooltip=\"Inactive\"></div>\n }\n <p class=\"font-semibold\">Performance Prompt</p>\n <span class=\"text-xs text-gray-400 ml-2\" pTooltip=\"Minimum messages required to trigger evaluation\">(MIN_MESSAGES_EVALUATE: 4 hardcoded)</span>\n </div>\n @if(agentCardStateService.conversationFlow$()?.enablePerformanceAnalysis !== false) {\n @if(agentCardStateService.conversationFlow$()?.performancePrompt; as prompt) {\n <div class=\"pl-5 mt-1 text-sm text-gray-600 italic\"> \n <markdown>\n {{ prompt }} \n </markdown>\n </div>\n } @else {\n <div class=\"pl-5 mt-1 text-sm text-gray-400 italic\"> No custom performance prompt defined (using default). </div>\n }\n } @else {\n <div class=\"pl-5 mt-1 text-sm text-gray-400 italic\"> Performance analysis disabled. </div>\n }\n </div>\n\n <p-divider>System Evaluation Prompt</p-divider>\n <details>\n <summary>Show Prompt</summary>\n <pre>{{ dynamicFlowService.generateSystemPromptForFlow(messageStateService.getMessagesSignal()()) }}</pre>\n </details>\n\n <!-- Dynamic Flow ends Here -->\n </ng-template>\n </p-tabpanel>\n <p-tabpanel value=\"5\">\n <ng-template #content>\n <pre>{{ conversationFlowStateService.flowState() | safeJson }}</pre>\n <details>\n <summary>Current Prompt</summary>\n <pre>{{ dynamicFlowService.generateSystemPromptForFlow(messageStateService.getMessagesSignal()()) }}</pre>\n </details>\n </ng-template>\n </p-tabpanel>\n <p-tabpanel value=\"2\">\n <ng-template #content>\n <div>\n <p-button label=\"Exportar todo\" (click)=\"exportChat('all')\" />\n <p-button label=\"Exportar conversaci\u00F3n\" (click)=\"exportChat('conversation')\" />\n <p-button [label]=\"'Vista ' + viewMode()\" (click)=\"toggleViewMode()\" />\n </div>\n <dc-prompt-preview [messages]=\"messageStateService.getMessagesSignal()()\" [view]=\"viewMode()\"></dc-prompt-preview>\n </ng-template>\n </p-tabpanel>\n <p-tabpanel value=\"6\">\n <ng-template #content>\n <dc-messages-state-inspector></dc-messages-state-inspector>\n </ng-template>\n </p-tabpanel>\n <p-tabpanel value=\"3\">\n <ng-template #content>\n <dc-cost-details></dc-cost-details>\n </ng-template>\n </p-tabpanel>\n <p-tabpanel value=\"4\">\n <ng-template #content>\n <!-- MORE INFO -->\n\n <details>\n <summary>Estado Global Conversation Flow</summary>\n <p>Goal</p>\n <pre>{{ dynamicFlowService.conversationFlowConfig()?.goal | safeJson }}</pre>\n <p>Trigger User Message</p>\n <pre>{{ dynamicFlowService.conversationFlowConfig()?.triggerTasks?.onUserMessage | safeJson }}</pre>\n <p>Trigger Assistant Message</p>\n <pre>{{ dynamicFlowService.conversationFlowConfig()?.triggerTasks?.onAssistantMessage | safeJson }}</pre>\n <p>Conditions</p>\n <pre>{{ dynamicFlowService.conversationFlowConfig()?.dynamicConditions | safeJson }}</pre>\n <p>Tools</p>\n <pre>{{ dynamicFlowService.conversationFlowConfig()?.tools | safeJson }}</pre>\n <p>Challenges</p>\n <pre>{{ dynamicFlowService.conversationFlowConfig()?.challenges | safeJson }}</pre>\n </details>\n\n <details>\n <summary>Conversation Settings (Debug)</summary>\n <pre>{{ conversationService.conversationSettings$() | safeJson }}</pre>\n </details>\n\n <details>\n <summary>Agent Card</summary>\n <pre>{{ agentCard | safeJson }}</pre>\n </details>\n\n <details>\n <summary>User Settings</summary>\n <pre>{{ chatUserSettings | safeJson }}</pre>\n </details>\n\n <!-- MORE INFO ends Here -->\n </ng-template>\n </p-tabpanel>\n <p-tabpanel value=\"7\">\n <ng-template #content>\n <dc-agent-card-detail [entityData]=\"agentCardStateService.agentCard$()\" />\n </ng-template>\n </p-tabpanel>\n </p-tabpanels>\n </p-tabs>\n</div>\n", styles: [":host{overflow-y:scroll}.info-content{display:flex;flex-direction:column;gap:1rem;padding:1rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { 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"] }, { kind: "ngmodule", type: SliderModule }, { kind: "component", type: i1$6.Slider, selector: "p-slider", inputs: ["animate", "min", "max", "orientation", "step", "range", "styleClass", "ariaLabel", "ariaLabelledBy", "tabindex", "autofocus"], outputs: ["onChange", "onSlideEnd"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: DividerModule }, { kind: "component", type: i1$3.Divider, selector: "p-divider", inputs: ["styleClass", "layout", "type", "align"] }, { kind: "component", type: PromptPreviewComponent, selector: "dc-prompt-preview", inputs: ["messages", "jailBrake", "view"] }, { kind: "ngmodule", type: TabsModule }, { kind: "component", type: i2$5.Tabs, selector: "p-tabs", inputs: ["value", "scrollable", "lazy", "selectOnFocus", "showNavigators", "tabindex"], outputs: ["valueChange"] }, { kind: "component", type: i2$5.TabPanels, selector: "p-tabpanels" }, { kind: "component", type: i2$5.TabPanel, selector: "p-tabpanel", inputs: ["lazy", "value"], outputs: ["valueChange"] }, { kind: "component", type: i2$5.TabList, selector: "p-tablist" }, { kind: "component", type: i2$5.Tab, selector: "p-tab", inputs: ["value", "disabled"], outputs: ["valueChange"] }, { kind: "component", type: CostDetailsComponent, selector: "dc-cost-details" }, { kind: "component", type: MessagesStateInspectorComponent, selector: "dc-messages-state-inspector" }, { kind: "component", type: DcAgentCardDetailComponent, selector: "dc-agent-card-detail", inputs: ["entityData"] }, { kind: "pipe", type: SafeJsonPipe, name: "safeJson" }] }); }
6124
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: ConversationInspector, isStandalone: true, selector: "dc-conversation-info", outputs: { completeEvent: "completeEvent" }, ngImport: i0, template: "<div class=\"info-content\">\n <p-tabs value=\"0\">\n <p-tablist>\n <p-tab value=\"0\">\uD83D\uDCCA Summary</p-tab>\n <p-tab value=\"1\">\uD83D\uDD00 Dynamic Flow</p-tab>\n <p-tab value=\"6\">\uD83D\uDCE6 Messages State</p-tab>\n <p-tab value=\"7\">\uD83D\uDC64 Preview Card</p-tab>\n <p-tab value=\"5\">\uD83D\uDCBE Conversation State</p-tab>\n <p-tab value=\"2\">\uD83D\uDCAC Conversation Messages</p-tab>\n <p-tab value=\"3\">\uD83D\uDCB0 Pricing</p-tab>\n <p-tab value=\"4\">\uD83D\uDC1B More</p-tab>\n </p-tablist>\n <p-tabpanels>\n <p-tabpanel value=\"0\">\n <ng-template #content>\n @if (conversationFlowStateService.flowState(); as flowState) {\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4 mb-4 mt-2\">\n <!-- Goal State -->\n <div class=\"p-4 border rounded-lg shadow-sm\">\n <h3 class=\"text-lg font-bold mb-3 flex items-center gap-2\">\n <span>\uD83C\uDFAF</span> Goal Progress\n </h3>\n <div class=\"flex items-end gap-4 mb-3\">\n <div class=\"text-5xl font-black leading-none\">\n {{ flowState.goal?.value || 0 }}\n </div>\n @if (flowState.goal?.deltaPoints !== undefined) {\n <div class=\"text-xl font-bold mb-1\" \n [class.text-green-600]=\"flowState.goal.deltaPoints > 0\"\n [class.text-red-600]=\"flowState.goal.deltaPoints < 0\"\n [class.opacity-50]=\"flowState.goal.deltaPoints === 0\">\n {{ flowState.goal.deltaPoints > 0 ? '+' : '' }}{{ flowState.goal.deltaPoints }}\n </div>\n }\n </div>\n \n @if (flowState.goal?.feedback) {\n <div class=\"mt-4 p-3 rounded border-l-4 text-sm italic shadow-sm opacity-80\">\n \"{{ flowState.goal.feedback }}\"\n </div>\n }\n </div>\n\n <!-- Mood State -->\n <div class=\"p-4 border rounded-lg shadow-sm flex flex-col\">\n <h3 class=\"text-lg font-bold mb-2 flex items-center gap-2\">\n <span>\uD83C\uDFAD</span> Agent Mood\n </h3>\n <div class=\"flex-grow flex items-center justify-center\">\n @if (flowState.moodState?.value) {\n <div class=\"text-4xl font-black uppercase tracking-widest text-center drop-shadow-sm\">\n {{ flowState.moodState.value }}\n </div>\n } @else {\n <div class=\"text-xl font-medium italic opacity-50\">Neutral</div>\n }\n </div>\n </div>\n </div>\n }\n <dc-conversation-summary [agentCard]=\"agentCard\" [parentInjector]=\"config.data.injector\" (completeEvent)=\"complete()\"></dc-conversation-summary>\n </ng-template>\n </p-tabpanel>\n <p-tabpanel value=\"1\">\n <ng-template #content>\n <!-- Dynamic Flow -->\n\n <p-divider>Conversation Flow</p-divider>\n <div class=\"mb-2\">\n <div class=\"flex items-center gap-2\">\n @if (dynamicFlowService.conversationFlowConfig()?.goal?.enabled) {\n <div class=\"w-3 h-3 bg-green-500 rounded-full\" pTooltip=\"Active\"></div>\n } @else {\n <div class=\"w-3 h-3 bg-red-500 rounded-full\" pTooltip=\"Inactive\"></div>\n }\n <p class=\"font-semibold\">Goal</p>\n </div>\n @if(dynamicFlowService.conversationFlowConfig()?.goal?.task; as task) {\n <div class=\"pl-5 mt-1 text-sm text-gray-600 italic\"> {{ task }} </div>\n }\n </div>\n\n <div class=\"mb-2\">\n <div class=\"flex items-center gap-2\">\n @if (agentCardStateService.conversationFlow$()?.triggerTasks?.onUserMessage?.enabled) {\n <div class=\"w-3 h-3 bg-green-500 rounded-full\" pTooltip=\"Active\"></div>\n } @else {\n <div class=\"w-3 h-3 bg-red-500 rounded-full\" pTooltip=\"Inactive\"></div>\n }\n <p class=\"font-semibold\">Trigger User Message</p>\n </div>\n @if(agentCardStateService.conversationFlow$()?.triggerTasks?.onUserMessage?.task; as task) {\n <div class=\"pl-5 mt-1 text-sm text-gray-600 italic\"> {{ task }} </div>\n }\n </div>\n\n <div class=\"mb-2\">\n <div class=\"flex items-center gap-2\">\n @if (agentCardStateService.conversationFlow$()?.triggerTasks?.onAssistantMessage?.enabled) {\n <div class=\"w-3 h-3 bg-green-500 rounded-full\" pTooltip=\"Active\"></div>\n } @else {\n <div class=\"w-3 h-3 bg-red-500 rounded-full\" pTooltip=\"Inactive\"></div>\n }\n <p class=\"font-semibold\">Trigger Assistant Message</p>\n </div>\n @if(agentCardStateService.conversationFlow$()?.triggerTasks?.onAssistantMessage?.task; as task) {\n <div class=\"pl-5 mt-1 text-sm text-gray-600 italic\"> {{ task }} </div>\n }\n </div>\n\n <h3>Herramientas</h3>\n @for (tool of agentCardStateService.conversationFlow$()?.tools; track tool.name) {\n <div class=\"mb-2\">\n <div class=\"flex items-center gap-2\">\n @if (tool.enabled) {\n <div class=\"w-3 h-3 bg-green-500 rounded-full\" pTooltip=\"Active\"></div>\n } @else {\n <div class=\"w-3 h-3 bg-red-500 rounded-full\" pTooltip=\"Inactive\"></div>\n }\n <p class=\"font-semibold\">{{ tool.name }}</p>\n </div>\n @if(tool.description) {\n <div class=\"pl-5 mt-1 text-sm text-gray-600 italic\"> {{ tool.description }} </div>\n }\n </div>\n }\n\n <h3>Challenges Retos</h3>\n @for (challenge of dynamicFlowService.conversationFlowConfig()?.challenges; track challenge.name) {\n <div class=\"mb-2\">\n <div class=\"flex items-center gap-2\">\n @if (challenge.enabled) {\n <div class=\"w-3 h-3 bg-green-500 rounded-full\" pTooltip=\"Active\"></div>\n } @else {\n <div class=\"w-3 h-3 bg-red-500 rounded-full\" pTooltip=\"Inactive\"></div>\n }\n\n <p class=\"font-semibold\"> {{ challenge.emoji }} {{ challenge.name }}</p>\n </div>\n @if(challenge.description) {\n <div class=\"pl-5 mt-1 text-sm text-gray-600 italic\"> {{ challenge.description }} </div>\n }\n </div>\n }\n <h5>Conditions</h5>\n\n @for (condition of dynamicFlowService.conversationFlowConfig()?.dynamicConditions; track $index) {\n <div class=\"pl-2 mt-1 text-sm text-gray-600 italic\"> When the {{ condition.what }} is {{ condition.when }} than {{ condition.value }} Do </div>\n <ol>\n @for (doAction of condition.do; track $index) {\n <li class=\"pl-5 mt-1 text-sm text-gray-600 italic\">\n {{ $index }})\n <span style=\"color: brown\"> {{ doAction.actionType }}</span>\n <span style=\"color: green\"> {{ doAction.systemPromptType }}</span>\n <span style=\"color: green\"> {{ doAction.dynamicFlowTaskType }}</span>\n\n to\n <span style=\"color: rgb(49, 23, 177)\"> {{ doAction.enabled }}</span>\n \"{{ doAction.prompt }}\"\n </li>\n }\n </ol>\n }\n\n <p>Challenges</p>\n <pre>{{ agentCardStateService.conversationFlow$()?.challenges | safeJson }}</pre>\n\n <p-divider>Performance Evaluation</p-divider>\n <div class=\"mb-2\">\n <div class=\"flex items-center gap-2\">\n @if (agentCardStateService.conversationFlow$()?.enablePerformanceAnalysis !== false) {\n <div class=\"w-3 h-3 bg-green-500 rounded-full\" pTooltip=\"Active\"></div>\n } @else {\n <div class=\"w-3 h-3 bg-red-500 rounded-full\" pTooltip=\"Inactive\"></div>\n }\n <p class=\"font-semibold\">Performance Prompt</p>\n <span class=\"text-xs text-gray-400 ml-2\" pTooltip=\"Minimum messages required to trigger evaluation\">(MIN_MESSAGES_EVALUATE: 4 hardcoded)</span>\n </div>\n @if(agentCardStateService.conversationFlow$()?.enablePerformanceAnalysis !== false) {\n @if(agentCardStateService.conversationFlow$()?.performancePrompt; as prompt) {\n <div class=\"pl-5 mt-1 text-sm text-gray-600 italic\"> \n <markdown>\n {{ prompt }} \n </markdown>\n </div>\n } @else {\n <div class=\"pl-5 mt-1 text-sm text-gray-400 italic\"> No custom performance prompt defined (using default). </div>\n }\n } @else {\n <div class=\"pl-5 mt-1 text-sm text-gray-400 italic\"> Performance analysis disabled. </div>\n }\n </div>\n\n <p-divider>System Evaluation Prompt</p-divider>\n <details>\n <summary>Show Prompt</summary>\n <pre>{{ dynamicFlowService.generateSystemPromptForFlow(messageStateService.getMessagesSignal()()) }}</pre>\n </details>\n\n <!-- Dynamic Flow ends Here -->\n </ng-template>\n </p-tabpanel>\n <p-tabpanel value=\"5\">\n <ng-template #content>\n @if (conversationFlowStateService.flowState(); as flowState) {\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4 mb-4 mt-2\">\n <!-- Goal State -->\n <div class=\"p-4 border rounded-lg shadow-sm\">\n <h3 class=\"text-lg font-bold mb-3 flex items-center gap-2\">\n <span>\uD83C\uDFAF</span> Goal Progress\n </h3>\n <div class=\"flex items-end gap-4 mb-3\">\n <div class=\"text-5xl font-black leading-none\">\n {{ flowState.goal?.value || 0 }}\n </div>\n @if (flowState.goal?.deltaPoints !== undefined) {\n <div class=\"text-xl font-bold mb-1\" \n [class.text-green-600]=\"flowState.goal.deltaPoints > 0\"\n [class.text-red-600]=\"flowState.goal.deltaPoints < 0\"\n [class.opacity-50]=\"flowState.goal.deltaPoints === 0\">\n {{ flowState.goal.deltaPoints > 0 ? '+' : '' }}{{ flowState.goal.deltaPoints }}\n </div>\n }\n </div>\n \n @if (flowState.goal?.feedback) {\n <div class=\"mt-4 p-3 rounded border-l-4 text-sm italic shadow-sm opacity-80\">\n \"{{ flowState.goal.feedback }}\"\n </div>\n }\n </div>\n\n <!-- Mood State -->\n <div class=\"p-4 border rounded-lg shadow-sm flex flex-col\">\n <h3 class=\"text-lg font-bold mb-2 flex items-center gap-2\">\n <span>\uD83C\uDFAD</span> Agent Mood\n </h3>\n <div class=\"flex-grow flex items-center justify-center\">\n @if (flowState.moodState?.value) {\n <div class=\"text-4xl font-black uppercase tracking-widest text-center drop-shadow-sm\">\n {{ flowState.moodState.value }}\n </div>\n } @else {\n <div class=\"text-xl font-medium italic opacity-50\">Neutral</div>\n }\n </div>\n </div>\n </div>\n\n @if (flowState.challenges?.length) {\n <div class=\"mb-4 p-4 border rounded-lg shadow-sm\">\n <h3 class=\"text-lg font-bold mb-3 flex items-center gap-2\">\n <span>\uD83C\uDFC6</span> Completed Challenges\n </h3>\n <ul class=\"list-disc pl-5 space-y-1\">\n @for (challenge of flowState.challenges; track challenge) {\n <li>{{ challenge }}</li>\n }\n </ul>\n </div>\n }\n\n <details class=\"mt-4\">\n <summary class=\"cursor-pointer text-sm font-medium\">Raw JSON State</summary>\n <pre class=\"mt-2 p-2 rounded text-xs overflow-auto\">{{ flowState | safeJson }}</pre>\n </details>\n } @else {\n <p class=\"italic mt-2 opacity-50\">No conversation state available.</p>\n }\n\n <details class=\"mt-2\">\n <summary class=\"cursor-pointer text-sm font-medium\">Current Prompt</summary>\n <pre class=\"mt-2 p-2 rounded text-xs overflow-auto\">{{ dynamicFlowService.generateSystemPromptForFlow(messageStateService.getMessagesSignal()()) }}</pre>\n </details>\n </ng-template>\n </p-tabpanel>\n <p-tabpanel value=\"2\">\n <ng-template #content>\n <div>\n <p-button label=\"Exportar todo\" (click)=\"exportChat('all')\" />\n <p-button label=\"Exportar conversaci\u00F3n\" (click)=\"exportChat('conversation')\" />\n <p-button [label]=\"'Vista ' + viewMode()\" (click)=\"toggleViewMode()\" />\n </div>\n <dc-prompt-preview [messages]=\"messageStateService.getMessagesSignal()()\" [view]=\"viewMode()\"></dc-prompt-preview>\n </ng-template>\n </p-tabpanel>\n <p-tabpanel value=\"6\">\n <ng-template #content>\n <dc-messages-state-inspector></dc-messages-state-inspector>\n </ng-template>\n </p-tabpanel>\n <p-tabpanel value=\"3\">\n <ng-template #content>\n <dc-cost-details></dc-cost-details>\n </ng-template>\n </p-tabpanel>\n <p-tabpanel value=\"4\">\n <ng-template #content>\n <!-- MORE INFO -->\n\n <details>\n <summary>Estado Global Conversation Flow</summary>\n <p>Goal</p>\n <pre>{{ dynamicFlowService.conversationFlowConfig()?.goal | safeJson }}</pre>\n <p>Trigger User Message</p>\n <pre>{{ dynamicFlowService.conversationFlowConfig()?.triggerTasks?.onUserMessage | safeJson }}</pre>\n <p>Trigger Assistant Message</p>\n <pre>{{ dynamicFlowService.conversationFlowConfig()?.triggerTasks?.onAssistantMessage | safeJson }}</pre>\n <p>Conditions</p>\n <pre>{{ dynamicFlowService.conversationFlowConfig()?.dynamicConditions | safeJson }}</pre>\n <p>Tools</p>\n <pre>{{ dynamicFlowService.conversationFlowConfig()?.tools | safeJson }}</pre>\n <p>Challenges</p>\n <pre>{{ dynamicFlowService.conversationFlowConfig()?.challenges | safeJson }}</pre>\n </details>\n\n <details>\n <summary>Conversation Settings (Debug)</summary>\n <pre>{{ conversationService.conversationSettings$() | safeJson }}</pre>\n </details>\n\n <details>\n <summary>Agent Card</summary>\n <pre>{{ agentCard | safeJson }}</pre>\n </details>\n\n <details>\n <summary>User Settings</summary>\n <pre>{{ chatUserSettings | safeJson }}</pre>\n </details>\n\n <!-- MORE INFO ends Here -->\n </ng-template>\n </p-tabpanel>\n <p-tabpanel value=\"7\">\n <ng-template #content>\n <dc-agent-card-detail [entityData]=\"agentCardStateService.agentCard$()\" />\n </ng-template>\n </p-tabpanel>\n </p-tabpanels>\n </p-tabs>\n</div>\n", styles: [":host{overflow-y:scroll}.info-content{display:flex;flex-direction:column;gap:1rem;padding:1rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { 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"] }, { kind: "ngmodule", type: SliderModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: DividerModule }, { kind: "component", type: i2$4.Divider, selector: "p-divider", inputs: ["styleClass", "layout", "type", "align"] }, { kind: "component", type: PromptPreviewComponent, selector: "dc-prompt-preview", inputs: ["messages", "jailBrake", "view"] }, { kind: "ngmodule", type: TabsModule }, { kind: "component", type: i2$6.Tabs, selector: "p-tabs", inputs: ["value", "scrollable", "lazy", "selectOnFocus", "showNavigators", "tabindex"], outputs: ["valueChange"] }, { kind: "component", type: i2$6.TabPanels, selector: "p-tabpanels" }, { kind: "component", type: i2$6.TabPanel, selector: "p-tabpanel", inputs: ["lazy", "value"], outputs: ["valueChange"] }, { kind: "component", type: i2$6.TabList, selector: "p-tablist" }, { kind: "component", type: i2$6.Tab, selector: "p-tab", inputs: ["value", "disabled"], outputs: ["valueChange"] }, { kind: "component", type: CostDetailsComponent, selector: "dc-cost-details" }, { kind: "component", type: MessagesStateInspectorComponent, selector: "dc-messages-state-inspector" }, { kind: "component", type: DcAgentCardDetailComponent, selector: "dc-agent-card-detail", inputs: ["entityData"] }, { kind: "component", type: ConversationSummaryComponent, selector: "dc-conversation-summary", inputs: ["agentCard", "parentInjector"], outputs: ["completeEvent"] }, { kind: "pipe", type: SafeJsonPipe, name: "safeJson" }] }); }
5654
6125
  }
5655
6126
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ConversationInspector, decorators: [{
5656
6127
  type: Component,
5657
- args: [{ selector: 'dc-conversation-info', standalone: true, imports: [CommonModule, SafeJsonPipe, MarkdownComponent, SliderModule, ButtonModule, FormsModule, DividerModule, PromptPreviewComponent, TabsModule, CostDetailsComponent, MessagesStateInspectorComponent, DcAgentCardDetailComponent], template: "<div class=\"info-content\">\n <p-tabs value=\"0\">\n <p-tablist>\n <p-tab value=\"0\">Summary</p-tab>\n <p-tab value=\"1\">Dynamic Flow</p-tab>\n <p-tab value=\"5\">Conversation State</p-tab>\n <p-tab value=\"2\">Conversation Messages</p-tab>\n <p-tab value=\"6\">Messages State</p-tab>\n <p-tab value=\"3\">Pricing</p-tab>\n <p-tab value=\"4\">More</p-tab>\n <p-tab value=\"7\">Preview</p-tab>\n </p-tablist>\n <p-tabpanels>\n <p-tabpanel value=\"0\">\n <ng-template #content>\n <div class=\"flex flex-wrap gap-2 mb-2\">\n <p-button label=\"Call Agent\" (click)=\"callAgent()\" />\n <p-button label=\"Feedback\" icon=\"pi pi-pencil\" (click)=\"openFeedback()\" />\n <p-button label=\"Complete\" icon=\"pi pi-check\" (click)=\"complete()\" />\n </div>\n\n <!-- Summary -->\n <p-divider>Score</p-divider>\n\n <label for=\"slider\">Current Score : {{ conversationFlowStateService.flowState().goal.value }}</label>\n\n <div class=\"flex flex gap-3\">\n <p-slider [(ngModel)]=\"value\" [step]=\"10\" class=\"w-56\" />\n <p-button label=\"Set Score to {{ value }}\" (onClick)=\"setScore()\" />\n </div>\n <!-- Summary ends Here -->\n </ng-template>\n </p-tabpanel>\n <p-tabpanel value=\"1\">\n <ng-template #content>\n <!-- Dynamic Flow -->\n\n <p-divider>Conversation Flow</p-divider>\n <div class=\"mb-2\">\n <div class=\"flex items-center gap-2\">\n @if (dynamicFlowService.conversationFlowConfig()?.goal?.enabled) {\n <div class=\"w-3 h-3 bg-green-500 rounded-full\" pTooltip=\"Active\"></div>\n } @else {\n <div class=\"w-3 h-3 bg-red-500 rounded-full\" pTooltip=\"Inactive\"></div>\n }\n <p class=\"font-semibold\">Goal</p>\n </div>\n @if(dynamicFlowService.conversationFlowConfig()?.goal?.task; as task) {\n <div class=\"pl-5 mt-1 text-sm text-gray-600 italic\"> {{ task }} </div>\n }\n </div>\n\n <div class=\"mb-2\">\n <div class=\"flex items-center gap-2\">\n @if (agentCardStateService.conversationFlow$()?.triggerTasks?.onUserMessage?.enabled) {\n <div class=\"w-3 h-3 bg-green-500 rounded-full\" pTooltip=\"Active\"></div>\n } @else {\n <div class=\"w-3 h-3 bg-red-500 rounded-full\" pTooltip=\"Inactive\"></div>\n }\n <p class=\"font-semibold\">Trigger User Message</p>\n </div>\n @if(agentCardStateService.conversationFlow$()?.triggerTasks?.onUserMessage?.task; as task) {\n <div class=\"pl-5 mt-1 text-sm text-gray-600 italic\"> {{ task }} </div>\n }\n </div>\n\n <div class=\"mb-2\">\n <div class=\"flex items-center gap-2\">\n @if (agentCardStateService.conversationFlow$()?.triggerTasks?.onAssistantMessage?.enabled) {\n <div class=\"w-3 h-3 bg-green-500 rounded-full\" pTooltip=\"Active\"></div>\n } @else {\n <div class=\"w-3 h-3 bg-red-500 rounded-full\" pTooltip=\"Inactive\"></div>\n }\n <p class=\"font-semibold\">Trigger Assistant Message</p>\n </div>\n @if(agentCardStateService.conversationFlow$()?.triggerTasks?.onAssistantMessage?.task; as task) {\n <div class=\"pl-5 mt-1 text-sm text-gray-600 italic\"> {{ task }} </div>\n }\n </div>\n\n <h3>Herramientas</h3>\n @for (tool of agentCardStateService.conversationFlow$()?.tools; track tool.name) {\n <div class=\"mb-2\">\n <div class=\"flex items-center gap-2\">\n @if (tool.enabled) {\n <div class=\"w-3 h-3 bg-green-500 rounded-full\" pTooltip=\"Active\"></div>\n } @else {\n <div class=\"w-3 h-3 bg-red-500 rounded-full\" pTooltip=\"Inactive\"></div>\n }\n <p class=\"font-semibold\">{{ tool.name }}</p>\n </div>\n @if(tool.description) {\n <div class=\"pl-5 mt-1 text-sm text-gray-600 italic\"> {{ tool.description }} </div>\n }\n </div>\n }\n\n <h3>Challenges Retos</h3>\n @for (challenge of dynamicFlowService.conversationFlowConfig()?.challenges; track challenge.name) {\n <div class=\"mb-2\">\n <div class=\"flex items-center gap-2\">\n @if (challenge.enabled) {\n <div class=\"w-3 h-3 bg-green-500 rounded-full\" pTooltip=\"Active\"></div>\n } @else {\n <div class=\"w-3 h-3 bg-red-500 rounded-full\" pTooltip=\"Inactive\"></div>\n }\n\n <p class=\"font-semibold\"> {{ challenge.emoji }} {{ challenge.name }}</p>\n </div>\n @if(challenge.description) {\n <div class=\"pl-5 mt-1 text-sm text-gray-600 italic\"> {{ challenge.description }} </div>\n }\n </div>\n }\n <h5>Conditions</h5>\n\n @for (condition of dynamicFlowService.conversationFlowConfig()?.dynamicConditions; track $index) {\n <div class=\"pl-2 mt-1 text-sm text-gray-600 italic\"> When the {{ condition.what }} is {{ condition.when }} than {{ condition.value }} Do </div>\n <ol>\n @for (doAction of condition.do; track $index) {\n <li class=\"pl-5 mt-1 text-sm text-gray-600 italic\">\n {{ $index }})\n <span style=\"color: brown\"> {{ doAction.actionType }}</span>\n <span style=\"color: green\"> {{ doAction.systemPromptType }}</span>\n <span style=\"color: green\"> {{ doAction.dynamicFlowTaskType }}</span>\n\n to\n <span style=\"color: rgb(49, 23, 177)\"> {{ doAction.enabled }}</span>\n \"{{ doAction.prompt }}\"\n </li>\n }\n </ol>\n }\n\n <p>Challenges</p>\n <pre>{{ agentCardStateService.conversationFlow$()?.challenges | safeJson }}</pre>\n\n <p-divider>Performance Evaluation</p-divider>\n <div class=\"mb-2\">\n <div class=\"flex items-center gap-2\">\n @if (agentCardStateService.conversationFlow$()?.enablePerformanceAnalysis !== false) {\n <div class=\"w-3 h-3 bg-green-500 rounded-full\" pTooltip=\"Active\"></div>\n } @else {\n <div class=\"w-3 h-3 bg-red-500 rounded-full\" pTooltip=\"Inactive\"></div>\n }\n <p class=\"font-semibold\">Performance Prompt</p>\n <span class=\"text-xs text-gray-400 ml-2\" pTooltip=\"Minimum messages required to trigger evaluation\">(MIN_MESSAGES_EVALUATE: 4 hardcoded)</span>\n </div>\n @if(agentCardStateService.conversationFlow$()?.enablePerformanceAnalysis !== false) {\n @if(agentCardStateService.conversationFlow$()?.performancePrompt; as prompt) {\n <div class=\"pl-5 mt-1 text-sm text-gray-600 italic\"> \n <markdown>\n {{ prompt }} \n </markdown>\n </div>\n } @else {\n <div class=\"pl-5 mt-1 text-sm text-gray-400 italic\"> No custom performance prompt defined (using default). </div>\n }\n } @else {\n <div class=\"pl-5 mt-1 text-sm text-gray-400 italic\"> Performance analysis disabled. </div>\n }\n </div>\n\n <p-divider>System Evaluation Prompt</p-divider>\n <details>\n <summary>Show Prompt</summary>\n <pre>{{ dynamicFlowService.generateSystemPromptForFlow(messageStateService.getMessagesSignal()()) }}</pre>\n </details>\n\n <!-- Dynamic Flow ends Here -->\n </ng-template>\n </p-tabpanel>\n <p-tabpanel value=\"5\">\n <ng-template #content>\n <pre>{{ conversationFlowStateService.flowState() | safeJson }}</pre>\n <details>\n <summary>Current Prompt</summary>\n <pre>{{ dynamicFlowService.generateSystemPromptForFlow(messageStateService.getMessagesSignal()()) }}</pre>\n </details>\n </ng-template>\n </p-tabpanel>\n <p-tabpanel value=\"2\">\n <ng-template #content>\n <div>\n <p-button label=\"Exportar todo\" (click)=\"exportChat('all')\" />\n <p-button label=\"Exportar conversaci\u00F3n\" (click)=\"exportChat('conversation')\" />\n <p-button [label]=\"'Vista ' + viewMode()\" (click)=\"toggleViewMode()\" />\n </div>\n <dc-prompt-preview [messages]=\"messageStateService.getMessagesSignal()()\" [view]=\"viewMode()\"></dc-prompt-preview>\n </ng-template>\n </p-tabpanel>\n <p-tabpanel value=\"6\">\n <ng-template #content>\n <dc-messages-state-inspector></dc-messages-state-inspector>\n </ng-template>\n </p-tabpanel>\n <p-tabpanel value=\"3\">\n <ng-template #content>\n <dc-cost-details></dc-cost-details>\n </ng-template>\n </p-tabpanel>\n <p-tabpanel value=\"4\">\n <ng-template #content>\n <!-- MORE INFO -->\n\n <details>\n <summary>Estado Global Conversation Flow</summary>\n <p>Goal</p>\n <pre>{{ dynamicFlowService.conversationFlowConfig()?.goal | safeJson }}</pre>\n <p>Trigger User Message</p>\n <pre>{{ dynamicFlowService.conversationFlowConfig()?.triggerTasks?.onUserMessage | safeJson }}</pre>\n <p>Trigger Assistant Message</p>\n <pre>{{ dynamicFlowService.conversationFlowConfig()?.triggerTasks?.onAssistantMessage | safeJson }}</pre>\n <p>Conditions</p>\n <pre>{{ dynamicFlowService.conversationFlowConfig()?.dynamicConditions | safeJson }}</pre>\n <p>Tools</p>\n <pre>{{ dynamicFlowService.conversationFlowConfig()?.tools | safeJson }}</pre>\n <p>Challenges</p>\n <pre>{{ dynamicFlowService.conversationFlowConfig()?.challenges | safeJson }}</pre>\n </details>\n\n <details>\n <summary>Conversation Settings (Debug)</summary>\n <pre>{{ conversationService.conversationSettings$() | safeJson }}</pre>\n </details>\n\n <details>\n <summary>Agent Card</summary>\n <pre>{{ agentCard | safeJson }}</pre>\n </details>\n\n <details>\n <summary>User Settings</summary>\n <pre>{{ chatUserSettings | safeJson }}</pre>\n </details>\n\n <!-- MORE INFO ends Here -->\n </ng-template>\n </p-tabpanel>\n <p-tabpanel value=\"7\">\n <ng-template #content>\n <dc-agent-card-detail [entityData]=\"agentCardStateService.agentCard$()\" />\n </ng-template>\n </p-tabpanel>\n </p-tabpanels>\n </p-tabs>\n</div>\n", styles: [":host{overflow-y:scroll}.info-content{display:flex;flex-direction:column;gap:1rem;padding:1rem}\n"] }]
6128
+ args: [{ selector: 'dc-conversation-info', standalone: true, imports: [CommonModule, SafeJsonPipe, MarkdownComponent, SliderModule, ButtonModule, FormsModule, DividerModule, PromptPreviewComponent, TabsModule, CostDetailsComponent, MessagesStateInspectorComponent, DcAgentCardDetailComponent, ConversationSummaryComponent], template: "<div class=\"info-content\">\n <p-tabs value=\"0\">\n <p-tablist>\n <p-tab value=\"0\">\uD83D\uDCCA Summary</p-tab>\n <p-tab value=\"1\">\uD83D\uDD00 Dynamic Flow</p-tab>\n <p-tab value=\"6\">\uD83D\uDCE6 Messages State</p-tab>\n <p-tab value=\"7\">\uD83D\uDC64 Preview Card</p-tab>\n <p-tab value=\"5\">\uD83D\uDCBE Conversation State</p-tab>\n <p-tab value=\"2\">\uD83D\uDCAC Conversation Messages</p-tab>\n <p-tab value=\"3\">\uD83D\uDCB0 Pricing</p-tab>\n <p-tab value=\"4\">\uD83D\uDC1B More</p-tab>\n </p-tablist>\n <p-tabpanels>\n <p-tabpanel value=\"0\">\n <ng-template #content>\n @if (conversationFlowStateService.flowState(); as flowState) {\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4 mb-4 mt-2\">\n <!-- Goal State -->\n <div class=\"p-4 border rounded-lg shadow-sm\">\n <h3 class=\"text-lg font-bold mb-3 flex items-center gap-2\">\n <span>\uD83C\uDFAF</span> Goal Progress\n </h3>\n <div class=\"flex items-end gap-4 mb-3\">\n <div class=\"text-5xl font-black leading-none\">\n {{ flowState.goal?.value || 0 }}\n </div>\n @if (flowState.goal?.deltaPoints !== undefined) {\n <div class=\"text-xl font-bold mb-1\" \n [class.text-green-600]=\"flowState.goal.deltaPoints > 0\"\n [class.text-red-600]=\"flowState.goal.deltaPoints < 0\"\n [class.opacity-50]=\"flowState.goal.deltaPoints === 0\">\n {{ flowState.goal.deltaPoints > 0 ? '+' : '' }}{{ flowState.goal.deltaPoints }}\n </div>\n }\n </div>\n \n @if (flowState.goal?.feedback) {\n <div class=\"mt-4 p-3 rounded border-l-4 text-sm italic shadow-sm opacity-80\">\n \"{{ flowState.goal.feedback }}\"\n </div>\n }\n </div>\n\n <!-- Mood State -->\n <div class=\"p-4 border rounded-lg shadow-sm flex flex-col\">\n <h3 class=\"text-lg font-bold mb-2 flex items-center gap-2\">\n <span>\uD83C\uDFAD</span> Agent Mood\n </h3>\n <div class=\"flex-grow flex items-center justify-center\">\n @if (flowState.moodState?.value) {\n <div class=\"text-4xl font-black uppercase tracking-widest text-center drop-shadow-sm\">\n {{ flowState.moodState.value }}\n </div>\n } @else {\n <div class=\"text-xl font-medium italic opacity-50\">Neutral</div>\n }\n </div>\n </div>\n </div>\n }\n <dc-conversation-summary [agentCard]=\"agentCard\" [parentInjector]=\"config.data.injector\" (completeEvent)=\"complete()\"></dc-conversation-summary>\n </ng-template>\n </p-tabpanel>\n <p-tabpanel value=\"1\">\n <ng-template #content>\n <!-- Dynamic Flow -->\n\n <p-divider>Conversation Flow</p-divider>\n <div class=\"mb-2\">\n <div class=\"flex items-center gap-2\">\n @if (dynamicFlowService.conversationFlowConfig()?.goal?.enabled) {\n <div class=\"w-3 h-3 bg-green-500 rounded-full\" pTooltip=\"Active\"></div>\n } @else {\n <div class=\"w-3 h-3 bg-red-500 rounded-full\" pTooltip=\"Inactive\"></div>\n }\n <p class=\"font-semibold\">Goal</p>\n </div>\n @if(dynamicFlowService.conversationFlowConfig()?.goal?.task; as task) {\n <div class=\"pl-5 mt-1 text-sm text-gray-600 italic\"> {{ task }} </div>\n }\n </div>\n\n <div class=\"mb-2\">\n <div class=\"flex items-center gap-2\">\n @if (agentCardStateService.conversationFlow$()?.triggerTasks?.onUserMessage?.enabled) {\n <div class=\"w-3 h-3 bg-green-500 rounded-full\" pTooltip=\"Active\"></div>\n } @else {\n <div class=\"w-3 h-3 bg-red-500 rounded-full\" pTooltip=\"Inactive\"></div>\n }\n <p class=\"font-semibold\">Trigger User Message</p>\n </div>\n @if(agentCardStateService.conversationFlow$()?.triggerTasks?.onUserMessage?.task; as task) {\n <div class=\"pl-5 mt-1 text-sm text-gray-600 italic\"> {{ task }} </div>\n }\n </div>\n\n <div class=\"mb-2\">\n <div class=\"flex items-center gap-2\">\n @if (agentCardStateService.conversationFlow$()?.triggerTasks?.onAssistantMessage?.enabled) {\n <div class=\"w-3 h-3 bg-green-500 rounded-full\" pTooltip=\"Active\"></div>\n } @else {\n <div class=\"w-3 h-3 bg-red-500 rounded-full\" pTooltip=\"Inactive\"></div>\n }\n <p class=\"font-semibold\">Trigger Assistant Message</p>\n </div>\n @if(agentCardStateService.conversationFlow$()?.triggerTasks?.onAssistantMessage?.task; as task) {\n <div class=\"pl-5 mt-1 text-sm text-gray-600 italic\"> {{ task }} </div>\n }\n </div>\n\n <h3>Herramientas</h3>\n @for (tool of agentCardStateService.conversationFlow$()?.tools; track tool.name) {\n <div class=\"mb-2\">\n <div class=\"flex items-center gap-2\">\n @if (tool.enabled) {\n <div class=\"w-3 h-3 bg-green-500 rounded-full\" pTooltip=\"Active\"></div>\n } @else {\n <div class=\"w-3 h-3 bg-red-500 rounded-full\" pTooltip=\"Inactive\"></div>\n }\n <p class=\"font-semibold\">{{ tool.name }}</p>\n </div>\n @if(tool.description) {\n <div class=\"pl-5 mt-1 text-sm text-gray-600 italic\"> {{ tool.description }} </div>\n }\n </div>\n }\n\n <h3>Challenges Retos</h3>\n @for (challenge of dynamicFlowService.conversationFlowConfig()?.challenges; track challenge.name) {\n <div class=\"mb-2\">\n <div class=\"flex items-center gap-2\">\n @if (challenge.enabled) {\n <div class=\"w-3 h-3 bg-green-500 rounded-full\" pTooltip=\"Active\"></div>\n } @else {\n <div class=\"w-3 h-3 bg-red-500 rounded-full\" pTooltip=\"Inactive\"></div>\n }\n\n <p class=\"font-semibold\"> {{ challenge.emoji }} {{ challenge.name }}</p>\n </div>\n @if(challenge.description) {\n <div class=\"pl-5 mt-1 text-sm text-gray-600 italic\"> {{ challenge.description }} </div>\n }\n </div>\n }\n <h5>Conditions</h5>\n\n @for (condition of dynamicFlowService.conversationFlowConfig()?.dynamicConditions; track $index) {\n <div class=\"pl-2 mt-1 text-sm text-gray-600 italic\"> When the {{ condition.what }} is {{ condition.when }} than {{ condition.value }} Do </div>\n <ol>\n @for (doAction of condition.do; track $index) {\n <li class=\"pl-5 mt-1 text-sm text-gray-600 italic\">\n {{ $index }})\n <span style=\"color: brown\"> {{ doAction.actionType }}</span>\n <span style=\"color: green\"> {{ doAction.systemPromptType }}</span>\n <span style=\"color: green\"> {{ doAction.dynamicFlowTaskType }}</span>\n\n to\n <span style=\"color: rgb(49, 23, 177)\"> {{ doAction.enabled }}</span>\n \"{{ doAction.prompt }}\"\n </li>\n }\n </ol>\n }\n\n <p>Challenges</p>\n <pre>{{ agentCardStateService.conversationFlow$()?.challenges | safeJson }}</pre>\n\n <p-divider>Performance Evaluation</p-divider>\n <div class=\"mb-2\">\n <div class=\"flex items-center gap-2\">\n @if (agentCardStateService.conversationFlow$()?.enablePerformanceAnalysis !== false) {\n <div class=\"w-3 h-3 bg-green-500 rounded-full\" pTooltip=\"Active\"></div>\n } @else {\n <div class=\"w-3 h-3 bg-red-500 rounded-full\" pTooltip=\"Inactive\"></div>\n }\n <p class=\"font-semibold\">Performance Prompt</p>\n <span class=\"text-xs text-gray-400 ml-2\" pTooltip=\"Minimum messages required to trigger evaluation\">(MIN_MESSAGES_EVALUATE: 4 hardcoded)</span>\n </div>\n @if(agentCardStateService.conversationFlow$()?.enablePerformanceAnalysis !== false) {\n @if(agentCardStateService.conversationFlow$()?.performancePrompt; as prompt) {\n <div class=\"pl-5 mt-1 text-sm text-gray-600 italic\"> \n <markdown>\n {{ prompt }} \n </markdown>\n </div>\n } @else {\n <div class=\"pl-5 mt-1 text-sm text-gray-400 italic\"> No custom performance prompt defined (using default). </div>\n }\n } @else {\n <div class=\"pl-5 mt-1 text-sm text-gray-400 italic\"> Performance analysis disabled. </div>\n }\n </div>\n\n <p-divider>System Evaluation Prompt</p-divider>\n <details>\n <summary>Show Prompt</summary>\n <pre>{{ dynamicFlowService.generateSystemPromptForFlow(messageStateService.getMessagesSignal()()) }}</pre>\n </details>\n\n <!-- Dynamic Flow ends Here -->\n </ng-template>\n </p-tabpanel>\n <p-tabpanel value=\"5\">\n <ng-template #content>\n @if (conversationFlowStateService.flowState(); as flowState) {\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4 mb-4 mt-2\">\n <!-- Goal State -->\n <div class=\"p-4 border rounded-lg shadow-sm\">\n <h3 class=\"text-lg font-bold mb-3 flex items-center gap-2\">\n <span>\uD83C\uDFAF</span> Goal Progress\n </h3>\n <div class=\"flex items-end gap-4 mb-3\">\n <div class=\"text-5xl font-black leading-none\">\n {{ flowState.goal?.value || 0 }}\n </div>\n @if (flowState.goal?.deltaPoints !== undefined) {\n <div class=\"text-xl font-bold mb-1\" \n [class.text-green-600]=\"flowState.goal.deltaPoints > 0\"\n [class.text-red-600]=\"flowState.goal.deltaPoints < 0\"\n [class.opacity-50]=\"flowState.goal.deltaPoints === 0\">\n {{ flowState.goal.deltaPoints > 0 ? '+' : '' }}{{ flowState.goal.deltaPoints }}\n </div>\n }\n </div>\n \n @if (flowState.goal?.feedback) {\n <div class=\"mt-4 p-3 rounded border-l-4 text-sm italic shadow-sm opacity-80\">\n \"{{ flowState.goal.feedback }}\"\n </div>\n }\n </div>\n\n <!-- Mood State -->\n <div class=\"p-4 border rounded-lg shadow-sm flex flex-col\">\n <h3 class=\"text-lg font-bold mb-2 flex items-center gap-2\">\n <span>\uD83C\uDFAD</span> Agent Mood\n </h3>\n <div class=\"flex-grow flex items-center justify-center\">\n @if (flowState.moodState?.value) {\n <div class=\"text-4xl font-black uppercase tracking-widest text-center drop-shadow-sm\">\n {{ flowState.moodState.value }}\n </div>\n } @else {\n <div class=\"text-xl font-medium italic opacity-50\">Neutral</div>\n }\n </div>\n </div>\n </div>\n\n @if (flowState.challenges?.length) {\n <div class=\"mb-4 p-4 border rounded-lg shadow-sm\">\n <h3 class=\"text-lg font-bold mb-3 flex items-center gap-2\">\n <span>\uD83C\uDFC6</span> Completed Challenges\n </h3>\n <ul class=\"list-disc pl-5 space-y-1\">\n @for (challenge of flowState.challenges; track challenge) {\n <li>{{ challenge }}</li>\n }\n </ul>\n </div>\n }\n\n <details class=\"mt-4\">\n <summary class=\"cursor-pointer text-sm font-medium\">Raw JSON State</summary>\n <pre class=\"mt-2 p-2 rounded text-xs overflow-auto\">{{ flowState | safeJson }}</pre>\n </details>\n } @else {\n <p class=\"italic mt-2 opacity-50\">No conversation state available.</p>\n }\n\n <details class=\"mt-2\">\n <summary class=\"cursor-pointer text-sm font-medium\">Current Prompt</summary>\n <pre class=\"mt-2 p-2 rounded text-xs overflow-auto\">{{ dynamicFlowService.generateSystemPromptForFlow(messageStateService.getMessagesSignal()()) }}</pre>\n </details>\n </ng-template>\n </p-tabpanel>\n <p-tabpanel value=\"2\">\n <ng-template #content>\n <div>\n <p-button label=\"Exportar todo\" (click)=\"exportChat('all')\" />\n <p-button label=\"Exportar conversaci\u00F3n\" (click)=\"exportChat('conversation')\" />\n <p-button [label]=\"'Vista ' + viewMode()\" (click)=\"toggleViewMode()\" />\n </div>\n <dc-prompt-preview [messages]=\"messageStateService.getMessagesSignal()()\" [view]=\"viewMode()\"></dc-prompt-preview>\n </ng-template>\n </p-tabpanel>\n <p-tabpanel value=\"6\">\n <ng-template #content>\n <dc-messages-state-inspector></dc-messages-state-inspector>\n </ng-template>\n </p-tabpanel>\n <p-tabpanel value=\"3\">\n <ng-template #content>\n <dc-cost-details></dc-cost-details>\n </ng-template>\n </p-tabpanel>\n <p-tabpanel value=\"4\">\n <ng-template #content>\n <!-- MORE INFO -->\n\n <details>\n <summary>Estado Global Conversation Flow</summary>\n <p>Goal</p>\n <pre>{{ dynamicFlowService.conversationFlowConfig()?.goal | safeJson }}</pre>\n <p>Trigger User Message</p>\n <pre>{{ dynamicFlowService.conversationFlowConfig()?.triggerTasks?.onUserMessage | safeJson }}</pre>\n <p>Trigger Assistant Message</p>\n <pre>{{ dynamicFlowService.conversationFlowConfig()?.triggerTasks?.onAssistantMessage | safeJson }}</pre>\n <p>Conditions</p>\n <pre>{{ dynamicFlowService.conversationFlowConfig()?.dynamicConditions | safeJson }}</pre>\n <p>Tools</p>\n <pre>{{ dynamicFlowService.conversationFlowConfig()?.tools | safeJson }}</pre>\n <p>Challenges</p>\n <pre>{{ dynamicFlowService.conversationFlowConfig()?.challenges | safeJson }}</pre>\n </details>\n\n <details>\n <summary>Conversation Settings (Debug)</summary>\n <pre>{{ conversationService.conversationSettings$() | safeJson }}</pre>\n </details>\n\n <details>\n <summary>Agent Card</summary>\n <pre>{{ agentCard | safeJson }}</pre>\n </details>\n\n <details>\n <summary>User Settings</summary>\n <pre>{{ chatUserSettings | safeJson }}</pre>\n </details>\n\n <!-- MORE INFO ends Here -->\n </ng-template>\n </p-tabpanel>\n <p-tabpanel value=\"7\">\n <ng-template #content>\n <dc-agent-card-detail [entityData]=\"agentCardStateService.agentCard$()\" />\n </ng-template>\n </p-tabpanel>\n </p-tabpanels>\n </p-tabs>\n</div>\n", styles: [":host{overflow-y:scroll}.info-content{display:flex;flex-direction:column;gap:1rem;padding:1rem}\n"] }]
5658
6129
  }], ctorParameters: () => [], propDecorators: { completeEvent: [{ type: i0.Output, args: ["completeEvent"] }] } });
5659
6130
 
5660
6131
  class ConversationInfoService {
@@ -5822,11 +6293,11 @@ class DCChatComponent {
5822
6293
  this.goalCompleted.emit();
5823
6294
  }
5824
6295
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DCChatComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5825
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", 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 }, conversationFlow: { classPropertyName: "conversationFlow", publicName: "conversationFlow", isSignal: false, isRequired: false, transformFunction: null }, agentCard: { classPropertyName: "agentCard", publicName: "agentCard", isSignal: false, isRequired: false, transformFunction: null }, parseDict: { classPropertyName: "parseDict", publicName: "parseDict", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { chatEvent: "chatEvent", goalCompleted: "goalCompleted" }, providers: [ConversationService, AIGenerationService, EvaluationService, DynamicFlowTaskService, ConversationInfoService, MessageOrchestrationService, AudioTextSyncService], viewQueries: [{ propertyName: "chatFooterComponent", first: true, predicate: ChatFooterComponent, descendants: true }], ngImport: i0, template: "<div class=\"chat-container\">\n <dc-chat-header\n [agentCard]=\"agentCard\"\n [viewMode]=\"viewMode()\"\n (showInfoEvent)=\"showInfo()\"\n (settingsClickEvent)=\"changeUserChatSettings()\"\n (restartConversationEvent)=\"restartConversation($event)\"\n (completeEvent)=\"complete()\"\n (viewModeChanged)=\"viewMode.set($event)\">\n </dc-chat-header>\n\n @if (viewMode() === 'chat') {\n <dc-chat-messages-list [chatUserSettings]=\"chatUserSettings\"> </dc-chat-messages-list>\n <dc-chat-footer [micSettings]=\"micSettings\"> </dc-chat-footer>\n } @else {\n <dc-immersive-chat [micSettings]=\"micSettings\"></dc-immersive-chat>\n }\n</div>\n", styles: ["::ng-deep .p-drawer-content{padding:0!important}::ng-deep .p-dialog-content{display:contents}.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;padding:1rem}.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: ["alternativeConversation", "agentCard", "viewMode"], outputs: ["restartConversationEvent", "showInfoEvent", "settingsClickEvent", "viewModeChanged"] }, { kind: "component", type: ChatFooterComponent, selector: "dc-chat-footer", inputs: ["isAIThinking", "micSettings"], outputs: ["sendMessage", "textInputChanged"] }, { kind: "component", type: ChatMessagesListComponent, selector: "dc-chat-messages-list", inputs: ["chatUserSettings"] }, { kind: "ngmodule", type: ProgressBarModule }, { kind: "component", type: DcImmersiveChatComponent, selector: "dc-immersive-chat", inputs: ["micSettings"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
6296
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", 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 }, conversationFlow: { classPropertyName: "conversationFlow", publicName: "conversationFlow", isSignal: false, isRequired: false, transformFunction: null }, agentCard: { classPropertyName: "agentCard", publicName: "agentCard", isSignal: false, isRequired: false, transformFunction: null }, parseDict: { classPropertyName: "parseDict", publicName: "parseDict", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { chatEvent: "chatEvent", goalCompleted: "goalCompleted" }, providers: [ConversationService, AIGenerationService, EvaluationService, DynamicFlowTaskService, ConversationInfoService, MessageOrchestrationService, AudioTextSyncService], viewQueries: [{ propertyName: "chatFooterComponent", first: true, predicate: ChatFooterComponent, descendants: true }], ngImport: i0, template: "<div class=\"chat-container\">\n <dc-chat-header\n [agentCard]=\"agentCard\"\n [viewMode]=\"viewMode()\"\n (showInfoEvent)=\"showInfo()\"\n (settingsClickEvent)=\"changeUserChatSettings()\"\n (restartConversationEvent)=\"restartConversation($event)\"\n (completeEvent)=\"complete()\"\n (viewModeChanged)=\"viewMode.set($event)\">\n </dc-chat-header>\n\n @if (viewMode() === 'chat') {\n <dc-chat-messages-list [chatUserSettings]=\"chatUserSettings\"> </dc-chat-messages-list>\n <dc-chat-footer [micSettings]=\"micSettings\"> </dc-chat-footer>\n } @else {\n <dc-immersive-chat [micSettings]=\"micSettings\"></dc-immersive-chat>\n }\n\n <dc-polito-notification></dc-polito-notification>\n</div>\n", styles: ["::ng-deep .p-drawer-content{padding:0!important}::ng-deep .p-dialog-content{display:contents}.chat-container{display:flex;flex-direction:column;height:100%;max-height:100vh;overflow:hidden;background-color:transparent;position:relative}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;padding:1rem}.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: ["alternativeConversation", "agentCard", "viewMode"], outputs: ["restartConversationEvent", "showInfoEvent", "settingsClickEvent", "viewModeChanged"] }, { kind: "component", type: ChatFooterComponent, selector: "dc-chat-footer", inputs: ["isAIThinking", "micSettings"], outputs: ["sendMessage", "textInputChanged"] }, { kind: "component", type: ChatMessagesListComponent, selector: "dc-chat-messages-list", inputs: ["chatUserSettings"] }, { kind: "ngmodule", type: ProgressBarModule }, { kind: "component", type: DcImmersiveChatComponent, selector: "dc-immersive-chat", inputs: ["micSettings"] }, { kind: "component", type: PolitoNotificationComponent, selector: "dc-polito-notification" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
5826
6297
  }
5827
6298
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DCChatComponent, decorators: [{
5828
6299
  type: Component,
5829
- args: [{ selector: 'dc-chat', standalone: true, imports: [CommonModule, ChatHeaderComponent, ChatFooterComponent, ChatMessagesListComponent, ProgressBarModule, DcImmersiveChatComponent], changeDetection: ChangeDetectionStrategy.OnPush, providers: [ConversationService, AIGenerationService, EvaluationService, DynamicFlowTaskService, ConversationInfoService, MessageOrchestrationService, AudioTextSyncService], template: "<div class=\"chat-container\">\n <dc-chat-header\n [agentCard]=\"agentCard\"\n [viewMode]=\"viewMode()\"\n (showInfoEvent)=\"showInfo()\"\n (settingsClickEvent)=\"changeUserChatSettings()\"\n (restartConversationEvent)=\"restartConversation($event)\"\n (completeEvent)=\"complete()\"\n (viewModeChanged)=\"viewMode.set($event)\">\n </dc-chat-header>\n\n @if (viewMode() === 'chat') {\n <dc-chat-messages-list [chatUserSettings]=\"chatUserSettings\"> </dc-chat-messages-list>\n <dc-chat-footer [micSettings]=\"micSettings\"> </dc-chat-footer>\n } @else {\n <dc-immersive-chat [micSettings]=\"micSettings\"></dc-immersive-chat>\n }\n</div>\n", styles: ["::ng-deep .p-drawer-content{padding:0!important}::ng-deep .p-dialog-content{display:contents}.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;padding:1rem}.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"] }]
6300
+ args: [{ selector: 'dc-chat', standalone: true, imports: [CommonModule, ChatHeaderComponent, ChatFooterComponent, ChatMessagesListComponent, ProgressBarModule, DcImmersiveChatComponent, PolitoNotificationComponent], changeDetection: ChangeDetectionStrategy.OnPush, providers: [ConversationService, AIGenerationService, EvaluationService, DynamicFlowTaskService, ConversationInfoService, MessageOrchestrationService, AudioTextSyncService], template: "<div class=\"chat-container\">\n <dc-chat-header\n [agentCard]=\"agentCard\"\n [viewMode]=\"viewMode()\"\n (showInfoEvent)=\"showInfo()\"\n (settingsClickEvent)=\"changeUserChatSettings()\"\n (restartConversationEvent)=\"restartConversation($event)\"\n (completeEvent)=\"complete()\"\n (viewModeChanged)=\"viewMode.set($event)\">\n </dc-chat-header>\n\n @if (viewMode() === 'chat') {\n <dc-chat-messages-list [chatUserSettings]=\"chatUserSettings\"> </dc-chat-messages-list>\n <dc-chat-footer [micSettings]=\"micSettings\"> </dc-chat-footer>\n } @else {\n <dc-immersive-chat [micSettings]=\"micSettings\"></dc-immersive-chat>\n }\n\n <dc-polito-notification></dc-polito-notification>\n</div>\n", styles: ["::ng-deep .p-drawer-content{padding:0!important}::ng-deep .p-dialog-content{display:contents}.chat-container{display:flex;flex-direction:column;height:100%;max-height:100vh;overflow:hidden;background-color:transparent;position:relative}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;padding:1rem}.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"] }]
5830
6301
  }], ctorParameters: () => [], propDecorators: { chatFooterComponent: [{
5831
6302
  type: ViewChild,
5832
6303
  args: [ChatFooterComponent]
@@ -6277,7 +6748,7 @@ class ACCMotionGenerationComponent {
6277
6748
  this.videoPrompt = '';
6278
6749
  }
6279
6750
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ACCMotionGenerationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6280
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: ACCMotionGenerationComponent, isStandalone: true, selector: "dc-acc-motion-generation", inputs: { agentCard: "agentCard" }, ngImport: i0, template: "<div class=\"motion-generation-container\">\n <img class=\"character-image\" [src]=\"agentCard.assets.image.url\" alt=\"Character Image\" />\n\n <div class=\"form-container\">\n <p-select\n [options]=\"MoodStateOptions\"\n [(ngModel)]=\"emotionSelected\"\n (ngModelChange)=\"addEmotion($event)\"\n optionLabel=\"label\"\n optionValue=\"value\"\n placeholder=\"Select an emotion\" />\n <p-select\n [options]=\"aspectRatioOptions\"\n [ngModel]=\"ratioSelected\"\n (ngModelChange)=\"changeRatio($event)\"\n optionLabel=\"description\"\n placeholder=\"Select a ratio\">\n <ng-template pTemplate=\"selectedItem\" let-selectedOption>\n @if(selectedOption) {\n <div class=\"flex items-center gap-2\">\n <div [innerHTML]=\"selectedOption.icon | safeHtml\"></div>\n <div>{{ selectedOption.description }}</div>\n </div>\n }\n </ng-template>\n <ng-template let-ratio pTemplate=\"item\">\n <div class=\"flex items-center gap-2\">\n <div [innerHTML]=\"ratio.icon | safeHtml\"></div>\n <div>{{ ratio.description }}</div>\n </div>\n </ng-template>\n </p-select>\n @if (ratioSelected) {\n <p-select\n [options]=\"resolutionOptions\"\n [(ngModel)]=\"resolutionSelected\"\n (ngModelChange)=\"onResolutionChange($event)\"\n optionLabel=\"key\"\n placeholder=\"Select a resolution\" />\n }\n <textarea rows=\"5\" cols=\"30\" pTextarea [(ngModel)]=\"videoPrompt\"></textarea>\n\n <div class=\"flex gap-2\">\n <p-button label=\"Generar\" icon=\"pi pi-video\" [loading]=\"isLoading()\" [disabled]=\"isLoading()\" (onClick)=\"generateVideoWithCharacterImage()\" />\n <div> {{this.agentCard?.assets?.motions?.length}} Motions </div>\n @if(storageMotion()) {\n <p-button label=\"Guardar\" severity=\"success\" icon=\"pi pi-save\" (onClick)=\"saveMotion()\" />\n }\n </div>\n\n @if (message()) {\n <p-message [severity]=\"'warn'\"> \u2757\uFE0F {{ message() }}</p-message>\n }\n </div>\n\n @if (generatedAsset()) {\n <video controls autoplay width=\"150\" [src]=\"generatedAsset()?.result?.url\"></video>\n }\n</div>\n", styles: [".motion-generation-container{display:flex;gap:20px;align-items:flex-start}.character-image{width:150px;flex-shrink:0}.form-container{display:flex;flex-direction:column;gap:10px;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i5.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "directive", type: i2$4.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: FormsModule }, { 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.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TextareaModule }, { kind: "directive", type: i3$1.Textarea, selector: "[pTextarea], [pInputTextarea]", inputs: ["pTextareaPT", "pTextareaUnstyled", "autoResize", "pSize", "variant", "fluid", "invalid"], outputs: ["onResize"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: MessageModule }, { kind: "component", type: i3$4.Message, selector: "p-message", inputs: ["severity", "text", "escape", "style", "styleClass", "closable", "icon", "closeIcon", "life", "showTransitionOptions", "hideTransitionOptions", "size", "variant", "motionOptions"], outputs: ["onClose"] }, { kind: "pipe", type: SafeHtmlPipe, name: "safeHtml" }] }); }
6751
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: ACCMotionGenerationComponent, isStandalone: true, selector: "dc-acc-motion-generation", inputs: { agentCard: "agentCard" }, ngImport: i0, template: "<div class=\"motion-generation-container\">\n <img class=\"character-image\" [src]=\"agentCard.assets.image.url\" alt=\"Character Image\" />\n\n <div class=\"form-container\">\n <p-select\n [options]=\"MoodStateOptions\"\n [(ngModel)]=\"emotionSelected\"\n (ngModelChange)=\"addEmotion($event)\"\n optionLabel=\"label\"\n optionValue=\"value\"\n placeholder=\"Select an emotion\" />\n <p-select\n [options]=\"aspectRatioOptions\"\n [ngModel]=\"ratioSelected\"\n (ngModelChange)=\"changeRatio($event)\"\n optionLabel=\"description\"\n placeholder=\"Select a ratio\">\n <ng-template pTemplate=\"selectedItem\" let-selectedOption>\n @if(selectedOption) {\n <div class=\"flex items-center gap-2\">\n <div [innerHTML]=\"selectedOption.icon | safeHtml\"></div>\n <div>{{ selectedOption.description }}</div>\n </div>\n }\n </ng-template>\n <ng-template let-ratio pTemplate=\"item\">\n <div class=\"flex items-center gap-2\">\n <div [innerHTML]=\"ratio.icon | safeHtml\"></div>\n <div>{{ ratio.description }}</div>\n </div>\n </ng-template>\n </p-select>\n @if (ratioSelected) {\n <p-select\n [options]=\"resolutionOptions\"\n [(ngModel)]=\"resolutionSelected\"\n (ngModelChange)=\"onResolutionChange($event)\"\n optionLabel=\"key\"\n placeholder=\"Select a resolution\" />\n }\n <textarea rows=\"5\" cols=\"30\" pTextarea [(ngModel)]=\"videoPrompt\"></textarea>\n\n <div class=\"flex gap-2\">\n <p-button label=\"Generar\" icon=\"pi pi-video\" [loading]=\"isLoading()\" [disabled]=\"isLoading()\" (onClick)=\"generateVideoWithCharacterImage()\" />\n <div> {{this.agentCard?.assets?.motions?.length}} Motions </div>\n @if(storageMotion()) {\n <p-button label=\"Guardar\" severity=\"success\" icon=\"pi pi-save\" (onClick)=\"saveMotion()\" />\n }\n </div>\n\n @if (message()) {\n <p-message [severity]=\"'warn'\"> \u2757\uFE0F {{ message() }}</p-message>\n }\n </div>\n\n @if (generatedAsset()) {\n <video controls autoplay width=\"150\" [src]=\"generatedAsset()?.result?.url\"></video>\n }\n</div>\n", styles: [".motion-generation-container{display:flex;gap:20px;align-items:flex-start}.character-image{width:150px;flex-shrink:0}.form-container{display:flex;flex-direction:column;gap:10px;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i5.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "directive", type: i2$5.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: FormsModule }, { 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.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TextareaModule }, { kind: "directive", type: i3$1.Textarea, selector: "[pTextarea], [pInputTextarea]", inputs: ["pTextareaPT", "pTextareaUnstyled", "autoResize", "pSize", "variant", "fluid", "invalid"], outputs: ["onResize"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: MessageModule }, { kind: "component", type: i3$4.Message, selector: "p-message", inputs: ["severity", "text", "escape", "style", "styleClass", "closable", "icon", "closeIcon", "life", "showTransitionOptions", "hideTransitionOptions", "size", "variant", "motionOptions"], outputs: ["onClose"] }, { kind: "pipe", type: SafeHtmlPipe, name: "safeHtml" }] }); }
6281
6752
  }
6282
6753
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ACCMotionGenerationComponent, decorators: [{
6283
6754
  type: Component,
@@ -6300,9 +6771,11 @@ class ACCTranslationGenerationComponent {
6300
6771
  this.top10Languages = ['en', 'zh', 'es', 'ar', 'fr', 'hi', 'pt', 'ru', 'de', 'ja'];
6301
6772
  }
6302
6773
  ngOnInit() {
6303
- const allGrettings = this.agentCard?.characterCard?.data?.greetings || [];
6304
- allGrettings.push(this.agentCard?.characterCard?.data.first_mes);
6305
- this.greetings.set(allGrettings);
6774
+ const originalGreetings = this.agentCard?.characterCard?.data?.greetings || [];
6775
+ const allGrettings = [...originalGreetings]; // Clone to avoid mutating original
6776
+ // Filter out any empty, null or undefined greetings
6777
+ const validGreetings = allGrettings.filter(g => g && typeof g === 'string' && g.trim() !== '');
6778
+ this.greetings.set(validGreetings);
6306
6779
  }
6307
6780
  getLanguageText(languages = null) {
6308
6781
  if (languages) {
@@ -6389,6 +6862,14 @@ ${prompt_user}
6389
6862
  else {
6390
6863
  improvements = response.content;
6391
6864
  }
6865
+ // Clean up empty greetings returned by the LLM
6866
+ if (improvements) {
6867
+ for (const lang of Object.keys(improvements)) {
6868
+ if (improvements[lang] && Array.isArray(improvements[lang].greetings)) {
6869
+ improvements[lang].greetings = improvements[lang].greetings.filter((g) => g && typeof g === 'string' && g.trim() !== '');
6870
+ }
6871
+ }
6872
+ }
6392
6873
  this.cardImprovements.set(improvements);
6393
6874
  this.cardImprovementsChange.emit(improvements);
6394
6875
  this.generationStep.set('result');
@@ -6672,7 +7153,7 @@ class GenerateCharacterDialogComponent {
6672
7153
  this.ref.close(result);
6673
7154
  }
6674
7155
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: GenerateCharacterDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6675
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: GenerateCharacterDialogComponent, isStandalone: true, selector: "dc-generate-character-dialog", ngImport: i0, template: "<div class=\"card\">\n <p-tabs lazy value=\"0\">\n <p-tablist>\n <p-tab value=\"0\">Informaci\u00F3n del personaje</p-tab>\n <p-tab value=\"1\">Movimientos</p-tab>\n <p-tab value=\"2\">Traducciones</p-tab>\n <p-tab value=\"3\">Flujo Din\u00E1mico</p-tab>\n <p-tab value=\"4\">Settings</p-tab>\n </p-tablist>\n <p-tabpanels>\n <p-tabpanel value=\"0\">\n <dc-acc-data-generation [agentCard]=\"agentCard\" (cardImprovementsChange)=\"onCardImprovementsChange($event)\"></dc-acc-data-generation>\n @if(cardImprovements.persona){\n <p-button class=\"w-full\" label=\"Guardar Datos\" (click)=\"accept()\"></p-button>\n }\n </p-tabpanel>\n <p-tabpanel value=\"1\">\n <dc-acc-motion-generation [agentCard]=\"agentCard\"></dc-acc-motion-generation>\n </p-tabpanel>\n <p-tabpanel value=\"2\">\n <ng-template #content>\n <dc-acc-translation-generation\n [agentCard]=\"agentCard\"\n (cardImprovementsChange)=\"onTranslationImprovementsChange($event)\"></dc-acc-translation-generation>\n @if(cardImprovements.langTranslation){\n <p-button class=\"w-full\" label=\"Guardar Datos\" (click)=\"accept()\"></p-button>\n }\n </ng-template>\n </p-tabpanel>\n\n <p-tabpanel value=\"3\">\n <dc-acc-dynamic-flow-generation\n [agentCard]=\"agentCard\"\n (cardImprovementsChange)=\"onDynamicFlowImprovementsChange($event)\"></dc-acc-dynamic-flow-generation>\n @if(cardImprovements.conversationFlow){\n <p-button class=\"w-full\" label=\"Guardar Datos\" (click)=\"accept()\"></p-button>\n }\n </p-tabpanel>\n\n <p-tabpanel value=\"4\">\n <ng-template #content>\n <h3> Esta es la secci\u00F3n de configuraci\u00F3n</h3>\n <dc-acc-settings-generation [agentCard]=\"agentCard\" (cardImprovementsChange)=\"onSettingsImprovementsChange($event)\"></dc-acc-settings-generation>\n @if(cardImprovements.name){\n <p-button class=\"w-full\" label=\"Guardar Datos\" (click)=\"accept()\"></p-button>\n }\n </ng-template>\n </p-tabpanel>\n </p-tabpanels>\n </p-tabs>\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: ACCDataGenerationComponent, selector: "dc-acc-data-generation", inputs: ["agentCard"], outputs: ["cardImprovementsChange"] }, { kind: "component", type: ACCMotionGenerationComponent, selector: "dc-acc-motion-generation", inputs: ["agentCard"] }, { kind: "component", type: ACCTranslationGenerationComponent, selector: "dc-acc-translation-generation", inputs: ["agentCard"], outputs: ["cardImprovementsChange"] }, { kind: "component", type: ACCSettingsGenerationComponent, selector: "dc-acc-settings-generation", inputs: ["agentCard"], outputs: ["cardImprovementsChange"] }, { kind: "component", type: ACCDynamicFlowGenerationComponent, selector: "dc-acc-dynamic-flow-generation", inputs: ["agentCard"], outputs: ["cardImprovementsChange"] }, { kind: "ngmodule", type: TabsModule }, { kind: "component", type: i2$5.Tabs, selector: "p-tabs", inputs: ["value", "scrollable", "lazy", "selectOnFocus", "showNavigators", "tabindex"], outputs: ["valueChange"] }, { kind: "component", type: i2$5.TabPanels, selector: "p-tabpanels" }, { kind: "component", type: i2$5.TabPanel, selector: "p-tabpanel", inputs: ["lazy", "value"], outputs: ["valueChange"] }, { kind: "component", type: i2$5.TabList, selector: "p-tablist" }, { kind: "component", type: i2$5.Tab, selector: "p-tab", inputs: ["value", "disabled"], outputs: ["valueChange"] }] }); }
7156
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: GenerateCharacterDialogComponent, isStandalone: true, selector: "dc-generate-character-dialog", ngImport: i0, template: "<div class=\"card\">\n <p-tabs lazy value=\"0\">\n <p-tablist>\n <p-tab value=\"0\">Informaci\u00F3n del personaje</p-tab>\n <p-tab value=\"1\">Movimientos</p-tab>\n <p-tab value=\"2\">Traducciones</p-tab>\n <p-tab value=\"3\">Flujo Din\u00E1mico</p-tab>\n <p-tab value=\"4\">Settings</p-tab>\n </p-tablist>\n <p-tabpanels>\n <p-tabpanel value=\"0\">\n <dc-acc-data-generation [agentCard]=\"agentCard\" (cardImprovementsChange)=\"onCardImprovementsChange($event)\"></dc-acc-data-generation>\n @if(cardImprovements.persona){\n <p-button class=\"w-full\" label=\"Guardar Datos\" (click)=\"accept()\"></p-button>\n }\n </p-tabpanel>\n <p-tabpanel value=\"1\">\n <dc-acc-motion-generation [agentCard]=\"agentCard\"></dc-acc-motion-generation>\n </p-tabpanel>\n <p-tabpanel value=\"2\">\n <ng-template #content>\n <dc-acc-translation-generation\n [agentCard]=\"agentCard\"\n (cardImprovementsChange)=\"onTranslationImprovementsChange($event)\"></dc-acc-translation-generation>\n @if(cardImprovements.langTranslation){\n <p-button class=\"w-full\" label=\"Guardar Datos\" (click)=\"accept()\"></p-button>\n }\n </ng-template>\n </p-tabpanel>\n\n <p-tabpanel value=\"3\">\n <dc-acc-dynamic-flow-generation\n [agentCard]=\"agentCard\"\n (cardImprovementsChange)=\"onDynamicFlowImprovementsChange($event)\"></dc-acc-dynamic-flow-generation>\n @if(cardImprovements.conversationFlow){\n <p-button class=\"w-full\" label=\"Guardar Datos\" (click)=\"accept()\"></p-button>\n }\n </p-tabpanel>\n\n <p-tabpanel value=\"4\">\n <ng-template #content>\n <h3> Esta es la secci\u00F3n de configuraci\u00F3n</h3>\n <dc-acc-settings-generation [agentCard]=\"agentCard\" (cardImprovementsChange)=\"onSettingsImprovementsChange($event)\"></dc-acc-settings-generation>\n @if(cardImprovements.name){\n <p-button class=\"w-full\" label=\"Guardar Datos\" (click)=\"accept()\"></p-button>\n }\n </ng-template>\n </p-tabpanel>\n </p-tabpanels>\n </p-tabs>\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: ACCDataGenerationComponent, selector: "dc-acc-data-generation", inputs: ["agentCard"], outputs: ["cardImprovementsChange"] }, { kind: "component", type: ACCMotionGenerationComponent, selector: "dc-acc-motion-generation", inputs: ["agentCard"] }, { kind: "component", type: ACCTranslationGenerationComponent, selector: "dc-acc-translation-generation", inputs: ["agentCard"], outputs: ["cardImprovementsChange"] }, { kind: "component", type: ACCSettingsGenerationComponent, selector: "dc-acc-settings-generation", inputs: ["agentCard"], outputs: ["cardImprovementsChange"] }, { kind: "component", type: ACCDynamicFlowGenerationComponent, selector: "dc-acc-dynamic-flow-generation", inputs: ["agentCard"], outputs: ["cardImprovementsChange"] }, { kind: "ngmodule", type: TabsModule }, { kind: "component", type: i2$6.Tabs, selector: "p-tabs", inputs: ["value", "scrollable", "lazy", "selectOnFocus", "showNavigators", "tabindex"], outputs: ["valueChange"] }, { kind: "component", type: i2$6.TabPanels, selector: "p-tabpanels" }, { kind: "component", type: i2$6.TabPanel, selector: "p-tabpanel", inputs: ["lazy", "value"], outputs: ["valueChange"] }, { kind: "component", type: i2$6.TabList, selector: "p-tablist" }, { kind: "component", type: i2$6.Tab, selector: "p-tab", inputs: ["value", "disabled"], outputs: ["valueChange"] }] }); }
6676
7157
  }
6677
7158
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: GenerateCharacterDialogComponent, decorators: [{
6678
7159
  type: Component,
@@ -6750,7 +7231,7 @@ class AccountPlatformForm {
6750
7231
  }
6751
7232
  }
6752
7233
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: AccountPlatformForm, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6753
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: AccountPlatformForm, isStandalone: true, selector: "account-platform-form", inputs: { formArray: "formArray" }, ngImport: i0, template: "<div class=\"source-form-card\">\n <p-card header=\"Cuenta\">\n @for (formAccount of formArray.controls; track formAccount) {\n <form [formGroup]=\"$any(formAccount)\">\n <div class=\"form-field\">\n <label class=\"block\">Platform</label>\n <p-select [options]=\"platformOptions\" formControlName=\"platform\" optionLabel=\"label\" optionValue=\"value\" placeholder=\"Select a platform\"></p-select>\n </div>\n\n <div class=\"form-field\">\n <label for=\"name\" class=\"block\">Username</label>\n <input pInputText id=\"name\" type=\"text\" formControlName=\"name\" placeholder=\"Enter name\" class=\"w-full\" />\n </div>\n\n <div class=\"form-field\">\n <label class=\"block\">Email</label>\n <input pInputText type=\"text\" formControlName=\"email\" placeholder=\"Enter name\" class=\"w-full\" />\n </div>\n </form>\n }\n </p-card>\n</div>\n", styles: [":host{display:block;padding:1rem}.source-form-card{max-width:800px;margin:0 auto}.form-field{margin-bottom:1.5rem;display:flex;flex-direction:column}.form-field label{margin-bottom:.5rem;font-weight:500;color:#495057}.form-field input,.form-field textarea,.form-field ::ng-deep .p-element{margin-top:.25rem}:host ::ng-deep .p-card .p-card-content>div:last-child{margin-top:1.5rem;display:flex;justify-content:flex-end}:host ::ng-deep .p-card .p-card-header{background-color:#f8f9fa;padding:1rem;border-bottom:1px solid #dee2e6}h3{color:#495057;margin-bottom:1.5rem;text-align:center}\n"], dependencies: [{ 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],[formArray],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"] }, { kind: "ngmodule", type: CardModule }, { kind: "component", type: i2$6.Card, selector: "p-card", inputs: ["header", "subheader", "style", "styleClass"] }, { kind: "ngmodule", type: TextareaModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i5.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i3$5.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: ChipModule }, { kind: "ngmodule", type: TooltipModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
7234
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: AccountPlatformForm, isStandalone: true, selector: "account-platform-form", inputs: { formArray: "formArray" }, ngImport: i0, template: "<div class=\"source-form-card\">\n <p-card header=\"Cuenta\">\n @for (formAccount of formArray.controls; track formAccount) {\n <form [formGroup]=\"$any(formAccount)\">\n <div class=\"form-field\">\n <label class=\"block\">Platform</label>\n <p-select [options]=\"platformOptions\" formControlName=\"platform\" optionLabel=\"label\" optionValue=\"value\" placeholder=\"Select a platform\"></p-select>\n </div>\n\n <div class=\"form-field\">\n <label for=\"name\" class=\"block\">Username</label>\n <input pInputText id=\"name\" type=\"text\" formControlName=\"name\" placeholder=\"Enter name\" class=\"w-full\" />\n </div>\n\n <div class=\"form-field\">\n <label class=\"block\">Email</label>\n <input pInputText type=\"text\" formControlName=\"email\" placeholder=\"Enter name\" class=\"w-full\" />\n </div>\n </form>\n }\n </p-card>\n</div>\n", styles: [":host{display:block;padding:1rem}.source-form-card{max-width:800px;margin:0 auto}.form-field{margin-bottom:1.5rem;display:flex;flex-direction:column}.form-field label{margin-bottom:.5rem;font-weight:500;color:#495057}.form-field input,.form-field textarea,.form-field ::ng-deep .p-element{margin-top:.25rem}:host ::ng-deep .p-card .p-card-content>div:last-child{margin-top:1.5rem;display:flex;justify-content:flex-end}:host ::ng-deep .p-card .p-card-header{background-color:#f8f9fa;padding:1rem;border-bottom:1px solid #dee2e6}h3{color:#495057;margin-bottom:1.5rem;text-align:center}\n"], dependencies: [{ 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],[formArray],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"] }, { kind: "ngmodule", type: CardModule }, { kind: "component", type: i2$7.Card, selector: "p-card", inputs: ["header", "subheader", "style", "styleClass"] }, { kind: "ngmodule", type: TextareaModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i5.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i3$5.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: ChipModule }, { kind: "ngmodule", type: TooltipModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
6754
7235
  }
6755
7236
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: AccountPlatformForm, decorators: [{
6756
7237
  type: Component,
@@ -6932,6 +7413,7 @@ class CharacterFormGroupService {
6932
7413
  conversationType: [ConversationType.General],
6933
7414
  autoStart: [true],
6934
7415
  userMustStart: [false],
7416
+ streamResponses: [false],
6935
7417
  displayMode: ['chat'],
6936
7418
  mainVoice: this.createVoiceTTSFormGroup(),
6937
7419
  secondaryVoice: this.createVoiceTTSFormGroup(),
@@ -7109,11 +7591,11 @@ class AgentTaskFormComponent {
7109
7591
  this.shortForm = false; // is short means AITask else SimpleAgentTask AiTaks is shorter
7110
7592
  }
7111
7593
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: AgentTaskFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
7112
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: AgentTaskFormComponent, isStandalone: true, selector: "agent-task-form", inputs: { formGroup: "formGroup", shortForm: "shortForm" }, ngImport: i0, template: "<div [formGroup]=\"formGroup\" class=\"space-y-6 p-4\">\n @if(formGroup.controls?.task) {\n <div class=\"form-field\">\n <div class=\"flex space-x-4\">\n <div> <p-checkbox id=\"enabled\" [formControl]=\"formGroup.controls.enabled\" binary=\"true\" /> Activada </div>\n\n <div> <p-checkbox id=\"enabled\" [formControl]=\"formGroup.controls.disableFeature\" binary=\"true\" /> Disable Feature </div>\n </div>\n\n <label for=\"task\" class=\"block text-sm font-medium\">Descripci\u00F3n de la evaluaci\u00F3n y asignaci\u00F3n de puntaje por turno</label>\n\n <textarea pTextarea [autoResize]=\"true\" class=\"w-full\" [formControl]=\"formGroup.controls?.task\"></textarea>\n </div>\n } @if(!shortForm && formGroup.controls?.expectedResponseType) {\n <div class=\"form-field\">\n <label for=\"expectedResponseType\" class=\"block text-sm font-medium\">Expected Response Type</label>\n <input pInputText id=\"expectedResponseType\" type=\"text\" [formControl]=\"formGroup.controls?.expectedResponseType\" class=\"w-full\" />\n </div>\n } @if (formGroup.controls?.model) {\n\n <dc-model-selector [modelForm]=\"formGroup.controls.model\" [shortForm]=\"shortForm\"></dc-model-selector>\n } @if (!shortForm && formGroup.controls?.systemPrompt) {\n <div class=\"form-field\">\n <label for=\"systemPrompt\" class=\"block text-sm font-medium mb-1\">System Prompt</label>\n <input pInputText id=\"systemPrompt\" [formControl]=\"formGroup.controls?.systemPrompt\" class=\"w-full\" />\n </div>\n }\n</div>\n", styles: [":host{display:block}.form-field{margin:0}\n"], dependencies: [{ kind: "ngmodule", type: TextareaModule }, { kind: "directive", type: i3$1.Textarea, selector: "[pTextarea], [pInputTextarea]", inputs: ["pTextareaPT", "pTextareaUnstyled", "autoResize", "pSize", "variant", "fluid", "invalid"], outputs: ["onResize"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i3$5.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { 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],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: ModelSelectorComponent, selector: "dc-model-selector", inputs: ["modelForm", "shortForm"] }, { kind: "ngmodule", type: CheckboxModule }, { kind: "component", type: i4.Checkbox, selector: "p-checkbox, p-checkBox, p-check-box", inputs: ["hostName", "value", "binary", "ariaLabelledBy", "ariaLabel", "tabindex", "inputId", "inputStyle", "styleClass", "inputClass", "indeterminate", "formControl", "checkboxIcon", "readonly", "autofocus", "trueValue", "falseValue", "variant", "size"], outputs: ["onChange", "onFocus", "onBlur"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
7594
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: AgentTaskFormComponent, isStandalone: true, selector: "agent-task-form", inputs: { formGroup: "formGroup", shortForm: "shortForm" }, ngImport: i0, template: "<div [formGroup]=\"formGroup\" class=\"space-y-6 p-4\">\n @if(formGroup.controls?.task) {\n <div class=\"form-field\">\n <div class=\"flex flex-col space-y-2 mb-4\">\n <div class=\"flex items-start gap-2\">\n <p-checkbox inputId=\"enabled\" [formControl]=\"formGroup.controls.enabled\" binary=\"true\" />\n <label for=\"enabled\" class=\"text-sm cursor-pointer select-none\">\n <strong>Activada:</strong> Habilita la tarea en esta carta (si el texto est\u00E1 vac\u00EDo, puede ser sobrescrito por la configuraci\u00F3n por defecto de la aplicaci\u00F3n host).\n </label>\n </div>\n\n <div class=\"flex items-start gap-2\">\n <p-checkbox inputId=\"disableFeature\" [formControl]=\"formGroup.controls.disableFeature\" binary=\"true\" />\n <label for=\"disableFeature\" class=\"text-sm cursor-pointer select-none text-red-600 dark:text-red-400\">\n <strong>Desactivar funci\u00F3n (Disable Feature):</strong> Ignora la configuraci\u00F3n por defecto y desactiva esta funci\u00F3n/tarea por completo para esta carta.\n </label>\n </div>\n </div>\n\n <label for=\"task\" class=\"block text-sm font-medium\">Descripci\u00F3n de la evaluaci\u00F3n y asignaci\u00F3n de puntaje por turno</label>\n\n <textarea pTextarea [autoResize]=\"true\" class=\"w-full\" [formControl]=\"formGroup.controls?.task\"></textarea>\n </div>\n } @if(!shortForm && formGroup.controls?.expectedResponseType) {\n <div class=\"form-field\">\n <label for=\"expectedResponseType\" class=\"block text-sm font-medium\">Expected Response Type</label>\n <input pInputText id=\"expectedResponseType\" type=\"text\" [formControl]=\"formGroup.controls?.expectedResponseType\" class=\"w-full\" />\n </div>\n } @if (formGroup.controls?.model) {\n\n <dc-model-selector [modelForm]=\"formGroup.controls.model\" [shortForm]=\"shortForm\"></dc-model-selector>\n } @if (!shortForm && formGroup.controls?.systemPrompt) {\n <div class=\"form-field\">\n <label for=\"systemPrompt\" class=\"block text-sm font-medium mb-1\">System Prompt</label>\n <input pInputText id=\"systemPrompt\" [formControl]=\"formGroup.controls?.systemPrompt\" class=\"w-full\" />\n </div>\n }\n</div>\n", styles: [":host{display:block}.form-field{margin:0}\n"], dependencies: [{ kind: "ngmodule", type: TextareaModule }, { kind: "directive", type: i3$1.Textarea, selector: "[pTextarea], [pInputTextarea]", inputs: ["pTextareaPT", "pTextareaUnstyled", "autoResize", "pSize", "variant", "fluid", "invalid"], outputs: ["onResize"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i3$5.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { 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],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: ModelSelectorComponent, selector: "dc-model-selector", inputs: ["modelForm", "shortForm"] }, { kind: "ngmodule", type: CheckboxModule }, { kind: "component", type: i4.Checkbox, selector: "p-checkbox, p-checkBox, p-check-box", inputs: ["hostName", "value", "binary", "ariaLabelledBy", "ariaLabel", "tabindex", "inputId", "inputStyle", "styleClass", "inputClass", "indeterminate", "formControl", "checkboxIcon", "readonly", "autofocus", "trueValue", "falseValue", "variant", "size"], outputs: ["onChange", "onFocus", "onBlur"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
7113
7595
  }
7114
7596
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: AgentTaskFormComponent, decorators: [{
7115
7597
  type: Component,
7116
- args: [{ selector: 'agent-task-form', imports: [TextareaModule, InputTextModule, ReactiveFormsModule, SelectModule, ModelSelectorComponent, ModelSelectorComponent, CheckboxModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [formGroup]=\"formGroup\" class=\"space-y-6 p-4\">\n @if(formGroup.controls?.task) {\n <div class=\"form-field\">\n <div class=\"flex space-x-4\">\n <div> <p-checkbox id=\"enabled\" [formControl]=\"formGroup.controls.enabled\" binary=\"true\" /> Activada </div>\n\n <div> <p-checkbox id=\"enabled\" [formControl]=\"formGroup.controls.disableFeature\" binary=\"true\" /> Disable Feature </div>\n </div>\n\n <label for=\"task\" class=\"block text-sm font-medium\">Descripci\u00F3n de la evaluaci\u00F3n y asignaci\u00F3n de puntaje por turno</label>\n\n <textarea pTextarea [autoResize]=\"true\" class=\"w-full\" [formControl]=\"formGroup.controls?.task\"></textarea>\n </div>\n } @if(!shortForm && formGroup.controls?.expectedResponseType) {\n <div class=\"form-field\">\n <label for=\"expectedResponseType\" class=\"block text-sm font-medium\">Expected Response Type</label>\n <input pInputText id=\"expectedResponseType\" type=\"text\" [formControl]=\"formGroup.controls?.expectedResponseType\" class=\"w-full\" />\n </div>\n } @if (formGroup.controls?.model) {\n\n <dc-model-selector [modelForm]=\"formGroup.controls.model\" [shortForm]=\"shortForm\"></dc-model-selector>\n } @if (!shortForm && formGroup.controls?.systemPrompt) {\n <div class=\"form-field\">\n <label for=\"systemPrompt\" class=\"block text-sm font-medium mb-1\">System Prompt</label>\n <input pInputText id=\"systemPrompt\" [formControl]=\"formGroup.controls?.systemPrompt\" class=\"w-full\" />\n </div>\n }\n</div>\n", styles: [":host{display:block}.form-field{margin:0}\n"] }]
7598
+ args: [{ selector: 'agent-task-form', imports: [TextareaModule, InputTextModule, ReactiveFormsModule, SelectModule, ModelSelectorComponent, ModelSelectorComponent, CheckboxModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [formGroup]=\"formGroup\" class=\"space-y-6 p-4\">\n @if(formGroup.controls?.task) {\n <div class=\"form-field\">\n <div class=\"flex flex-col space-y-2 mb-4\">\n <div class=\"flex items-start gap-2\">\n <p-checkbox inputId=\"enabled\" [formControl]=\"formGroup.controls.enabled\" binary=\"true\" />\n <label for=\"enabled\" class=\"text-sm cursor-pointer select-none\">\n <strong>Activada:</strong> Habilita la tarea en esta carta (si el texto est\u00E1 vac\u00EDo, puede ser sobrescrito por la configuraci\u00F3n por defecto de la aplicaci\u00F3n host).\n </label>\n </div>\n\n <div class=\"flex items-start gap-2\">\n <p-checkbox inputId=\"disableFeature\" [formControl]=\"formGroup.controls.disableFeature\" binary=\"true\" />\n <label for=\"disableFeature\" class=\"text-sm cursor-pointer select-none text-red-600 dark:text-red-400\">\n <strong>Desactivar funci\u00F3n (Disable Feature):</strong> Ignora la configuraci\u00F3n por defecto y desactiva esta funci\u00F3n/tarea por completo para esta carta.\n </label>\n </div>\n </div>\n\n <label for=\"task\" class=\"block text-sm font-medium\">Descripci\u00F3n de la evaluaci\u00F3n y asignaci\u00F3n de puntaje por turno</label>\n\n <textarea pTextarea [autoResize]=\"true\" class=\"w-full\" [formControl]=\"formGroup.controls?.task\"></textarea>\n </div>\n } @if(!shortForm && formGroup.controls?.expectedResponseType) {\n <div class=\"form-field\">\n <label for=\"expectedResponseType\" class=\"block text-sm font-medium\">Expected Response Type</label>\n <input pInputText id=\"expectedResponseType\" type=\"text\" [formControl]=\"formGroup.controls?.expectedResponseType\" class=\"w-full\" />\n </div>\n } @if (formGroup.controls?.model) {\n\n <dc-model-selector [modelForm]=\"formGroup.controls.model\" [shortForm]=\"shortForm\"></dc-model-selector>\n } @if (!shortForm && formGroup.controls?.systemPrompt) {\n <div class=\"form-field\">\n <label for=\"systemPrompt\" class=\"block text-sm font-medium mb-1\">System Prompt</label>\n <input pInputText id=\"systemPrompt\" [formControl]=\"formGroup.controls?.systemPrompt\" class=\"w-full\" />\n </div>\n }\n</div>\n", styles: [":host{display:block}.form-field{margin:0}\n"] }]
7117
7599
  }], propDecorators: { formGroup: [{
7118
7600
  type: Input
7119
7601
  }], shortForm: [{
@@ -7325,7 +7807,7 @@ class DCConversationFlowFormComponent {
7325
7807
  console.log(this.formGroup.value);
7326
7808
  }
7327
7809
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DCConversationFlowFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
7328
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: DCConversationFlowFormComponent, isStandalone: true, selector: "dc-conversation-flow-form", inputs: { formGroup: "formGroup" }, ngImport: i0, template: "<div [formGroup]=\"formGroup\" class=\"group\">\n <h3>Conversation Flow <span pTooltip=\"Define the flow and logic of the conversation\">\u2139\uFE0F</span></h3>\n\n <div formGroupName=\"moodState\" class=\"group\">\n <h4>Mood State <span pTooltip=\"Configure mood detection settings\">\u2139\uFE0F</span></h4>\n <div class=\"form-field\">\n <p-toggleswitch formControlName=\"enabled\"></p-toggleswitch>\n\n <label for=\"enabled\"> Detectar estado de animo? \uD83D\uDE12 \uD83E\uDD22 \uD83D\uDE24 \uD83D\uDE08 \uD83D\uDE31 <span pTooltip=\"Enable mood state detection\">\u2139\uFE0F</span></label>\n </div>\n\n @if (formGroup.controls.moodState.controls.enabled.value) {\n <div class=\"form-field\">\n <p-toggleswitch formControlName=\"useAssetStatesOnly\"></p-toggleswitch>\n\n <label for=\"useAssetStatesOnly\"\n > Solo puede sentir emociones Etiquetadas <span pTooltip=\"Depends on the motion assets, if you tag with moods, those will be the only ones detected\">\u2139\uFE0F</span></label\n >\n </div>\n\n <p-divider></p-divider>\n\n\n }\n </div>\n\n <div class=\"form-field\">\n <label for=\"flowGoal\"\n >Goal\n <span pTooltip=\"Aqu\u00ED se especifican las reglas de como se progresa en la conversaci\u00F3n , si esta desmarcada utiliza el prompt default\">\u2139\uFE0F</span></label\n >\n\n <agent-task-form [formGroup]=\"formGroup.controls.goal\" [shortForm]=\"true\"></agent-task-form>\n </div>\n\n <details>\n <summary>Trigger Task (Tareas autom\u00E1ticas que se activan al conversar)</summary>\n\n <div formGroupName=\"triggerTasks\" class=\"group\">\n <h4\n >Trigger Tasks\n <span\n (click)=\"showData()\"\n pTooltip=\"Tareas que se ejecutan en eventos espec\u00EDficos de la conversaci\u00F3n como cuando el usuario env\u00EDa un mensaje, cuando el agente responde, etc. se visualizan normalmente en la secci\u00F3n de retro\"\n >\u2139\uFE0F</span\n ></h4\n >\n @for (eventKey of objectKeys(formGroup.controls.triggerTasks.controls); track eventKey) {\n <div class=\"form-field\">\n <label [for]=\"eventKey\">\n <b>{{ eventKey | formatKey }}</b>\n </label>\n <agent-task-form [formGroup]=\"formGroup.controls.triggerTasks.controls[eventKey]\" [shortForm]=\"true\"></agent-task-form>\n </div>\n }\n </div>\n </details>\n <details>\n <summary>Tools (Herramientas que usa la APP al ocurrir eventos)</summary>\n <dc-dynamic-criteria-form [formArray]=\"formGroup.controls.tools\" title=\"Tool\" mode=\"select\" [availableItems]=\"validTools\"> </dc-dynamic-criteria-form>\n </details>\n <details>\n <summary>Challenges (Mini Desafios al conversar)</summary>\n <dc-dynamic-criteria-form [formArray]=\"formGroup.controls.challenges\" title=\"Challenge\" mode=\"free-text\"> </dc-dynamic-criteria-form>\n </details>\n\n <br />\n <div class=\"form-field\">\n <label for=\"maxTurns\"\n >Max Turns (Assistant Role)\n <span pTooltip=\"Maximum number of turns (assistant responses) before the conversation ends. Recommended: 10-30. Default: 20\">\u2139\uFE0F</span></label\n >\n <br />\n <p-inputnumber formControlName=\"maxTurns\" [showButtons]=\"true\" [min]=\"0\" [max]=\"100\" placeholder=\"Set max turns...\"></p-inputnumber>\n </div>\n\n <hr />\n\n <h4>Performance Analysis</h4>\n <div class=\"form-field\">\n <p-toggleswitch formControlName=\"enablePerformanceAnalysis\"></p-toggleswitch>\n <label>\n Retroalimentaci\u00F3n y Rendimiento Final\n <span pTooltip=\"When enabled, an AI performance analysis is triggered when the conversation ends. Requires at least 5 messages.\">\u2139\uFE0F</span>\n </label>\n </div>\n\n\n\n\n\n @if (formGroup.controls.enablePerformanceAnalysis.value) {\n <div class=\"form-field\">\n <label for=\"performancePrompt\"\n >Prompt de Retroalimentaci\u00F3n\n <span pTooltip=\"Custom prompt for the final performance analysis. If empty, the system uses the default template.\">\u2139\uFE0F</span></label\n >\n <textarea pTextarea [autoResize]=\"true\" class=\"w-full\" formControlName=\"performancePrompt\" placeholder=\"Enter custom performance prompt...\"></textarea>\n </div>\n }\n\n <dc-dynamic-conditions-form\n [dynamicConditionsArray]=\"formGroup.controls.dynamicConditions\"\n [dynamicConditionsPath]=\"'formGroup.controls.dynamicConditions'\"\n [entityWhatOptions]=\"entityWhatOptions\"\n [entityWhenOptions]=\"entityWhenOptions\"\n [systemPromptTypeOptions]=\"systemPromptTypeOptions\">\n </dc-dynamic-conditions-form>\n</div>\n", styles: [".nested-group{border:1px solid #eee;padding:10px;margin-top:10px;border-radius:4px}.very-nested-group{border:1px dashed #ccc;padding:8px;margin-top:8px;border-radius:4px}.dynamic-condition-item{margin-bottom:15px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { 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],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormArrayDirective, selector: "[formArray]", inputs: ["formArray"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "ngmodule", type: InputTextModule }, { kind: "ngmodule", type: TextareaModule }, { kind: "directive", type: i3$1.Textarea, selector: "[pTextarea], [pInputTextarea]", inputs: ["pTextareaPT", "pTextareaUnstyled", "autoResize", "pSize", "variant", "fluid", "invalid"], outputs: ["onResize"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i3.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "component", type: AgentTaskFormComponent, selector: "agent-task-form", inputs: ["formGroup", "shortForm"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: DcDynamicConditionsFormComponent, selector: "dc-dynamic-conditions-form", inputs: ["dynamicConditionsArray", "dynamicConditionsPath", "entityWhatOptions", "entityWhenOptions", "systemPromptTypeOptions"] }, { kind: "component", type: DcDynamicCriteriaFormComponent, selector: "dc-dynamic-criteria-form", inputs: ["formArray", "title", "mode", "availableItems"] }, { kind: "ngmodule", type: ToggleSwitchModule }, { kind: "component", type: i4$1.ToggleSwitch, selector: "p-toggleswitch, p-toggleSwitch, p-toggle-switch", inputs: ["styleClass", "tabindex", "inputId", "readonly", "trueValue", "falseValue", "ariaLabel", "size", "ariaLabelledBy", "autofocus"], outputs: ["onChange"] }, { kind: "ngmodule", type: InputNumberModule }, { kind: "component", type: i5$2.InputNumber, selector: "p-inputNumber, p-inputnumber, p-input-number", inputs: ["showButtons", "format", "buttonLayout", "inputId", "styleClass", "placeholder", "tabindex", "title", "ariaLabelledBy", "ariaDescribedBy", "ariaLabel", "ariaRequired", "autocomplete", "incrementButtonClass", "decrementButtonClass", "incrementButtonIcon", "decrementButtonIcon", "readonly", "allowEmpty", "locale", "localeMatcher", "mode", "currency", "currencyDisplay", "useGrouping", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "inputStyle", "inputStyleClass", "showClear", "autofocus"], outputs: ["onInput", "onFocus", "onBlur", "onKeyDown", "onClear"] }, { kind: "ngmodule", type: DividerModule }, { kind: "component", type: i1$3.Divider, selector: "p-divider", inputs: ["styleClass", "layout", "type", "align"] }, { kind: "pipe", type: FormatKeyPipe, name: "formatKey" }] }); }
7810
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: DCConversationFlowFormComponent, isStandalone: true, selector: "dc-conversation-flow-form", inputs: { formGroup: "formGroup" }, ngImport: i0, template: "<div [formGroup]=\"formGroup\" class=\"group\">\n <h3>Conversation Flow <span pTooltip=\"Define the flow and logic of the conversation\">\u2139\uFE0F</span></h3>\n\n <div formGroupName=\"moodState\" class=\"group\">\n <h4>Mood State <span pTooltip=\"Configure mood detection settings\">\u2139\uFE0F</span></h4>\n <div class=\"form-field\">\n <p-toggleswitch formControlName=\"enabled\"></p-toggleswitch>\n\n <label for=\"enabled\"> Detectar estado de animo? \uD83D\uDE12 \uD83E\uDD22 \uD83D\uDE24 \uD83D\uDE08 \uD83D\uDE31 <span pTooltip=\"Enable mood state detection\">\u2139\uFE0F</span></label>\n </div>\n\n @if (formGroup.controls.moodState.controls.enabled.value) {\n <div class=\"form-field\">\n <p-toggleswitch formControlName=\"useAssetStatesOnly\"></p-toggleswitch>\n\n <label for=\"useAssetStatesOnly\"\n > Solo puede sentir emociones Etiquetadas <span pTooltip=\"Depends on the motion assets, if you tag with moods, those will be the only ones detected\">\u2139\uFE0F</span></label\n >\n </div>\n\n <p-divider></p-divider>\n\n\n }\n </div>\n\n <div class=\"form-field\">\n <label for=\"flowGoal\"\n >Goal\n <span pTooltip=\"Aqu\u00ED se especifican las reglas de como se progresa en la conversaci\u00F3n , si esta desmarcada utiliza el prompt default\">\u2139\uFE0F</span></label\n >\n\n <agent-task-form [formGroup]=\"formGroup.controls.goal\" [shortForm]=\"true\"></agent-task-form>\n </div>\n\n <details>\n <summary>Trigger Task (Tareas autom\u00E1ticas que se activan al conversar)</summary>\n\n <div formGroupName=\"triggerTasks\" class=\"group\">\n <h4\n >Trigger Tasks\n <span\n (click)=\"showData()\"\n pTooltip=\"Tareas que se ejecutan en eventos espec\u00EDficos de la conversaci\u00F3n como cuando el usuario env\u00EDa un mensaje, cuando el agente responde, etc. se visualizan normalmente en la secci\u00F3n de retro\"\n >\u2139\uFE0F</span\n ></h4\n >\n @for (eventKey of objectKeys(formGroup.controls.triggerTasks.controls); track eventKey) {\n <div class=\"form-field\">\n <label [for]=\"eventKey\">\n <b>{{ eventKey | formatKey }}</b>\n </label>\n <agent-task-form [formGroup]=\"formGroup.controls.triggerTasks.controls[eventKey]\" [shortForm]=\"true\"></agent-task-form>\n </div>\n }\n </div>\n </details>\n <details>\n <summary>Tools (Herramientas que usa la APP al ocurrir eventos)</summary>\n <dc-dynamic-criteria-form [formArray]=\"formGroup.controls.tools\" title=\"Tool\" mode=\"select\" [availableItems]=\"validTools\"> </dc-dynamic-criteria-form>\n </details>\n <details>\n <summary>Challenges (Mini Desafios al conversar)</summary>\n <dc-dynamic-criteria-form [formArray]=\"formGroup.controls.challenges\" title=\"Challenge\" mode=\"free-text\"> </dc-dynamic-criteria-form>\n </details>\n\n <br />\n <div class=\"form-field\">\n <label for=\"maxTurns\"\n >Max Turns (Assistant Role)\n <span pTooltip=\"Maximum number of turns (assistant responses) before the conversation ends. Recommended: 10-30. Default: 20\">\u2139\uFE0F</span></label\n >\n <br />\n <p-inputnumber formControlName=\"maxTurns\" [showButtons]=\"true\" [min]=\"0\" [max]=\"100\" placeholder=\"Set max turns...\"></p-inputnumber>\n </div>\n\n <hr />\n\n <h4>Performance Analysis</h4>\n <div class=\"form-field\">\n <p-toggleswitch formControlName=\"enablePerformanceAnalysis\"></p-toggleswitch>\n <label>\n Retroalimentaci\u00F3n y Rendimiento Final\n <span pTooltip=\"When enabled, an AI performance analysis is triggered when the conversation ends. Requires at least 5 messages.\">\u2139\uFE0F</span>\n </label>\n </div>\n\n\n\n\n\n @if (formGroup.controls.enablePerformanceAnalysis.value) {\n <div class=\"form-field\">\n <label for=\"performancePrompt\"\n >Prompt de Retroalimentaci\u00F3n\n <span pTooltip=\"Custom prompt for the final performance analysis. If empty, the system uses the default template.\">\u2139\uFE0F</span></label\n >\n <textarea pTextarea [autoResize]=\"true\" class=\"w-full\" formControlName=\"performancePrompt\" placeholder=\"Enter custom performance prompt...\"></textarea>\n </div>\n }\n\n <dc-dynamic-conditions-form\n [dynamicConditionsArray]=\"formGroup.controls.dynamicConditions\"\n [dynamicConditionsPath]=\"'formGroup.controls.dynamicConditions'\"\n [entityWhatOptions]=\"entityWhatOptions\"\n [entityWhenOptions]=\"entityWhenOptions\"\n [systemPromptTypeOptions]=\"systemPromptTypeOptions\">\n </dc-dynamic-conditions-form>\n</div>\n", styles: [".nested-group{border:1px solid #eee;padding:10px;margin-top:10px;border-radius:4px}.very-nested-group{border:1px dashed #ccc;padding:8px;margin-top:8px;border-radius:4px}.dynamic-condition-item{margin-bottom:15px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { 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],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormArrayDirective, selector: "[formArray]", inputs: ["formArray"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "ngmodule", type: InputTextModule }, { kind: "ngmodule", type: TextareaModule }, { kind: "directive", type: i3$1.Textarea, selector: "[pTextarea], [pInputTextarea]", inputs: ["pTextareaPT", "pTextareaUnstyled", "autoResize", "pSize", "variant", "fluid", "invalid"], outputs: ["onResize"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i3.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "component", type: AgentTaskFormComponent, selector: "agent-task-form", inputs: ["formGroup", "shortForm"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: DcDynamicConditionsFormComponent, selector: "dc-dynamic-conditions-form", inputs: ["dynamicConditionsArray", "dynamicConditionsPath", "entityWhatOptions", "entityWhenOptions", "systemPromptTypeOptions"] }, { kind: "component", type: DcDynamicCriteriaFormComponent, selector: "dc-dynamic-criteria-form", inputs: ["formArray", "title", "mode", "availableItems"] }, { kind: "ngmodule", type: ToggleSwitchModule }, { kind: "component", type: i4$2.ToggleSwitch, selector: "p-toggleswitch, p-toggleSwitch, p-toggle-switch", inputs: ["styleClass", "tabindex", "inputId", "readonly", "trueValue", "falseValue", "ariaLabel", "size", "ariaLabelledBy", "autofocus"], outputs: ["onChange"] }, { kind: "ngmodule", type: InputNumberModule }, { kind: "component", type: i5$2.InputNumber, selector: "p-inputNumber, p-inputnumber, p-input-number", inputs: ["showButtons", "format", "buttonLayout", "inputId", "styleClass", "placeholder", "tabindex", "title", "ariaLabelledBy", "ariaDescribedBy", "ariaLabel", "ariaRequired", "autocomplete", "incrementButtonClass", "decrementButtonClass", "incrementButtonIcon", "decrementButtonIcon", "readonly", "allowEmpty", "locale", "localeMatcher", "mode", "currency", "currencyDisplay", "useGrouping", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "inputStyle", "inputStyleClass", "showClear", "autofocus"], outputs: ["onInput", "onFocus", "onBlur", "onKeyDown", "onClear"] }, { kind: "ngmodule", type: DividerModule }, { kind: "component", type: i2$4.Divider, selector: "p-divider", inputs: ["styleClass", "layout", "type", "align"] }, { kind: "pipe", type: FormatKeyPipe, name: "formatKey" }] }); }
7329
7811
  }
7330
7812
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DCConversationFlowFormComponent, decorators: [{
7331
7813
  type: Component,
@@ -7402,11 +7884,11 @@ class DcCharacterCardTranslationsTabsFormComponent {
7402
7884
  this.formGroup.removeControl(langCode);
7403
7885
  }
7404
7886
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DcCharacterCardTranslationsTabsFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
7405
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: DcCharacterCardTranslationsTabsFormComponent, isStandalone: true, selector: "dc-character-card-translations-tabs-form", inputs: { formGroup: "formGroup" }, ngImport: i0, template: "<div class=\"flex justify-between items-center mb-4\">\n <h4 class=\"text-lg font-semibold\">Translations ({{ (formGroup?.controls | keyvalue)?.length }})</h4>\n <p-button icon=\"pi pi-plus\" label=\"Add Language\" (click)=\"showAddLanguageDialog()\" />\n</div>\n\n<p-tabs value=\"0\" [scrollable]=\"true\">\n <p-tablist>\n @for (control of formGroup.controls | keyvalue; track control.key; let i = $index) {\n <p-tab [value]=\"control.key\">\n <div class=\"flex items-center\">\n <span>{{ control.key }}</span>\n <button\n pButton\n type=\"button\"\n icon=\"pi pi-times\"\n class=\"p-button-rounded p-button-danger p-button-text ml-2\"\n (click)=\"removeLanguage(control.key)\"></button>\n </div>\n </p-tab>\n }\n </p-tablist>\n <p-tabpanels>\n @for (control of formGroup.controls | keyvalue; track control.key) {\n <p-tabpanel [value]=\"control.key\">\n @if (control.value) {\n <dc-character-card-translation-form [formGroup]=\"control.value\" />\n }\n </p-tabpanel>\n }\n </p-tabpanels>\n</p-tabs>\n\n<p-dialog header=\"Add New Language\" [(visible)]=\"displayAddLanguageDialog\" [modal]=\"true\" [style]=\"{ width: '50vw', height: '50vh' }\">\n <div style=\"height: 30vh\">\n <label for=\"language\">Only Valid Languages and not added yet are displayed</label>\n <br />\n <p-select\n [options]=\"availableLanguages()\"\n [(ngModel)]=\"selectedLanguage\"\n placeholder=\"Select a Language\"\n optionLabel=\"description\"\n optionValue=\"code\"\n [filter]=\"true\"\n filterBy=\"description\"\n [showClear]=\"true\"></p-select>\n </div>\n\n <ng-template pTemplate=\"footer\">\n <p-button icon=\"pi pi-times\" label=\"Cancel\" styleClass=\"p-button-text\" (click)=\"displayAddLanguageDialog = false\" />\n <p-button icon=\"pi pi-check\" label=\"Add\" (click)=\"addLanguage()\" [disabled]=\"!selectedLanguage\" />\n </ng-template>\n</p-dialog>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TabsModule }, { kind: "component", type: i2$5.Tabs, selector: "p-tabs", inputs: ["value", "scrollable", "lazy", "selectOnFocus", "showNavigators", "tabindex"], outputs: ["valueChange"] }, { kind: "component", type: i2$5.TabPanels, selector: "p-tabpanels" }, { kind: "component", type: i2$5.TabPanel, selector: "p-tabpanel", inputs: ["lazy", "value"], outputs: ["valueChange"] }, { kind: "component", type: i2$5.TabList, selector: "p-tablist" }, { kind: "component", type: i2$5.Tab, selector: "p-tab", inputs: ["value", "disabled"], outputs: ["valueChange"] }, { kind: "component", type: DcCharacterCardTranslationFormComponent, selector: "dc-character-card-translation-form", inputs: ["formGroup"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i2.ButtonDirective, selector: "[pButton]", inputs: ["ptButtonDirective", "pButtonPT", "pButtonUnstyled", "hostName", "text", "plain", "raised", "size", "outlined", "rounded", "iconPos", "loadingIcon", "fluid", "label", "icon", "loading", "buttonProps", "severity"] }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "directive", type: i2$4.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: DialogModule }, { kind: "component", type: i5$1.Dialog, selector: "p-dialog", inputs: ["hostName", "header", "draggable", "resizable", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "maskMotionOptions", "motionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "appendTo", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i5.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "pipe", type: KeyValuePipe, name: "keyvalue" }] }); }
7887
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: DcCharacterCardTranslationsTabsFormComponent, isStandalone: true, selector: "dc-character-card-translations-tabs-form", inputs: { formGroup: "formGroup" }, ngImport: i0, template: "<div class=\"flex justify-between items-center mb-4\">\n <h4 class=\"text-lg font-semibold\">Translations ({{ (formGroup?.controls | keyvalue)?.length }})</h4>\n <p-button icon=\"pi pi-plus\" label=\"Add Language\" (click)=\"showAddLanguageDialog()\" />\n</div>\n\n<p-tabs value=\"0\" [scrollable]=\"true\">\n <p-tablist>\n @for (control of formGroup.controls | keyvalue; track control.key; let i = $index) {\n <p-tab [value]=\"control.key\">\n <div class=\"flex items-center gap-2\">\n @if(control.key | flagImg) {\n <img [src]=\"control.key | flagImg\" alt=\"{{ control.key }}\" class=\"w-5 h-auto rounded-sm border border-gray-300 shadow-sm\" />\n } @else {\n <span class=\"text-lg\">{{ control.key | flagEmoji }}</span>\n }\n <span class=\"font-medium capitalize\">{{ control.key | langDesc:'es' }}</span>\n </div>\n </p-tab>\n }\n </p-tablist>\n <p-tabpanels>\n @for (control of formGroup.controls | keyvalue; track control.key) {\n <p-tabpanel [value]=\"control.key\">\n <div class=\"flex justify-end mb-4\">\n <p-button\n severity=\"danger\"\n icon=\"pi pi-trash\"\n label=\"Remove {{ control.key | langDesc:'es' }}\"\n [outlined]=\"true\"\n size=\"small\"\n (click)=\"removeLanguage(control.key)\"></p-button>\n </div>\n @if (control.value) {\n <dc-character-card-translation-form [formGroup]=\"control.value\" />\n }\n </p-tabpanel>\n }\n </p-tabpanels>\n</p-tabs>\n\n<p-dialog header=\"Add New Language\" [(visible)]=\"displayAddLanguageDialog\" [modal]=\"true\" [style]=\"{ width: '50vw', height: '50vh' }\">\n <div style=\"height: 30vh\">\n <label for=\"language\">Only Valid Languages and not added yet are displayed</label>\n <br />\n <p-select\n [options]=\"availableLanguages()\"\n [(ngModel)]=\"selectedLanguage\"\n placeholder=\"Select a Language\"\n optionLabel=\"description\"\n optionValue=\"code\"\n [filter]=\"true\"\n filterBy=\"description\"\n [showClear]=\"true\"></p-select>\n </div>\n\n <ng-template pTemplate=\"footer\">\n <p-button icon=\"pi pi-times\" label=\"Cancel\" styleClass=\"p-button-text\" (click)=\"displayAddLanguageDialog = false\" />\n <p-button icon=\"pi pi-check\" label=\"Add\" (click)=\"addLanguage()\" [disabled]=\"!selectedLanguage\" />\n </ng-template>\n</p-dialog>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TabsModule }, { kind: "component", type: i2$6.Tabs, selector: "p-tabs", inputs: ["value", "scrollable", "lazy", "selectOnFocus", "showNavigators", "tabindex"], outputs: ["valueChange"] }, { kind: "component", type: i2$6.TabPanels, selector: "p-tabpanels" }, { kind: "component", type: i2$6.TabPanel, selector: "p-tabpanel", inputs: ["lazy", "value"], outputs: ["valueChange"] }, { kind: "component", type: i2$6.TabList, selector: "p-tablist" }, { kind: "component", type: i2$6.Tab, selector: "p-tab", inputs: ["value", "disabled"], outputs: ["valueChange"] }, { kind: "component", type: DcCharacterCardTranslationFormComponent, selector: "dc-character-card-translation-form", inputs: ["formGroup"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "directive", type: i2$5.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: DialogModule }, { kind: "component", type: i5$1.Dialog, selector: "p-dialog", inputs: ["hostName", "header", "draggable", "resizable", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "maskMotionOptions", "motionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "appendTo", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i5.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "pipe", type: KeyValuePipe, name: "keyvalue" }, { kind: "pipe", type: LangDescTranslation, name: "langDesc" }, { kind: "pipe", type: FlagPipe, name: "flagEmoji" }, { kind: "pipe", type: FlagImgPipe, name: "flagImg" }] }); }
7406
7888
  }
7407
7889
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DcCharacterCardTranslationsTabsFormComponent, decorators: [{
7408
7890
  type: Component,
7409
- args: [{ selector: 'dc-character-card-translations-tabs-form', standalone: true, imports: [ReactiveFormsModule, FormsModule, TabsModule, DcCharacterCardTranslationFormComponent, ButtonModule, DialogModule, SelectModule, KeyValuePipe], template: "<div class=\"flex justify-between items-center mb-4\">\n <h4 class=\"text-lg font-semibold\">Translations ({{ (formGroup?.controls | keyvalue)?.length }})</h4>\n <p-button icon=\"pi pi-plus\" label=\"Add Language\" (click)=\"showAddLanguageDialog()\" />\n</div>\n\n<p-tabs value=\"0\" [scrollable]=\"true\">\n <p-tablist>\n @for (control of formGroup.controls | keyvalue; track control.key; let i = $index) {\n <p-tab [value]=\"control.key\">\n <div class=\"flex items-center\">\n <span>{{ control.key }}</span>\n <button\n pButton\n type=\"button\"\n icon=\"pi pi-times\"\n class=\"p-button-rounded p-button-danger p-button-text ml-2\"\n (click)=\"removeLanguage(control.key)\"></button>\n </div>\n </p-tab>\n }\n </p-tablist>\n <p-tabpanels>\n @for (control of formGroup.controls | keyvalue; track control.key) {\n <p-tabpanel [value]=\"control.key\">\n @if (control.value) {\n <dc-character-card-translation-form [formGroup]=\"control.value\" />\n }\n </p-tabpanel>\n }\n </p-tabpanels>\n</p-tabs>\n\n<p-dialog header=\"Add New Language\" [(visible)]=\"displayAddLanguageDialog\" [modal]=\"true\" [style]=\"{ width: '50vw', height: '50vh' }\">\n <div style=\"height: 30vh\">\n <label for=\"language\">Only Valid Languages and not added yet are displayed</label>\n <br />\n <p-select\n [options]=\"availableLanguages()\"\n [(ngModel)]=\"selectedLanguage\"\n placeholder=\"Select a Language\"\n optionLabel=\"description\"\n optionValue=\"code\"\n [filter]=\"true\"\n filterBy=\"description\"\n [showClear]=\"true\"></p-select>\n </div>\n\n <ng-template pTemplate=\"footer\">\n <p-button icon=\"pi pi-times\" label=\"Cancel\" styleClass=\"p-button-text\" (click)=\"displayAddLanguageDialog = false\" />\n <p-button icon=\"pi pi-check\" label=\"Add\" (click)=\"addLanguage()\" [disabled]=\"!selectedLanguage\" />\n </ng-template>\n</p-dialog>\n" }]
7891
+ args: [{ selector: 'dc-character-card-translations-tabs-form', standalone: true, imports: [ReactiveFormsModule, FormsModule, TabsModule, DcCharacterCardTranslationFormComponent, ButtonModule, DialogModule, SelectModule, KeyValuePipe, LangDescTranslation, FlagPipe, FlagImgPipe], template: "<div class=\"flex justify-between items-center mb-4\">\n <h4 class=\"text-lg font-semibold\">Translations ({{ (formGroup?.controls | keyvalue)?.length }})</h4>\n <p-button icon=\"pi pi-plus\" label=\"Add Language\" (click)=\"showAddLanguageDialog()\" />\n</div>\n\n<p-tabs value=\"0\" [scrollable]=\"true\">\n <p-tablist>\n @for (control of formGroup.controls | keyvalue; track control.key; let i = $index) {\n <p-tab [value]=\"control.key\">\n <div class=\"flex items-center gap-2\">\n @if(control.key | flagImg) {\n <img [src]=\"control.key | flagImg\" alt=\"{{ control.key }}\" class=\"w-5 h-auto rounded-sm border border-gray-300 shadow-sm\" />\n } @else {\n <span class=\"text-lg\">{{ control.key | flagEmoji }}</span>\n }\n <span class=\"font-medium capitalize\">{{ control.key | langDesc:'es' }}</span>\n </div>\n </p-tab>\n }\n </p-tablist>\n <p-tabpanels>\n @for (control of formGroup.controls | keyvalue; track control.key) {\n <p-tabpanel [value]=\"control.key\">\n <div class=\"flex justify-end mb-4\">\n <p-button\n severity=\"danger\"\n icon=\"pi pi-trash\"\n label=\"Remove {{ control.key | langDesc:'es' }}\"\n [outlined]=\"true\"\n size=\"small\"\n (click)=\"removeLanguage(control.key)\"></p-button>\n </div>\n @if (control.value) {\n <dc-character-card-translation-form [formGroup]=\"control.value\" />\n }\n </p-tabpanel>\n }\n </p-tabpanels>\n</p-tabs>\n\n<p-dialog header=\"Add New Language\" [(visible)]=\"displayAddLanguageDialog\" [modal]=\"true\" [style]=\"{ width: '50vw', height: '50vh' }\">\n <div style=\"height: 30vh\">\n <label for=\"language\">Only Valid Languages and not added yet are displayed</label>\n <br />\n <p-select\n [options]=\"availableLanguages()\"\n [(ngModel)]=\"selectedLanguage\"\n placeholder=\"Select a Language\"\n optionLabel=\"description\"\n optionValue=\"code\"\n [filter]=\"true\"\n filterBy=\"description\"\n [showClear]=\"true\"></p-select>\n </div>\n\n <ng-template pTemplate=\"footer\">\n <p-button icon=\"pi pi-times\" label=\"Cancel\" styleClass=\"p-button-text\" (click)=\"displayAddLanguageDialog = false\" />\n <p-button icon=\"pi pi-check\" label=\"Add\" (click)=\"addLanguage()\" [disabled]=\"!selectedLanguage\" />\n </ng-template>\n</p-dialog>\n" }]
7410
7892
  }], propDecorators: { formGroup: [{
7411
7893
  type: Input
7412
7894
  }] } });
@@ -7538,7 +8020,7 @@ Improve the following first message:`;
7538
8020
  return control;
7539
8021
  }
7540
8022
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DcCharacterCardFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
7541
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: DcCharacterCardFormComponent, isStandalone: true, selector: "dc-character-card-form", inputs: { characterCardForm: "characterCardForm" }, outputs: { generateMissingDataRequest: "generateMissingDataRequest" }, ngImport: i0, template: "<div [formGroup]=\"characterCardForm\">\n <div formGroupName=\"data\" class=\"card-group space-y-6 p-8 rounded-lg shadow-md\">\n <div class=\"flex justify-end\">\n <p-button\n (click)=\"generateMissingDataRequest.emit()\"\n icon=\"pi pi-sparkles\"\n [rounded]=\"true\"\n severity=\"info\"\n label=\"Arreglar Campos\"\n styleClass=\"p-button-sm\" />\n </div>\n\n <h3 class=\"text-2xl font-semibold mb-6\"\n >Character Card <span pTooltip=\"Informaci\u00F3n de la ficha del personaje\" class=\"text-blue-500 cursor-pointer\">\u2139\uFE0F</span></h3\n >\n\n <div class=\"grid grid-cols-2 gap-6\">\n <div class=\"form-field\">\n <label for=\"cardName\" class=\"block text-sm font-medium \"\n >Character Name <span pTooltip=\"El nombre del personaje\" class=\"text-blue-500 cursor-pointer\">\u2139\uFE0F</span></label\n >\n <input\n pInputText\n id=\"cardName\"\n type=\"text\"\n formControlName=\"name\"\n class=\"mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm\" />\n @if (dataGroup.controls['name']?.errors?.['required'] && dataGroup.controls['name']?.touched) {\n <div class=\"error text-red-500 text-xs mt-1\"> Name is required </div>\n }\n </div>\n\n <div class=\"form-field\">\n <label for=\"gender\" class=\"block text-sm font-medium \"\n >Gender <span pTooltip=\"El genero del personaje\" class=\"text-blue-500 cursor-pointer\">\u2139\uFE0F</span></label\n >\n <p-select\n class=\"w-full\"\n id=\"gender\"\n [options]=\"genderOptions\"\n formControlName=\"gender\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"'Select Gender'\"></p-select>\n @if (dataGroup.controls['gender']?.errors?.['required'] && dataGroup.controls['gender']?.touched) {\n <div class=\"error text-red-500 text-xs mt-1\"> Gender is required </div>\n }\n </div>\n </div>\n\n <div class=\"form-field grid grid-cols-1 gap-2\">\n <label for=\"cardDescription\" class=\"block text-sm font-medium \"\n >Description\n <span pTooltip=\"Descripci\u00F3n de la tarjeta, si es una tarjeta compleja utiliza los campos de PERSONA\" class=\"text-blue-500 cursor-pointer\"\n >\u2139\uFE0F</span\n ></label\n >\n <textarea\n class=\"textmin mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm\"\n rows=\"1\"\n pTextarea\n [autoResize]=\"true\"\n id=\"cardDescription\"\n formControlName=\"description\"></textarea>\n @if (dataGroup.controls['description']?.errors?.['required'] && dataGroup.controls['description']?.touched) {\n <div class=\"error text-red-500 text-xs mt-1\"> Description is required </div>\n }\n </div>\n\n <div class=\"form-field grid grid-cols-1 gap-2\">\n <label for=\"cardCreatorNotes\" class=\"block text-sm font-medium \"\n >Hook <span pTooltip=\"Texto gancho para atraer al usuario a interactuar con esta tarjeta\" class=\"text-blue-500 cursor-pointer\">\u2139\uFE0F</span></label\n >\n <textarea\n rows=\"2\"\n pTextarea\n [autoResize]=\"true\"\n id=\"cardHook\"\n formControlName=\"hook\"\n class=\"mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm\"></textarea>\n </div>\n <div class=\"form-field grid grid-cols-1 gap-2\">\n <label for=\"cardInstructions\" class=\"block text-sm font-medium \"\n >Instructions <span pTooltip=\"Instrucciones para el usuario, sepa que tiene que hacer.\" class=\"text-blue-500 cursor-pointer\">\u2139\uFE0F</span></label\n >\n <textarea\n rows=\"2\"\n pTextarea\n [autoResize]=\"true\"\n id=\"cardInstructions\"\n formControlName=\"instructions\"\n class=\"mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm\"></textarea>\n </div>\n\n <div class=\"form-field grid grid-cols-1 gap-2\">\n <label for=\"cardScenario\" class=\"block text-sm font-medium \"\n >Scenario <span pTooltip=\"Describe the context or setting for the conversation\" class=\"text-blue-500 cursor-pointer\">\u2139\uFE0F</span></label\n >\n <textarea\n rows=\"2\"\n pTextarea\n [autoResize]=\"true\"\n id=\"cardScenario\"\n formControlName=\"scenario\"\n class=\"mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm\"></textarea>\n </div>\n\n <div class=\"form-field grid grid-cols-1 gap-2\">\n <label for=\"cardAlternateGreetings\" class=\"block text-sm font-medium \"\n >Greetings (Saludos Iniciales)<span pTooltip=\"Saludos alternativos para comenzar una historia diferente\" class=\"text-blue-500 cursor-pointer\"\n >\u2139\uFE0F</span\n ></label\n >\n <div class=\"array-field space-y-2\">\n @for (greeting of alternateGreetingsArray.controls; track greeting; let i = $index) {\n <div class=\"array-item flex items-center space-x-2\" style=\"position: relative\">\n <textarea\n pTextarea\n rows=\"1\"\n [autoResize]=\"true\"\n [id]=\"'cardAlternateGreeting' + i\"\n [formControl]=\"asFormControl(greeting)\"\n (input)=\"updateArrayField('greetings', i, $event)\"\n class=\"mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm flex-grow\">\n </textarea>\n <button\n pButton\n severity=\"danger\"\n icon=\"pi pi-times\"\n class=\"remove-button p-button-sm p-button-rounded p-button-danger\"\n (click)=\"removeArrayItem('greetings', i)\"></button>\n </div>\n }\n <button pButton severity=\"info\" label=\"Add Greeting\" icon=\"pi pi-plus\" (click)=\"addArrayItem('greetings')\" class=\"p-button-sm\"></button>\n </div>\n </div>\n\n <p-divider> Persona </p-divider>\n\n <dc-persona-form [personaForm]=\"personaGroup\" />\n\n <p-divider> Avanzado </p-divider>\n\n <div class=\"form-field grid grid-cols-1 gap-2\">\n <label for=\"cardPostHistoryInstructions\" class=\"block text-sm font-medium \"\n >(\u2757\uFE0FObsoleto) Post-History Instructions\n <span\n pTooltip=\"Dejar en blanco, al menos que se sepa como funciona, esto se llama jailbreak, es para darle instrucciones finales y m\u00E1s importantes al modelo\"\n class=\"text-blue-500 cursor-pointer\"\n >\u2139\uFE0F</span\n ></label\n >\n <textarea\n rows=\"1\"\n pTextarea\n [autoResize]=\"true\"\n formControlName=\"post_history_instructions\"\n class=\"mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm\"></textarea>\n </div>\n\n <div class=\"form-field grid grid-cols-1 gap-2\">\n <label for=\"cardSystemPrompt\" class=\"block text-sm font-medium \">\n (\u26A0\uFE0F Cuidado) System Prompt <span pTooltip=\"Instrucciones del sistema para la conversaci\u00F3n\" class=\"text-blue-500 cursor-pointer\">\u2139\uFE0F</span>\n </label>\n <textarea\n rows=\"1\"\n pTextarea\n [autoResize]=\"true\"\n id=\"cardSystemPrompt\"\n formControlName=\"system_prompt\"\n class=\"mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm\"></textarea>\n @if (dataGroup.controls['system_prompt']?.errors?.['required'] && dataGroup.controls['system_prompt']?.touched) {\n <div class=\"error text-red-500 text-xs mt-1\"> System prompt is required </div>\n }\n </div>\n\n <div class=\"form-field grid grid-cols-1 gap-2\">\n <label for=\"cardCreatorNotes\" class=\"block text-sm font-medium \"\n >Creator Notes <span pTooltip=\"son solo notas del creador, no afecta nada a la conversaci\u00F3n\" class=\"text-blue-500 cursor-pointer\">\u2139\uFE0F</span></label\n >\n <textarea\n rows=\"1\"\n pTextarea\n [autoResize]=\"true\"\n id=\"cardCreatorNotes\"\n formControlName=\"creator_notes\"\n class=\"mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm\"></textarea>\n </div>\n\n <div class=\"form-field grid grid-cols-1 gap-2\">\n <label pTooltip=\"Agrega las categorias\" for=\"cardTags\" class=\"block text-sm font-medium \">Tags \u2139\uFE0F</label>\n <dc-tags-form [form]=\"dataGroup\" />\n </div>\n\n <p-divider align=\"center\" type=\"dotted\">\n <b>Traducciones a otros idiomas</b>\n </p-divider>\n\n @if(langTranslationGroup){\n <dc-character-card-translations-tabs-form [formGroup]=\"langTranslationGroup\" />\n }\n </div>\n</div>\n", styles: [".textmin{min-height:40px}.array-field{display:flex;flex-direction:column;gap:8px}.array-item{display:flex;align-items:center;gap:8px;position:relative}.array-item textarea,.array-item input[type=text]{flex-grow:1}.remove-button{position:absolute;right:5px;top:5px;min-width:auto!important;width:2rem;height:2rem}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { 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],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["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"] }, { kind: "directive", type: i1$1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i2.ButtonDirective, selector: "[pButton]", inputs: ["ptButtonDirective", "pButtonPT", "pButtonUnstyled", "hostName", "text", "plain", "raised", "size", "outlined", "rounded", "iconPos", "loadingIcon", "fluid", "label", "icon", "loading", "buttonProps", "severity"] }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i3$5.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: TextareaModule }, { kind: "directive", type: i3$1.Textarea, selector: "[pTextarea], [pInputTextarea]", inputs: ["pTextareaPT", "pTextareaUnstyled", "autoResize", "pSize", "variant", "fluid", "invalid"], outputs: ["onResize"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i3.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "ngmodule", type: ToggleButtonModule }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i5.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: DividerModule }, { kind: "component", type: i1$3.Divider, selector: "p-divider", inputs: ["styleClass", "layout", "type", "align"] }, { kind: "component", type: DcCharacterCardTranslationsTabsFormComponent, selector: "dc-character-card-translations-tabs-form", inputs: ["formGroup"] }, { kind: "component", type: DcPersonaFormComponent, selector: "dc-persona-form", inputs: ["personaForm"] }, { kind: "component", type: DcTagsFormComponent, selector: "dc-tags-form", inputs: ["form"] }] }); }
8023
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: DcCharacterCardFormComponent, isStandalone: true, selector: "dc-character-card-form", inputs: { characterCardForm: "characterCardForm" }, outputs: { generateMissingDataRequest: "generateMissingDataRequest" }, ngImport: i0, template: "<div [formGroup]=\"characterCardForm\">\n <div formGroupName=\"data\" class=\"card-group space-y-6 p-8 rounded-lg shadow-md\">\n <div class=\"flex justify-end\">\n <p-button\n (click)=\"generateMissingDataRequest.emit()\"\n icon=\"pi pi-sparkles\"\n [rounded]=\"true\"\n severity=\"info\"\n label=\"Arreglar Campos\"\n styleClass=\"p-button-sm\" />\n </div>\n\n <h3 class=\"text-2xl font-semibold mb-6\"\n >Character Card <span pTooltip=\"Informaci\u00F3n de la ficha del personaje\" class=\"text-blue-500 cursor-pointer\">\u2139\uFE0F</span></h3\n >\n\n <div class=\"grid grid-cols-2 gap-6\">\n <div class=\"form-field\">\n <label for=\"cardName\" class=\"block text-sm font-medium \"\n >Character Name <span pTooltip=\"El nombre del personaje\" class=\"text-blue-500 cursor-pointer\">\u2139\uFE0F</span></label\n >\n <input\n pInputText\n id=\"cardName\"\n type=\"text\"\n formControlName=\"name\"\n class=\"mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm\" />\n @if (dataGroup.controls['name']?.errors?.['required'] && dataGroup.controls['name']?.touched) {\n <div class=\"error text-red-500 text-xs mt-1\"> Name is required </div>\n }\n </div>\n\n <div class=\"form-field\">\n <label for=\"gender\" class=\"block text-sm font-medium \"\n >Gender <span pTooltip=\"El genero del personaje\" class=\"text-blue-500 cursor-pointer\">\u2139\uFE0F</span></label\n >\n <p-select\n class=\"w-full\"\n id=\"gender\"\n [options]=\"genderOptions\"\n formControlName=\"gender\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"'Select Gender'\"></p-select>\n @if (dataGroup.controls['gender']?.errors?.['required'] && dataGroup.controls['gender']?.touched) {\n <div class=\"error text-red-500 text-xs mt-1\"> Gender is required </div>\n }\n </div>\n </div>\n\n <div class=\"form-field grid grid-cols-1 gap-2\">\n <label for=\"cardDescription\" class=\"block text-sm font-medium \"\n >Description\n <span pTooltip=\"Descripci\u00F3n de la tarjeta, si es una tarjeta compleja utiliza los campos de PERSONA\" class=\"text-blue-500 cursor-pointer\"\n >\u2139\uFE0F</span\n ></label\n >\n <textarea\n class=\"textmin mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm\"\n rows=\"1\"\n pTextarea\n [autoResize]=\"true\"\n id=\"cardDescription\"\n formControlName=\"description\"></textarea>\n @if (dataGroup.controls['description']?.errors?.['required'] && dataGroup.controls['description']?.touched) {\n <div class=\"error text-red-500 text-xs mt-1\"> Description is required </div>\n }\n </div>\n\n <div class=\"form-field grid grid-cols-1 gap-2\">\n <label for=\"cardCreatorNotes\" class=\"block text-sm font-medium \"\n >Hook <span pTooltip=\"Texto gancho para atraer al usuario a interactuar con esta tarjeta\" class=\"text-blue-500 cursor-pointer\">\u2139\uFE0F</span></label\n >\n <textarea\n rows=\"2\"\n pTextarea\n [autoResize]=\"true\"\n id=\"cardHook\"\n formControlName=\"hook\"\n class=\"mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm\"></textarea>\n </div>\n <div class=\"form-field grid grid-cols-1 gap-2\">\n <label for=\"cardInstructions\" class=\"block text-sm font-medium \"\n >Instructions <span pTooltip=\"Instrucciones para el usuario, sepa que tiene que hacer.\" class=\"text-blue-500 cursor-pointer\">\u2139\uFE0F</span></label\n >\n <textarea\n rows=\"2\"\n pTextarea\n [autoResize]=\"true\"\n id=\"cardInstructions\"\n formControlName=\"instructions\"\n class=\"mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm\"></textarea>\n </div>\n\n <div class=\"form-field grid grid-cols-1 gap-2\">\n <label for=\"cardScenario\" class=\"block text-sm font-medium \"\n >Scenario <span pTooltip=\"Describe the context or setting for the conversation\" class=\"text-blue-500 cursor-pointer\">\u2139\uFE0F</span></label\n >\n <textarea\n rows=\"2\"\n pTextarea\n [autoResize]=\"true\"\n id=\"cardScenario\"\n formControlName=\"scenario\"\n class=\"mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm\"></textarea>\n </div>\n\n <div class=\"form-field grid grid-cols-1 gap-2\">\n <label for=\"cardAlternateGreetings\" class=\"block text-sm font-medium \"\n >Greetings (Saludos Iniciales)<span pTooltip=\"Saludos alternativos para comenzar una historia diferente\" class=\"text-blue-500 cursor-pointer\"\n >\u2139\uFE0F</span\n ></label\n >\n <div class=\"array-field space-y-2\">\n @for (greeting of alternateGreetingsArray.controls; track greeting; let i = $index) {\n <div class=\"array-item flex items-center space-x-2\" style=\"position: relative\">\n <textarea\n pTextarea\n rows=\"1\"\n [autoResize]=\"true\"\n [id]=\"'cardAlternateGreeting' + i\"\n [formControl]=\"asFormControl(greeting)\"\n (input)=\"updateArrayField('greetings', i, $event)\"\n class=\"mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm flex-grow\">\n </textarea>\n <button\n pButton\n severity=\"danger\"\n icon=\"pi pi-times\"\n class=\"remove-button p-button-sm p-button-rounded p-button-danger\"\n (click)=\"removeArrayItem('greetings', i)\"></button>\n </div>\n }\n <button pButton severity=\"info\" label=\"Add Greeting\" icon=\"pi pi-plus\" (click)=\"addArrayItem('greetings')\" class=\"p-button-sm\"></button>\n </div>\n </div>\n\n <p-divider> Persona </p-divider>\n\n <dc-persona-form [personaForm]=\"personaGroup\" />\n\n <p-divider> Avanzado </p-divider>\n\n <div class=\"form-field grid grid-cols-1 gap-2\">\n <label for=\"cardPostHistoryInstructions\" class=\"block text-sm font-medium \"\n >(\u2757\uFE0FObsoleto) Post-History Instructions\n <span\n pTooltip=\"Dejar en blanco, al menos que se sepa como funciona, esto se llama jailbreak, es para darle instrucciones finales y m\u00E1s importantes al modelo\"\n class=\"text-blue-500 cursor-pointer\"\n >\u2139\uFE0F</span\n ></label\n >\n <textarea\n rows=\"1\"\n pTextarea\n [autoResize]=\"true\"\n formControlName=\"post_history_instructions\"\n class=\"mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm\"></textarea>\n </div>\n\n <div class=\"form-field grid grid-cols-1 gap-2\">\n <label for=\"cardSystemPrompt\" class=\"block text-sm font-medium \">\n (\u26A0\uFE0F Cuidado) System Prompt <span pTooltip=\"Instrucciones del sistema para la conversaci\u00F3n\" class=\"text-blue-500 cursor-pointer\">\u2139\uFE0F</span>\n </label>\n <textarea\n rows=\"1\"\n pTextarea\n [autoResize]=\"true\"\n id=\"cardSystemPrompt\"\n formControlName=\"system_prompt\"\n class=\"mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm\"></textarea>\n @if (dataGroup.controls['system_prompt']?.errors?.['required'] && dataGroup.controls['system_prompt']?.touched) {\n <div class=\"error text-red-500 text-xs mt-1\"> System prompt is required </div>\n }\n </div>\n\n <div class=\"form-field grid grid-cols-1 gap-2\">\n <label for=\"cardCreatorNotes\" class=\"block text-sm font-medium \"\n >Creator Notes <span pTooltip=\"son solo notas del creador, no afecta nada a la conversaci\u00F3n\" class=\"text-blue-500 cursor-pointer\">\u2139\uFE0F</span></label\n >\n <textarea\n rows=\"1\"\n pTextarea\n [autoResize]=\"true\"\n id=\"cardCreatorNotes\"\n formControlName=\"creator_notes\"\n class=\"mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm\"></textarea>\n </div>\n\n <div class=\"form-field grid grid-cols-1 gap-2\">\n <label pTooltip=\"Agrega las categorias\" for=\"cardTags\" class=\"block text-sm font-medium \">Tags \u2139\uFE0F</label>\n <dc-tags-form [form]=\"dataGroup\" />\n </div>\n\n <p-divider align=\"center\" type=\"dotted\">\n <b>Traducciones a otros idiomas</b>\n </p-divider>\n\n @if(langTranslationGroup){\n <dc-character-card-translations-tabs-form [formGroup]=\"langTranslationGroup\" />\n }\n </div>\n</div>\n", styles: [".textmin{min-height:40px}.array-field{display:flex;flex-direction:column;gap:8px}.array-item{display:flex;align-items:center;gap:8px;position:relative}.array-item textarea,.array-item input[type=text]{flex-grow:1}.remove-button{position:absolute;right:5px;top:5px;min-width:auto!important;width:2rem;height:2rem}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { 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],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["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"] }, { kind: "directive", type: i1$1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i2.ButtonDirective, selector: "[pButton]", inputs: ["ptButtonDirective", "pButtonPT", "pButtonUnstyled", "hostName", "text", "plain", "raised", "size", "outlined", "rounded", "iconPos", "loadingIcon", "fluid", "label", "icon", "loading", "buttonProps", "severity"] }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i3$5.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: TextareaModule }, { kind: "directive", type: i3$1.Textarea, selector: "[pTextarea], [pInputTextarea]", inputs: ["pTextareaPT", "pTextareaUnstyled", "autoResize", "pSize", "variant", "fluid", "invalid"], outputs: ["onResize"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i3.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "ngmodule", type: ToggleButtonModule }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i5.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: DividerModule }, { kind: "component", type: i2$4.Divider, selector: "p-divider", inputs: ["styleClass", "layout", "type", "align"] }, { kind: "component", type: DcCharacterCardTranslationsTabsFormComponent, selector: "dc-character-card-translations-tabs-form", inputs: ["formGroup"] }, { kind: "component", type: DcPersonaFormComponent, selector: "dc-persona-form", inputs: ["personaForm"] }, { kind: "component", type: DcTagsFormComponent, selector: "dc-tags-form", inputs: ["form"] }] }); }
7542
8024
  }
7543
8025
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DcCharacterCardFormComponent, decorators: [{
7544
8026
  type: Component,
@@ -7597,11 +8079,11 @@ class DcVoiceTtsFormComponent {
7597
8079
  });
7598
8080
  }
7599
8081
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DcVoiceTtsFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
7600
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: DcVoiceTtsFormComponent, isStandalone: true, selector: "dc-voice-tts-form", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: true, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, voiceTTSOptions: { classPropertyName: "voiceTTSOptions", publicName: "voiceTTSOptions", isSignal: true, isRequired: false, transformFunction: null }, fullForm: { classPropertyName: "fullForm", publicName: "fullForm", isSignal: true, isRequired: false, transformFunction: null } }, providers: [DialogService], ngImport: i0, template: "<h3> {{ title() }}</h3>\n<div [formGroup]=\"form()\" class=\"form-grid\">\n <div class=\"form-field\">\n <label for=\"voice\">Voice <span pTooltip=\"Select the voice for text-to-speech\">\u2139\uFE0F</span></label>\n <p-inputgroup>\n <p-inputgroup-addon>\n <p-button [rounded]=\"true\" [text]=\"true\" icon=\"pi pi-exclamation-circle\" (click)=\"openVoiceSelector()\" />\n </p-inputgroup-addon>\n <p-select\n id=\"voice\"\n [editable]=\"true\"\n [options]=\"voiceTTSOptions()\"\n formControlName=\"voice\"\n optionLabel=\"name\"\n optionValue=\"id\"\n [placeholder]=\"'Select Voice'\" />\n </p-inputgroup>\n </div>\n\n <div class=\"form-field\">\n <label for=\"speedRate\">Speed Rate <span pTooltip=\"Adjust the rate of speech delivery\">\u2139\uFE0F</span></label>\n <br />\n <input pInputText id=\"speedRate\" type=\"number\" formControlName=\"speedRate\" step=\"0.1\" />\n </div>\n\n @if (fullForm()) {\n <div class=\"form-field\">\n <label for=\"provider\">Provider <span pTooltip=\"TTS provider\">\u2139\uFE0F</span></label>\n <p-select id=\"provider\" [options]=\"providerOptions\" formControlName=\"provider\" optionLabel=\"label\" optionValue=\"value\" placeholder=\"Select Provider\" class=\"w-full\"></p-select>\n </div>\n\n <div class=\"form-field\">\n <label for=\"model\">Model <span pTooltip=\"Model ID if the provider requires it\">\u2139\uFE0F</span></label>\n <input pInputText id=\"model\" type=\"text\" formControlName=\"model\" />\n </div>\n\n <div class=\"form-field\">\n <label for=\"lang\">Language <span pTooltip=\"Language code override (optional, usually included in the voice ID)\">\u2139\uFE0F</span></label>\n <input pInputText id=\"lang\" type=\"text\" formControlName=\"lang\" />\n </div>\n\n <div class=\"form-field\">\n <label for=\"effect\">Effect <span pTooltip=\"Platform audio effect\">\u2139\uFE0F</span></label>\n <input pInputText id=\"effect\" type=\"text\" formControlName=\"effect\" />\n </div>\n }\n</div>\n", dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { 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.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],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"] }, { kind: "ngmodule", type: DynamicDialogModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: InputGroupModule }, { kind: "component", type: i3$6.InputGroup, selector: "p-inputgroup, p-inputGroup, p-input-group", inputs: ["styleClass"] }, { kind: "ngmodule", type: InputGroupAddonModule }, { kind: "component", type: i4$2.InputGroupAddon, selector: "p-inputgroup-addon, p-inputGroupAddon", inputs: ["style", "styleClass"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i5.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i3$5.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: CardModule }] }); }
8082
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: DcVoiceTtsFormComponent, isStandalone: true, selector: "dc-voice-tts-form", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: true, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, voiceTTSOptions: { classPropertyName: "voiceTTSOptions", publicName: "voiceTTSOptions", isSignal: true, isRequired: false, transformFunction: null }, fullForm: { classPropertyName: "fullForm", publicName: "fullForm", isSignal: true, isRequired: false, transformFunction: null } }, providers: [DialogService], ngImport: i0, template: "<h3> {{ title() }}</h3>\n<div [formGroup]=\"form()\" class=\"form-grid\">\n @if (fullForm()) {\n <div class=\"form-field\">\n <label for=\"provider\">Provider <span pTooltip=\"TTS provider\">\u2139\uFE0F</span></label>\n <p-select id=\"provider\" [options]=\"providerOptions\" formControlName=\"provider\" optionLabel=\"label\" optionValue=\"value\" placeholder=\"Select Provider\" class=\"w-full\"></p-select>\n </div>\n }\n\n <div class=\"form-field\">\n <label for=\"voice\">Voice <span pTooltip=\"Select the voice for text-to-speech\">\u2139\uFE0F</span></label>\n <p-inputgroup>\n <p-inputgroup-addon>\n <p-button [rounded]=\"true\" [text]=\"true\" icon=\"pi pi-exclamation-circle\" (click)=\"openVoiceSelector()\" />\n </p-inputgroup-addon>\n <p-select\n id=\"voice\"\n [editable]=\"true\"\n [options]=\"voiceTTSOptions()\"\n formControlName=\"voice\"\n optionLabel=\"name\"\n optionValue=\"id\"\n [placeholder]=\"'Select Voice'\" />\n </p-inputgroup>\n </div>\n\n <div class=\"form-field\">\n <label for=\"speedRate\">Speed Rate <span pTooltip=\"Adjust the rate of speech delivery\">\u2139\uFE0F</span></label>\n <br />\n <input pInputText id=\"speedRate\" type=\"number\" formControlName=\"speedRate\" step=\"0.1\" />\n </div>\n\n @if (fullForm()) {\n <div class=\"form-field\">\n <label for=\"model\">Model <span pTooltip=\"Model ID if the provider requires it\">\u2139\uFE0F</span></label>\n <input pInputText id=\"model\" type=\"text\" formControlName=\"model\" />\n </div>\n\n <div class=\"form-field\">\n <label for=\"lang\">Language <span pTooltip=\"Language code override (optional, usually included in the voice ID)\">\u2139\uFE0F</span></label>\n <input pInputText id=\"lang\" type=\"text\" formControlName=\"lang\" />\n </div>\n\n <div class=\"form-field\">\n <label for=\"effect\">Effect <span pTooltip=\"Platform audio effect\">\u2139\uFE0F</span></label>\n <input pInputText id=\"effect\" type=\"text\" formControlName=\"effect\" />\n </div>\n }\n</div>\n", dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { 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.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],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"] }, { kind: "ngmodule", type: DynamicDialogModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: InputGroupModule }, { kind: "component", type: i3$6.InputGroup, selector: "p-inputgroup, p-inputGroup, p-input-group", inputs: ["styleClass"] }, { kind: "ngmodule", type: InputGroupAddonModule }, { kind: "component", type: i4$3.InputGroupAddon, selector: "p-inputgroup-addon, p-inputGroupAddon", inputs: ["style", "styleClass"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i5.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i3$5.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: CardModule }] }); }
7601
8083
  }
7602
8084
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DcVoiceTtsFormComponent, decorators: [{
7603
8085
  type: Component,
7604
- args: [{ selector: 'dc-voice-tts-form', standalone: true, imports: [ReactiveFormsModule, DynamicDialogModule, ButtonModule, InputGroupModule, InputGroupAddonModule, SelectModule, InputTextModule, CardModule], providers: [DialogService], template: "<h3> {{ title() }}</h3>\n<div [formGroup]=\"form()\" class=\"form-grid\">\n <div class=\"form-field\">\n <label for=\"voice\">Voice <span pTooltip=\"Select the voice for text-to-speech\">\u2139\uFE0F</span></label>\n <p-inputgroup>\n <p-inputgroup-addon>\n <p-button [rounded]=\"true\" [text]=\"true\" icon=\"pi pi-exclamation-circle\" (click)=\"openVoiceSelector()\" />\n </p-inputgroup-addon>\n <p-select\n id=\"voice\"\n [editable]=\"true\"\n [options]=\"voiceTTSOptions()\"\n formControlName=\"voice\"\n optionLabel=\"name\"\n optionValue=\"id\"\n [placeholder]=\"'Select Voice'\" />\n </p-inputgroup>\n </div>\n\n <div class=\"form-field\">\n <label for=\"speedRate\">Speed Rate <span pTooltip=\"Adjust the rate of speech delivery\">\u2139\uFE0F</span></label>\n <br />\n <input pInputText id=\"speedRate\" type=\"number\" formControlName=\"speedRate\" step=\"0.1\" />\n </div>\n\n @if (fullForm()) {\n <div class=\"form-field\">\n <label for=\"provider\">Provider <span pTooltip=\"TTS provider\">\u2139\uFE0F</span></label>\n <p-select id=\"provider\" [options]=\"providerOptions\" formControlName=\"provider\" optionLabel=\"label\" optionValue=\"value\" placeholder=\"Select Provider\" class=\"w-full\"></p-select>\n </div>\n\n <div class=\"form-field\">\n <label for=\"model\">Model <span pTooltip=\"Model ID if the provider requires it\">\u2139\uFE0F</span></label>\n <input pInputText id=\"model\" type=\"text\" formControlName=\"model\" />\n </div>\n\n <div class=\"form-field\">\n <label for=\"lang\">Language <span pTooltip=\"Language code override (optional, usually included in the voice ID)\">\u2139\uFE0F</span></label>\n <input pInputText id=\"lang\" type=\"text\" formControlName=\"lang\" />\n </div>\n\n <div class=\"form-field\">\n <label for=\"effect\">Effect <span pTooltip=\"Platform audio effect\">\u2139\uFE0F</span></label>\n <input pInputText id=\"effect\" type=\"text\" formControlName=\"effect\" />\n </div>\n }\n</div>\n" }]
8086
+ args: [{ selector: 'dc-voice-tts-form', standalone: true, imports: [ReactiveFormsModule, DynamicDialogModule, ButtonModule, InputGroupModule, InputGroupAddonModule, SelectModule, InputTextModule, CardModule], providers: [DialogService], template: "<h3> {{ title() }}</h3>\n<div [formGroup]=\"form()\" class=\"form-grid\">\n @if (fullForm()) {\n <div class=\"form-field\">\n <label for=\"provider\">Provider <span pTooltip=\"TTS provider\">\u2139\uFE0F</span></label>\n <p-select id=\"provider\" [options]=\"providerOptions\" formControlName=\"provider\" optionLabel=\"label\" optionValue=\"value\" placeholder=\"Select Provider\" class=\"w-full\"></p-select>\n </div>\n }\n\n <div class=\"form-field\">\n <label for=\"voice\">Voice <span pTooltip=\"Select the voice for text-to-speech\">\u2139\uFE0F</span></label>\n <p-inputgroup>\n <p-inputgroup-addon>\n <p-button [rounded]=\"true\" [text]=\"true\" icon=\"pi pi-exclamation-circle\" (click)=\"openVoiceSelector()\" />\n </p-inputgroup-addon>\n <p-select\n id=\"voice\"\n [editable]=\"true\"\n [options]=\"voiceTTSOptions()\"\n formControlName=\"voice\"\n optionLabel=\"name\"\n optionValue=\"id\"\n [placeholder]=\"'Select Voice'\" />\n </p-inputgroup>\n </div>\n\n <div class=\"form-field\">\n <label for=\"speedRate\">Speed Rate <span pTooltip=\"Adjust the rate of speech delivery\">\u2139\uFE0F</span></label>\n <br />\n <input pInputText id=\"speedRate\" type=\"number\" formControlName=\"speedRate\" step=\"0.1\" />\n </div>\n\n @if (fullForm()) {\n <div class=\"form-field\">\n <label for=\"model\">Model <span pTooltip=\"Model ID if the provider requires it\">\u2139\uFE0F</span></label>\n <input pInputText id=\"model\" type=\"text\" formControlName=\"model\" />\n </div>\n\n <div class=\"form-field\">\n <label for=\"lang\">Language <span pTooltip=\"Language code override (optional, usually included in the voice ID)\">\u2139\uFE0F</span></label>\n <input pInputText id=\"lang\" type=\"text\" formControlName=\"lang\" />\n </div>\n\n <div class=\"form-field\">\n <label for=\"effect\">Effect <span pTooltip=\"Platform audio effect\">\u2139\uFE0F</span></label>\n <input pInputText id=\"effect\" type=\"text\" formControlName=\"effect\" />\n </div>\n }\n</div>\n" }]
7605
8087
  }], propDecorators: { form: [{ type: i0.Input, args: [{ isSignal: true, alias: "form", required: true }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], voiceTTSOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "voiceTTSOptions", required: false }] }], fullForm: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullForm", required: false }] }] } });
7606
8088
 
7607
8089
  class PromptConversationTypesDialogComponent {
@@ -7701,7 +8183,7 @@ class DcConversationSettingsFormComponent {
7701
8183
  this.getRules();
7702
8184
  }
7703
8185
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DcConversationSettingsFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
7704
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: DcConversationSettingsFormComponent, isStandalone: true, selector: "dc-conversation-settings-form", inputs: { form: "form", textEngineOptions: "textEngineOptions", conversationOptions: "conversationOptions", voiceTTSOptions: "voiceTTSOptions" }, providers: [DialogService], ngImport: i0, template: "<div [formGroup]=\"form\">\n <h3 class=\"text-xl font-bold border-b pb-2\">\n Chat Conversation Settings\n <span pTooltip=\"Additional information about the conversation use in the chat\" class=\"text-blue-500 cursor-help text-sm\">\u2139\uFE0F</span>\n </h3>\n\n <div>\n <label for=\"rules\" class=\"block text-sm font-medium\">\n Conversation Rules\n <span pTooltip=\"Add rules to the conversation\" class=\"text-blue-500 cursor-help\">\u2139\uFE0F</span>\n </label>\n <p-select id=\"rules\" [options]=\"rules\" (onChange)=\"addRule($event.value)\" placeholder=\"Select a Rule\" optionLabel=\"name\" class=\"w-full\"></p-select>\n\n <div formArrayName=\"rules\" class=\"mt-4 space-y-2\">\n @for (rule of rulesFormArray.controls; track rule; let i = $index) {\n <div [formGroupName]=\"i\" class=\"flex items-center justify-between p-2 border rounded-md\">\n <span>{{ rule.value.name }}</span>\n <button pButton type=\"button\" icon=\"pi pi-trash\" class=\"p-button-danger p-button-text\" (click)=\"removeRule(i)\"></button>\n </div>\n }\n </div>\n </div>\n\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n <div>\n <label for=\"conversationType\" class=\"block text-sm font-medium\">\n Conversation Type\n <span class=\"cursor-pointer text-blue-500\" (click)=\"openConversationTypeDialog()\" pTooltip=\"Choose the type of conversation interaction\">\u2139\uFE0F</span>\n </label>\n <p-select\n id=\"conversationType\"\n [options]=\"conversationOptions\"\n formControlName=\"conversationType\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"'Select Conversation Type'\"\n class=\"w-full mt-1\"></p-select>\n </div>\n\n <div>\n <label for=\"textEngine\" class=\"block text-sm font-medium\">\n Text Engine\n <span\n class=\"cursor-pointer text-blue-500\"\n (click)=\"textEngineDialog.toggle($event)\"\n pTooltip=\"Sistema de generaci\u00F3n de texto y audios. Client: el cliente llama al servidor en cada dialogo de voz/personaje, es optimo para historias, Server SSML: se sintetiza todo el audio en uno solo con los distintos cambios de voz/personaje, util para la reflexi\u00F3n porque es bilingue, utiliza dialogos en ingles y espa\u00F1ol en el mismo dialogo/audio\"\n >\u2139\uFE0F</span\n >\n </label>\n <p-select\n id=\"textEngine\"\n [options]=\"textEngineOptions\"\n formControlName=\"textEngine\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"'Select Text Engine'\"\n class=\"w-full mt-1\"></p-select>\n </div>\n\n <div class=\"flex items-center justify-between md:col-span-2\">\n <label class=\"text-sm font-medium\">\n Auto Start\n <span pTooltip=\"Start conversation automatically\" class=\"text-blue-500 cursor-help\">\u2139\uFE0F</span>\n </label>\n <p-toggleSwitch formControlName=\"autoStart\"></p-toggleSwitch>\n </div>\n\n <div class=\"md:col-span-2\">\n <label for=\"displayMode\" class=\"block text-sm font-medium\">\n Display Mode\n <span pTooltip=\"chat: standard card layout | immersive: full-screen experience | transparent: character floats over background (requires transparent WebM video)\" class=\"text-blue-500 cursor-help\">\u2139\uFE0F</span>\n </label>\n <p-select\n id=\"displayMode\"\n [options]=\"displayModeOptions\"\n formControlName=\"displayMode\"\n optionLabel=\"label\"\n optionValue=\"value\"\n placeholder=\"Select Display Mode\"\n class=\"w-full mt-1\"></p-select>\n </div>\n\n <div class=\"flex items-center justify-between md:col-span-2\">\n <label class=\"text-sm font-medium\">\n User Must Start\n <span pTooltip=\"If true the user must start the conversation, ignoring first message if any.\" class=\"text-blue-500 cursor-help\">\u2139\uFE0F</span>\n </label>\n <p-toggleSwitch formControlName=\"userMustStart\"></p-toggleSwitch>\n </div>\n </div>\n\n <hr />\n\n <dc-voice-tts-form [form]=\"mainVoiceFormGroup\" [title]=\"'Main Voice TTS Settings'\" [voiceTTSOptions]=\"voiceTTSOptions\"></dc-voice-tts-form>\n\n <dc-voice-tts-form [form]=\"secondaryVoiceFormGroup\" [title]=\"'Secondary Voice TTS Settings'\" [voiceTTSOptions]=\"voiceTTSOptions\"></dc-voice-tts-form>\n\n <hr />\n\n <dc-model-selector [modelForm]=\"modelFormGroup\" [shortForm]=\"true\"></dc-model-selector>\n <hr />\n</div>\n\n<p-popover #textEngineDialog [style]=\"{ width: '350px' }\" header=\"Text Engine Information\">\n <ng-template pTemplate=\"content\">\n <div class=\"p-4\">\n <h3 class=\"text-md font-semibold mb-3 text-gray-800\">Text Engine Types</h3>\n <ul class=\"space-y-3 text-sm text-gray-600\">\n <li>\n <strong class=\"font-semibold text-gray-900\">Texto Simple:</strong>\n La conversaci\u00F3n es como chatgpt, preguntas y responde, es la m\u00E1s b\u00E1sica.\n </li>\n <li>\n <strong class=\"font-semibold text-gray-900\">Multi Mensajes:</strong>\n Utiliza markdown (recomendable entenderlo), para dar formato al texto. El sistema puede partir dialogos con distinto formato (normal, cursiva,\n negritas) para generar distintas voces y estilos para el narrador y personaje.\n </li>\n <li>\n <strong class=\"font-semibold text-gray-900\">MD SSML:</strong>\n Markdown con SSML. Similar a Multi Mensajes, pero se presenta en un solo mensaje y la voz se genera para toda la linea. \u00DAtil para conversaciones\n biling\u00FCes.\n </li>\n </ul>\n </div>\n </ng-template>\n</p-popover>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],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"] }, { kind: "directive", type: i1$1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1$1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i2.ButtonDirective, selector: "[pButton]", inputs: ["ptButtonDirective", "pButtonPT", "pButtonUnstyled", "hostName", "text", "plain", "raised", "size", "outlined", "rounded", "iconPos", "loadingIcon", "fluid", "label", "icon", "loading", "buttonProps", "severity"] }, { kind: "directive", type: i2$4.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i5.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: ToggleSwitchModule }, { kind: "component", type: i4$1.ToggleSwitch, selector: "p-toggleswitch, p-toggleSwitch, p-toggle-switch", inputs: ["styleClass", "tabindex", "inputId", "readonly", "trueValue", "falseValue", "ariaLabel", "size", "ariaLabelledBy", "autofocus"], outputs: ["onChange"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i3.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: i2$3.Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions", "motionOptions"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: DynamicDialogModule }, { kind: "component", type: ModelSelectorComponent, selector: "dc-model-selector", inputs: ["modelForm", "shortForm"] }, { kind: "component", type: DcVoiceTtsFormComponent, selector: "dc-voice-tts-form", inputs: ["form", "title", "voiceTTSOptions", "fullForm"] }] }); }
8186
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: DcConversationSettingsFormComponent, isStandalone: true, selector: "dc-conversation-settings-form", inputs: { form: "form", textEngineOptions: "textEngineOptions", conversationOptions: "conversationOptions", voiceTTSOptions: "voiceTTSOptions" }, providers: [DialogService], ngImport: i0, template: "<div [formGroup]=\"form\">\n <h3 class=\"text-xl font-bold border-b pb-2\">\n Chat Conversation Settings\n <span pTooltip=\"Additional information about the conversation use in the chat\" class=\"text-blue-500 cursor-help text-sm\">\u2139\uFE0F</span>\n </h3>\n\n <div>\n <label for=\"rules\" class=\"block text-sm font-medium\">\n Conversation Rules\n <span pTooltip=\"Add rules to the conversation\" class=\"text-blue-500 cursor-help\">\u2139\uFE0F</span>\n </label>\n <p-select id=\"rules\" [options]=\"rules\" (onChange)=\"addRule($event.value)\" placeholder=\"Select a Rule\" optionLabel=\"name\" class=\"w-full\"></p-select>\n\n <div formArrayName=\"rules\" class=\"mt-4 space-y-2\">\n @for (rule of rulesFormArray.controls; track rule; let i = $index) {\n <div [formGroupName]=\"i\" class=\"flex items-center justify-between p-2 border rounded-md\">\n <span>{{ rule.value.name }}</span>\n <button pButton type=\"button\" icon=\"pi pi-trash\" class=\"p-button-danger p-button-text\" (click)=\"removeRule(i)\"></button>\n </div>\n }\n </div>\n </div>\n\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n <div>\n <label for=\"conversationType\" class=\"block text-sm font-medium\">\n Conversation Type\n <span class=\"cursor-pointer text-blue-500\" (click)=\"openConversationTypeDialog()\" pTooltip=\"Choose the type of conversation interaction\">\u2139\uFE0F</span>\n </label>\n <p-select\n id=\"conversationType\"\n [options]=\"conversationOptions\"\n formControlName=\"conversationType\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"'Select Conversation Type'\"\n class=\"w-full mt-1\"></p-select>\n </div>\n\n <div>\n <label for=\"textEngine\" class=\"block text-sm font-medium\">\n Text Engine\n <span\n class=\"cursor-pointer text-blue-500\"\n (click)=\"textEngineDialog.toggle($event)\"\n pTooltip=\"Sistema de generaci\u00F3n de texto y audios. Client: el cliente llama al servidor en cada dialogo de voz/personaje, es optimo para historias, Server SSML: se sintetiza todo el audio en uno solo con los distintos cambios de voz/personaje, util para la reflexi\u00F3n porque es bilingue, utiliza dialogos en ingles y espa\u00F1ol en el mismo dialogo/audio\"\n >\u2139\uFE0F</span\n >\n </label>\n <p-select\n id=\"textEngine\"\n [options]=\"textEngineOptions\"\n formControlName=\"textEngine\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"'Select Text Engine'\"\n class=\"w-full mt-1\"></p-select>\n </div>\n\n <div class=\"flex items-center justify-between md:col-span-2\">\n <label class=\"text-sm font-medium\">\n Auto Start\n <span pTooltip=\"Start conversation automatically\" class=\"text-blue-500 cursor-help\">\u2139\uFE0F</span>\n </label>\n <p-toggleSwitch formControlName=\"autoStart\"></p-toggleSwitch>\n </div>\n\n <div class=\"md:col-span-2\">\n <label for=\"displayMode\" class=\"block text-sm font-medium\">\n Display Mode\n <span pTooltip=\"chat: standard card layout | immersive: full-screen experience | transparent: character floats over background (requires transparent WebM video)\" class=\"text-blue-500 cursor-help\">\u2139\uFE0F</span>\n </label>\n <p-select\n id=\"displayMode\"\n [options]=\"displayModeOptions\"\n formControlName=\"displayMode\"\n optionLabel=\"label\"\n optionValue=\"value\"\n placeholder=\"Select Display Mode\"\n class=\"w-full mt-1\"></p-select>\n </div>\n\n <div class=\"flex items-center justify-between md:col-span-2\">\n <label class=\"text-sm font-medium\">\n User Must Start\n <span pTooltip=\"If true the user must start the conversation, ignoring first message if any.\" class=\"text-blue-500 cursor-help\">\u2139\uFE0F</span>\n </label>\n <p-toggleSwitch formControlName=\"userMustStart\"></p-toggleSwitch>\n </div>\n\n <div class=\"flex items-center justify-between md:col-span-2\">\n <label class=\"text-sm font-medium\">\n Stream Responses\n <span pTooltip=\"Enable real-time token streaming for LLM responses.\" class=\"text-blue-500 cursor-help\">\u2139\uFE0F</span>\n </label>\n <p-toggleSwitch formControlName=\"streamResponses\"></p-toggleSwitch>\n </div>\n </div>\n\n <hr />\n\n <dc-voice-tts-form [form]=\"mainVoiceFormGroup\" [title]=\"'Main Voice TTS Settings'\" [voiceTTSOptions]=\"voiceTTSOptions\"></dc-voice-tts-form>\n\n <dc-voice-tts-form [form]=\"secondaryVoiceFormGroup\" [title]=\"'Secondary Voice TTS Settings'\" [voiceTTSOptions]=\"voiceTTSOptions\"></dc-voice-tts-form>\n\n <hr />\n\n <dc-model-selector [modelForm]=\"modelFormGroup\" [shortForm]=\"true\"></dc-model-selector>\n <hr />\n</div>\n\n<p-popover #textEngineDialog [style]=\"{ width: '350px' }\" header=\"Text Engine Information\">\n <ng-template pTemplate=\"content\">\n <div class=\"p-4\">\n <h3 class=\"text-md font-semibold mb-3 text-gray-800\">Text Engine Types</h3>\n <ul class=\"space-y-3 text-sm text-gray-600\">\n <li>\n <strong class=\"font-semibold text-gray-900\">Texto Simple:</strong>\n La conversaci\u00F3n es como chatgpt, preguntas y responde, es la m\u00E1s b\u00E1sica.\n </li>\n <li>\n <strong class=\"font-semibold text-gray-900\">Multi Mensajes:</strong>\n Utiliza markdown (recomendable entenderlo), para dar formato al texto. El sistema puede partir dialogos con distinto formato (normal, cursiva,\n negritas) para generar distintas voces y estilos para el narrador y personaje.\n </li>\n <li>\n <strong class=\"font-semibold text-gray-900\">MD SSML:</strong>\n Markdown con SSML. Similar a Multi Mensajes, pero se presenta en un solo mensaje y la voz se genera para toda la linea. \u00DAtil para conversaciones\n biling\u00FCes.\n </li>\n </ul>\n </div>\n </ng-template>\n</p-popover>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],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"] }, { kind: "directive", type: i1$1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1$1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i2.ButtonDirective, selector: "[pButton]", inputs: ["ptButtonDirective", "pButtonPT", "pButtonUnstyled", "hostName", "text", "plain", "raised", "size", "outlined", "rounded", "iconPos", "loadingIcon", "fluid", "label", "icon", "loading", "buttonProps", "severity"] }, { kind: "directive", type: i2$5.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i5.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: ToggleSwitchModule }, { kind: "component", type: i4$2.ToggleSwitch, selector: "p-toggleswitch, p-toggleSwitch, p-toggle-switch", inputs: ["styleClass", "tabindex", "inputId", "readonly", "trueValue", "falseValue", "ariaLabel", "size", "ariaLabelledBy", "autofocus"], outputs: ["onChange"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i3.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: i2$3.Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions", "motionOptions"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: DynamicDialogModule }, { kind: "component", type: ModelSelectorComponent, selector: "dc-model-selector", inputs: ["modelForm", "shortForm"] }, { kind: "component", type: DcVoiceTtsFormComponent, selector: "dc-voice-tts-form", inputs: ["form", "title", "voiceTTSOptions", "fullForm"] }] }); }
7705
8187
  }
7706
8188
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DcConversationSettingsFormComponent, decorators: [{
7707
8189
  type: Component,
@@ -7716,7 +8198,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
7716
8198
  DynamicDialogModule,
7717
8199
  ModelSelectorComponent,
7718
8200
  DcVoiceTtsFormComponent,
7719
- ], providers: [DialogService], template: "<div [formGroup]=\"form\">\n <h3 class=\"text-xl font-bold border-b pb-2\">\n Chat Conversation Settings\n <span pTooltip=\"Additional information about the conversation use in the chat\" class=\"text-blue-500 cursor-help text-sm\">\u2139\uFE0F</span>\n </h3>\n\n <div>\n <label for=\"rules\" class=\"block text-sm font-medium\">\n Conversation Rules\n <span pTooltip=\"Add rules to the conversation\" class=\"text-blue-500 cursor-help\">\u2139\uFE0F</span>\n </label>\n <p-select id=\"rules\" [options]=\"rules\" (onChange)=\"addRule($event.value)\" placeholder=\"Select a Rule\" optionLabel=\"name\" class=\"w-full\"></p-select>\n\n <div formArrayName=\"rules\" class=\"mt-4 space-y-2\">\n @for (rule of rulesFormArray.controls; track rule; let i = $index) {\n <div [formGroupName]=\"i\" class=\"flex items-center justify-between p-2 border rounded-md\">\n <span>{{ rule.value.name }}</span>\n <button pButton type=\"button\" icon=\"pi pi-trash\" class=\"p-button-danger p-button-text\" (click)=\"removeRule(i)\"></button>\n </div>\n }\n </div>\n </div>\n\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n <div>\n <label for=\"conversationType\" class=\"block text-sm font-medium\">\n Conversation Type\n <span class=\"cursor-pointer text-blue-500\" (click)=\"openConversationTypeDialog()\" pTooltip=\"Choose the type of conversation interaction\">\u2139\uFE0F</span>\n </label>\n <p-select\n id=\"conversationType\"\n [options]=\"conversationOptions\"\n formControlName=\"conversationType\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"'Select Conversation Type'\"\n class=\"w-full mt-1\"></p-select>\n </div>\n\n <div>\n <label for=\"textEngine\" class=\"block text-sm font-medium\">\n Text Engine\n <span\n class=\"cursor-pointer text-blue-500\"\n (click)=\"textEngineDialog.toggle($event)\"\n pTooltip=\"Sistema de generaci\u00F3n de texto y audios. Client: el cliente llama al servidor en cada dialogo de voz/personaje, es optimo para historias, Server SSML: se sintetiza todo el audio en uno solo con los distintos cambios de voz/personaje, util para la reflexi\u00F3n porque es bilingue, utiliza dialogos en ingles y espa\u00F1ol en el mismo dialogo/audio\"\n >\u2139\uFE0F</span\n >\n </label>\n <p-select\n id=\"textEngine\"\n [options]=\"textEngineOptions\"\n formControlName=\"textEngine\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"'Select Text Engine'\"\n class=\"w-full mt-1\"></p-select>\n </div>\n\n <div class=\"flex items-center justify-between md:col-span-2\">\n <label class=\"text-sm font-medium\">\n Auto Start\n <span pTooltip=\"Start conversation automatically\" class=\"text-blue-500 cursor-help\">\u2139\uFE0F</span>\n </label>\n <p-toggleSwitch formControlName=\"autoStart\"></p-toggleSwitch>\n </div>\n\n <div class=\"md:col-span-2\">\n <label for=\"displayMode\" class=\"block text-sm font-medium\">\n Display Mode\n <span pTooltip=\"chat: standard card layout | immersive: full-screen experience | transparent: character floats over background (requires transparent WebM video)\" class=\"text-blue-500 cursor-help\">\u2139\uFE0F</span>\n </label>\n <p-select\n id=\"displayMode\"\n [options]=\"displayModeOptions\"\n formControlName=\"displayMode\"\n optionLabel=\"label\"\n optionValue=\"value\"\n placeholder=\"Select Display Mode\"\n class=\"w-full mt-1\"></p-select>\n </div>\n\n <div class=\"flex items-center justify-between md:col-span-2\">\n <label class=\"text-sm font-medium\">\n User Must Start\n <span pTooltip=\"If true the user must start the conversation, ignoring first message if any.\" class=\"text-blue-500 cursor-help\">\u2139\uFE0F</span>\n </label>\n <p-toggleSwitch formControlName=\"userMustStart\"></p-toggleSwitch>\n </div>\n </div>\n\n <hr />\n\n <dc-voice-tts-form [form]=\"mainVoiceFormGroup\" [title]=\"'Main Voice TTS Settings'\" [voiceTTSOptions]=\"voiceTTSOptions\"></dc-voice-tts-form>\n\n <dc-voice-tts-form [form]=\"secondaryVoiceFormGroup\" [title]=\"'Secondary Voice TTS Settings'\" [voiceTTSOptions]=\"voiceTTSOptions\"></dc-voice-tts-form>\n\n <hr />\n\n <dc-model-selector [modelForm]=\"modelFormGroup\" [shortForm]=\"true\"></dc-model-selector>\n <hr />\n</div>\n\n<p-popover #textEngineDialog [style]=\"{ width: '350px' }\" header=\"Text Engine Information\">\n <ng-template pTemplate=\"content\">\n <div class=\"p-4\">\n <h3 class=\"text-md font-semibold mb-3 text-gray-800\">Text Engine Types</h3>\n <ul class=\"space-y-3 text-sm text-gray-600\">\n <li>\n <strong class=\"font-semibold text-gray-900\">Texto Simple:</strong>\n La conversaci\u00F3n es como chatgpt, preguntas y responde, es la m\u00E1s b\u00E1sica.\n </li>\n <li>\n <strong class=\"font-semibold text-gray-900\">Multi Mensajes:</strong>\n Utiliza markdown (recomendable entenderlo), para dar formato al texto. El sistema puede partir dialogos con distinto formato (normal, cursiva,\n negritas) para generar distintas voces y estilos para el narrador y personaje.\n </li>\n <li>\n <strong class=\"font-semibold text-gray-900\">MD SSML:</strong>\n Markdown con SSML. Similar a Multi Mensajes, pero se presenta en un solo mensaje y la voz se genera para toda la linea. \u00DAtil para conversaciones\n biling\u00FCes.\n </li>\n </ul>\n </div>\n </ng-template>\n</p-popover>\n" }]
8201
+ ], providers: [DialogService], template: "<div [formGroup]=\"form\">\n <h3 class=\"text-xl font-bold border-b pb-2\">\n Chat Conversation Settings\n <span pTooltip=\"Additional information about the conversation use in the chat\" class=\"text-blue-500 cursor-help text-sm\">\u2139\uFE0F</span>\n </h3>\n\n <div>\n <label for=\"rules\" class=\"block text-sm font-medium\">\n Conversation Rules\n <span pTooltip=\"Add rules to the conversation\" class=\"text-blue-500 cursor-help\">\u2139\uFE0F</span>\n </label>\n <p-select id=\"rules\" [options]=\"rules\" (onChange)=\"addRule($event.value)\" placeholder=\"Select a Rule\" optionLabel=\"name\" class=\"w-full\"></p-select>\n\n <div formArrayName=\"rules\" class=\"mt-4 space-y-2\">\n @for (rule of rulesFormArray.controls; track rule; let i = $index) {\n <div [formGroupName]=\"i\" class=\"flex items-center justify-between p-2 border rounded-md\">\n <span>{{ rule.value.name }}</span>\n <button pButton type=\"button\" icon=\"pi pi-trash\" class=\"p-button-danger p-button-text\" (click)=\"removeRule(i)\"></button>\n </div>\n }\n </div>\n </div>\n\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n <div>\n <label for=\"conversationType\" class=\"block text-sm font-medium\">\n Conversation Type\n <span class=\"cursor-pointer text-blue-500\" (click)=\"openConversationTypeDialog()\" pTooltip=\"Choose the type of conversation interaction\">\u2139\uFE0F</span>\n </label>\n <p-select\n id=\"conversationType\"\n [options]=\"conversationOptions\"\n formControlName=\"conversationType\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"'Select Conversation Type'\"\n class=\"w-full mt-1\"></p-select>\n </div>\n\n <div>\n <label for=\"textEngine\" class=\"block text-sm font-medium\">\n Text Engine\n <span\n class=\"cursor-pointer text-blue-500\"\n (click)=\"textEngineDialog.toggle($event)\"\n pTooltip=\"Sistema de generaci\u00F3n de texto y audios. Client: el cliente llama al servidor en cada dialogo de voz/personaje, es optimo para historias, Server SSML: se sintetiza todo el audio en uno solo con los distintos cambios de voz/personaje, util para la reflexi\u00F3n porque es bilingue, utiliza dialogos en ingles y espa\u00F1ol en el mismo dialogo/audio\"\n >\u2139\uFE0F</span\n >\n </label>\n <p-select\n id=\"textEngine\"\n [options]=\"textEngineOptions\"\n formControlName=\"textEngine\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"'Select Text Engine'\"\n class=\"w-full mt-1\"></p-select>\n </div>\n\n <div class=\"flex items-center justify-between md:col-span-2\">\n <label class=\"text-sm font-medium\">\n Auto Start\n <span pTooltip=\"Start conversation automatically\" class=\"text-blue-500 cursor-help\">\u2139\uFE0F</span>\n </label>\n <p-toggleSwitch formControlName=\"autoStart\"></p-toggleSwitch>\n </div>\n\n <div class=\"md:col-span-2\">\n <label for=\"displayMode\" class=\"block text-sm font-medium\">\n Display Mode\n <span pTooltip=\"chat: standard card layout | immersive: full-screen experience | transparent: character floats over background (requires transparent WebM video)\" class=\"text-blue-500 cursor-help\">\u2139\uFE0F</span>\n </label>\n <p-select\n id=\"displayMode\"\n [options]=\"displayModeOptions\"\n formControlName=\"displayMode\"\n optionLabel=\"label\"\n optionValue=\"value\"\n placeholder=\"Select Display Mode\"\n class=\"w-full mt-1\"></p-select>\n </div>\n\n <div class=\"flex items-center justify-between md:col-span-2\">\n <label class=\"text-sm font-medium\">\n User Must Start\n <span pTooltip=\"If true the user must start the conversation, ignoring first message if any.\" class=\"text-blue-500 cursor-help\">\u2139\uFE0F</span>\n </label>\n <p-toggleSwitch formControlName=\"userMustStart\"></p-toggleSwitch>\n </div>\n\n <div class=\"flex items-center justify-between md:col-span-2\">\n <label class=\"text-sm font-medium\">\n Stream Responses\n <span pTooltip=\"Enable real-time token streaming for LLM responses.\" class=\"text-blue-500 cursor-help\">\u2139\uFE0F</span>\n </label>\n <p-toggleSwitch formControlName=\"streamResponses\"></p-toggleSwitch>\n </div>\n </div>\n\n <hr />\n\n <dc-voice-tts-form [form]=\"mainVoiceFormGroup\" [title]=\"'Main Voice TTS Settings'\" [voiceTTSOptions]=\"voiceTTSOptions\"></dc-voice-tts-form>\n\n <dc-voice-tts-form [form]=\"secondaryVoiceFormGroup\" [title]=\"'Secondary Voice TTS Settings'\" [voiceTTSOptions]=\"voiceTTSOptions\"></dc-voice-tts-form>\n\n <hr />\n\n <dc-model-selector [modelForm]=\"modelFormGroup\" [shortForm]=\"true\"></dc-model-selector>\n <hr />\n</div>\n\n<p-popover #textEngineDialog [style]=\"{ width: '350px' }\" header=\"Text Engine Information\">\n <ng-template pTemplate=\"content\">\n <div class=\"p-4\">\n <h3 class=\"text-md font-semibold mb-3 text-gray-800\">Text Engine Types</h3>\n <ul class=\"space-y-3 text-sm text-gray-600\">\n <li>\n <strong class=\"font-semibold text-gray-900\">Texto Simple:</strong>\n La conversaci\u00F3n es como chatgpt, preguntas y responde, es la m\u00E1s b\u00E1sica.\n </li>\n <li>\n <strong class=\"font-semibold text-gray-900\">Multi Mensajes:</strong>\n Utiliza markdown (recomendable entenderlo), para dar formato al texto. El sistema puede partir dialogos con distinto formato (normal, cursiva,\n negritas) para generar distintas voces y estilos para el narrador y personaje.\n </li>\n <li>\n <strong class=\"font-semibold text-gray-900\">MD SSML:</strong>\n Markdown con SSML. Similar a Multi Mensajes, pero se presenta en un solo mensaje y la voz se genera para toda la linea. \u00DAtil para conversaciones\n biling\u00FCes.\n </li>\n </ul>\n </div>\n </ng-template>\n</p-popover>\n" }]
7720
8202
  }], propDecorators: { form: [{
7721
8203
  type: Input
7722
8204
  }], textEngineOptions: [{
@@ -7735,6 +8217,7 @@ class DCAgentCardFormComponent extends EntityBaseFormComponent {
7735
8217
  this.entityCommunicationService = inject(CONVERSATION_AI_TOKEN);
7736
8218
  this.dialogService = inject(DialogService);
7737
8219
  this.characterFormGroupService = inject(CharacterFormGroupService);
8220
+ this.ttsService = inject(TtsService);
7738
8221
  // select options
7739
8222
  this.conversationOptions = ConversationTypeOptions;
7740
8223
  this.voiceTTSOptions = Object.values(VoiceTTSOptions);
@@ -7744,6 +8227,18 @@ class DCAgentCardFormComponent extends EntityBaseFormComponent {
7744
8227
  this.onSave = output();
7745
8228
  this.form = this.characterFormGroupService.createAgentCardForm();
7746
8229
  this.isGenerating = signal(false, ...(ngDevMode ? [{ debugName: "isGenerating" }] : /* istanbul ignore next */ []));
8230
+ this.isCloningVoice = signal(false, ...(ngDevMode ? [{ debugName: "isCloningVoice" }] : /* istanbul ignore next */ []));
8231
+ this.canCloneVoice = computed(() => {
8232
+ const sampleUrl = this.form.get('voiceCloning.sample')?.value?.url;
8233
+ const voiceId = this.form.get('voiceCloning.main.voice')?.value;
8234
+ const canCloneVoiceVar = !!sampleUrl && !voiceId;
8235
+ return canCloneVoiceVar;
8236
+ }, ...(ngDevMode ? [{ debugName: "canCloneVoice" }] : /* istanbul ignore next */ []));
8237
+ this.fishModelId = computed(() => {
8238
+ const voiceId = this.form.get('voiceCloning.main.voice')?.value;
8239
+ const provider = this.form.get('voiceCloning.main.provider')?.value;
8240
+ return voiceId && provider === 'fish-audio' ? voiceId : null;
8241
+ }, ...(ngDevMode ? [{ debugName: "fishModelId" }] : /* istanbul ignore next */ []));
7747
8242
  }
7748
8243
  patchForm(agentCard) {
7749
8244
  this.characterFormGroupService.patchFormWithConversationData(this.form, agentCard);
@@ -7928,6 +8423,36 @@ class DCAgentCardFormComponent extends EntityBaseFormComponent {
7928
8423
  console.log('File uploaded', event);
7929
8424
  this.form.controls.voiceCloning.patchValue({ sample: event });
7930
8425
  }
8426
+ async cloneVoice() {
8427
+ const sample = this.form.get('voiceCloning.sample')?.value;
8428
+ if (!sample?.url) {
8429
+ this.toastService?.error({ title: 'Falta el sample', subtitle: 'Sube un audio antes de crear el modelo' });
8430
+ return;
8431
+ }
8432
+ const text = this.form.get('voiceCloning.transcription')?.value || '';
8433
+ const agentName = this.form.get('name')?.value || 'Polilan';
8434
+ const title = `${agentName} — voice`;
8435
+ this.isCloningVoice.set(true);
8436
+ try {
8437
+ const res = await this.ttsService.createFishVoiceModel({
8438
+ sampleUrl: sample.url,
8439
+ title,
8440
+ text,
8441
+ trainMode: 'fast',
8442
+ });
8443
+ const mainCtrl = this.form.get('voiceCloning.main');
8444
+ mainCtrl?.patchValue({ voice: res._id, provider: 'fish-audio' });
8445
+ mainCtrl?.markAsDirty();
8446
+ this.toastService?.success({ title: 'Modelo de voz creado', subtitle: res._id });
8447
+ }
8448
+ catch (e) {
8449
+ console.error('cloneVoice error', e);
8450
+ this.toastService?.error({ title: 'No se pudo crear el modelo de voz', subtitle: e?.message ?? 'Error desconocido' });
8451
+ }
8452
+ finally {
8453
+ this.isCloningVoice.set(false);
8454
+ }
8455
+ }
7931
8456
  async deleteCard() {
7932
8457
  const isOk = confirm('PELIGRO! Are you sure you want to delete this card?');
7933
8458
  if (!isOk) {
@@ -7938,7 +8463,7 @@ class DCAgentCardFormComponent extends EntityBaseFormComponent {
7938
8463
  this.router.navigate(['../../cards-creator'], { relativeTo: this.route });
7939
8464
  }
7940
8465
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DCAgentCardFormComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
7941
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: DCAgentCardFormComponent, isStandalone: true, selector: "dc-agent-form", outputs: { onSave: "onSave" }, providers: [DialogService], usesInheritance: true, ngImport: i0, template: "<p-card>\n <div class=\"top-buttons\">\n <button pButton severity=\"info\" (click)=\"checkPrompt()\" label=\"\uD83D\uDC41\uFE0F Ver instrucciones finales \uD83D\uDCD3\"></button>\n\n <button pButton severity=\"info\" (click)=\"goToDetails()\" label=\"\uD83D\uDCAC Conversar\"></button>\n <button pButton severity=\"primary\" (click)=\"save()\" label=\"\uD83D\uDCBE Guardar cambios\"></button>\n </div>\n\n <div class=\"top-buttons\">\n <p-button [loading]=\"isGenerating()\" severity=\"help\" (click)=\"generateCharacter()\" label=\"Generar \uD83E\uDDBE\"></p-button>\n <p-button severity=\"help\" (click)=\"goToCardsCreator()\" label=\" Creador masivo \"></p-button>\n\n <p-button severity=\"info\" (click)=\"downloadConversation()\" label=\"\uD83D\uDCC1 Exportar \u2B07\uFE0F\"></p-button>\n <p-button severity=\"info\" (click)=\"importConversation()\" label=\"\uD83C\uDCCF Importar \u2B06\uFE0F\"></p-button>\n <p-button severity=\"danger\" (click)=\"deleteCard()\" icon=\"pi pi-trash\"></p-button>\n </div>\n\n <br />\n <br />\n <form [formGroup]=\"form\" class=\"conversation-form\">\n <div class=\"form-grid\">\n <div class=\"left-column\">\n <div title=\"Main data\" >\n <div style=\"display: flex; gap: 15px\">\n <div class=\"form-field\">\n <label for=\"version\">Version: {{ form.get('version').value }} <span pTooltip=\"Version number of the conversation\">\u2139\uFE0F</span></label>\n </div>\n\n <div class=\"form-field\">\n <label for=\"id\"\n >ID: <span pTooltip=\"Unique identifier for this conversation\"> {{ form.get('id').value }} \u2139\uFE0F</span></label\n >\n </div>\n </div>\n\n\n <div class=\"form-field\">\n <label for=\"name\">Card Name <span pTooltip=\"Name of the Agent Card\">\u2139\uFE0F</span></label>\n <input pInputText id=\"name\" type=\"text\" formControlName=\"name\" />\n @if(form.get('name').errors?.['required'] && form.get('name').touched){\n <div class=\"error\"> Name is required </div>\n }\n </div>\n\n <div class=\"form-field\">\n <label for=\"description\"> Description <span pTooltip=\"Description of the conversation\">\u2139\uFE0F</span></label>\n <input pInputText id=\"description\" type=\"text\" formControlName=\"description\" />\n @if(form.get('description').errors?.['required'] && form.get('description').touched){\n <div class=\"error\"> Description is required </div>\n }\n </div>\n\n <div class=\"form-field\">\n <label for=\"lang\">Language <span pTooltip=\"Select the primary language for the conversation\">\u2139\uFE0F</span></label>\n <p-select\n id=\"lang\"\n [options]=\"languageOptions\"\n [filter]=\"true\"\n formControlName=\"lang\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"'Select Language'\"></p-select>\n </div>\n\n <div class=\"form-field\">\n <label for=\"agentType\">Agent Type <span pTooltip=\"Select the type of agent\">\u2139\uFE0F</span></label>\n <p-select id=\"agentType\" [options]=\"agentTypeOptions\" formControlName=\"agentType\" [placeholder]=\"'Select Agent Type'\"></p-select>\n </div>\n </div>\n\n <p-accordion [multiple]=\"true\" >\n <p-accordion-panel value=\"manageable\">\n <p-accordion-header>\n <span>Manageable</span>\n <span style=\"margin-left: 8px; font-size: 0.75rem; color: var(--p-text-muted-color); font-weight: normal\">Controla visibilidad y acceso</span>\n </p-accordion-header>\n <p-accordion-content>\n <dc-manageable-form [form]=\"form.controls.manageable\"></dc-manageable-form>\n </p-accordion-content>\n </p-accordion-panel>\n <p-accordion-panel value=\"learnable\">\n <p-accordion-header>\n <span>Learnable</span>\n <span style=\"margin-left: 8px; font-size: 0.75rem; color: var(--p-text-muted-color); font-weight: normal\">Aprendizaje y conocimiento</span>\n </p-accordion-header>\n <p-accordion-content>\n <dc-learnable-form [form]=\"form.controls.learnable\"></dc-learnable-form>\n </p-accordion-content>\n </p-accordion-panel>\n <p-accordion-panel value=\"conversationSettings\">\n <p-accordion-header>\n <span>Conversation Settings</span>\n <span style=\"margin-left: 8px; font-size: 0.75rem; color: var(--p-text-muted-color); font-weight: normal\">Modelo, voz y configuraci\u00F3n del chat</span>\n </p-accordion-header>\n <p-accordion-content>\n <dc-conversation-settings-form\n [form]=\"form.controls.conversationSettings\"\n [textEngineOptions]=\"textEngineOptions\"\n [conversationOptions]=\"conversationOptions\"\n [voiceTTSOptions]=\"voiceTTSOptions\">\n </dc-conversation-settings-form>\n </p-accordion-content>\n </p-accordion-panel>\n @if(form.controls.conversationFlow){\n <p-accordion-panel value=\"conversationFlow\">\n <p-accordion-header>\n <span>Conversation Flow</span>\n <span style=\"margin-left: 8px; font-size: 0.75rem; color: var(--p-text-muted-color); font-weight: normal\">Objetivos, triggers y condiciones din\u00E1micas</span>\n </p-accordion-header>\n <p-accordion-content>\n <dc-conversation-flow-form [formGroup]=\"form.controls.conversationFlow\"></dc-conversation-flow-form>\n </p-accordion-content>\n </p-accordion-panel>\n }\n <p-accordion-panel value=\"accounts\">\n <p-accordion-header>\n <span>Gesti\u00F3n de cuentas</span>\n <span style=\"margin-left: 8px; font-size: 0.75rem; color: var(--p-text-muted-color); font-weight: normal\">Beta</span>\n </p-accordion-header>\n <p-accordion-content>\n @if(form.controls.accounts) {\n <account-platform-form [formArray]=\"form.controls.accounts\"></account-platform-form>\n }\n </p-accordion-content>\n </p-accordion-panel>\n <p-accordion-panel value=\"voiceCloning\">\n <p-accordion-header>\n <span>Clonaci\u00F3n de voz</span>\n <span style=\"margin-left: 8px; font-size: 0.75rem; color: var(--p-text-muted-color); font-weight: normal\">Beta</span>\n </p-accordion-header>\n <p-accordion-content>\n <div formGroupName=\"voiceCloning\">\n <div class=\"form-field\">\n <label for=\"transcription\">Transcription</label>\n <textarea pTextarea id=\"transcription\" formControlName=\"transcription\" rows=\"3\"></textarea>\n </div>\n <div class=\"form-field\">\n <dc-simple-uploader\n buttonLabel=\"Subir audio\"\n [storagePath]=\"'conversation-cards/' + entityId()\"\n (fileUploaded)=\"onFileUploaded($event)\"></dc-simple-uploader>\n @if(form.get('voiceCloning.sample').value?.url){\n <audio controls [src]=\"form.get('voiceCloning.sample').value.url\"></audio>\n }\n </div>\n <dc-voice-tts-form\n [form]=\"$any(form.get('voiceCloning.main'))\"\n [title]=\"'Voice Cloning \u2014 Main Voice'\"\n [voiceTTSOptions]=\"voiceTTSOptions\"\n [fullForm]=\"true\">\n </dc-voice-tts-form>\n </div>\n </p-accordion-content>\n </p-accordion-panel>\n </p-accordion>\n\n </div>\n\n <div class=\"right-column\">\n @if(entity() && entityId()){\n <assets-loader\n [assets]=\"entity().assets\"\n [storagePath]=\"'conversation-cards/' + entityId()\"\n (assetsChange)=\"onAssetsChange($event)\"\n (assetUpdate)=\"onUpdateAsset($event)\"\n (onFileSelected)=\"onImageSelected($event)\"></assets-loader>\n } @if(form.controls.characterCard){\n\n <br />\n <dc-character-card-form [characterCardForm]=\"form.controls.characterCard\" (generateMissingDataRequest)=\"generateMissingData()\">\n </dc-character-card-form>\n }\n </div>\n </div>\n </form>\n\n <div class=\"float-button\">\n <p-button icon=\"pi pi-eye\" (click)=\"inspect()\" severity=\"secondary\" [rounded]=\"true\" [raised]=\"true\" pTooltip=\"Inspeccionar\"> </p-button>\n\n <p-button icon=\"pi pi-save\" (click)=\"save()\" severity=\"primary\" [rounded]=\"true\" [raised]=\"true\" pTooltip=\"Guardar (Ctrl + S)\"> </p-button>\n </div>\n</p-card>\n", styles: [".conversation-form{max-width:100%;padding:20px;border-radius:8px;box-shadow:0 2px 4px #0000001a}.conversation-form .card-group{padding:20px;border-radius:6px;margin-bottom:24px}.conversation-form .card-group h3{margin:0 0 20px;color:#2c3e50;font-size:1.25rem}.conversation-form .form-grid{display:flex;flex-wrap:wrap;gap:2rem;width:100%}.conversation-form .form-field{margin-bottom:1.5rem;display:flex;flex-direction:column;gap:.5rem}.conversation-form .form-field label{font-weight:500}.conversation-form .form-field.checkbox{flex-direction:row;align-items:center;gap:.5rem}.conversation-form .form-field.checkbox input[type=checkbox]{width:auto}.conversation-form .form-field .error{color:#dc3545;font-size:.875rem;margin-top:.25rem}.conversation-form .form-field .remove-button{position:absolute;border:none;border-radius:50%;width:20px;height:20px;display:flex;align-items:center;justify-content:center;cursor:pointer;top:-10px;right:-10px}.conversation-form .left-column,.conversation-form .right-column{display:flex;flex-direction:column;flex:1 1 calc(50% - 1rem);min-width:300px}@media(max-width:768px){.conversation-form .left-column,.conversation-form .right-column{flex:1 1 100%}}.conversation-form .card-group{padding:1rem;margin-bottom:1.5rem}.conversation-form .card-group h3{margin-top:0;margin-bottom:1rem}.top-buttons{display:flex;justify-content:space-between;margin-bottom:2rem;gap:1rem}.top-buttons button{flex:1}::ng-deep em{font-weight:900;color:#014a93}.float-button{position:fixed;bottom:4rem;right:2rem;z-index:1000;display:flex;gap:1px}.float-button :host ::ng-deep .p-button{width:4rem;height:4rem;border-radius:50%}\n"], dependencies: [{ 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],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormArrayDirective, selector: "[formArray]", inputs: ["formArray"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "component", type: AssetsLoaderComponent, selector: "assets-loader", inputs: ["assets", "storagePath"], outputs: ["assetsChange", "assetUpdate", "onFileSelected"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i2.ButtonDirective, selector: "[pButton]", inputs: ["ptButtonDirective", "pButtonPT", "pButtonUnstyled", "hostName", "text", "plain", "raised", "size", "outlined", "rounded", "iconPos", "loadingIcon", "fluid", "label", "icon", "loading", "buttonProps", "severity"] }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i3$5.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: CheckboxModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i3.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i5.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: DialogModule }, { kind: "ngmodule", type: DynamicDialogModule }, { kind: "component", type: AccountPlatformForm, selector: "account-platform-form", inputs: ["formArray"] }, { kind: "ngmodule", type: CardModule }, { kind: "component", type: i2$6.Card, selector: "p-card", inputs: ["header", "subheader", "style", "styleClass"] }, { kind: "ngmodule", type: AccordionModule }, { kind: "component", type: i7.Accordion, selector: "p-accordion", inputs: ["value", "multiple", "styleClass", "expandIcon", "collapseIcon", "selectOnFocus", "transitionOptions", "motionOptions"], outputs: ["valueChange", "onClose", "onOpen"] }, { kind: "component", type: i7.AccordionPanel, selector: "p-accordion-panel, p-accordionpanel", inputs: ["value", "disabled"], outputs: ["valueChange"] }, { kind: "component", type: i7.AccordionHeader, selector: "p-accordion-header, p-accordionheader" }, { kind: "component", type: i7.AccordionContent, selector: "p-accordion-content, p-accordioncontent" }, { kind: "component", type: DCConversationFlowFormComponent, selector: "dc-conversation-flow-form", inputs: ["formGroup"] }, { kind: "component", type: DcCharacterCardFormComponent, selector: "dc-character-card-form", inputs: ["characterCardForm"], outputs: ["generateMissingDataRequest"] }, { kind: "ngmodule", type: MessageModule }, { kind: "component", type: DcConversationSettingsFormComponent, selector: "dc-conversation-settings-form", inputs: ["form", "textEngineOptions", "conversationOptions", "voiceTTSOptions"] }, { kind: "component", type: DcVoiceTtsFormComponent, selector: "dc-voice-tts-form", inputs: ["form", "title", "voiceTTSOptions", "fullForm"] }, { kind: "component", type: DcManageableFormComponent, selector: "dc-manageable-form", inputs: ["form"] }, { kind: "component", type: DcLearnableFormComponent, selector: "dc-learnable-form", inputs: ["form"] }, { kind: "component", type: SimpleUploaderComponent, selector: "dc-simple-uploader", inputs: ["storagePath", "buttonLabel", "accept", "disabled", "metadata", "provider"], outputs: ["fileUploaded", "uploadError"] }, { kind: "ngmodule", type: TextareaModule }, { kind: "directive", type: i3$1.Textarea, selector: "[pTextarea], [pInputTextarea]", inputs: ["pTextareaPT", "pTextareaUnstyled", "autoResize", "pSize", "variant", "fluid", "invalid"], outputs: ["onResize"] }] }); }
8466
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: DCAgentCardFormComponent, isStandalone: true, selector: "dc-agent-form", outputs: { onSave: "onSave" }, providers: [DialogService], usesInheritance: true, ngImport: i0, template: "<p-card>\n <div class=\"top-buttons\">\n <button pButton severity=\"info\" (click)=\"checkPrompt()\" label=\"\uD83D\uDC41\uFE0F Ver instrucciones finales \uD83D\uDCD3\"></button>\n\n <button pButton severity=\"info\" (click)=\"goToDetails()\" label=\"\uD83D\uDCAC Conversar\"></button>\n <button pButton severity=\"primary\" (click)=\"save()\" label=\"\uD83D\uDCBE Guardar cambios\"></button>\n </div>\n\n <div class=\"top-buttons\">\n <p-button [loading]=\"isGenerating()\" severity=\"help\" (click)=\"generateCharacter()\" label=\"Generar \uD83E\uDDBE\"></p-button>\n <p-button severity=\"help\" (click)=\"goToCardsCreator()\" label=\" Creador masivo \"></p-button>\n\n <p-button severity=\"info\" (click)=\"downloadConversation()\" label=\"\uD83D\uDCC1 Exportar \u2B07\uFE0F\"></p-button>\n <p-button severity=\"info\" (click)=\"importConversation()\" label=\"\uD83C\uDCCF Importar \u2B06\uFE0F\"></p-button>\n <p-button severity=\"danger\" (click)=\"deleteCard()\" icon=\"pi pi-trash\"></p-button>\n </div>\n\n <br />\n <br />\n <form [formGroup]=\"form\" class=\"conversation-form\">\n <div class=\"form-grid\">\n <div class=\"left-column\">\n <div title=\"Main data\" >\n <div style=\"display: flex; gap: 15px\">\n <div class=\"form-field\">\n <label for=\"version\">Version: {{ form.get('version').value }} <span pTooltip=\"Version number of the conversation\">\u2139\uFE0F</span></label>\n </div>\n\n <div class=\"form-field\">\n <label for=\"id\"\n >ID: <span pTooltip=\"Unique identifier for this conversation\"> {{ form.get('id').value }} \u2139\uFE0F</span></label\n >\n </div>\n </div>\n\n\n <div class=\"form-field\">\n <label for=\"name\">Card Name <span pTooltip=\"Name of the Agent Card\">\u2139\uFE0F</span></label>\n <input pInputText id=\"name\" type=\"text\" formControlName=\"name\" />\n @if(form.get('name').errors?.['required'] && form.get('name').touched){\n <div class=\"error\"> Name is required </div>\n }\n </div>\n\n <div class=\"form-field\">\n <label for=\"description\"> Description <span pTooltip=\"Description of the conversation\">\u2139\uFE0F</span></label>\n <input pInputText id=\"description\" type=\"text\" formControlName=\"description\" />\n @if(form.get('description').errors?.['required'] && form.get('description').touched){\n <div class=\"error\"> Description is required </div>\n }\n </div>\n\n <div class=\"form-field\">\n <label for=\"lang\">Language <span pTooltip=\"Select the primary language for the conversation\">\u2139\uFE0F</span></label>\n <p-select\n id=\"lang\"\n [options]=\"languageOptions\"\n [filter]=\"true\"\n formControlName=\"lang\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"'Select Language'\"></p-select>\n </div>\n\n <div class=\"form-field\">\n <label for=\"agentType\">Agent Type <span pTooltip=\"Select the type of agent\">\u2139\uFE0F</span></label>\n <p-select id=\"agentType\" [options]=\"agentTypeOptions\" formControlName=\"agentType\" [placeholder]=\"'Select Agent Type'\"></p-select>\n </div>\n </div>\n\n <p-accordion [multiple]=\"true\" >\n <p-accordion-panel value=\"manageable\">\n <p-accordion-header>\n <span>Manageable</span>\n <span style=\"margin-left: 8px; font-size: 0.75rem; color: var(--p-text-muted-color); font-weight: normal\">Controla visibilidad y acceso</span>\n </p-accordion-header>\n <p-accordion-content>\n <dc-manageable-form [form]=\"form.controls.manageable\"></dc-manageable-form>\n </p-accordion-content>\n </p-accordion-panel>\n <p-accordion-panel value=\"learnable\">\n <p-accordion-header>\n <span>Learnable</span>\n <span style=\"margin-left: 8px; font-size: 0.75rem; color: var(--p-text-muted-color); font-weight: normal\">Aprendizaje y conocimiento</span>\n </p-accordion-header>\n <p-accordion-content>\n <dc-learnable-form [form]=\"form.controls.learnable\"></dc-learnable-form>\n </p-accordion-content>\n </p-accordion-panel>\n <p-accordion-panel value=\"conversationSettings\">\n <p-accordion-header>\n <span>Conversation Settings</span>\n <span style=\"margin-left: 8px; font-size: 0.75rem; color: var(--p-text-muted-color); font-weight: normal\">Modelo, voz y configuraci\u00F3n del chat</span>\n </p-accordion-header>\n <p-accordion-content>\n <dc-conversation-settings-form\n [form]=\"form.controls.conversationSettings\"\n [textEngineOptions]=\"textEngineOptions\"\n [conversationOptions]=\"conversationOptions\"\n [voiceTTSOptions]=\"voiceTTSOptions\">\n </dc-conversation-settings-form>\n </p-accordion-content>\n </p-accordion-panel>\n @if(form.controls.conversationFlow){\n <p-accordion-panel value=\"conversationFlow\">\n <p-accordion-header>\n <span>Conversation Flow</span>\n <span style=\"margin-left: 8px; font-size: 0.75rem; color: var(--p-text-muted-color); font-weight: normal\">Objetivos, triggers y condiciones din\u00E1micas</span>\n </p-accordion-header>\n <p-accordion-content>\n <dc-conversation-flow-form [formGroup]=\"form.controls.conversationFlow\"></dc-conversation-flow-form>\n </p-accordion-content>\n </p-accordion-panel>\n }\n <p-accordion-panel value=\"accounts\">\n <p-accordion-header>\n <span>Gesti\u00F3n de cuentas</span>\n <span style=\"margin-left: 8px; font-size: 0.75rem; color: var(--p-text-muted-color); font-weight: normal\">Beta</span>\n </p-accordion-header>\n <p-accordion-content>\n @if(form.controls.accounts) {\n <account-platform-form [formArray]=\"form.controls.accounts\"></account-platform-form>\n }\n </p-accordion-content>\n </p-accordion-panel>\n <p-accordion-panel value=\"voiceCloning\">\n <p-accordion-header>\n <span>Clonaci\u00F3n de voz</span>\n <span style=\"margin-left: 8px; font-size: 0.75rem; color: var(--p-text-muted-color); font-weight: normal\">Beta</span>\n </p-accordion-header>\n <p-accordion-content>\n <div formGroupName=\"voiceCloning\">\n <div class=\"form-field\">\n <label for=\"transcription\">Transcription</label>\n <textarea pTextarea id=\"transcription\" formControlName=\"transcription\" rows=\"3\"></textarea>\n </div>\n <div class=\"form-field\">\n <dc-simple-uploader\n buttonLabel=\"Subir audio\"\n [storagePath]=\"'conversation-cards/' + entityId()\"\n (fileUploaded)=\"onFileUploaded($event)\"></dc-simple-uploader>\n @if(form.get('voiceCloning.sample').value?.url){\n <audio controls [src]=\"form.get('voiceCloning.sample').value.url\"></audio>\n }\n </div>\n <div class=\"form-field voice-clone-status\">\n @if(!form.get('voiceCloning.sample').value?.url){\n <small class=\"muted\">Sube un audio para entrenar un modelo de voz.</small>\n }\n <!-- @if(canCloneVoice()){ -->\n <p-button\n icon=\"pi pi-bolt\"\n severity=\"help\"\n [loading]=\"isCloningVoice()\"\n label=\"Crear modelo en Fish Audio\"\n (click)=\"cloneVoice()\">\n </p-button>\n <!-- } -->\n @if(fishModelId()){\n <div class=\"model-tag\">\n <span>Modelo Fish Audio: <code>{{ fishModelId() }}</code></span>\n <p-button\n icon=\"pi pi-refresh\"\n severity=\"secondary\"\n [text]=\"true\"\n [loading]=\"isCloningVoice()\"\n label=\"Regenerar\"\n (click)=\"cloneVoice()\">\n </p-button>\n </div>\n }\n </div>\n <dc-voice-tts-form\n [form]=\"$any(form.get('voiceCloning.main'))\"\n [title]=\"'Voice Cloning \u2014 Main Voice'\"\n [voiceTTSOptions]=\"voiceTTSOptions\"\n [fullForm]=\"true\">\n </dc-voice-tts-form>\n </div>\n </p-accordion-content>\n </p-accordion-panel>\n </p-accordion>\n\n </div>\n\n <div class=\"right-column\">\n @if(entity() && entityId()){\n <assets-loader\n [assets]=\"entity().assets\"\n [storagePath]=\"'conversation-cards/' + entityId()\"\n (assetsChange)=\"onAssetsChange($event)\"\n (assetUpdate)=\"onUpdateAsset($event)\"\n (onFileSelected)=\"onImageSelected($event)\"></assets-loader>\n } @if(form.controls.characterCard){\n\n <br />\n <dc-character-card-form [characterCardForm]=\"form.controls.characterCard\" (generateMissingDataRequest)=\"generateMissingData()\">\n </dc-character-card-form>\n }\n </div>\n </div>\n </form>\n\n <div class=\"float-button\">\n <p-button icon=\"pi pi-eye\" (click)=\"inspect()\" severity=\"secondary\" [rounded]=\"true\" [raised]=\"true\" pTooltip=\"Inspeccionar\"> </p-button>\n\n <p-button icon=\"pi pi-save\" (click)=\"save()\" severity=\"primary\" [rounded]=\"true\" [raised]=\"true\" pTooltip=\"Guardar (Ctrl + S)\"> </p-button>\n </div>\n</p-card>\n", styles: [".conversation-form{max-width:100%;padding:20px;border-radius:8px;box-shadow:0 2px 4px #0000001a}.conversation-form .card-group{padding:20px;border-radius:6px;margin-bottom:24px}.conversation-form .card-group h3{margin:0 0 20px;color:#2c3e50;font-size:1.25rem}.conversation-form .form-grid{display:flex;flex-wrap:wrap;gap:2rem;width:100%}.conversation-form .form-field{margin-bottom:1.5rem;display:flex;flex-direction:column;gap:.5rem}.conversation-form .form-field label{font-weight:500}.conversation-form .form-field.checkbox{flex-direction:row;align-items:center;gap:.5rem}.conversation-form .form-field.checkbox input[type=checkbox]{width:auto}.conversation-form .form-field .error{color:#dc3545;font-size:.875rem;margin-top:.25rem}.conversation-form .form-field .remove-button{position:absolute;border:none;border-radius:50%;width:20px;height:20px;display:flex;align-items:center;justify-content:center;cursor:pointer;top:-10px;right:-10px}.conversation-form .left-column,.conversation-form .right-column{display:flex;flex-direction:column;flex:1 1 calc(50% - 1rem);min-width:300px}@media(max-width:768px){.conversation-form .left-column,.conversation-form .right-column{flex:1 1 100%}}.conversation-form .card-group{padding:1rem;margin-bottom:1.5rem}.conversation-form .card-group h3{margin-top:0;margin-bottom:1rem}.top-buttons{display:flex;justify-content:space-between;margin-bottom:2rem;gap:1rem}.top-buttons button{flex:1}::ng-deep em{font-weight:900;color:#014a93}.float-button{position:fixed;bottom:4rem;right:2rem;z-index:1000;display:flex;gap:1px}.float-button :host ::ng-deep .p-button{width:4rem;height:4rem;border-radius:50%}.voice-clone-status{display:flex;flex-direction:column;gap:.5rem;margin:.75rem 0}.voice-clone-status .muted{color:var(--p-text-muted-color)}.voice-clone-status .model-tag{display:flex;align-items:center;gap:.75rem;padding:.5rem .75rem;background:var(--p-surface-100, #f3f4f6);border-radius:6px;font-size:.9rem}.voice-clone-status .model-tag code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.8rem}\n"], dependencies: [{ 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],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormArrayDirective, selector: "[formArray]", inputs: ["formArray"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "component", type: AssetsLoaderComponent, selector: "assets-loader", inputs: ["assets", "storagePath"], outputs: ["assetsChange", "assetUpdate", "onFileSelected"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i2.ButtonDirective, selector: "[pButton]", inputs: ["ptButtonDirective", "pButtonPT", "pButtonUnstyled", "hostName", "text", "plain", "raised", "size", "outlined", "rounded", "iconPos", "loadingIcon", "fluid", "label", "icon", "loading", "buttonProps", "severity"] }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i3$5.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: CheckboxModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i3.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i5.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: DialogModule }, { kind: "ngmodule", type: DynamicDialogModule }, { kind: "component", type: AccountPlatformForm, selector: "account-platform-form", inputs: ["formArray"] }, { kind: "ngmodule", type: CardModule }, { kind: "component", type: i2$7.Card, selector: "p-card", inputs: ["header", "subheader", "style", "styleClass"] }, { kind: "ngmodule", type: AccordionModule }, { kind: "component", type: i7.Accordion, selector: "p-accordion", inputs: ["value", "multiple", "styleClass", "expandIcon", "collapseIcon", "selectOnFocus", "transitionOptions", "motionOptions"], outputs: ["valueChange", "onClose", "onOpen"] }, { kind: "component", type: i7.AccordionPanel, selector: "p-accordion-panel, p-accordionpanel", inputs: ["value", "disabled"], outputs: ["valueChange"] }, { kind: "component", type: i7.AccordionHeader, selector: "p-accordion-header, p-accordionheader" }, { kind: "component", type: i7.AccordionContent, selector: "p-accordion-content, p-accordioncontent" }, { kind: "component", type: DCConversationFlowFormComponent, selector: "dc-conversation-flow-form", inputs: ["formGroup"] }, { kind: "component", type: DcCharacterCardFormComponent, selector: "dc-character-card-form", inputs: ["characterCardForm"], outputs: ["generateMissingDataRequest"] }, { kind: "ngmodule", type: MessageModule }, { kind: "component", type: DcConversationSettingsFormComponent, selector: "dc-conversation-settings-form", inputs: ["form", "textEngineOptions", "conversationOptions", "voiceTTSOptions"] }, { kind: "component", type: DcVoiceTtsFormComponent, selector: "dc-voice-tts-form", inputs: ["form", "title", "voiceTTSOptions", "fullForm"] }, { kind: "component", type: DcManageableFormComponent, selector: "dc-manageable-form", inputs: ["form"] }, { kind: "component", type: DcLearnableFormComponent, selector: "dc-learnable-form", inputs: ["form"] }, { kind: "component", type: SimpleUploaderComponent, selector: "dc-simple-uploader", inputs: ["storagePath", "buttonLabel", "accept", "disabled", "metadata", "provider"], outputs: ["fileUploaded", "uploadError"] }, { kind: "ngmodule", type: TextareaModule }, { kind: "directive", type: i3$1.Textarea, selector: "[pTextarea], [pInputTextarea]", inputs: ["pTextareaPT", "pTextareaUnstyled", "autoResize", "pSize", "variant", "fluid", "invalid"], outputs: ["onResize"] }] }); }
7942
8467
  }
7943
8468
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DCAgentCardFormComponent, decorators: [{
7944
8469
  type: Component,
@@ -7965,7 +8490,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
7965
8490
  DcLearnableFormComponent,
7966
8491
  SimpleUploaderComponent,
7967
8492
  TextareaModule,
7968
- ], template: "<p-card>\n <div class=\"top-buttons\">\n <button pButton severity=\"info\" (click)=\"checkPrompt()\" label=\"\uD83D\uDC41\uFE0F Ver instrucciones finales \uD83D\uDCD3\"></button>\n\n <button pButton severity=\"info\" (click)=\"goToDetails()\" label=\"\uD83D\uDCAC Conversar\"></button>\n <button pButton severity=\"primary\" (click)=\"save()\" label=\"\uD83D\uDCBE Guardar cambios\"></button>\n </div>\n\n <div class=\"top-buttons\">\n <p-button [loading]=\"isGenerating()\" severity=\"help\" (click)=\"generateCharacter()\" label=\"Generar \uD83E\uDDBE\"></p-button>\n <p-button severity=\"help\" (click)=\"goToCardsCreator()\" label=\" Creador masivo \"></p-button>\n\n <p-button severity=\"info\" (click)=\"downloadConversation()\" label=\"\uD83D\uDCC1 Exportar \u2B07\uFE0F\"></p-button>\n <p-button severity=\"info\" (click)=\"importConversation()\" label=\"\uD83C\uDCCF Importar \u2B06\uFE0F\"></p-button>\n <p-button severity=\"danger\" (click)=\"deleteCard()\" icon=\"pi pi-trash\"></p-button>\n </div>\n\n <br />\n <br />\n <form [formGroup]=\"form\" class=\"conversation-form\">\n <div class=\"form-grid\">\n <div class=\"left-column\">\n <div title=\"Main data\" >\n <div style=\"display: flex; gap: 15px\">\n <div class=\"form-field\">\n <label for=\"version\">Version: {{ form.get('version').value }} <span pTooltip=\"Version number of the conversation\">\u2139\uFE0F</span></label>\n </div>\n\n <div class=\"form-field\">\n <label for=\"id\"\n >ID: <span pTooltip=\"Unique identifier for this conversation\"> {{ form.get('id').value }} \u2139\uFE0F</span></label\n >\n </div>\n </div>\n\n\n <div class=\"form-field\">\n <label for=\"name\">Card Name <span pTooltip=\"Name of the Agent Card\">\u2139\uFE0F</span></label>\n <input pInputText id=\"name\" type=\"text\" formControlName=\"name\" />\n @if(form.get('name').errors?.['required'] && form.get('name').touched){\n <div class=\"error\"> Name is required </div>\n }\n </div>\n\n <div class=\"form-field\">\n <label for=\"description\"> Description <span pTooltip=\"Description of the conversation\">\u2139\uFE0F</span></label>\n <input pInputText id=\"description\" type=\"text\" formControlName=\"description\" />\n @if(form.get('description').errors?.['required'] && form.get('description').touched){\n <div class=\"error\"> Description is required </div>\n }\n </div>\n\n <div class=\"form-field\">\n <label for=\"lang\">Language <span pTooltip=\"Select the primary language for the conversation\">\u2139\uFE0F</span></label>\n <p-select\n id=\"lang\"\n [options]=\"languageOptions\"\n [filter]=\"true\"\n formControlName=\"lang\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"'Select Language'\"></p-select>\n </div>\n\n <div class=\"form-field\">\n <label for=\"agentType\">Agent Type <span pTooltip=\"Select the type of agent\">\u2139\uFE0F</span></label>\n <p-select id=\"agentType\" [options]=\"agentTypeOptions\" formControlName=\"agentType\" [placeholder]=\"'Select Agent Type'\"></p-select>\n </div>\n </div>\n\n <p-accordion [multiple]=\"true\" >\n <p-accordion-panel value=\"manageable\">\n <p-accordion-header>\n <span>Manageable</span>\n <span style=\"margin-left: 8px; font-size: 0.75rem; color: var(--p-text-muted-color); font-weight: normal\">Controla visibilidad y acceso</span>\n </p-accordion-header>\n <p-accordion-content>\n <dc-manageable-form [form]=\"form.controls.manageable\"></dc-manageable-form>\n </p-accordion-content>\n </p-accordion-panel>\n <p-accordion-panel value=\"learnable\">\n <p-accordion-header>\n <span>Learnable</span>\n <span style=\"margin-left: 8px; font-size: 0.75rem; color: var(--p-text-muted-color); font-weight: normal\">Aprendizaje y conocimiento</span>\n </p-accordion-header>\n <p-accordion-content>\n <dc-learnable-form [form]=\"form.controls.learnable\"></dc-learnable-form>\n </p-accordion-content>\n </p-accordion-panel>\n <p-accordion-panel value=\"conversationSettings\">\n <p-accordion-header>\n <span>Conversation Settings</span>\n <span style=\"margin-left: 8px; font-size: 0.75rem; color: var(--p-text-muted-color); font-weight: normal\">Modelo, voz y configuraci\u00F3n del chat</span>\n </p-accordion-header>\n <p-accordion-content>\n <dc-conversation-settings-form\n [form]=\"form.controls.conversationSettings\"\n [textEngineOptions]=\"textEngineOptions\"\n [conversationOptions]=\"conversationOptions\"\n [voiceTTSOptions]=\"voiceTTSOptions\">\n </dc-conversation-settings-form>\n </p-accordion-content>\n </p-accordion-panel>\n @if(form.controls.conversationFlow){\n <p-accordion-panel value=\"conversationFlow\">\n <p-accordion-header>\n <span>Conversation Flow</span>\n <span style=\"margin-left: 8px; font-size: 0.75rem; color: var(--p-text-muted-color); font-weight: normal\">Objetivos, triggers y condiciones din\u00E1micas</span>\n </p-accordion-header>\n <p-accordion-content>\n <dc-conversation-flow-form [formGroup]=\"form.controls.conversationFlow\"></dc-conversation-flow-form>\n </p-accordion-content>\n </p-accordion-panel>\n }\n <p-accordion-panel value=\"accounts\">\n <p-accordion-header>\n <span>Gesti\u00F3n de cuentas</span>\n <span style=\"margin-left: 8px; font-size: 0.75rem; color: var(--p-text-muted-color); font-weight: normal\">Beta</span>\n </p-accordion-header>\n <p-accordion-content>\n @if(form.controls.accounts) {\n <account-platform-form [formArray]=\"form.controls.accounts\"></account-platform-form>\n }\n </p-accordion-content>\n </p-accordion-panel>\n <p-accordion-panel value=\"voiceCloning\">\n <p-accordion-header>\n <span>Clonaci\u00F3n de voz</span>\n <span style=\"margin-left: 8px; font-size: 0.75rem; color: var(--p-text-muted-color); font-weight: normal\">Beta</span>\n </p-accordion-header>\n <p-accordion-content>\n <div formGroupName=\"voiceCloning\">\n <div class=\"form-field\">\n <label for=\"transcription\">Transcription</label>\n <textarea pTextarea id=\"transcription\" formControlName=\"transcription\" rows=\"3\"></textarea>\n </div>\n <div class=\"form-field\">\n <dc-simple-uploader\n buttonLabel=\"Subir audio\"\n [storagePath]=\"'conversation-cards/' + entityId()\"\n (fileUploaded)=\"onFileUploaded($event)\"></dc-simple-uploader>\n @if(form.get('voiceCloning.sample').value?.url){\n <audio controls [src]=\"form.get('voiceCloning.sample').value.url\"></audio>\n }\n </div>\n <dc-voice-tts-form\n [form]=\"$any(form.get('voiceCloning.main'))\"\n [title]=\"'Voice Cloning \u2014 Main Voice'\"\n [voiceTTSOptions]=\"voiceTTSOptions\"\n [fullForm]=\"true\">\n </dc-voice-tts-form>\n </div>\n </p-accordion-content>\n </p-accordion-panel>\n </p-accordion>\n\n </div>\n\n <div class=\"right-column\">\n @if(entity() && entityId()){\n <assets-loader\n [assets]=\"entity().assets\"\n [storagePath]=\"'conversation-cards/' + entityId()\"\n (assetsChange)=\"onAssetsChange($event)\"\n (assetUpdate)=\"onUpdateAsset($event)\"\n (onFileSelected)=\"onImageSelected($event)\"></assets-loader>\n } @if(form.controls.characterCard){\n\n <br />\n <dc-character-card-form [characterCardForm]=\"form.controls.characterCard\" (generateMissingDataRequest)=\"generateMissingData()\">\n </dc-character-card-form>\n }\n </div>\n </div>\n </form>\n\n <div class=\"float-button\">\n <p-button icon=\"pi pi-eye\" (click)=\"inspect()\" severity=\"secondary\" [rounded]=\"true\" [raised]=\"true\" pTooltip=\"Inspeccionar\"> </p-button>\n\n <p-button icon=\"pi pi-save\" (click)=\"save()\" severity=\"primary\" [rounded]=\"true\" [raised]=\"true\" pTooltip=\"Guardar (Ctrl + S)\"> </p-button>\n </div>\n</p-card>\n", styles: [".conversation-form{max-width:100%;padding:20px;border-radius:8px;box-shadow:0 2px 4px #0000001a}.conversation-form .card-group{padding:20px;border-radius:6px;margin-bottom:24px}.conversation-form .card-group h3{margin:0 0 20px;color:#2c3e50;font-size:1.25rem}.conversation-form .form-grid{display:flex;flex-wrap:wrap;gap:2rem;width:100%}.conversation-form .form-field{margin-bottom:1.5rem;display:flex;flex-direction:column;gap:.5rem}.conversation-form .form-field label{font-weight:500}.conversation-form .form-field.checkbox{flex-direction:row;align-items:center;gap:.5rem}.conversation-form .form-field.checkbox input[type=checkbox]{width:auto}.conversation-form .form-field .error{color:#dc3545;font-size:.875rem;margin-top:.25rem}.conversation-form .form-field .remove-button{position:absolute;border:none;border-radius:50%;width:20px;height:20px;display:flex;align-items:center;justify-content:center;cursor:pointer;top:-10px;right:-10px}.conversation-form .left-column,.conversation-form .right-column{display:flex;flex-direction:column;flex:1 1 calc(50% - 1rem);min-width:300px}@media(max-width:768px){.conversation-form .left-column,.conversation-form .right-column{flex:1 1 100%}}.conversation-form .card-group{padding:1rem;margin-bottom:1.5rem}.conversation-form .card-group h3{margin-top:0;margin-bottom:1rem}.top-buttons{display:flex;justify-content:space-between;margin-bottom:2rem;gap:1rem}.top-buttons button{flex:1}::ng-deep em{font-weight:900;color:#014a93}.float-button{position:fixed;bottom:4rem;right:2rem;z-index:1000;display:flex;gap:1px}.float-button :host ::ng-deep .p-button{width:4rem;height:4rem;border-radius:50%}\n"] }]
8493
+ ], template: "<p-card>\n <div class=\"top-buttons\">\n <button pButton severity=\"info\" (click)=\"checkPrompt()\" label=\"\uD83D\uDC41\uFE0F Ver instrucciones finales \uD83D\uDCD3\"></button>\n\n <button pButton severity=\"info\" (click)=\"goToDetails()\" label=\"\uD83D\uDCAC Conversar\"></button>\n <button pButton severity=\"primary\" (click)=\"save()\" label=\"\uD83D\uDCBE Guardar cambios\"></button>\n </div>\n\n <div class=\"top-buttons\">\n <p-button [loading]=\"isGenerating()\" severity=\"help\" (click)=\"generateCharacter()\" label=\"Generar \uD83E\uDDBE\"></p-button>\n <p-button severity=\"help\" (click)=\"goToCardsCreator()\" label=\" Creador masivo \"></p-button>\n\n <p-button severity=\"info\" (click)=\"downloadConversation()\" label=\"\uD83D\uDCC1 Exportar \u2B07\uFE0F\"></p-button>\n <p-button severity=\"info\" (click)=\"importConversation()\" label=\"\uD83C\uDCCF Importar \u2B06\uFE0F\"></p-button>\n <p-button severity=\"danger\" (click)=\"deleteCard()\" icon=\"pi pi-trash\"></p-button>\n </div>\n\n <br />\n <br />\n <form [formGroup]=\"form\" class=\"conversation-form\">\n <div class=\"form-grid\">\n <div class=\"left-column\">\n <div title=\"Main data\" >\n <div style=\"display: flex; gap: 15px\">\n <div class=\"form-field\">\n <label for=\"version\">Version: {{ form.get('version').value }} <span pTooltip=\"Version number of the conversation\">\u2139\uFE0F</span></label>\n </div>\n\n <div class=\"form-field\">\n <label for=\"id\"\n >ID: <span pTooltip=\"Unique identifier for this conversation\"> {{ form.get('id').value }} \u2139\uFE0F</span></label\n >\n </div>\n </div>\n\n\n <div class=\"form-field\">\n <label for=\"name\">Card Name <span pTooltip=\"Name of the Agent Card\">\u2139\uFE0F</span></label>\n <input pInputText id=\"name\" type=\"text\" formControlName=\"name\" />\n @if(form.get('name').errors?.['required'] && form.get('name').touched){\n <div class=\"error\"> Name is required </div>\n }\n </div>\n\n <div class=\"form-field\">\n <label for=\"description\"> Description <span pTooltip=\"Description of the conversation\">\u2139\uFE0F</span></label>\n <input pInputText id=\"description\" type=\"text\" formControlName=\"description\" />\n @if(form.get('description').errors?.['required'] && form.get('description').touched){\n <div class=\"error\"> Description is required </div>\n }\n </div>\n\n <div class=\"form-field\">\n <label for=\"lang\">Language <span pTooltip=\"Select the primary language for the conversation\">\u2139\uFE0F</span></label>\n <p-select\n id=\"lang\"\n [options]=\"languageOptions\"\n [filter]=\"true\"\n formControlName=\"lang\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"'Select Language'\"></p-select>\n </div>\n\n <div class=\"form-field\">\n <label for=\"agentType\">Agent Type <span pTooltip=\"Select the type of agent\">\u2139\uFE0F</span></label>\n <p-select id=\"agentType\" [options]=\"agentTypeOptions\" formControlName=\"agentType\" [placeholder]=\"'Select Agent Type'\"></p-select>\n </div>\n </div>\n\n <p-accordion [multiple]=\"true\" >\n <p-accordion-panel value=\"manageable\">\n <p-accordion-header>\n <span>Manageable</span>\n <span style=\"margin-left: 8px; font-size: 0.75rem; color: var(--p-text-muted-color); font-weight: normal\">Controla visibilidad y acceso</span>\n </p-accordion-header>\n <p-accordion-content>\n <dc-manageable-form [form]=\"form.controls.manageable\"></dc-manageable-form>\n </p-accordion-content>\n </p-accordion-panel>\n <p-accordion-panel value=\"learnable\">\n <p-accordion-header>\n <span>Learnable</span>\n <span style=\"margin-left: 8px; font-size: 0.75rem; color: var(--p-text-muted-color); font-weight: normal\">Aprendizaje y conocimiento</span>\n </p-accordion-header>\n <p-accordion-content>\n <dc-learnable-form [form]=\"form.controls.learnable\"></dc-learnable-form>\n </p-accordion-content>\n </p-accordion-panel>\n <p-accordion-panel value=\"conversationSettings\">\n <p-accordion-header>\n <span>Conversation Settings</span>\n <span style=\"margin-left: 8px; font-size: 0.75rem; color: var(--p-text-muted-color); font-weight: normal\">Modelo, voz y configuraci\u00F3n del chat</span>\n </p-accordion-header>\n <p-accordion-content>\n <dc-conversation-settings-form\n [form]=\"form.controls.conversationSettings\"\n [textEngineOptions]=\"textEngineOptions\"\n [conversationOptions]=\"conversationOptions\"\n [voiceTTSOptions]=\"voiceTTSOptions\">\n </dc-conversation-settings-form>\n </p-accordion-content>\n </p-accordion-panel>\n @if(form.controls.conversationFlow){\n <p-accordion-panel value=\"conversationFlow\">\n <p-accordion-header>\n <span>Conversation Flow</span>\n <span style=\"margin-left: 8px; font-size: 0.75rem; color: var(--p-text-muted-color); font-weight: normal\">Objetivos, triggers y condiciones din\u00E1micas</span>\n </p-accordion-header>\n <p-accordion-content>\n <dc-conversation-flow-form [formGroup]=\"form.controls.conversationFlow\"></dc-conversation-flow-form>\n </p-accordion-content>\n </p-accordion-panel>\n }\n <p-accordion-panel value=\"accounts\">\n <p-accordion-header>\n <span>Gesti\u00F3n de cuentas</span>\n <span style=\"margin-left: 8px; font-size: 0.75rem; color: var(--p-text-muted-color); font-weight: normal\">Beta</span>\n </p-accordion-header>\n <p-accordion-content>\n @if(form.controls.accounts) {\n <account-platform-form [formArray]=\"form.controls.accounts\"></account-platform-form>\n }\n </p-accordion-content>\n </p-accordion-panel>\n <p-accordion-panel value=\"voiceCloning\">\n <p-accordion-header>\n <span>Clonaci\u00F3n de voz</span>\n <span style=\"margin-left: 8px; font-size: 0.75rem; color: var(--p-text-muted-color); font-weight: normal\">Beta</span>\n </p-accordion-header>\n <p-accordion-content>\n <div formGroupName=\"voiceCloning\">\n <div class=\"form-field\">\n <label for=\"transcription\">Transcription</label>\n <textarea pTextarea id=\"transcription\" formControlName=\"transcription\" rows=\"3\"></textarea>\n </div>\n <div class=\"form-field\">\n <dc-simple-uploader\n buttonLabel=\"Subir audio\"\n [storagePath]=\"'conversation-cards/' + entityId()\"\n (fileUploaded)=\"onFileUploaded($event)\"></dc-simple-uploader>\n @if(form.get('voiceCloning.sample').value?.url){\n <audio controls [src]=\"form.get('voiceCloning.sample').value.url\"></audio>\n }\n </div>\n <div class=\"form-field voice-clone-status\">\n @if(!form.get('voiceCloning.sample').value?.url){\n <small class=\"muted\">Sube un audio para entrenar un modelo de voz.</small>\n }\n <!-- @if(canCloneVoice()){ -->\n <p-button\n icon=\"pi pi-bolt\"\n severity=\"help\"\n [loading]=\"isCloningVoice()\"\n label=\"Crear modelo en Fish Audio\"\n (click)=\"cloneVoice()\">\n </p-button>\n <!-- } -->\n @if(fishModelId()){\n <div class=\"model-tag\">\n <span>Modelo Fish Audio: <code>{{ fishModelId() }}</code></span>\n <p-button\n icon=\"pi pi-refresh\"\n severity=\"secondary\"\n [text]=\"true\"\n [loading]=\"isCloningVoice()\"\n label=\"Regenerar\"\n (click)=\"cloneVoice()\">\n </p-button>\n </div>\n }\n </div>\n <dc-voice-tts-form\n [form]=\"$any(form.get('voiceCloning.main'))\"\n [title]=\"'Voice Cloning \u2014 Main Voice'\"\n [voiceTTSOptions]=\"voiceTTSOptions\"\n [fullForm]=\"true\">\n </dc-voice-tts-form>\n </div>\n </p-accordion-content>\n </p-accordion-panel>\n </p-accordion>\n\n </div>\n\n <div class=\"right-column\">\n @if(entity() && entityId()){\n <assets-loader\n [assets]=\"entity().assets\"\n [storagePath]=\"'conversation-cards/' + entityId()\"\n (assetsChange)=\"onAssetsChange($event)\"\n (assetUpdate)=\"onUpdateAsset($event)\"\n (onFileSelected)=\"onImageSelected($event)\"></assets-loader>\n } @if(form.controls.characterCard){\n\n <br />\n <dc-character-card-form [characterCardForm]=\"form.controls.characterCard\" (generateMissingDataRequest)=\"generateMissingData()\">\n </dc-character-card-form>\n }\n </div>\n </div>\n </form>\n\n <div class=\"float-button\">\n <p-button icon=\"pi pi-eye\" (click)=\"inspect()\" severity=\"secondary\" [rounded]=\"true\" [raised]=\"true\" pTooltip=\"Inspeccionar\"> </p-button>\n\n <p-button icon=\"pi pi-save\" (click)=\"save()\" severity=\"primary\" [rounded]=\"true\" [raised]=\"true\" pTooltip=\"Guardar (Ctrl + S)\"> </p-button>\n </div>\n</p-card>\n", styles: [".conversation-form{max-width:100%;padding:20px;border-radius:8px;box-shadow:0 2px 4px #0000001a}.conversation-form .card-group{padding:20px;border-radius:6px;margin-bottom:24px}.conversation-form .card-group h3{margin:0 0 20px;color:#2c3e50;font-size:1.25rem}.conversation-form .form-grid{display:flex;flex-wrap:wrap;gap:2rem;width:100%}.conversation-form .form-field{margin-bottom:1.5rem;display:flex;flex-direction:column;gap:.5rem}.conversation-form .form-field label{font-weight:500}.conversation-form .form-field.checkbox{flex-direction:row;align-items:center;gap:.5rem}.conversation-form .form-field.checkbox input[type=checkbox]{width:auto}.conversation-form .form-field .error{color:#dc3545;font-size:.875rem;margin-top:.25rem}.conversation-form .form-field .remove-button{position:absolute;border:none;border-radius:50%;width:20px;height:20px;display:flex;align-items:center;justify-content:center;cursor:pointer;top:-10px;right:-10px}.conversation-form .left-column,.conversation-form .right-column{display:flex;flex-direction:column;flex:1 1 calc(50% - 1rem);min-width:300px}@media(max-width:768px){.conversation-form .left-column,.conversation-form .right-column{flex:1 1 100%}}.conversation-form .card-group{padding:1rem;margin-bottom:1.5rem}.conversation-form .card-group h3{margin-top:0;margin-bottom:1rem}.top-buttons{display:flex;justify-content:space-between;margin-bottom:2rem;gap:1rem}.top-buttons button{flex:1}::ng-deep em{font-weight:900;color:#014a93}.float-button{position:fixed;bottom:4rem;right:2rem;z-index:1000;display:flex;gap:1px}.float-button :host ::ng-deep .p-button{width:4rem;height:4rem;border-radius:50%}.voice-clone-status{display:flex;flex-direction:column;gap:.5rem;margin:.75rem 0}.voice-clone-status .muted{color:var(--p-text-muted-color)}.voice-clone-status .model-tag{display:flex;align-items:center;gap:.75rem;padding:.5rem .75rem;background:var(--p-surface-100, #f3f4f6);border-radius:6px;font-size:.9rem}.voice-clone-status .model-tag code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.8rem}\n"] }]
7969
8494
  }], propDecorators: { onSave: [{ type: i0.Output, args: ["onSave"] }] } });
7970
8495
 
7971
8496
  class TruncatePipe {
@@ -8025,11 +8550,11 @@ class AgentCardUI {
8025
8550
  if (this.card()?.characterCard?.data?.langTranslation?.[baseLang]) {
8026
8551
  const cardTranslation = this.card()?.characterCard?.data?.langTranslation[baseLang];
8027
8552
  console.log(cardTranslation);
8028
- description = cardTranslation?.hook || this.card()?.description || this.card()?.characterCard?.data?.creator_notes || '';
8553
+ description = cardTranslation?.hook || cardTranslation?.instructions || this.card()?.description || this.card()?.characterCard?.data?.creator_notes || '';
8029
8554
  this.name.set(this.card()?.characterCard?.data?.name);
8030
8555
  }
8031
8556
  else {
8032
- description = this.card()?.characterCard?.data?.hook || this.card()?.characterCard?.data?.creator_notes || this.card()?.description || '';
8557
+ description = this.card()?.characterCard?.data?.hook || this.card()?.characterCard?.data?.instructions || this.card()?.characterCard?.data?.creator_notes || this.card()?.description || '';
8033
8558
  this.name.set(this.card()?.name);
8034
8559
  }
8035
8560
  description = description?.replace(/{{char}}/g, this.card()?.name).replace(/{{user}}/g, this.userService.userName());
@@ -8047,7 +8572,7 @@ class AgentCardUI {
8047
8572
  }
8048
8573
  }
8049
8574
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: AgentCardUI, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
8050
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: AgentCardUI, isStandalone: true, selector: "dc-agent-card-ui", inputs: { card: { classPropertyName: "card", publicName: "card", isSignal: true, isRequired: false, transformFunction: null }, showOptions: { classPropertyName: "showOptions", publicName: "showOptions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onAction: "onAction" }, ngImport: i0, template: "<p-card class=\"card-image\">\n @if(this.userService.isAdmin()) {\n <div style=\"position: absolute; top: 5px; right: 5px; z-index: 1000\">\n <p-speeddial\n [model]=\"speedDialModel\"\n [radius]=\"70\"\n type=\"quarter-circle\"\n direction=\"down-left\"\n [tooltipOptions]=\"{ tooltipPosition: 'top' }\"\n [buttonProps]=\"{ severity: 'primary', rounded: true, outlined: true, raised: true }\" />\n </div>\n }\n\n <img [src]=\"card()?.assets?.image?.url || 'defaults/images/default_conversation_card.webp'\" alt=\"\" />\n\n <div (click)=\"eventCard(eventType.Select)\" class=\"content\">\n <p class=\"text-xl font-bold text-shadow-lg/30\">{{ name() }}</p>\n\n <p style=\"margin-top: 40px\">\n <span class=\"title text-shadow-lg/30\" [innerHTML]=\"finalDescription() | truncate : 200\"></span>\n </p>\n\n <div style=\"position: absolute; bottom: 10px; left: 10px\">\n @if(isTaken()){\n <p-tag icon=\"pi pi-check-circle\" severity=\"success\" value=\"Tomada\" [rounded]=\"true\" />\n } @if(userService.isAdmin()){\n\n <p-tag icon=\"pi pi-eye\" severity=\"secondary\" [value]=\"card()?.manageable?.status || 'Sin estado'\" [rounded]=\"true\" />\n }\n </div>\n\n <p-button\n (click)=\"eventCard(eventType.Select); $event.stopPropagation()\"\n [style]=\"{ position: 'absolute', bottom: '10px', right: '10px' }\"\n icon=\"pi pi-comment\"\n [rounded]=\"true\"\n severity=\"info\"\n [outlined]=\"true\"\n [raised]=\"true\" />\n </div>\n</p-card>\n", styles: [":host{display:block}:host ::ng-deep .p-card{height:100%}:host ::ng-deep .p-card-body{height:100%;padding:0!important}.card-image{width:280px;height:380px;position:relative;align-items:center;display:block;padding:-10px}.card-image img{position:absolute;z-index:3;width:100%;height:100%;opacity:.75;object-fit:cover;transition:opacity .5s}.content{position:absolute;inset:0;z-index:4;padding:1rem;color:#fff;background:linear-gradient(to bottom,#0003,#0000001a);height:100%;display:flex;flex-direction:column;justify-content:space-between}.content:hover{background:linear-gradient(to bottom,color-mix(in srgb,var(--p-primary-color) 20%,transparent),color-mix(in srgb,black 10%,transparent));cursor:pointer}\n"], dependencies: [{ kind: "ngmodule", type: PopoverModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: SpeedDialModule }, { kind: "component", type: i3$7.SpeedDial, selector: "p-speeddial, p-speedDial, p-speed-dial", inputs: ["id", "model", "visible", "style", "className", "direction", "transitionDelay", "type", "radius", "mask", "disabled", "hideOnClickOutside", "buttonStyle", "buttonClassName", "maskStyle", "maskClassName", "showIcon", "hideIcon", "rotateAnimation", "ariaLabel", "ariaLabelledBy", "tooltipOptions", "buttonProps"], outputs: ["onVisibleChange", "visibleChange", "onClick", "onShow", "onHide"] }, { kind: "ngmodule", type: CardModule }, { kind: "component", type: i2$6.Card, selector: "p-card", inputs: ["header", "subheader", "style", "styleClass"] }, { kind: "ngmodule", type: TagModule }, { kind: "component", type: i1$4.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "pipe", type: TruncatePipe, name: "truncate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
8575
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: AgentCardUI, isStandalone: true, selector: "dc-agent-card-ui", inputs: { card: { classPropertyName: "card", publicName: "card", isSignal: true, isRequired: false, transformFunction: null }, showOptions: { classPropertyName: "showOptions", publicName: "showOptions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onAction: "onAction" }, ngImport: i0, template: "<p-card class=\"card-image\">\n @if(this.userService.isAdmin()) {\n <div style=\"position: absolute; top: 5px; right: 5px; z-index: 1000\">\n <p-speeddial\n [model]=\"speedDialModel\"\n [radius]=\"70\"\n type=\"quarter-circle\"\n direction=\"down-left\"\n [tooltipOptions]=\"{ tooltipPosition: 'top' }\"\n [buttonProps]=\"{ severity: 'primary', rounded: true, outlined: true, raised: true }\" />\n </div>\n }\n\n <img [src]=\"card()?.assets?.image?.url || 'defaults/images/default_conversation_card.webp'\" alt=\"\" />\n\n <div (click)=\"eventCard(eventType.Select)\" class=\"content\">\n <p class=\"text-xl font-bold text-shadow-lg/30\">{{ name() }}</p>\n\n <p style=\"margin-top: 40px\">\n <span class=\"title text-shadow-lg/30\" [innerHTML]=\"finalDescription() | truncate : 200\"></span>\n </p>\n\n <div style=\"position: absolute; bottom: 10px; left: 10px\">\n @if(isTaken()){\n <p-tag icon=\"pi pi-check-circle\" severity=\"success\" value=\"Tomada\" [rounded]=\"true\" />\n } @if(userService.isAdmin()){\n\n <p-tag icon=\"pi pi-eye\" severity=\"secondary\" [value]=\"card()?.manageable?.status || 'Sin estado'\" [rounded]=\"true\" />\n }\n </div>\n\n <p-button\n (click)=\"eventCard(eventType.Select); $event.stopPropagation()\"\n [style]=\"{ position: 'absolute', bottom: '10px', right: '10px' }\"\n icon=\"pi pi-comment\"\n [rounded]=\"true\"\n severity=\"info\"\n [outlined]=\"true\"\n [raised]=\"true\" />\n </div>\n</p-card>\n", styles: [":host{display:block}:host ::ng-deep .p-card{height:100%}:host ::ng-deep .p-card-body{height:100%;padding:0!important}.card-image{width:280px;height:380px;position:relative;align-items:center;display:block;padding:-10px}.card-image img{position:absolute;z-index:3;width:100%;height:100%;opacity:.75;object-fit:cover;transition:opacity .5s}.content{position:absolute;inset:0;z-index:4;padding:1rem;color:#fff;background:linear-gradient(to bottom,#0003,#0000001a);height:100%;display:flex;flex-direction:column;justify-content:space-between}.content:hover{background:linear-gradient(to bottom,color-mix(in srgb,var(--p-primary-color) 20%,transparent),color-mix(in srgb,black 10%,transparent));cursor:pointer}\n"], dependencies: [{ kind: "ngmodule", type: PopoverModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: SpeedDialModule }, { kind: "component", type: i3$7.SpeedDial, selector: "p-speeddial, p-speedDial, p-speed-dial", inputs: ["id", "model", "visible", "style", "className", "direction", "transitionDelay", "type", "radius", "mask", "disabled", "hideOnClickOutside", "buttonStyle", "buttonClassName", "maskStyle", "maskClassName", "showIcon", "hideIcon", "rotateAnimation", "ariaLabel", "ariaLabelledBy", "tooltipOptions", "buttonProps"], outputs: ["onVisibleChange", "visibleChange", "onClick", "onShow", "onHide"] }, { kind: "ngmodule", type: CardModule }, { kind: "component", type: i2$7.Card, selector: "p-card", inputs: ["header", "subheader", "style", "styleClass"] }, { kind: "ngmodule", type: TagModule }, { kind: "component", type: i1$3.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "pipe", type: TruncatePipe, name: "truncate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
8051
8576
  }
8052
8577
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: AgentCardUI, decorators: [{
8053
8578
  type: Component,
@@ -8071,6 +8596,7 @@ class AgentCardListComponent extends EntityBaseListV2Component {
8071
8596
  this.showOptions = input(true, ...(ngDevMode ? [{ debugName: "showOptions" }] : /* istanbul ignore next */ []));
8072
8597
  this.gridLayout = input(true, ...(ngDevMode ? [{ debugName: "gridLayout" }] : /* istanbul ignore next */ []));
8073
8598
  this.customGetButtons = input(...(ngDevMode ? [undefined, { debugName: "customGetButtons" }] : /* istanbul ignore next */ []));
8599
+ // Services
8074
8600
  this.agentCardsMasterStateService = inject(AGENT_CARDS_STATE_SERVICE);
8075
8601
  this.userService = inject(UserService);
8076
8602
  // Injected Services
@@ -8078,6 +8604,7 @@ class AgentCardListComponent extends EntityBaseListV2Component {
8078
8604
  this.columns = DefaultColumns;
8079
8605
  this.customFilters = [];
8080
8606
  this.mongoState.options.sort = { _id: -1 };
8607
+ const baseLang = this.userService.getBaseLanguage?.() || 'en';
8081
8608
  this.mongoState.projection = {
8082
8609
  _id: 1,
8083
8610
  name: 1,
@@ -8086,6 +8613,7 @@ class AgentCardListComponent extends EntityBaseListV2Component {
8086
8613
  'characterCard.data.name': 1,
8087
8614
  'characterCard.data.creator_notes': 1,
8088
8615
  'characterCard.data.hook': 1,
8616
+ [`characterCard.data.langTranslation.${baseLang}.hook`]: 1,
8089
8617
  manageable: 1,
8090
8618
  };
8091
8619
  this.agentCardsMasterStateService.getUserState();
@@ -8175,7 +8703,7 @@ class AgentCardListComponent extends EntityBaseListV2Component {
8175
8703
  }
8176
8704
  }
8177
8705
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: AgentCardListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
8178
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: AgentCardListComponent, isStandalone: true, selector: "dc-agent-card-lists", inputs: { extraFilters: { classPropertyName: "extraFilters", publicName: "extraFilters", isSignal: false, isRequired: false, transformFunction: null }, persistenceKey: { classPropertyName: "persistenceKey", publicName: "persistenceKey", isSignal: false, 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 }, customGetButtons: { classPropertyName: "customGetButtons", publicName: "customGetButtons", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: "<dc-filter-bar\n [isAdmin]=\"userService.isAdmin()\"\n [options]=\"filterBarOptions\"\n [customFilters]=\"customFilters\"\n [persistenceKey]=\"persistenceKey\"\n (onFilterAction)=\"doAction($event)\"\n (onNew)=\"onNew()\"></dc-filter-bar>\n\n@if(viewType() === 'table'){\n<app-quick-table [columns]=\"columns\" [tableData]=\"items()\" [actions]=\"actions()\" (onAction)=\"handleTableAction($event)\"></app-quick-table>\n\n} @else {\n\n<div class=\"conversation-card-lists\">\n <div [ngClass]=\"{ 'cards-container': gridLayout() }\">\n @if(!isLoading()) { @for (card of items(); track card._id) {\n <dc-agent-card-ui [card]=\"card\" [showOptions]=\"showOptions()\" (onAction)=\"handleAction($event)\"></dc-agent-card-ui>\n } @if(items().length === 0 && !isLoading()) {\n <div>\n <dc-empty-state\n headingText=\"No hay conversaciones para este idioma\"\n subHeadingText=\"Estamos trabajando en ello...\"\n mainIconSrcString=\"/img/empty-states/empty-box.png\">\n </dc-empty-state>\n </div>\n } } @else { @for (i of [1,2,3,4,5,6]; track i) {\n <p-card class=\"card-image skeleton-card\">\n <div class=\"content\">\n <p-skeleton width=\"80%\" height=\"1.5rem\" styleClass=\"mb-4\" />\n <div style=\"margin-top: 40px\">\n <p-skeleton width=\"100%\" height=\"1rem\" styleClass=\"mb-2\" />\n <p-skeleton width=\"90%\" height=\"1rem\" styleClass=\"mb-2\" />\n <p-skeleton width=\"60%\" height=\"1rem\" />\n </div>\n <div style=\"position: absolute; bottom: 10px; left: 10px\">\n <p-skeleton shape=\"circle\" size=\"2rem\" />\n </div>\n <p-skeleton\n shape=\"circle\"\n size=\"3rem\"\n [style]=\"{ position: 'absolute', bottom: '10px', right: '10px' }\" />\n </div>\n </p-card>\n } }\n </div>\n</div>\n}\n\n\n<!-- Mobile Paginator -->\n<p-paginator\n [first]=\"first()\"\n [rows]=\"rows()\"\n [totalRecords]=\"totalRecordsSignal()\"\n (onPageChange)=\"onPageChange($event)\"\n [showCurrentPageReport]=\"true\"\n [showPageLinks]=\"false\"\n [showFirstLastIcon]=\"false\"\n [rowsPerPageOptions]=\"[10, 20, 30]\"\n currentPageReportTemplate=\" {first}- {last} de {totalRecords} \" />\n", styles: [":host{display:flex;flex-direction:column;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:.7rem 0 0;width:100%;flex:1;min-height:0;display:flex;flex-direction:column}@media(min-width:900px){.conversation-card-lists{padding:1.5rem}}.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)}::ng-deep p-paginator .p-paginator{padding:0!important;background:transparent!important}.skeleton-card ::ng-deep .p-card-body{padding:0!important;height:100%}.card-image{width:280px;height:380px;position:relative;align-items:center;display:block}.card-image .content{position:absolute;inset:0;z-index:4;padding:1rem;color:#fff;background:linear-gradient(to bottom,#0006,#0003);height:100%;display:flex;flex-direction:column}\n"], dependencies: [{ kind: "component", type: AgentCardUI, selector: "dc-agent-card-ui", inputs: ["card", "showOptions"], outputs: ["onAction"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "ngmodule", type: PaginatorModule }, { kind: "component", type: i4$3.Paginator, selector: "p-paginator", inputs: ["pageLinkSize", "styleClass", "alwaysShow", "dropdownAppendTo", "templateLeft", "templateRight", "dropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showFirstLastIcon", "totalRecords", "rows", "rowsPerPageOptions", "showJumpToPageDropdown", "showJumpToPageInput", "jumpToPageItemTemplate", "showPageLinks", "locale", "dropdownItemTemplate", "first", "appendTo"], outputs: ["onPageChange"] }, { kind: "component", type: DCFilterBarComponent, selector: "dc-filter-bar", inputs: ["items", "options", "customFilters", "customSortOptions", "isAdmin", "persistenceKey"], outputs: ["onFilterAction", "onNew"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i1$2.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "ngmodule", type: SpeedDialModule }, { kind: "ngmodule", type: TagModule }, { kind: "ngmodule", type: CardModule }, { kind: "component", type: i2$6.Card, selector: "p-card", inputs: ["header", "subheader", "style", "styleClass"] }, { kind: "component", type: QuickTableComponent, selector: "app-quick-table", inputs: ["columns", "tableData", "actions"], outputs: ["onAction"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: EmptyStateComponent, selector: "dc-empty-state", inputs: ["headingText", "subHeadingText", "mainIconSrcString"] }] }); }
8706
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: AgentCardListComponent, isStandalone: true, selector: "dc-agent-card-lists", inputs: { extraFilters: { classPropertyName: "extraFilters", publicName: "extraFilters", isSignal: false, isRequired: false, transformFunction: null }, persistenceKey: { classPropertyName: "persistenceKey", publicName: "persistenceKey", isSignal: false, 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 }, customGetButtons: { classPropertyName: "customGetButtons", publicName: "customGetButtons", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: "<dc-filter-bar\n [isAdmin]=\"userService.isAdmin()\"\n [options]=\"filterBarOptions\"\n [customFilters]=\"customFilters\"\n [persistenceKey]=\"persistenceKey\"\n (onFilterAction)=\"doAction($event)\"\n (onNew)=\"onNew()\"></dc-filter-bar>\n\n@if(viewType() === 'table'){\n<app-quick-table [columns]=\"columns\" [tableData]=\"items()\" [actions]=\"actions()\" (onAction)=\"handleTableAction($event)\"></app-quick-table>\n\n} @else {\n\n<div class=\"conversation-card-lists\">\n <div [ngClass]=\"{ 'cards-container': gridLayout() }\">\n @if(!isLoading()) { @for (card of items(); track card._id) {\n <dc-agent-card-ui [card]=\"card\" [showOptions]=\"showOptions()\" (onAction)=\"handleAction($event)\"></dc-agent-card-ui>\n } @if(items().length === 0 && !isLoading()) {\n <div>\n <dc-empty-state\n headingText=\"No hay conversaciones para este idioma\"\n subHeadingText=\"Estamos trabajando en ello...\"\n mainIconSrcString=\"/img/empty-states/empty-box.png\">\n </dc-empty-state>\n </div>\n } } @else { @for (i of [1,2,3,4,5,6]; track i) {\n <p-card class=\"card-image skeleton-card\">\n <div class=\"content\">\n <p-skeleton width=\"80%\" height=\"1.5rem\" styleClass=\"mb-4\" />\n <div style=\"margin-top: 40px\">\n <p-skeleton width=\"100%\" height=\"1rem\" styleClass=\"mb-2\" />\n <p-skeleton width=\"90%\" height=\"1rem\" styleClass=\"mb-2\" />\n <p-skeleton width=\"60%\" height=\"1rem\" />\n </div>\n <div style=\"position: absolute; bottom: 10px; left: 10px\">\n <p-skeleton shape=\"circle\" size=\"2rem\" />\n </div>\n <p-skeleton\n shape=\"circle\"\n size=\"3rem\"\n [style]=\"{ position: 'absolute', bottom: '10px', right: '10px' }\" />\n </div>\n </p-card>\n } }\n </div>\n</div>\n}\n\n\n<!-- Mobile Paginator -->\n<p-paginator\n [first]=\"first()\"\n [rows]=\"rows()\"\n [totalRecords]=\"totalRecordsSignal()\"\n (onPageChange)=\"onPageChange($event)\"\n [showCurrentPageReport]=\"true\"\n [showPageLinks]=\"false\"\n [showFirstLastIcon]=\"false\"\n [rowsPerPageOptions]=\"[10, 20, 30]\"\n currentPageReportTemplate=\" {first}- {last} de {totalRecords} \" />\n", styles: [":host{display:flex;flex-direction:column;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:.7rem 0 0;width:100%;flex:1;min-height:0;display:flex;flex-direction:column}@media(min-width:900px){.conversation-card-lists{padding:1.5rem}}.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)}::ng-deep p-paginator .p-paginator{padding:0!important;background:transparent!important}.skeleton-card ::ng-deep .p-card-body{padding:0!important;height:100%}.card-image{width:280px;height:380px;position:relative;align-items:center;display:block}.card-image .content{position:absolute;inset:0;z-index:4;padding:1rem;color:#fff;background:linear-gradient(to bottom,#0006,#0003);height:100%;display:flex;flex-direction:column}\n"], dependencies: [{ kind: "component", type: AgentCardUI, selector: "dc-agent-card-ui", inputs: ["card", "showOptions"], outputs: ["onAction"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "ngmodule", type: PaginatorModule }, { kind: "component", type: i4$4.Paginator, selector: "p-paginator", inputs: ["pageLinkSize", "styleClass", "alwaysShow", "dropdownAppendTo", "templateLeft", "templateRight", "dropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showFirstLastIcon", "totalRecords", "rows", "rowsPerPageOptions", "showJumpToPageDropdown", "showJumpToPageInput", "jumpToPageItemTemplate", "showPageLinks", "locale", "dropdownItemTemplate", "first", "appendTo"], outputs: ["onPageChange"] }, { kind: "component", type: DCFilterBarComponent, selector: "dc-filter-bar", inputs: ["items", "options", "customFilters", "customSortOptions", "isAdmin", "persistenceKey"], outputs: ["onFilterAction", "onNew"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i1$2.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "ngmodule", type: SpeedDialModule }, { kind: "ngmodule", type: TagModule }, { kind: "ngmodule", type: CardModule }, { kind: "component", type: i2$7.Card, selector: "p-card", inputs: ["header", "subheader", "style", "styleClass"] }, { kind: "component", type: QuickTableComponent, selector: "app-quick-table", inputs: ["columns", "tableData", "actions"], outputs: ["onAction"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: EmptyStateComponent, selector: "dc-empty-state", inputs: ["headingText", "subHeadingText", "mainIconSrcString"] }] }); }
8179
8707
  }
8180
8708
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: AgentCardListComponent, decorators: [{
8181
8709
  type: Component,
@@ -8281,6 +8809,16 @@ class DcAgentCardConverseComponent {
8281
8809
  console.warn('⚠️ Conversation settings not found ⚠️ probably is an old version of the card.');
8282
8810
  card.conversationSettings = {};
8283
8811
  }
8812
+ const baseLang = this.userService.getBaseLanguage();
8813
+ if (card.characterCard?.data?.langTranslation?.[baseLang]) {
8814
+ const translation = card.characterCard.data.langTranslation[baseLang];
8815
+ if (translation.instructions) {
8816
+ card.characterCard.data.instructions = translation.instructions;
8817
+ }
8818
+ if (translation.hook) {
8819
+ card.characterCard.data.hook = translation.hook;
8820
+ }
8821
+ }
8284
8822
  this.agentCard.set(card);
8285
8823
  if (card.assets.banner?.url) {
8286
8824
  this.chatMonitorService.setBackground(card.assets.banner.url);
@@ -8343,7 +8881,7 @@ class DcAgentCardConverseComponent {
8343
8881
  this.showInfoLayer.update((value) => !value);
8344
8882
  }
8345
8883
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DcAgentCardConverseComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
8346
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: DcAgentCardConverseComponent, isStandalone: true, selector: "dc-agent-card-converse", inputs: { agentCardId: "agentCardId", useNativePlayer: "useNativePlayer" }, outputs: { onStartConversation: "onStartConversation" }, viewQueries: [{ propertyName: "videoPlayerA", first: true, predicate: ["videoPlayerA"], descendants: true, isSignal: true }, { propertyName: "videoPlayerB", first: true, predicate: ["videoPlayerB"], descendants: true, isSignal: true }], ngImport: i0, template: "<ng-template #cardContent>\n <div class=\"card-container\">\n <img class=\"card-image\" [src]=\"agentCard()?.assets?.image?.url\" [style.opacity]=\"videoPlayerService.isVideoPlaying() ? 0 : 1\" style=\"transition: opacity 0.5s ease-in-out;\" alt=\"\" />\n <!-- Se implementa l\u00F3gica de doble video (ping-pong) para evitar parpadeos -->\n <video #videoPlayerA class=\"card-image\" style=\"position: absolute; top: 0; left: 0; transition: opacity 0.3s ease-in-out; opacity: 1; z-index: 1;\" playsinline></video>\n <video #videoPlayerB class=\"card-image\" style=\"position: absolute; top: 0; left: 0; transition: opacity 0.3s ease-in-out; opacity: 0; z-index: 2;\" playsinline></video>\n\n\n\n @if (!chatMonitorService.isConversationActive()) {\n\n <div class=\"info-button\" (click)=\"toggleInfoLayer()\">\n <p-button icon=\"pi pi-arrow-down-left\" [rounded]=\"true\" [raised]=\"true\" severity=\"primary\" [outlined]=\"true\" />\n </div>\n \n <div style=\"position: absolute; bottom: 20px; right: 50%; transform: translateX(50%); z-index: 3\">\n <p-button\n size=\"large\"\n [label]=\"'dataclouder.agentCards.dcAgentCardDetails.startConversation' | translate\"\n [rounded]=\"true\"\n (click)=\"startConversation()\" />\n </div>\n }\n\n <div class=\"info-layer\" [class.active]=\"showInfoLayer()\">\n <div class=\"info-content\">\n <h1\n ><strong>{{ agentCard()?.name || agentCard()?.characterCard?.data?.name }}</strong></h1\n >\n\n @if (agentCard()?.characterCard?.data?.instructions) {\n <div class=\"scenario\">\n <h4>{{ 'dataclouder.agentCards.dcAgentCardDetails.instructions' | translate }}</h4>\n <p>{{ agentCard()?.characterCard?.data?.instructions | parseCard: agentCard() }}</p>\n </div>\n }\n </div>\n </div>\n </div>\n</ng-template>\n\n<div style=\"display: flex; justify-content: center; align-items: center\" [class.transparent-mode]=\"isTransparent()\">\n @if (isTransparent()) {\n <ng-container *ngTemplateOutlet=\"cardContent\"></ng-container>\n } @else {\n <p-card>\n <ng-container *ngTemplateOutlet=\"cardContent\"></ng-container>\n </p-card>\n }\n</div>\n", styles: ["::ng-deep .p-card{width:420px;height:700px}::ng-deep .p-card .p-card-body{width:100%;height:100%}.transparent-mode .card-container{width:420px;height:700px;position:relative}.transparent-mode .card-image{background:transparent}.card-image{height:100%;width:100%;object-fit:cover;object-position:center;position:absolute;top:0;left:0;transition:filter .3s ease}::ng-deep .plyr--full-ui{width:100%;object-fit:cover;object-position:center;position:absolute;top:0;left:0;transition:filter .3s ease}.info-button{position:absolute;top:15px;right:15px;z-index:3}.info-button:hover{transform:scale(1.1)}.info-layer{height:100%;width:100%;position:absolute;top:0;left:0;display:flex;justify-content:center;align-items:center;z-index:2;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);background-color:var(--chat-user-message-bg);color:#fff;opacity:1;clip-path:circle(0% at top right);transition:clip-path .5s cubic-bezier(.25,1,.5,1);pointer-events:none}.info-layer.active{clip-path:circle(150% at top right);pointer-events:auto}.info-content{padding:15px;text-align:center;max-width:90%}.info-content h1{margin-top:0;font-size:18px;margin-bottom:10px}.info-content p{font-size:12px;margin:0}::ng-deep .info-button .p-button{background-color:#ffffff47}\n"], dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: CardModule }, { kind: "component", type: i2$6.Card, selector: "p-card", inputs: ["header", "subheader", "style", "styleClass"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: ParseCardPipe, name: "parseCard" }, { kind: "pipe", type: i3$8.TranslatePipe, name: "translate" }] }); }
8884
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: DcAgentCardConverseComponent, isStandalone: true, selector: "dc-agent-card-converse", inputs: { agentCardId: "agentCardId", useNativePlayer: "useNativePlayer" }, outputs: { onStartConversation: "onStartConversation" }, viewQueries: [{ propertyName: "videoPlayerA", first: true, predicate: ["videoPlayerA"], descendants: true, isSignal: true }, { propertyName: "videoPlayerB", first: true, predicate: ["videoPlayerB"], descendants: true, isSignal: true }], ngImport: i0, template: "<ng-template #cardContent>\n <div class=\"card-container\">\n <img class=\"card-image\" [src]=\"agentCard()?.assets?.image?.url\" [style.opacity]=\"videoPlayerService.isVideoPlaying() ? 0 : 1\" style=\"transition: opacity 0.5s ease-in-out;\" alt=\"\" />\n <!-- Se implementa l\u00F3gica de doble video (ping-pong) para evitar parpadeos -->\n <video #videoPlayerA class=\"card-image\" style=\"position: absolute; top: 0; left: 0; transition: opacity 0.3s ease-in-out; opacity: 1; z-index: 1;\" playsinline></video>\n <video #videoPlayerB class=\"card-image\" style=\"position: absolute; top: 0; left: 0; transition: opacity 0.3s ease-in-out; opacity: 0; z-index: 2;\" playsinline></video>\n\n\n\n @if (!chatMonitorService.isConversationActive()) {\n\n <div class=\"info-button\" (click)=\"toggleInfoLayer()\">\n <p-button icon=\"pi pi-arrow-down-left\" [rounded]=\"true\" [raised]=\"true\" severity=\"primary\" [outlined]=\"true\" />\n </div>\n \n <div style=\"position: absolute; bottom: 20px; right: 50%; transform: translateX(50%); z-index: 3\">\n <p-button\n size=\"large\"\n [label]=\"'dataclouder.agentCards.dcAgentCardDetails.startConversation' | translate\"\n [rounded]=\"true\"\n (click)=\"startConversation()\" />\n </div>\n }\n\n <div class=\"info-layer\" [class.active]=\"showInfoLayer()\">\n <div class=\"info-content\">\n <h1\n ><strong>{{ agentCard()?.name || agentCard()?.characterCard?.data?.name }}</strong></h1\n >\n\n @if (agentCard()?.characterCard?.data?.instructions) {\n <div class=\"scenario\">\n <h4>{{ 'dataclouder.agentCards.dcAgentCardDetails.instructions' | translate }}</h4>\n <p>{{ agentCard()?.characterCard?.data?.instructions | parseCard: agentCard() }}</p>\n </div>\n }\n </div>\n </div>\n </div>\n</ng-template>\n\n<div style=\"display: flex; justify-content: center; align-items: center\" [class.transparent-mode]=\"isTransparent()\">\n @if (isTransparent()) {\n <ng-container *ngTemplateOutlet=\"cardContent\"></ng-container>\n } @else {\n <p-card>\n <ng-container *ngTemplateOutlet=\"cardContent\"></ng-container>\n </p-card>\n }\n</div>\n", styles: ["::ng-deep .p-card{width:420px;height:700px}::ng-deep .p-card .p-card-body{width:100%;height:100%}.transparent-mode .card-container{width:420px;height:700px;position:relative}.transparent-mode .card-image{background:transparent}.card-image{height:100%;width:100%;object-fit:cover;object-position:center;position:absolute;top:0;left:0;transition:filter .3s ease}::ng-deep .plyr--full-ui{width:100%;object-fit:cover;object-position:center;position:absolute;top:0;left:0;transition:filter .3s ease}.info-button{position:absolute;top:15px;right:15px;z-index:3}.info-button:hover{transform:scale(1.1)}.info-layer{height:100%;width:100%;position:absolute;top:0;left:0;display:flex;justify-content:center;align-items:center;z-index:2;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);background-color:var(--chat-user-message-bg);color:#fff;opacity:1;clip-path:circle(0% at top right);transition:clip-path .5s cubic-bezier(.25,1,.5,1);pointer-events:none}.info-layer.active{clip-path:circle(150% at top right);pointer-events:auto}.info-content{padding:15px;text-align:center;max-width:90%}.info-content h1{margin-top:0;font-size:18px;margin-bottom:10px}.info-content p{font-size:12px;margin:0}::ng-deep .info-button .p-button{background-color:#ffffff47}\n"], dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: CardModule }, { kind: "component", type: i2$7.Card, selector: "p-card", inputs: ["header", "subheader", "style", "styleClass"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: ParseCardPipe, name: "parseCard" }, { kind: "pipe", type: i3$8.TranslatePipe, name: "translate" }] }); }
8347
8885
  }
8348
8886
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DcAgentCardConverseComponent, decorators: [{
8349
8887
  type: Component,
@@ -8499,14 +9037,14 @@ class CardsCreatorComponent {
8499
9037
  this.notPublishedResults.set(res);
8500
9038
  }
8501
9039
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CardsCreatorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
8502
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: CardsCreatorComponent, isStandalone: true, selector: "app-cards-creator", ngImport: i0, template: "<div>\n <h2 class=\"text-2xl font-bold mb-4\">Card Generation</h2>\n <p-message severity=\"secondary\"\n >Paso 1: Genearar una o varias tarjetas vacias con solo la idea, estas tiene estatus de pending. no lo cambies ser\u00E1 necesario en el paso 2.\n </p-message>\n\n <div class=\"grid\">\n <div class=\"col-12\">\n <form [formGroup]=\"cardsForm\" (ngSubmit)=\"generateCards()\">\n <div class=\"p-panel p-4\">\n <h3 class=\"text-xl font-semibold mb-3\">Generate Cards</h3>\n <p-message severity=\"info\">Generate one or more cards with an idea. Cards will be created with a 'pending' status.</p-message>\n\n <div class=\"field mt-4\">\n <label for=\"idea\">Idea</label>\n <input id=\"idea\" type=\"text\" pInputText formControlName=\"idea\" placeholder=\"e.g., 'Ordering food at a restaurant'\" class=\"w-full\" />\n </div>\n\n <div class=\"form-field mt-4\">\n <label for=\"lang\">Language <span pTooltip=\"Select the primary language for the conversation\">\u2139\uFE0F</span></label>\n <p-select\n id=\"lang\"\n [options]=\"languageOptions\"\n [filter]=\"true\"\n formControlName=\"langCode\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"'Select Language'\"\n styleClass=\"w-full\"></p-select>\n </div>\n\n <div class=\"field mt-4\">\n <label for=\"num-cards\">Number of Cards</label>\n <input id=\"num-cards\" type=\"number\" pInputText formControlName=\"numCards\" placeholder=\"e.g., '10'\" class=\"w-full\" />\n </div>\n\n <div class=\"flex flex-wrap gap-4 mt-4\">\n <div class=\"flex align-items-center\">\n <p-toggleSwitch formControlName=\"autosave\" inputId=\"autosave-switch\"></p-toggleSwitch>\n <label for=\"autosave-switch\" class=\"ml-2\"> Auto-save?</label>\n </div>\n <div class=\"flex align-items-center\">\n <p-toggleSwitch formControlName=\"doNotRepeat\" inputId=\"repeat-switch\"></p-toggleSwitch>\n <label for=\"repeat-switch\" class=\"ml-2\"> Do not repeat topics?</label>\n </div>\n </div>\n\n <div class=\"mt-4\">\n <p-button label=\"Generate Cards\" icon=\"pi pi-bolt\" type=\"submit\" [loading]=\"loading()\" [disabled]=\"cardsForm.invalid\"></p-button>\n </div>\n </div>\n </form>\n </div>\n </div>\n\n <p-divider align=\"center\" styleClass=\"my-5\">\n <span class=\"p-tag\">Maintenance</span>\n </p-divider>\n\n <!-- Maintenance Section -->\n <div class=\"grid\">\n <!-- Card Specific Maintenance -->\n <div class=\"col-12 md:col-6\">\n <div class=\"p-panel p-4\">\n <h3 class=\"text-xl font-semibold mb-3\">Card Specific Maintenance</h3>\n <div class=\"field\">\n <label for=\"cardId\">Card ID</label>\n <input\n id=\"cardId\"\n type=\"text\"\n pInputText\n [value]=\"cardId()\"\n (input)=\"cardId.set($any($event.target).value)\"\n placeholder=\"Enter Card ID\"\n class=\"w-full\" />\n </div>\n <div class=\"mt-4 flex gap-2\">\n <p-button label=\"Generate Image\" icon=\"pi pi-image\" (onClick)=\"generateImageForCard()\" [loading]=\"loading()\"></p-button>\n <p-button\n label=\"Generate Missing Data\"\n icon=\"pi pi-database\"\n (onClick)=\"generateMissingData()\"\n [loading]=\"loading()\"\n styleClass=\"p-button-secondary\"></p-button>\n </div>\n </div>\n </div>\n\n <!-- Batch Operations -->\n <div class=\"col-12 md:col-6\">\n <div class=\"p-panel p-4\">\n <h3 class=\"text-xl font-semibold mb-3\">Batch Operations</h3>\n <p>Run maintenance tasks on all pending cards.</p>\n <div class=\"mt-4 flex gap-2\">\n <p-button label=\"Complete Pending Cards\" icon=\"pi pi-check-square\" (onClick)=\"completePendingCards()\" [loading]=\"loading()\"></p-button>\n <p-button\n label=\"Generate Pending Images\"\n icon=\"pi pi-images\"\n (onClick)=\"generatePendingImages()\"\n [loading]=\"loading()\"\n styleClass=\"p-button-secondary\"></p-button>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Result Section -->\n @if (result()) {\n <div class=\"col-12 mt-4\">\n <div class=\"p-panel p-4\">\n <h3 class=\"text-xl font-semibold mb-3\">Result</h3>\n <pre>{{ result() | json }}</pre>\n </div>\n </div>\n }\n\n <p-divider align=\"center\" styleClass=\"my-5\"> Busquedas pendientes </p-divider>\n\n <p-button label=\"Buscar No publicadas\" icon=\"pi pi-database\" (onClick)=\"searchNotPublic()\" [loading]=\"loading()\" severity=\"secondary\"></p-button>\n <p-button label=\"Buscar no publicadas (new)\" icon=\"pi pi-database\" (onClick)=\"searchNotpublished()\" [loading]=\"loading()\" severity=\"secondary\"></p-button>\n <br />\n\n <br />\n\n @if (notPublishedResults()) {\n <div class=\"mt-4\">\n <p-table [value]=\"notPublishedResults().rows\" [tableStyle]=\"{ 'min-width': '50rem' }\">\n <ng-template pTemplate=\"header\">\n <tr>\n <th>ID</th>\n <th>Name</th>\n <th>Language</th>\n <th>Status</th>\n <th>Character Name</th>\n <th>Actions</th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\" let-row>\n <tr>\n <td>{{ row?._id }}</td>\n <td>{{ row?.name }}</td>\n <td>{{ row?.lang }}</td>\n <td>{{ row?.manageable?.status }}</td>\n <td>{{ row?.characterCard?.data?.name }}</td>\n <td>\n <a [href]=\"'/app/conversations/edit/' + row._id\" target=\"_blank\">\n <p-button icon=\"pi pi-pencil\" styleClass=\"p-button-rounded p-button-text\"></p-button>\n </a>\n </td>\n </tr>\n </ng-template>\n </p-table>\n\n <br />\n <br />\n </div>\n }\n</div>\n", styles: [""], dependencies: [{ 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.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],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"] }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "directive", type: i2$4.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i3$5.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: DividerModule }, { kind: "component", type: i1$3.Divider, selector: "p-divider", inputs: ["styleClass", "layout", "type", "align"] }, { kind: "ngmodule", type: MessageModule }, { kind: "component", type: i3$4.Message, selector: "p-message", inputs: ["severity", "text", "escape", "style", "styleClass", "closable", "icon", "closeIcon", "life", "showTransitionOptions", "hideTransitionOptions", "size", "variant", "motionOptions"], outputs: ["onClose"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i5.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: ToggleSwitchModule }, { kind: "component", type: i4$1.ToggleSwitch, selector: "p-toggleswitch, p-toggleSwitch, p-toggle-switch", inputs: ["styleClass", "tabindex", "inputId", "readonly", "trueValue", "falseValue", "ariaLabel", "size", "ariaLabelledBy", "autofocus"], outputs: ["onChange"] }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: i1$5.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "pipe", type: i2$1.JsonPipe, name: "json" }] }); }
9040
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: CardsCreatorComponent, isStandalone: true, selector: "app-cards-creator", ngImport: i0, template: "<div>\n <h2 class=\"text-2xl font-bold mb-4\">Card Generation</h2>\n <p-message severity=\"secondary\"\n >Paso 1: Genearar una o varias tarjetas vacias con solo la idea, estas tiene estatus de pending. no lo cambies ser\u00E1 necesario en el paso 2.\n </p-message>\n\n <div class=\"grid\">\n <div class=\"col-12\">\n <form [formGroup]=\"cardsForm\" (ngSubmit)=\"generateCards()\">\n <div class=\"p-panel p-4\">\n <h3 class=\"text-xl font-semibold mb-3\">Generate Cards</h3>\n <p-message severity=\"info\">Generate one or more cards with an idea. Cards will be created with a 'pending' status.</p-message>\n\n <div class=\"field mt-4\">\n <label for=\"idea\">Idea</label>\n <input id=\"idea\" type=\"text\" pInputText formControlName=\"idea\" placeholder=\"e.g., 'Ordering food at a restaurant'\" class=\"w-full\" />\n </div>\n\n <div class=\"form-field mt-4\">\n <label for=\"lang\">Language <span pTooltip=\"Select the primary language for the conversation\">\u2139\uFE0F</span></label>\n <p-select\n id=\"lang\"\n [options]=\"languageOptions\"\n [filter]=\"true\"\n formControlName=\"langCode\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"'Select Language'\"\n styleClass=\"w-full\"></p-select>\n </div>\n\n <div class=\"field mt-4\">\n <label for=\"num-cards\">Number of Cards</label>\n <input id=\"num-cards\" type=\"number\" pInputText formControlName=\"numCards\" placeholder=\"e.g., '10'\" class=\"w-full\" />\n </div>\n\n <div class=\"flex flex-wrap gap-4 mt-4\">\n <div class=\"flex align-items-center\">\n <p-toggleSwitch formControlName=\"autosave\" inputId=\"autosave-switch\"></p-toggleSwitch>\n <label for=\"autosave-switch\" class=\"ml-2\"> Auto-save?</label>\n </div>\n <div class=\"flex align-items-center\">\n <p-toggleSwitch formControlName=\"doNotRepeat\" inputId=\"repeat-switch\"></p-toggleSwitch>\n <label for=\"repeat-switch\" class=\"ml-2\"> Do not repeat topics?</label>\n </div>\n </div>\n\n <div class=\"mt-4\">\n <p-button label=\"Generate Cards\" icon=\"pi pi-bolt\" type=\"submit\" [loading]=\"loading()\" [disabled]=\"cardsForm.invalid\"></p-button>\n </div>\n </div>\n </form>\n </div>\n </div>\n\n <p-divider align=\"center\" styleClass=\"my-5\">\n <span class=\"p-tag\">Maintenance</span>\n </p-divider>\n\n <!-- Maintenance Section -->\n <div class=\"grid\">\n <!-- Card Specific Maintenance -->\n <div class=\"col-12 md:col-6\">\n <div class=\"p-panel p-4\">\n <h3 class=\"text-xl font-semibold mb-3\">Card Specific Maintenance</h3>\n <div class=\"field\">\n <label for=\"cardId\">Card ID</label>\n <input\n id=\"cardId\"\n type=\"text\"\n pInputText\n [value]=\"cardId()\"\n (input)=\"cardId.set($any($event.target).value)\"\n placeholder=\"Enter Card ID\"\n class=\"w-full\" />\n </div>\n <div class=\"mt-4 flex gap-2\">\n <p-button label=\"Generate Image\" icon=\"pi pi-image\" (onClick)=\"generateImageForCard()\" [loading]=\"loading()\"></p-button>\n <p-button\n label=\"Generate Missing Data\"\n icon=\"pi pi-database\"\n (onClick)=\"generateMissingData()\"\n [loading]=\"loading()\"\n styleClass=\"p-button-secondary\"></p-button>\n </div>\n </div>\n </div>\n\n <!-- Batch Operations -->\n <div class=\"col-12 md:col-6\">\n <div class=\"p-panel p-4\">\n <h3 class=\"text-xl font-semibold mb-3\">Batch Operations</h3>\n <p>Run maintenance tasks on all pending cards.</p>\n <div class=\"mt-4 flex gap-2\">\n <p-button label=\"Complete Pending Cards\" icon=\"pi pi-check-square\" (onClick)=\"completePendingCards()\" [loading]=\"loading()\"></p-button>\n <p-button\n label=\"Generate Pending Images\"\n icon=\"pi pi-images\"\n (onClick)=\"generatePendingImages()\"\n [loading]=\"loading()\"\n styleClass=\"p-button-secondary\"></p-button>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Result Section -->\n @if (result()) {\n <div class=\"col-12 mt-4\">\n <div class=\"p-panel p-4\">\n <h3 class=\"text-xl font-semibold mb-3\">Result</h3>\n <pre>{{ result() | json }}</pre>\n </div>\n </div>\n }\n\n <p-divider align=\"center\" styleClass=\"my-5\"> Busquedas pendientes </p-divider>\n\n <p-button label=\"Buscar No publicadas\" icon=\"pi pi-database\" (onClick)=\"searchNotPublic()\" [loading]=\"loading()\" severity=\"secondary\"></p-button>\n <p-button label=\"Buscar no publicadas (new)\" icon=\"pi pi-database\" (onClick)=\"searchNotpublished()\" [loading]=\"loading()\" severity=\"secondary\"></p-button>\n <br />\n\n <br />\n\n @if (notPublishedResults()) {\n <div class=\"mt-4\">\n <p-table [value]=\"notPublishedResults().rows\" [tableStyle]=\"{ 'min-width': '50rem' }\">\n <ng-template pTemplate=\"header\">\n <tr>\n <th>ID</th>\n <th>Name</th>\n <th>Language</th>\n <th>Status</th>\n <th>Character Name</th>\n <th>Actions</th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\" let-row>\n <tr>\n <td>{{ row?._id }}</td>\n <td>{{ row?.name }}</td>\n <td>{{ row?.lang }}</td>\n <td>{{ row?.manageable?.status }}</td>\n <td>{{ row?.characterCard?.data?.name }}</td>\n <td>\n <a [href]=\"'/app/conversations/edit/' + row._id\" target=\"_blank\">\n <p-button icon=\"pi pi-pencil\" styleClass=\"p-button-rounded p-button-text\"></p-button>\n </a>\n </td>\n </tr>\n </ng-template>\n </p-table>\n\n <br />\n <br />\n </div>\n }\n</div>\n", styles: [""], dependencies: [{ 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.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],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"] }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "directive", type: i2$5.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i3$5.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: DividerModule }, { kind: "component", type: i2$4.Divider, selector: "p-divider", inputs: ["styleClass", "layout", "type", "align"] }, { kind: "ngmodule", type: MessageModule }, { kind: "component", type: i3$4.Message, selector: "p-message", inputs: ["severity", "text", "escape", "style", "styleClass", "closable", "icon", "closeIcon", "life", "showTransitionOptions", "hideTransitionOptions", "size", "variant", "motionOptions"], outputs: ["onClose"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i5.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: ToggleSwitchModule }, { kind: "component", type: i4$2.ToggleSwitch, selector: "p-toggleswitch, p-toggleSwitch, p-toggle-switch", inputs: ["styleClass", "tabindex", "inputId", "readonly", "trueValue", "falseValue", "ariaLabel", "size", "ariaLabelledBy", "autofocus"], outputs: ["onChange"] }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: i1$4.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "pipe", type: i2$1.JsonPipe, name: "json" }] }); }
8503
9041
  }
8504
9042
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CardsCreatorComponent, decorators: [{
8505
9043
  type: Component,
8506
9044
  args: [{ selector: 'app-cards-creator', standalone: true, imports: [ReactiveFormsModule, CommonModule, ButtonModule, InputTextModule, DividerModule, MessageModule, SelectModule, ToggleSwitchModule, TableModule], template: "<div>\n <h2 class=\"text-2xl font-bold mb-4\">Card Generation</h2>\n <p-message severity=\"secondary\"\n >Paso 1: Genearar una o varias tarjetas vacias con solo la idea, estas tiene estatus de pending. no lo cambies ser\u00E1 necesario en el paso 2.\n </p-message>\n\n <div class=\"grid\">\n <div class=\"col-12\">\n <form [formGroup]=\"cardsForm\" (ngSubmit)=\"generateCards()\">\n <div class=\"p-panel p-4\">\n <h3 class=\"text-xl font-semibold mb-3\">Generate Cards</h3>\n <p-message severity=\"info\">Generate one or more cards with an idea. Cards will be created with a 'pending' status.</p-message>\n\n <div class=\"field mt-4\">\n <label for=\"idea\">Idea</label>\n <input id=\"idea\" type=\"text\" pInputText formControlName=\"idea\" placeholder=\"e.g., 'Ordering food at a restaurant'\" class=\"w-full\" />\n </div>\n\n <div class=\"form-field mt-4\">\n <label for=\"lang\">Language <span pTooltip=\"Select the primary language for the conversation\">\u2139\uFE0F</span></label>\n <p-select\n id=\"lang\"\n [options]=\"languageOptions\"\n [filter]=\"true\"\n formControlName=\"langCode\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"'Select Language'\"\n styleClass=\"w-full\"></p-select>\n </div>\n\n <div class=\"field mt-4\">\n <label for=\"num-cards\">Number of Cards</label>\n <input id=\"num-cards\" type=\"number\" pInputText formControlName=\"numCards\" placeholder=\"e.g., '10'\" class=\"w-full\" />\n </div>\n\n <div class=\"flex flex-wrap gap-4 mt-4\">\n <div class=\"flex align-items-center\">\n <p-toggleSwitch formControlName=\"autosave\" inputId=\"autosave-switch\"></p-toggleSwitch>\n <label for=\"autosave-switch\" class=\"ml-2\"> Auto-save?</label>\n </div>\n <div class=\"flex align-items-center\">\n <p-toggleSwitch formControlName=\"doNotRepeat\" inputId=\"repeat-switch\"></p-toggleSwitch>\n <label for=\"repeat-switch\" class=\"ml-2\"> Do not repeat topics?</label>\n </div>\n </div>\n\n <div class=\"mt-4\">\n <p-button label=\"Generate Cards\" icon=\"pi pi-bolt\" type=\"submit\" [loading]=\"loading()\" [disabled]=\"cardsForm.invalid\"></p-button>\n </div>\n </div>\n </form>\n </div>\n </div>\n\n <p-divider align=\"center\" styleClass=\"my-5\">\n <span class=\"p-tag\">Maintenance</span>\n </p-divider>\n\n <!-- Maintenance Section -->\n <div class=\"grid\">\n <!-- Card Specific Maintenance -->\n <div class=\"col-12 md:col-6\">\n <div class=\"p-panel p-4\">\n <h3 class=\"text-xl font-semibold mb-3\">Card Specific Maintenance</h3>\n <div class=\"field\">\n <label for=\"cardId\">Card ID</label>\n <input\n id=\"cardId\"\n type=\"text\"\n pInputText\n [value]=\"cardId()\"\n (input)=\"cardId.set($any($event.target).value)\"\n placeholder=\"Enter Card ID\"\n class=\"w-full\" />\n </div>\n <div class=\"mt-4 flex gap-2\">\n <p-button label=\"Generate Image\" icon=\"pi pi-image\" (onClick)=\"generateImageForCard()\" [loading]=\"loading()\"></p-button>\n <p-button\n label=\"Generate Missing Data\"\n icon=\"pi pi-database\"\n (onClick)=\"generateMissingData()\"\n [loading]=\"loading()\"\n styleClass=\"p-button-secondary\"></p-button>\n </div>\n </div>\n </div>\n\n <!-- Batch Operations -->\n <div class=\"col-12 md:col-6\">\n <div class=\"p-panel p-4\">\n <h3 class=\"text-xl font-semibold mb-3\">Batch Operations</h3>\n <p>Run maintenance tasks on all pending cards.</p>\n <div class=\"mt-4 flex gap-2\">\n <p-button label=\"Complete Pending Cards\" icon=\"pi pi-check-square\" (onClick)=\"completePendingCards()\" [loading]=\"loading()\"></p-button>\n <p-button\n label=\"Generate Pending Images\"\n icon=\"pi pi-images\"\n (onClick)=\"generatePendingImages()\"\n [loading]=\"loading()\"\n styleClass=\"p-button-secondary\"></p-button>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Result Section -->\n @if (result()) {\n <div class=\"col-12 mt-4\">\n <div class=\"p-panel p-4\">\n <h3 class=\"text-xl font-semibold mb-3\">Result</h3>\n <pre>{{ result() | json }}</pre>\n </div>\n </div>\n }\n\n <p-divider align=\"center\" styleClass=\"my-5\"> Busquedas pendientes </p-divider>\n\n <p-button label=\"Buscar No publicadas\" icon=\"pi pi-database\" (onClick)=\"searchNotPublic()\" [loading]=\"loading()\" severity=\"secondary\"></p-button>\n <p-button label=\"Buscar no publicadas (new)\" icon=\"pi pi-database\" (onClick)=\"searchNotpublished()\" [loading]=\"loading()\" severity=\"secondary\"></p-button>\n <br />\n\n <br />\n\n @if (notPublishedResults()) {\n <div class=\"mt-4\">\n <p-table [value]=\"notPublishedResults().rows\" [tableStyle]=\"{ 'min-width': '50rem' }\">\n <ng-template pTemplate=\"header\">\n <tr>\n <th>ID</th>\n <th>Name</th>\n <th>Language</th>\n <th>Status</th>\n <th>Character Name</th>\n <th>Actions</th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\" let-row>\n <tr>\n <td>{{ row?._id }}</td>\n <td>{{ row?.name }}</td>\n <td>{{ row?.lang }}</td>\n <td>{{ row?.manageable?.status }}</td>\n <td>{{ row?.characterCard?.data?.name }}</td>\n <td>\n <a [href]=\"'/app/conversations/edit/' + row._id\" target=\"_blank\">\n <p-button icon=\"pi pi-pencil\" styleClass=\"p-button-rounded p-button-text\"></p-button>\n </a>\n </td>\n </tr>\n </ng-template>\n </p-table>\n\n <br />\n <br />\n </div>\n }\n</div>\n" }]
8507
9045
  }], ctorParameters: () => [] });
8508
9046
 
8509
- class ConversationRuleListComponent extends EntityBaseListComponent {
9047
+ class ConversationRuleListComponent extends EntityBaseListV2Component {
8510
9048
  constructor() {
8511
9049
  super(...arguments);
8512
9050
  this.entityCommunicationService = inject(ConversationRuleService);
@@ -8532,7 +9070,7 @@ class ConversationRuleListComponent extends EntityBaseListComponent {
8532
9070
  ];
8533
9071
  }
8534
9072
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ConversationRuleListComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
8535
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: ConversationRuleListComponent, isStandalone: true, selector: "app-conversationRule-list", usesInheritance: true, ngImport: i0, template: "@if (!onlyView()) {\n<p-button [icon]=\"viewType() === 'card' ? 'pi pi-table' : 'pi pi-list'\" label=\"Change View\" [link]=\"true\" (click)=\"toggleView()\" />\n}\n<div class=\"conversationRule-list-container\">\n <dc-filter-bar [isAdmin]=\"userService.isAdmin()\" [options]=\"filterBarOptions\" (onNew)=\"onNew()\" (onFilterAction)=\"doAction($event)\"></dc-filter-bar>\n\n @if (viewType() === 'card') {\n <div class=\"conversationRule-list-content\">\n @for (conversationRule of items(); track conversationRule.id) {\n <div class=\"card-source\">\n <div style=\"position: absolute; top: 4px; right: 4px; z-index: 1000\">\n <p-speeddial\n [model]=\"getCustomButtons(conversationRule)\"\n [radius]=\"70\"\n type=\"quarter-circle\"\n direction=\"down-left\"\n [buttonProps]=\"{ severity: 'primary', rounded: true, outlined: true }\" />\n </div>\n <p-card [header]=\"conversationRule.name\">\n <p class=\"m-0\">{{ conversationRule.description | slice : 0 : 250 }}...</p>\n <span>{{ conversationRule?.auditable?.updatedAt | date : 'dd/MM/yyyy HH:mm' }}</span>\n </p-card>\n </div>\n } @if (items().length === 0) {\n <p-card>\n <p>No conversationRules found</p>\n </p-card>\n }\n </div>\n } @else if ( viewType() === 'table'){\n\n <app-quick-table [tableData]=\"items()\"></app-quick-table>\n\n }\n\n <div class=\"paginator-container\">\n <p-paginator\n currentPageReportTemplate=\"{{ totalRecords() }} conversations\"\n [showCurrentPageReport]=\"true\"\n (onPageChange)=\"onPageChange($event)\"\n [first]=\"first()\"\n [rows]=\"rows()\"\n [totalRecords]=\"totalRecords()\"\n [rowsPerPageOptions]=\"[10, 20, 30]\">\n </p-paginator>\n </div>\n</div>\n", styles: [":host{display:block;height:100%}.conversationRule-list-container{display:flex;flex-direction:column;height:100%}.conversationRule-list-content{margin-top:10px;flex:1;overflow-y:auto;padding-bottom:10px}.card-source{margin-bottom:10px;position:relative}.paginator-container{margin-top:auto;padding-top:10px}\n"], dependencies: [{ kind: "ngmodule", type: CardModule }, { kind: "component", type: i2$6.Card, selector: "p-card", inputs: ["header", "subheader", "style", "styleClass"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: DCFilterBarComponent, selector: "dc-filter-bar", inputs: ["items", "options", "customFilters", "customSortOptions", "isAdmin", "persistenceKey"], outputs: ["onFilterAction", "onNew"] }, { kind: "ngmodule", type: SpeedDialModule }, { kind: "component", type: i3$7.SpeedDial, selector: "p-speeddial, p-speedDial, p-speed-dial", inputs: ["id", "model", "visible", "style", "className", "direction", "transitionDelay", "type", "radius", "mask", "disabled", "hideOnClickOutside", "buttonStyle", "buttonClassName", "maskStyle", "maskClassName", "showIcon", "hideIcon", "rotateAnimation", "ariaLabel", "ariaLabelledBy", "tooltipOptions", "buttonProps"], outputs: ["onVisibleChange", "visibleChange", "onClick", "onShow", "onHide"] }, { kind: "ngmodule", type: PaginatorModule }, { kind: "component", type: i4$3.Paginator, selector: "p-paginator", inputs: ["pageLinkSize", "styleClass", "alwaysShow", "dropdownAppendTo", "templateLeft", "templateRight", "dropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showFirstLastIcon", "totalRecords", "rows", "rowsPerPageOptions", "showJumpToPageDropdown", "showJumpToPageInput", "jumpToPageItemTemplate", "showPageLinks", "locale", "dropdownItemTemplate", "first", "appendTo"], outputs: ["onPageChange"] }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: QuickTableComponent, selector: "app-quick-table", inputs: ["columns", "tableData", "actions"], outputs: ["onAction"] }, { kind: "pipe", type: DatePipe, name: "date" }, { kind: "pipe", type: SlicePipe, name: "slice" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
9073
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: ConversationRuleListComponent, isStandalone: true, selector: "app-conversationRule-list", usesInheritance: true, ngImport: i0, template: "@if (!onlyView()) {\n<p-button [icon]=\"viewType() === 'card' ? 'pi pi-table' : 'pi pi-list'\" label=\"Change View\" [link]=\"true\" (click)=\"toggleView()\" />\n}\n<div class=\"conversationRule-list-container\">\n <dc-filter-bar [isAdmin]=\"userService.isAdmin()\" [options]=\"filterBarOptions\" (onNew)=\"onNew()\" (onFilterAction)=\"doAction($event)\"></dc-filter-bar>\n\n @if (viewType() === 'card') {\n <div class=\"conversationRule-list-content\">\n @for (conversationRule of items(); track conversationRule.id) {\n <div class=\"card-source\">\n <div style=\"position: absolute; top: 4px; right: 4px; z-index: 1000\">\n <p-speeddial\n [model]=\"getCustomButtons(conversationRule)\"\n [radius]=\"70\"\n type=\"quarter-circle\"\n direction=\"down-left\"\n [buttonProps]=\"{ severity: 'primary', rounded: true, outlined: true }\" />\n </div>\n <p-card [header]=\"conversationRule.name\">\n <p class=\"m-0\">{{ conversationRule.description | slice : 0 : 250 }}...</p>\n <span>{{ conversationRule?.auditable?.updatedAt | date : 'dd/MM/yyyy HH:mm' }}</span>\n </p-card>\n </div>\n } @if (items().length === 0) {\n <p-card>\n <p>No conversationRules found</p>\n </p-card>\n }\n </div>\n } @else if ( viewType() === 'table'){\n\n <app-quick-table [tableData]=\"items()\"></app-quick-table>\n\n }\n\n <div class=\"paginator-container\">\n <p-paginator\n currentPageReportTemplate=\"{{ totalRecords() }} conversations\"\n [showCurrentPageReport]=\"true\"\n (onPageChange)=\"onPageChange($event)\"\n [first]=\"first()\"\n [rows]=\"rows()\"\n [totalRecords]=\"totalRecords()\"\n [rowsPerPageOptions]=\"[10, 20, 30]\">\n </p-paginator>\n </div>\n</div>\n", styles: [":host{display:block;height:100%}.conversationRule-list-container{display:flex;flex-direction:column;height:100%}.conversationRule-list-content{margin-top:10px;flex:1;overflow-y:auto;padding-bottom:10px}.card-source{margin-bottom:10px;position:relative}.paginator-container{margin-top:auto;padding-top:10px}\n"], dependencies: [{ kind: "ngmodule", type: CardModule }, { kind: "component", type: i2$7.Card, selector: "p-card", inputs: ["header", "subheader", "style", "styleClass"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: DCFilterBarComponent, selector: "dc-filter-bar", inputs: ["items", "options", "customFilters", "customSortOptions", "isAdmin", "persistenceKey"], outputs: ["onFilterAction", "onNew"] }, { kind: "ngmodule", type: SpeedDialModule }, { kind: "component", type: i3$7.SpeedDial, selector: "p-speeddial, p-speedDial, p-speed-dial", inputs: ["id", "model", "visible", "style", "className", "direction", "transitionDelay", "type", "radius", "mask", "disabled", "hideOnClickOutside", "buttonStyle", "buttonClassName", "maskStyle", "maskClassName", "showIcon", "hideIcon", "rotateAnimation", "ariaLabel", "ariaLabelledBy", "tooltipOptions", "buttonProps"], outputs: ["onVisibleChange", "visibleChange", "onClick", "onShow", "onHide"] }, { kind: "ngmodule", type: PaginatorModule }, { kind: "component", type: i4$4.Paginator, selector: "p-paginator", inputs: ["pageLinkSize", "styleClass", "alwaysShow", "dropdownAppendTo", "templateLeft", "templateRight", "dropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showFirstLastIcon", "totalRecords", "rows", "rowsPerPageOptions", "showJumpToPageDropdown", "showJumpToPageInput", "jumpToPageItemTemplate", "showPageLinks", "locale", "dropdownItemTemplate", "first", "appendTo"], outputs: ["onPageChange"] }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: QuickTableComponent, selector: "app-quick-table", inputs: ["columns", "tableData", "actions"], outputs: ["onAction"] }, { kind: "pipe", type: DatePipe, name: "date" }, { kind: "pipe", type: SlicePipe, name: "slice" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
8536
9074
  }
8537
9075
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ConversationRuleListComponent, decorators: [{
8538
9076
  type: Component,
@@ -8613,7 +9151,7 @@ class ConversationRuleFormComponent extends EntityBaseSignalFormComponent {
8613
9151
  this.relationPopupSelector.push(relation);
8614
9152
  }
8615
9153
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ConversationRuleFormComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
8616
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: ConversationRuleFormComponent, isStandalone: true, selector: "app-conversation-rule-form", usesInheritance: true, ngImport: i0, template: "<h3>ConversationRules Form</h3>\n\n<div class=\"source-form-card\">\n <p-card [header]=\"entityId() ? 'Edit Conversation Rule' : 'New Conversation Rule'\">\n <div style=\"display: flex; gap: 10px\">\n <div style=\"width: 100%\">\n\n <div class=\"form-field\">\n <label for=\"name\" class=\"block\">Name</label>\n <input pInputText id=\"name\" type=\"text\"\n [formField]=\"form.name\"\n placeholder=\"Enter rule name\" />\n @if (form.name().touched() && form.name().invalid()) {\n <small class=\"p-error\">{{ form.name().errors()[0].message }}</small>\n }\n </div>\n\n <div class=\"form-field\">\n <label for=\"description\" class=\"block\">Description</label>\n <textarea id=\"description\" pTextarea rows=\"1\" class=\"w-full\"\n [ngModel]=\"entityForm().description\"\n (ngModelChange)=\"entityForm.update(m => ({ ...m, description: $event }))\"\n placeholder=\"Enter description\"></textarea>\n </div>\n\n <div class=\"form-field\">\n <label for=\"rule\" class=\"block\">Rule</label>\n <textarea id=\"rule\" pTextarea rows=\"3\" class=\"w-full\"\n [ngModel]=\"entityForm().rule\"\n (ngModelChange)=\"entityForm.update(m => ({ ...m, rule: $event }))\"\n placeholder=\"Enter rule content\"></textarea>\n </div>\n\n </div>\n </div>\n\n <div style=\"display: flex; justify-content: flex-end\">\n <p-button (click)=\"save()\" label=\"Save Rule\" [disabled]=\"!isValid()\" icon=\"pi pi-check\" iconPos=\"right\"></p-button>\n </div>\n\n <p-dialog header=\"Search for relation\" [(visible)]=\"isDialogVisible\" [modal]=\"true\" [style]=\"{ width: '50vw' }\" draggable=\"false\">\n <app-conversationRule-list [onlyView]=\"true\" (onSelect)=\"handleRelationSelection($event)\"></app-conversationRule-list>\n </p-dialog>\n </p-card>\n</div>\n", styles: [":host{display:block;padding:1rem}.source-form-card{max-width:800px;margin:0 auto}.form-field{margin-bottom:1.5rem;display:flex;flex-direction:column}.form-field label{margin-bottom:.5rem;font-weight:500;color:#495057}.form-field input,.form-field textarea,.form-field ::ng-deep .p-element{margin-top:.25rem}:host ::ng-deep .p-card .p-card-content>div:last-child{margin-top:1.5rem;display:flex;justify-content:flex-end}:host ::ng-deep .p-card .p-card-header{background-color:#f8f9fa;padding:1rem;border-bottom:1px solid #dee2e6}h3{color:#495057;margin-bottom:1.5rem;text-align:center}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { 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.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: CardModule }, { kind: "component", type: i2$6.Card, selector: "p-card", inputs: ["header", "subheader", "style", "styleClass"] }, { kind: "ngmodule", type: TextareaModule }, { kind: "directive", type: i3$1.Textarea, selector: "[pTextarea], [pInputTextarea]", inputs: ["pTextareaPT", "pTextareaUnstyled", "autoResize", "pSize", "variant", "fluid", "invalid"], outputs: ["onResize"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: SelectModule }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i3$5.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: ChipModule }, { kind: "ngmodule", type: TooltipModule }, { kind: "ngmodule", type: DialogModule }, { kind: "component", type: i5$1.Dialog, selector: "p-dialog", inputs: ["hostName", "header", "draggable", "resizable", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "maskMotionOptions", "motionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "appendTo", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "component", type: ConversationRuleListComponent, selector: "app-conversationRule-list" }, { kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"], exportAs: ["formField"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
9154
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: ConversationRuleFormComponent, isStandalone: true, selector: "app-conversation-rule-form", usesInheritance: true, ngImport: i0, template: "<h3>ConversationRules Form</h3>\n\n<div class=\"source-form-card\">\n <p-card [header]=\"entityId() ? 'Edit Conversation Rule' : 'New Conversation Rule'\">\n <div style=\"display: flex; gap: 10px\">\n <div style=\"width: 100%\">\n\n <div class=\"form-field\">\n <label for=\"name\" class=\"block\">Name</label>\n <input pInputText id=\"name\" type=\"text\"\n [formField]=\"form.name\"\n placeholder=\"Enter rule name\" />\n @if (form.name().touched() && form.name().invalid()) {\n <small class=\"p-error\">{{ form.name().errors()[0].message }}</small>\n }\n </div>\n\n <div class=\"form-field\">\n <label for=\"description\" class=\"block\">Description</label>\n <textarea id=\"description\" pTextarea rows=\"1\" class=\"w-full\"\n [ngModel]=\"entityForm().description\"\n (ngModelChange)=\"entityForm.update(m => ({ ...m, description: $event }))\"\n placeholder=\"Enter description\"></textarea>\n </div>\n\n <div class=\"form-field\">\n <label for=\"rule\" class=\"block\">Rule</label>\n <textarea id=\"rule\" pTextarea rows=\"3\" class=\"w-full\"\n [ngModel]=\"entityForm().rule\"\n (ngModelChange)=\"entityForm.update(m => ({ ...m, rule: $event }))\"\n placeholder=\"Enter rule content\"></textarea>\n </div>\n\n </div>\n </div>\n\n <div style=\"display: flex; justify-content: flex-end\">\n <p-button (click)=\"save()\" label=\"Save Rule\" [disabled]=\"!isValid()\" icon=\"pi pi-check\" iconPos=\"right\"></p-button>\n </div>\n\n <p-dialog header=\"Search for relation\" [(visible)]=\"isDialogVisible\" [modal]=\"true\" [style]=\"{ width: '50vw' }\" draggable=\"false\">\n <app-conversationRule-list [onlyView]=\"true\" (onSelect)=\"handleRelationSelection($event)\"></app-conversationRule-list>\n </p-dialog>\n </p-card>\n</div>\n", styles: [":host{display:block;padding:1rem}.source-form-card{max-width:800px;margin:0 auto}.form-field{margin-bottom:1.5rem;display:flex;flex-direction:column}.form-field label{margin-bottom:.5rem;font-weight:500;color:#495057}.form-field input,.form-field textarea,.form-field ::ng-deep .p-element{margin-top:.25rem}:host ::ng-deep .p-card .p-card-content>div:last-child{margin-top:1.5rem;display:flex;justify-content:flex-end}:host ::ng-deep .p-card .p-card-header{background-color:#f8f9fa;padding:1rem;border-bottom:1px solid #dee2e6}h3{color:#495057;margin-bottom:1.5rem;text-align:center}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { 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.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: CardModule }, { kind: "component", type: i2$7.Card, selector: "p-card", inputs: ["header", "subheader", "style", "styleClass"] }, { kind: "ngmodule", type: TextareaModule }, { kind: "directive", type: i3$1.Textarea, selector: "[pTextarea], [pInputTextarea]", inputs: ["pTextareaPT", "pTextareaUnstyled", "autoResize", "pSize", "variant", "fluid", "invalid"], outputs: ["onResize"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: SelectModule }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i3$5.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: ChipModule }, { kind: "ngmodule", type: TooltipModule }, { kind: "ngmodule", type: DialogModule }, { kind: "component", type: i5$1.Dialog, selector: "p-dialog", inputs: ["hostName", "header", "draggable", "resizable", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "maskMotionOptions", "motionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "appendTo", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "component", type: ConversationRuleListComponent, selector: "app-conversationRule-list" }, { kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"], exportAs: ["formField"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
8617
9155
  }
8618
9156
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ConversationRuleFormComponent, decorators: [{
8619
9157
  type: Component,
@@ -8660,7 +9198,7 @@ const GENERICS_ROUTES = [
8660
9198
  class ConversationRulesComponent {
8661
9199
  static { this.routes = GENERICS_ROUTES; }
8662
9200
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ConversationRulesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
8663
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.5", type: ConversationRulesComponent, isStandalone: true, selector: "app-conversationRules", ngImport: i0, template: "<router-outlet />\n", styles: [":host{display:block;height:100%}\n"], dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$7.RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
9201
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.5", type: ConversationRulesComponent, isStandalone: true, selector: "app-conversationRules", ngImport: i0, template: "<router-outlet />\n", styles: [":host{display:block;height:100%}\n"], dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$5.RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
8664
9202
  }
8665
9203
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ConversationRulesComponent, decorators: [{
8666
9204
  type: Component,
@@ -8703,7 +9241,7 @@ class CardRouteListComponent extends EntityBaseListV2Component {
8703
9241
  ];
8704
9242
  }
8705
9243
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CardRouteListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
8706
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: CardRouteListComponent, isStandalone: true, selector: "app-card-route-list", host: { classAttribute: "block h-full" }, usesInheritance: true, ngImport: i0, template: "<div class=\"flex flex-col h-full\">\n <dc-filter-bar [isAdmin]=\"userService.isAdmin()\" [options]=\"filterBarOptions\" (onNew)=\"onNew()\" (onFilterAction)=\"doAction($event)\"></dc-filter-bar>\n\n @if (viewType() === 'card') {\n <div class=\"mt-2.5 flex-1 overflow-y-auto pb-2.5\">\n @if (!isLoading()) { @for (generic of items(); track generic.id) {\n <div class=\"mb-2.5 relative\">\n <div class=\"absolute top-1 right-1 z-[1000]\">\n <p-speeddial\n [model]=\"getCustomButtons(generic)\"\n [radius]=\"70\"\n type=\"quarter-circle\"\n direction=\"down-left\"\n [buttonProps]=\"{ severity: 'primary', rounded: true, outlined: true }\" />\n </div>\n <p-card (click)=\"doAction({item: generic, action: 'view'})\" class=\"cursor-pointer\">\n <div class=\"flex gap-4\">\n <div class=\"w-24 h-24 flex-shrink-0 overflow-hidden rounded-lg bg-slate-100 border border-slate-200\">\n @if (generic.assets?.image?.url) {\n <img [src]=\"generic.assets.image.url\" class=\"w-full h-full object-cover\" alt=\"Card Route Image\" />\n } @else {\n <div class=\"w-full h-full flex items-center justify-center text-slate-300\">\n <i class=\"pi pi-image text-3xl\"></i>\n </div>\n }\n </div>\n <div class=\"flex-1 min-w-0\">\n <div class=\"flex justify-between items-start mb-1\">\n <h3 class=\"m-0 text-lg font-bold text-slate-800 truncate\">{{ generic.name }}</h3>\n </div>\n <p class=\"m-0 text-sm text-slate-500 line-clamp-2 leading-relaxed mb-2\">\n {{ generic.description || 'Sin descripci\u00F3n' }}\n </p>\n <div class=\"flex items-center gap-3\">\n <span class=\"text-[10px] uppercase tracking-wider font-semibold px-2 py-0.5 rounded-full\" \n [class]=\"generic.isActive ? 'bg-green-100 text-green-700' : 'bg-slate-100 text-slate-500'\">\n {{ generic.isActive ? 'Activo' : 'Inactivo' }}\n </span>\n <span class=\"text-xs text-slate-400\">\n <i class=\"pi pi-calendar text-[10px] mr-1\"></i>\n {{ generic?.auditable?.updatedAt | date : 'dd/MM/yyyy HH:mm' }}\n </span>\n </div>\n </div>\n </div>\n </p-card>\n </div>\n } @if (items().length === 0) {\n <p-card>\n <p>No generics found</p>\n </p-card>\n } } @else { @for (i of [1,2,3,4,5,6]; track i) {\n <p-card>\n <ng-template pTemplate=\"header\">\n <div class=\"p-4\">\n <p-skeleton width=\"80%\" height=\"1.5rem\" />\n </div>\n </ng-template>\n <div class=\"flex gap-2.5\">\n <p-skeleton width=\"120px\" height=\"120px\" />\n <div class=\"flex-1\">\n <p-skeleton width=\"100%\" height=\"1rem\" styleClass=\"mb-2\" />\n <p-skeleton width=\"90%\" height=\"1rem\" styleClass=\"mb-2\" />\n <p-skeleton width=\"60%\" height=\"1rem\" />\n </div>\n </div>\n <p-skeleton width=\"40%\" height=\"1rem\" styleClass=\"mt-2\" />\n </p-card>\n } }\n </div>\n } @else if ( viewType() === 'table'){\n\n <app-quick-table [tableData]=\"items()\"></app-quick-table>\n\n }\n\n <div class=\"mt-auto pt-2.5\">\n <p-paginator\n currentPageReportTemplate=\"{{ totalRecords() }} conversations\"\n [showCurrentPageReport]=\"true\"\n (onPageChange)=\"onPageChange($event)\"\n [first]=\"first()\"\n [rows]=\"rows()\"\n [totalRecords]=\"totalRecords()\"\n [rowsPerPageOptions]=\"[10, 20, 30]\">\n </p-paginator>\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CardModule }, { kind: "component", type: i2$6.Card, selector: "p-card", inputs: ["header", "subheader", "style", "styleClass"] }, { kind: "directive", type: i2$4.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: DCFilterBarComponent, selector: "dc-filter-bar", inputs: ["items", "options", "customFilters", "customSortOptions", "isAdmin", "persistenceKey"], outputs: ["onFilterAction", "onNew"] }, { kind: "ngmodule", type: SpeedDialModule }, { kind: "component", type: i3$7.SpeedDial, selector: "p-speeddial, p-speedDial, p-speed-dial", inputs: ["id", "model", "visible", "style", "className", "direction", "transitionDelay", "type", "radius", "mask", "disabled", "hideOnClickOutside", "buttonStyle", "buttonClassName", "maskStyle", "maskClassName", "showIcon", "hideIcon", "rotateAnimation", "ariaLabel", "ariaLabelledBy", "tooltipOptions", "buttonProps"], outputs: ["onVisibleChange", "visibleChange", "onClick", "onShow", "onHide"] }, { kind: "ngmodule", type: PaginatorModule }, { kind: "component", type: i4$3.Paginator, selector: "p-paginator", inputs: ["pageLinkSize", "styleClass", "alwaysShow", "dropdownAppendTo", "templateLeft", "templateRight", "dropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showFirstLastIcon", "totalRecords", "rows", "rowsPerPageOptions", "showJumpToPageDropdown", "showJumpToPageInput", "jumpToPageItemTemplate", "showPageLinks", "locale", "dropdownItemTemplate", "first", "appendTo"], outputs: ["onPageChange"] }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: QuickTableComponent, selector: "app-quick-table", inputs: ["columns", "tableData", "actions"], outputs: ["onAction"] }, { kind: "component", type: Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "pipe", type: DatePipe, name: "date" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
9244
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: CardRouteListComponent, isStandalone: true, selector: "app-card-route-list", host: { classAttribute: "block h-full" }, usesInheritance: true, ngImport: i0, template: "<div class=\"flex flex-col h-full\">\n <dc-filter-bar [isAdmin]=\"userService.isAdmin()\" [options]=\"filterBarOptions\" (onNew)=\"onNew()\" (onFilterAction)=\"doAction($event)\"></dc-filter-bar>\n\n @if (viewType() === 'card') {\n <div class=\"mt-2.5 flex-1 overflow-y-auto pb-2.5\">\n @if (!isLoading()) { @for (generic of items(); track generic.id) {\n <div class=\"mb-2.5 relative\">\n <div class=\"absolute top-1 right-1 z-[1000]\">\n <p-speeddial\n [model]=\"getCustomButtons(generic)\"\n [radius]=\"70\"\n type=\"quarter-circle\"\n direction=\"down-left\"\n [buttonProps]=\"{ severity: 'primary', rounded: true, outlined: true }\" />\n </div>\n <p-card (click)=\"doAction({item: generic, action: 'view'})\" class=\"cursor-pointer\">\n <div class=\"flex gap-4\">\n <div class=\"w-24 h-24 flex-shrink-0 overflow-hidden rounded-lg bg-slate-100 border border-slate-200\">\n @if (generic.assets?.image?.url) {\n <img [src]=\"generic.assets.image.url\" class=\"w-full h-full object-cover\" alt=\"Card Route Image\" />\n } @else {\n <div class=\"w-full h-full flex items-center justify-center text-slate-300\">\n <i class=\"pi pi-image text-3xl\"></i>\n </div>\n }\n </div>\n <div class=\"flex-1 min-w-0\">\n <div class=\"flex justify-between items-start mb-1\">\n <h3 class=\"m-0 text-lg font-bold text-slate-800 truncate\">{{ generic.name }}</h3>\n </div>\n <p class=\"m-0 text-sm text-slate-500 line-clamp-2 leading-relaxed mb-2\">\n {{ generic.description || 'Sin descripci\u00F3n' }}\n </p>\n <div class=\"flex items-center gap-3\">\n <span class=\"text-[10px] uppercase tracking-wider font-semibold px-2 py-0.5 rounded-full\" \n [class]=\"generic.isActive ? 'bg-green-100 text-green-700' : 'bg-slate-100 text-slate-500'\">\n {{ generic.isActive ? 'Activo' : 'Inactivo' }}\n </span>\n <span class=\"text-xs text-slate-400\">\n <i class=\"pi pi-calendar text-[10px] mr-1\"></i>\n {{ generic?.auditable?.updatedAt | date : 'dd/MM/yyyy HH:mm' }}\n </span>\n </div>\n </div>\n </div>\n </p-card>\n </div>\n } @if (items().length === 0) {\n <p-card>\n <p>No generics found</p>\n </p-card>\n } } @else { @for (i of [1,2,3,4,5,6]; track i) {\n <p-card>\n <ng-template pTemplate=\"header\">\n <div class=\"p-4\">\n <p-skeleton width=\"80%\" height=\"1.5rem\" />\n </div>\n </ng-template>\n <div class=\"flex gap-2.5\">\n <p-skeleton width=\"120px\" height=\"120px\" />\n <div class=\"flex-1\">\n <p-skeleton width=\"100%\" height=\"1rem\" styleClass=\"mb-2\" />\n <p-skeleton width=\"90%\" height=\"1rem\" styleClass=\"mb-2\" />\n <p-skeleton width=\"60%\" height=\"1rem\" />\n </div>\n </div>\n <p-skeleton width=\"40%\" height=\"1rem\" styleClass=\"mt-2\" />\n </p-card>\n } }\n </div>\n } @else if ( viewType() === 'table'){\n\n <app-quick-table [tableData]=\"items()\"></app-quick-table>\n\n }\n\n <div class=\"mt-auto pt-2.5\">\n <p-paginator\n currentPageReportTemplate=\"{{ totalRecords() }} conversations\"\n [showCurrentPageReport]=\"true\"\n (onPageChange)=\"onPageChange($event)\"\n [first]=\"first()\"\n [rows]=\"rows()\"\n [totalRecords]=\"totalRecords()\"\n [rowsPerPageOptions]=\"[10, 20, 30]\">\n </p-paginator>\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CardModule }, { kind: "component", type: i2$7.Card, selector: "p-card", inputs: ["header", "subheader", "style", "styleClass"] }, { kind: "directive", type: i2$5.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: DCFilterBarComponent, selector: "dc-filter-bar", inputs: ["items", "options", "customFilters", "customSortOptions", "isAdmin", "persistenceKey"], outputs: ["onFilterAction", "onNew"] }, { kind: "ngmodule", type: SpeedDialModule }, { kind: "component", type: i3$7.SpeedDial, selector: "p-speeddial, p-speedDial, p-speed-dial", inputs: ["id", "model", "visible", "style", "className", "direction", "transitionDelay", "type", "radius", "mask", "disabled", "hideOnClickOutside", "buttonStyle", "buttonClassName", "maskStyle", "maskClassName", "showIcon", "hideIcon", "rotateAnimation", "ariaLabel", "ariaLabelledBy", "tooltipOptions", "buttonProps"], outputs: ["onVisibleChange", "visibleChange", "onClick", "onShow", "onHide"] }, { kind: "ngmodule", type: PaginatorModule }, { kind: "component", type: i4$4.Paginator, selector: "p-paginator", inputs: ["pageLinkSize", "styleClass", "alwaysShow", "dropdownAppendTo", "templateLeft", "templateRight", "dropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showFirstLastIcon", "totalRecords", "rows", "rowsPerPageOptions", "showJumpToPageDropdown", "showJumpToPageInput", "jumpToPageItemTemplate", "showPageLinks", "locale", "dropdownItemTemplate", "first", "appendTo"], outputs: ["onPageChange"] }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: QuickTableComponent, selector: "app-quick-table", inputs: ["columns", "tableData", "actions"], outputs: ["onAction"] }, { kind: "component", type: Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "pipe", type: DatePipe, name: "date" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
8707
9245
  }
8708
9246
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CardRouteListComponent, decorators: [{
8709
9247
  type: Component,
@@ -8720,7 +9258,7 @@ class CardRouteDetailComponent extends EntityBaseDetailComponent {
8720
9258
  this.route = inject(ActivatedRoute);
8721
9259
  }
8722
9260
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CardRouteDetailComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
8723
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: CardRouteDetailComponent, isStandalone: true, selector: "app-card-route-detail", usesInheritance: true, ngImport: i0, template: "@if (isLoading()) {\n <div class=\"loading-wrapper\">\n <p-progressSpinner strokeWidth=\"3\" />\n </div>\n}\n\n@if (entity(); as cardRoute) {\n <div class=\"route-detail\">\n\n <!-- Header -->\n <div class=\"route-header\">\n <div class=\"header-content\">\n @if (cardRoute.assets?.image?.url) {\n <div class=\"route-image-wrapper\">\n <img [src]=\"cardRoute.assets.image.url\" [alt]=\"cardRoute.name\" class=\"route-image\" />\n </div>\n }\n <div class=\"header-text\">\n <div class=\"header-title-row\">\n <h1 class=\"route-title\">{{ cardRoute.name }}</h1>\n <p-tag\n [value]=\"cardRoute.isActive ? 'Active' : 'Inactive'\"\n [severity]=\"cardRoute.isActive ? 'success' : 'danger'\"\n />\n </div>\n @if (cardRoute.description) {\n <p class=\"route-description\">{{ cardRoute.description }}</p>\n }\n @if (cardRoute.tags?.length) {\n <div class=\"tags-row\">\n @for (tag of cardRoute.tags; track tag) {\n <p-tag [value]=\"tag\" severity=\"secondary\" />\n }\n </div>\n }\n </div>\n\n </div>\n </div>\n\n <!-- Steps Timeline -->\n <div class=\"steps-section\">\n <div class=\"steps-header\">\n <h2 class=\"steps-title\">\n <i class=\"pi pi-list-check\"></i>\n Learning Path\n </h2>\n <span class=\"steps-count\">{{ cardRoute.steps?.length ?? 0 }} steps</span>\n </div>\n\n @if (cardRoute.steps?.length) {\n <div class=\"steps-timeline\">\n @for (step of cardRoute.steps; track step.order; let i = $index; let last = $last) {\n <div class=\"step-row\" [class.step-row--right]=\"i % 2 === 1\">\n\n <!-- Left side -->\n <div class=\"step-side step-side--left\">\n @if (i % 2 === 0) {\n <div class=\"step-content\">\n <div class=\"step-avatar-wrapper\">\n @if (step.agentCard.imageUrl) {\n <img [src]=\"step.agentCard.imageUrl\" [alt]=\"step.agentCard.name\" class=\"step-avatar\" />\n } @else {\n <div class=\"step-avatar step-avatar-placeholder\"><i class=\"pi pi-robot\"></i></div>\n }\n <span class=\"step-avatar-name\">{{ step.name ?? step.agentCard.name }}</span>\n </div>\n <div class=\"step-label\">\n @if (step.passCondition) {\n <span class=\"pass-condition\"><i class=\"pi pi-check-circle\"></i> {{ step.passCondition.type }}</span>\n }\n </div>\n </div>\n }\n </div>\n\n <!-- Center line + badge -->\n <div class=\"step-center\">\n @if (!last) { <div class=\"center-line center-line--top\"></div> }\n <div class=\"step-order-badge\">{{ step.order }}</div>\n @if (!last) { <div class=\"center-line center-line--bottom\"></div> }\n </div>\n\n <!-- Right side -->\n <div class=\"step-side step-side--right\">\n @if (i % 2 === 1) {\n <div class=\"step-content\">\n <div class=\"step-avatar-wrapper\">\n @if (step.agentCard.imageUrl) {\n <img [src]=\"step.agentCard.imageUrl\" [alt]=\"step.agentCard.name\" class=\"step-avatar\" />\n } @else {\n <div class=\"step-avatar step-avatar-placeholder\"><i class=\"pi pi-robot\"></i></div>\n }\n <span class=\"step-avatar-name\">{{ step.name ?? step.agentCard.name }}</span>\n </div>\n <div class=\"step-label\">\n @if (step.passCondition) {\n <span class=\"pass-condition\"><i class=\"pi pi-check-circle\"></i> {{ step.passCondition.type }}</span>\n }\n </div>\n </div>\n }\n </div>\n\n </div>\n }\n </div>\n } @else {\n <div class=\"empty-steps\">\n <i class=\"pi pi-inbox\"></i>\n <p>No steps defined yet.</p>\n </div>\n }\n </div>\n\n <!-- Footer -->\n <div class=\"route-footer\">\n <small>\n <i class=\"pi pi-clock\"></i>\n Updated: {{ cardRoute.auditable?.updatedAt | date: 'dd/MM/yyyy HH:mm' }}\n </small>\n </div>\n\n </div>\n}\n", styles: [".loading-wrapper{display:flex;justify-content:center;padding:3rem}.route-detail{max-width:860px;margin:0 auto;padding:1.5rem;display:flex;flex-direction:column;gap:1.5rem}.route-header{background:var(--surface-card);border:1px solid var(--surface-border);border-radius:12px;padding:1.5rem}.route-image-wrapper{width:120px;height:120px;border-radius:12px;overflow:hidden;border:1px solid var(--surface-border);flex-shrink:0}.route-image{width:100%;height:100%;object-fit:cover}.header-content{display:flex;justify-content:space-between;align-items:flex-start;gap:1rem;flex-wrap:wrap}.header-text{flex:1;min-width:280px}.header-title-row{display:flex;align-items:center;gap:.75rem;flex-wrap:wrap;margin-bottom:.5rem}.route-title{font-size:1.6rem;font-weight:700;margin:0;color:var(--text-color)}.route-description{color:var(--text-color-secondary);margin:0 0 .75rem;line-height:1.5}.tags-row{display:flex;gap:.4rem;flex-wrap:wrap}.header-actions{display:flex;gap:.5rem;flex-shrink:0}.steps-section{display:flex;flex-direction:column;gap:1rem}.steps-header{display:flex;align-items:center;justify-content:space-between}.steps-title{font-size:1.1rem;font-weight:600;margin:0;display:flex;align-items:center;gap:.5rem;color:var(--text-color)}.steps-count{font-size:.85rem;color:var(--text-color-secondary);background:var(--surface-ground);border:1px solid var(--surface-border);border-radius:999px;padding:.2rem .75rem}.steps-timeline{display:flex;flex-direction:column}.step-row{display:grid;grid-template-columns:1fr 48px 1fr;align-items:stretch;min-height:200px}.step-side{display:flex;align-items:center}.step-side--left{justify-content:flex-end;padding-right:1.5rem}.step-side--right{justify-content:flex-start;padding-left:1.5rem}.step-content{display:flex;flex-direction:column;align-items:center;gap:.6rem;max-width:180px;text-align:center}.step-avatar-wrapper{position:relative;width:160px;height:160px;flex-shrink:0}.step-avatar-name{position:absolute;bottom:0;left:0;right:0;background:linear-gradient(transparent,#000000b8);color:#fff;font-size:.78rem;font-weight:600;text-align:center;padding:1rem .4rem .45rem;border-radius:0 0 50% 50%;line-height:1.2;pointer-events:none}.step-avatar{width:160px;height:160px;border-radius:50%;object-fit:cover;object-position:top;border:3px solid var(--primary-color);box-shadow:0 4px 16px #0000001f;flex-shrink:0}.step-avatar-placeholder{width:160px;height:160px;border-radius:50%;background:var(--surface-ground);border:3px solid var(--surface-border);display:flex;align-items:center;justify-content:center;color:var(--text-color-secondary);font-size:3rem;flex-shrink:0}.step-label{display:flex;flex-direction:column;align-items:center;gap:.25rem}.step-name{font-size:.95rem;font-weight:600;color:var(--text-color);line-height:1.3}.step-center{display:flex;flex-direction:column;align-items:center;justify-content:center}.center-line--top,.center-line--bottom{width:2px;flex:1;background:var(--surface-border)}.step-order-badge{width:2rem;height:2rem;border-radius:50%;background:var(--primary-color);color:var(--primary-color-text);display:flex;align-items:center;justify-content:center;font-weight:700;font-size:.85rem;flex-shrink:0;z-index:1}.pass-condition{display:flex;align-items:center;gap:.25rem;font-size:.75rem;color:var(--green-500)}.empty-steps{display:flex;flex-direction:column;align-items:center;padding:2.5rem;color:var(--text-color-secondary);gap:.5rem;background:var(--surface-ground);border-radius:10px;border:1px dashed var(--surface-border)}.empty-steps i{font-size:2rem}.route-footer{color:var(--text-color-secondary);display:flex;align-items:center;gap:.4rem;font-size:.8rem}.route-footer small{display:flex;align-items:center;gap:.35rem}\n"], dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "ngmodule", type: TagModule }, { kind: "component", type: i1$4.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "ngmodule", type: ProgressSpinnerModule }, { kind: "component", type: i3$3.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "pipe", type: DatePipe, name: "date" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
9261
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: CardRouteDetailComponent, isStandalone: true, selector: "app-card-route-detail", usesInheritance: true, ngImport: i0, template: "@if (isLoading()) {\n <div class=\"loading-wrapper\">\n <p-progressSpinner strokeWidth=\"3\" />\n </div>\n}\n\n@if (entity(); as cardRoute) {\n <div class=\"route-detail\">\n\n <!-- Header -->\n <div class=\"route-header\">\n <div class=\"header-content\">\n @if (cardRoute.assets?.image?.url) {\n <div class=\"route-image-wrapper\">\n <img [src]=\"cardRoute.assets.image.url\" [alt]=\"cardRoute.name\" class=\"route-image\" />\n </div>\n }\n <div class=\"header-text\">\n <div class=\"header-title-row\">\n <h1 class=\"route-title\">{{ cardRoute.name }}</h1>\n <p-tag\n [value]=\"cardRoute.isActive ? 'Active' : 'Inactive'\"\n [severity]=\"cardRoute.isActive ? 'success' : 'danger'\"\n />\n </div>\n @if (cardRoute.description) {\n <p class=\"route-description\">{{ cardRoute.description }}</p>\n }\n @if (cardRoute.tags?.length) {\n <div class=\"tags-row\">\n @for (tag of cardRoute.tags; track tag) {\n <p-tag [value]=\"tag\" severity=\"secondary\" />\n }\n </div>\n }\n </div>\n\n </div>\n </div>\n\n <!-- Steps Timeline -->\n <div class=\"steps-section\">\n <div class=\"steps-header\">\n <h2 class=\"steps-title\">\n <i class=\"pi pi-list-check\"></i>\n Learning Path\n </h2>\n <span class=\"steps-count\">{{ cardRoute.steps?.length ?? 0 }} steps</span>\n </div>\n\n @if (cardRoute.steps?.length) {\n <div class=\"steps-timeline\">\n @for (step of cardRoute.steps; track step.order; let i = $index; let last = $last) {\n <div class=\"step-row\" [class.step-row--right]=\"i % 2 === 1\">\n\n <!-- Left side -->\n <div class=\"step-side step-side--left\">\n @if (i % 2 === 0) {\n <div class=\"step-content\">\n <div class=\"step-avatar-wrapper\">\n @if (step.agentCard.imageUrl) {\n <img [src]=\"step.agentCard.imageUrl\" [alt]=\"step.agentCard.name\" class=\"step-avatar\" />\n } @else {\n <div class=\"step-avatar step-avatar-placeholder\"><i class=\"pi pi-robot\"></i></div>\n }\n <span class=\"step-avatar-name\">{{ step.name ?? step.agentCard.name }}</span>\n </div>\n <div class=\"step-label\">\n @if (step.passCondition) {\n <span class=\"pass-condition\"><i class=\"pi pi-check-circle\"></i> {{ step.passCondition.type }}</span>\n }\n </div>\n </div>\n }\n </div>\n\n <!-- Center line + badge -->\n <div class=\"step-center\">\n @if (!last) { <div class=\"center-line center-line--top\"></div> }\n <div class=\"step-order-badge\">{{ step.order }}</div>\n @if (!last) { <div class=\"center-line center-line--bottom\"></div> }\n </div>\n\n <!-- Right side -->\n <div class=\"step-side step-side--right\">\n @if (i % 2 === 1) {\n <div class=\"step-content\">\n <div class=\"step-avatar-wrapper\">\n @if (step.agentCard.imageUrl) {\n <img [src]=\"step.agentCard.imageUrl\" [alt]=\"step.agentCard.name\" class=\"step-avatar\" />\n } @else {\n <div class=\"step-avatar step-avatar-placeholder\"><i class=\"pi pi-robot\"></i></div>\n }\n <span class=\"step-avatar-name\">{{ step.name ?? step.agentCard.name }}</span>\n </div>\n <div class=\"step-label\">\n @if (step.passCondition) {\n <span class=\"pass-condition\"><i class=\"pi pi-check-circle\"></i> {{ step.passCondition.type }}</span>\n }\n </div>\n </div>\n }\n </div>\n\n </div>\n }\n </div>\n } @else {\n <div class=\"empty-steps\">\n <i class=\"pi pi-inbox\"></i>\n <p>No steps defined yet.</p>\n </div>\n }\n </div>\n\n <!-- Footer -->\n <div class=\"route-footer\">\n <small>\n <i class=\"pi pi-clock\"></i>\n Updated: {{ cardRoute.auditable?.updatedAt | date: 'dd/MM/yyyy HH:mm' }}\n </small>\n </div>\n\n </div>\n}\n", styles: [".loading-wrapper{display:flex;justify-content:center;padding:3rem}.route-detail{max-width:860px;margin:0 auto;padding:1.5rem;display:flex;flex-direction:column;gap:1.5rem}.route-header{background:var(--surface-card);border:1px solid var(--surface-border);border-radius:12px;padding:1.5rem}.route-image-wrapper{width:120px;height:120px;border-radius:12px;overflow:hidden;border:1px solid var(--surface-border);flex-shrink:0}.route-image{width:100%;height:100%;object-fit:cover}.header-content{display:flex;justify-content:space-between;align-items:flex-start;gap:1rem;flex-wrap:wrap}.header-text{flex:1;min-width:280px}.header-title-row{display:flex;align-items:center;gap:.75rem;flex-wrap:wrap;margin-bottom:.5rem}.route-title{font-size:1.6rem;font-weight:700;margin:0;color:var(--text-color)}.route-description{color:var(--text-color-secondary);margin:0 0 .75rem;line-height:1.5}.tags-row{display:flex;gap:.4rem;flex-wrap:wrap}.header-actions{display:flex;gap:.5rem;flex-shrink:0}.steps-section{display:flex;flex-direction:column;gap:1rem}.steps-header{display:flex;align-items:center;justify-content:space-between}.steps-title{font-size:1.1rem;font-weight:600;margin:0;display:flex;align-items:center;gap:.5rem;color:var(--text-color)}.steps-count{font-size:.85rem;color:var(--text-color-secondary);background:var(--surface-ground);border:1px solid var(--surface-border);border-radius:999px;padding:.2rem .75rem}.steps-timeline{display:flex;flex-direction:column}.step-row{display:grid;grid-template-columns:1fr 48px 1fr;align-items:stretch;min-height:200px}.step-side{display:flex;align-items:center}.step-side--left{justify-content:flex-end;padding-right:1.5rem}.step-side--right{justify-content:flex-start;padding-left:1.5rem}.step-content{display:flex;flex-direction:column;align-items:center;gap:.6rem;max-width:180px;text-align:center}.step-avatar-wrapper{position:relative;width:160px;height:160px;flex-shrink:0}.step-avatar-name{position:absolute;bottom:0;left:0;right:0;background:linear-gradient(transparent,#000000b8);color:#fff;font-size:.78rem;font-weight:600;text-align:center;padding:1rem .4rem .45rem;border-radius:0 0 50% 50%;line-height:1.2;pointer-events:none}.step-avatar{width:160px;height:160px;border-radius:50%;object-fit:cover;object-position:top;border:3px solid var(--primary-color);box-shadow:0 4px 16px #0000001f;flex-shrink:0}.step-avatar-placeholder{width:160px;height:160px;border-radius:50%;background:var(--surface-ground);border:3px solid var(--surface-border);display:flex;align-items:center;justify-content:center;color:var(--text-color-secondary);font-size:3rem;flex-shrink:0}.step-label{display:flex;flex-direction:column;align-items:center;gap:.25rem}.step-name{font-size:.95rem;font-weight:600;color:var(--text-color);line-height:1.3}.step-center{display:flex;flex-direction:column;align-items:center;justify-content:center}.center-line--top,.center-line--bottom{width:2px;flex:1;background:var(--surface-border)}.step-order-badge{width:2rem;height:2rem;border-radius:50%;background:var(--primary-color);color:var(--primary-color-text);display:flex;align-items:center;justify-content:center;font-weight:700;font-size:.85rem;flex-shrink:0;z-index:1}.pass-condition{display:flex;align-items:center;gap:.25rem;font-size:.75rem;color:var(--green-500)}.empty-steps{display:flex;flex-direction:column;align-items:center;padding:2.5rem;color:var(--text-color-secondary);gap:.5rem;background:var(--surface-ground);border-radius:10px;border:1px dashed var(--surface-border)}.empty-steps i{font-size:2rem}.route-footer{color:var(--text-color-secondary);display:flex;align-items:center;gap:.4rem;font-size:.8rem}.route-footer small{display:flex;align-items:center;gap:.35rem}\n"], dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "ngmodule", type: TagModule }, { kind: "component", type: i1$3.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "ngmodule", type: ProgressSpinnerModule }, { kind: "component", type: i3$3.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "pipe", type: DatePipe, name: "date" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
8724
9262
  }
8725
9263
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CardRouteDetailComponent, decorators: [{
8726
9264
  type: Component,
@@ -8804,7 +9342,7 @@ class CardRouteStepsFormComponent {
8804
9342
  this.showCardSelector.set(false);
8805
9343
  }
8806
9344
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CardRouteStepsFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
8807
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: CardRouteStepsFormComponent, isStandalone: true, selector: "app-card-route-steps-form", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { valueChange: "valueChange" }, ngImport: i0, template: "<div class=\"flex flex-col gap-4\">\n <div class=\"flex justify-between items-center\">\n <h3 class=\"text-xl font-semibold m-0\">Route Steps</h3>\n <p-button label=\"Add Step\" icon=\"pi pi-plus\" size=\"small\" (onClick)=\"addStep()\"></p-button>\n </div>\n\n @if (value().length === 0) {\n <div class=\"text-gray-500 italic p-4 text-center border rounded\">\n No steps added yet. Click \"Add Step\" to begin.\n </div>\n }\n\n @for (step of value(); track step.order; let i = $index) {\n <p-card class=\"mb-3 shadow-none border\">\n <div class=\"flex justify-between items-center mb-3\">\n <h4 class=\"m-0 font-medium\">Step {{ i + 1 }}</h4>\n <div class=\"flex gap-2\">\n <p-button icon=\"pi pi-arrow-up\" severity=\"secondary\" [text]=\"true\" [rounded]=\"true\" [disabled]=\"i === 0\" (onClick)=\"moveStep(i, 'up')\"></p-button>\n <p-button icon=\"pi pi-arrow-down\" severity=\"secondary\" [text]=\"true\" [rounded]=\"true\" [disabled]=\"i === value().length - 1\" (onClick)=\"moveStep(i, 'down')\"></p-button>\n <p-button icon=\"pi pi-trash\" severity=\"danger\" [text]=\"true\" [rounded]=\"true\" (onClick)=\"removeStep(i)\"></p-button>\n </div>\n </div>\n\n <div class=\"grid grid-cols-1 gap-4\">\n\n <!-- Card selector row -->\n <div class=\"flex flex-col gap-2\">\n <label>Agent Card *</label>\n <div class=\"flex items-center gap-3\">\n @if (step.agentCard.imageUrl) {\n <img [src]=\"step.agentCard.imageUrl\" class=\"w-12 h-12 rounded-full object-cover\" />\n }\n <div class=\"flex flex-col flex-1 min-w-0\">\n <span class=\"font-medium truncate\">{{ step.agentCard.name || 'No card selected' }}</span>\n <span class=\"text-xs text-gray-400 truncate\">{{ step.agentCard.id }}</span>\n </div>\n <p-button label=\"Select Card\" icon=\"pi pi-search\" size=\"small\" [outlined]=\"true\" (onClick)=\"openCardSelector(i)\"></p-button>\n </div>\n </div>\n\n <div>\n <button type=\"button\" class=\"text-xs text-blue-500 hover:text-blue-700 flex items-center gap-1\" (click)=\"toggleStepDetails(i)\">\n <i [class]=\"isStepExpanded(i) ? 'pi pi-chevron-up' : 'pi pi-chevron-down'\" class=\"text-xs\"></i>\n {{ isStepExpanded(i) ? 'Hide optional fields' : 'Add name & description' }}\n </button>\n </div>\n\n @if (isStepExpanded(i)) {\n <div class=\"flex flex-col gap-2\">\n <label [for]=\"'name_' + i\">Name</label>\n <input pInputText [id]=\"'name_' + i\"\n [ngModel]=\"step.name\"\n (ngModelChange)=\"patchStep(i, { name: $event })\"\n placeholder=\"Step name (optional)\" />\n </div>\n\n <div class=\"flex flex-col gap-2\">\n <label [for]=\"'description_' + i\">Description</label>\n <textarea pTextarea [id]=\"'description_' + i\" rows=\"2\"\n [ngModel]=\"step.description\"\n (ngModelChange)=\"patchStep(i, { description: $event })\"\n placeholder=\"Step description (optional)\"></textarea>\n </div>\n }\n </div>\n </p-card>\n }\n</div>\n\n<!-- Card Selector Dialog -->\n<p-dialog\n header=\"Select Agent Card\"\n [visible]=\"showCardSelector()\"\n (visibleChange)=\"showCardSelector.set($event)\"\n [modal]=\"true\"\n [style]=\"{ width: '85vw', maxWidth: '1100px' }\"\n [draggable]=\"false\"\n [resizable]=\"false\">\n\n <dc-agent-card-lists\n [onlyView]=\"true\"\n (onAction)=\"onCardSelected($event)\">\n </dc-agent-card-lists>\n\n</p-dialog>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: FormsModule }, { 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.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i3$5.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: TextareaModule }, { kind: "directive", type: i3$1.Textarea, selector: "[pTextarea], [pInputTextarea]", inputs: ["pTextareaPT", "pTextareaUnstyled", "autoResize", "pSize", "variant", "fluid", "invalid"], outputs: ["onResize"] }, { kind: "ngmodule", type: CardModule }, { kind: "component", type: i2$6.Card, selector: "p-card", inputs: ["header", "subheader", "style", "styleClass"] }, { kind: "ngmodule", type: DialogModule }, { kind: "component", type: i5$1.Dialog, selector: "p-dialog", inputs: ["hostName", "header", "draggable", "resizable", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "maskMotionOptions", "motionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "appendTo", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "ngmodule", type: CommonModule }, { kind: "component", type: AgentCardListComponent, selector: "dc-agent-card-lists", inputs: ["extraFilters", "persistenceKey", "showOptions", "gridLayout", "customGetButtons"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
9345
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: CardRouteStepsFormComponent, isStandalone: true, selector: "app-card-route-steps-form", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { valueChange: "valueChange" }, ngImport: i0, template: "<div class=\"flex flex-col gap-4\">\n <div class=\"flex justify-between items-center\">\n <h3 class=\"text-xl font-semibold m-0\">Route Steps</h3>\n <p-button label=\"Add Step\" icon=\"pi pi-plus\" size=\"small\" (onClick)=\"addStep()\"></p-button>\n </div>\n\n @if (value().length === 0) {\n <div class=\"text-gray-500 italic p-4 text-center border rounded\">\n No steps added yet. Click \"Add Step\" to begin.\n </div>\n }\n\n @for (step of value(); track step.order; let i = $index) {\n <p-card class=\"mb-3 shadow-none border\">\n <div class=\"flex justify-between items-center mb-3\">\n <h4 class=\"m-0 font-medium\">Step {{ i + 1 }}</h4>\n <div class=\"flex gap-2\">\n <p-button icon=\"pi pi-arrow-up\" severity=\"secondary\" [text]=\"true\" [rounded]=\"true\" [disabled]=\"i === 0\" (onClick)=\"moveStep(i, 'up')\"></p-button>\n <p-button icon=\"pi pi-arrow-down\" severity=\"secondary\" [text]=\"true\" [rounded]=\"true\" [disabled]=\"i === value().length - 1\" (onClick)=\"moveStep(i, 'down')\"></p-button>\n <p-button icon=\"pi pi-trash\" severity=\"danger\" [text]=\"true\" [rounded]=\"true\" (onClick)=\"removeStep(i)\"></p-button>\n </div>\n </div>\n\n <div class=\"grid grid-cols-1 gap-4\">\n\n <!-- Card selector row -->\n <div class=\"flex flex-col gap-2\">\n <label>Agent Card *</label>\n <div class=\"flex items-center gap-3\">\n @if (step.agentCard.imageUrl) {\n <img [src]=\"step.agentCard.imageUrl\" class=\"w-12 h-12 rounded-full object-cover\" />\n }\n <div class=\"flex flex-col flex-1 min-w-0\">\n <span class=\"font-medium truncate\">{{ step.agentCard.name || 'No card selected' }}</span>\n <span class=\"text-xs text-gray-400 truncate\">{{ step.agentCard.id }}</span>\n </div>\n <p-button label=\"Select Card\" icon=\"pi pi-search\" size=\"small\" [outlined]=\"true\" (onClick)=\"openCardSelector(i)\"></p-button>\n </div>\n </div>\n\n <div>\n <button type=\"button\" class=\"text-xs text-blue-500 hover:text-blue-700 flex items-center gap-1\" (click)=\"toggleStepDetails(i)\">\n <i [class]=\"isStepExpanded(i) ? 'pi pi-chevron-up' : 'pi pi-chevron-down'\" class=\"text-xs\"></i>\n {{ isStepExpanded(i) ? 'Hide optional fields' : 'Add name & description' }}\n </button>\n </div>\n\n @if (isStepExpanded(i)) {\n <div class=\"flex flex-col gap-2\">\n <label [for]=\"'name_' + i\">Name</label>\n <input pInputText [id]=\"'name_' + i\"\n [ngModel]=\"step.name\"\n (ngModelChange)=\"patchStep(i, { name: $event })\"\n placeholder=\"Step name (optional)\" />\n </div>\n\n <div class=\"flex flex-col gap-2\">\n <label [for]=\"'description_' + i\">Description</label>\n <textarea pTextarea [id]=\"'description_' + i\" rows=\"2\"\n [ngModel]=\"step.description\"\n (ngModelChange)=\"patchStep(i, { description: $event })\"\n placeholder=\"Step description (optional)\"></textarea>\n </div>\n }\n </div>\n </p-card>\n }\n</div>\n\n<!-- Card Selector Dialog -->\n<p-dialog\n header=\"Select Agent Card\"\n [visible]=\"showCardSelector()\"\n (visibleChange)=\"showCardSelector.set($event)\"\n [modal]=\"true\"\n [style]=\"{ width: '85vw', maxWidth: '1100px' }\"\n [draggable]=\"false\"\n [resizable]=\"false\">\n\n <dc-agent-card-lists\n [onlyView]=\"true\"\n (onAction)=\"onCardSelected($event)\">\n </dc-agent-card-lists>\n\n</p-dialog>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: FormsModule }, { 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.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i3$5.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: TextareaModule }, { kind: "directive", type: i3$1.Textarea, selector: "[pTextarea], [pInputTextarea]", inputs: ["pTextareaPT", "pTextareaUnstyled", "autoResize", "pSize", "variant", "fluid", "invalid"], outputs: ["onResize"] }, { kind: "ngmodule", type: CardModule }, { kind: "component", type: i2$7.Card, selector: "p-card", inputs: ["header", "subheader", "style", "styleClass"] }, { kind: "ngmodule", type: DialogModule }, { kind: "component", type: i5$1.Dialog, selector: "p-dialog", inputs: ["hostName", "header", "draggable", "resizable", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "maskMotionOptions", "motionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "appendTo", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "ngmodule", type: CommonModule }, { kind: "component", type: AgentCardListComponent, selector: "dc-agent-card-lists", inputs: ["extraFilters", "persistenceKey", "showOptions", "gridLayout", "customGetButtons"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
8808
9346
  }
8809
9347
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CardRouteStepsFormComponent, decorators: [{
8810
9348
  type: Component,
@@ -8852,7 +9390,7 @@ class CardRouteFormComponent extends EntityBaseSignalFormComponent {
8852
9390
  this.save();
8853
9391
  }
8854
9392
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CardRouteFormComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
8855
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: CardRouteFormComponent, isStandalone: true, selector: "app-card-route-form", usesInheritance: true, ngImport: i0, template: "<p-card [header]=\"entityId() ? 'Edit Card Route' : 'New Card Route'\">\n <div class=\"flex gap-2.5\">\n <div class=\"mb-4\">\n <label class=\"block font-medium mb-1\" pTooltip=\"Upload image after first save\">Image</label>\n <img width=\"218px\" [src]=\"entityForm().assets?.image?.url || 'defaults/images/face-3.jpg'\" alt=\"route image\" />\n <dc-cropper-modal [imgStorageSettings]=\"storageImgSettings\" (imageUploaded)=\"handleImageUpload($event)\"></dc-cropper-modal>\n </div>\n\n <div class=\"w-full\">\n <div class=\"form-field\">\n <label for=\"name\">Name *</label>\n <input pInputText id=\"name\" type=\"text\"\n [formField]=\"form.name\"\n placeholder=\"Route name\" class=\"w-full\" />\n @if (form.name().touched() && form.name().invalid()) {\n <small class=\"p-error\">{{ form.name().errors()[0].message }}</small>\n }\n </div>\n\n <div class=\"form-field mt-4\">\n <label for=\"description\">Description</label>\n <textarea pTextarea id=\"description\" rows=\"2\"\n [ngModel]=\"entityForm().description\"\n (ngModelChange)=\"entityForm.set({ ...entityForm(), description: $event })\"\n placeholder=\"Route description\" autoResize class=\"w-full\"></textarea>\n </div>\n </div>\n </div>\n\n <div class=\"form-field-inline\">\n <label for=\"isActive\">Active</label>\n <p-toggleswitch id=\"isActive\"\n [ngModel]=\"entityForm().isActive\"\n (ngModelChange)=\"entityForm.set({ ...entityForm(), isActive: $event })\" />\n </div>\n\n <div class=\"form-field mt-4\">\n <app-card-route-steps-form\n [value]=\"entityForm().steps\"\n (valueChange)=\"entityForm.set({ ...entityForm(), steps: $event })\">\n </app-card-route-steps-form>\n </div>\n\n <div class=\"form-actions mt-4\">\n <p-button label=\"Save\" (click)=\"save()\" [disabled]=\"!isValid()\" />\n </div>\n</p-card>\n", styles: [".form-field{display:flex;flex-direction:column;gap:.25rem;margin-bottom:1rem}.form-field input,.form-field textarea{width:100%}.form-field-inline{display:flex;align-items:center;gap:.5rem;margin-bottom:1rem}.form-actions{display:flex;justify-content:flex-end;gap:.5rem;margin-top:1rem}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { 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.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"], exportAs: ["formField"] }, { kind: "ngmodule", type: CardModule }, { kind: "component", type: i2$6.Card, selector: "p-card", inputs: ["header", "subheader", "style", "styleClass"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i3$5.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: TextareaModule }, { kind: "directive", type: i3$1.Textarea, selector: "[pTextarea], [pInputTextarea]", inputs: ["pTextareaPT", "pTextareaUnstyled", "autoResize", "pSize", "variant", "fluid", "invalid"], outputs: ["onResize"] }, { kind: "ngmodule", type: ToggleSwitchModule }, { kind: "component", type: i4$1.ToggleSwitch, selector: "p-toggleswitch, p-toggleSwitch, p-toggle-switch", inputs: ["styleClass", "tabindex", "inputId", "readonly", "trueValue", "falseValue", "ariaLabel", "size", "ariaLabelledBy", "autofocus"], outputs: ["onChange"] }, { kind: "component", type: CardRouteStepsFormComponent, selector: "app-card-route-steps-form", inputs: ["value"], outputs: ["valueChange"] }, { kind: "component", type: CropperComponentModal, selector: "dc-cropper-modal", inputs: ["imgStorageSettings", "buttonLabel", "currentStorage"], outputs: ["imageUploaded", "onImageCropped", "onFileSelected"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i3.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
9393
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: CardRouteFormComponent, isStandalone: true, selector: "app-card-route-form", usesInheritance: true, ngImport: i0, template: "<p-card [header]=\"entityId() ? 'Edit Card Route' : 'New Card Route'\">\n <div class=\"flex gap-2.5\">\n <div class=\"mb-4\">\n <label class=\"block font-medium mb-1\" pTooltip=\"Upload image after first save\">Image</label>\n <img width=\"218px\" [src]=\"entityForm().assets?.image?.url || 'defaults/images/face-3.jpg'\" alt=\"route image\" />\n <dc-cropper-modal [imgStorageSettings]=\"storageImgSettings\" (imageUploaded)=\"handleImageUpload($event)\"></dc-cropper-modal>\n </div>\n\n <div class=\"w-full\">\n <div class=\"form-field\">\n <label for=\"name\">Name *</label>\n <input pInputText id=\"name\" type=\"text\"\n [formField]=\"form.name\"\n placeholder=\"Route name\" class=\"w-full\" />\n @if (form.name().touched() && form.name().invalid()) {\n <small class=\"p-error\">{{ form.name().errors()[0].message }}</small>\n }\n </div>\n\n <div class=\"form-field mt-4\">\n <label for=\"description\">Description</label>\n <textarea pTextarea id=\"description\" rows=\"2\"\n [ngModel]=\"entityForm().description\"\n (ngModelChange)=\"entityForm.set({ ...entityForm(), description: $event })\"\n placeholder=\"Route description\" autoResize class=\"w-full\"></textarea>\n </div>\n </div>\n </div>\n\n <div class=\"form-field-inline\">\n <label for=\"isActive\">Active</label>\n <p-toggleswitch id=\"isActive\"\n [ngModel]=\"entityForm().isActive\"\n (ngModelChange)=\"entityForm.set({ ...entityForm(), isActive: $event })\" />\n </div>\n\n <div class=\"form-field mt-4\">\n <app-card-route-steps-form\n [value]=\"entityForm().steps\"\n (valueChange)=\"entityForm.set({ ...entityForm(), steps: $event })\">\n </app-card-route-steps-form>\n </div>\n\n <div class=\"form-actions mt-4\">\n <p-button label=\"Save\" (click)=\"save()\" [disabled]=\"!isValid()\" />\n </div>\n</p-card>\n", styles: [".form-field{display:flex;flex-direction:column;gap:.25rem;margin-bottom:1rem}.form-field input,.form-field textarea{width:100%}.form-field-inline{display:flex;align-items:center;gap:.5rem;margin-bottom:1rem}.form-actions{display:flex;justify-content:flex-end;gap:.5rem;margin-top:1rem}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { 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.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"], exportAs: ["formField"] }, { kind: "ngmodule", type: CardModule }, { kind: "component", type: i2$7.Card, selector: "p-card", inputs: ["header", "subheader", "style", "styleClass"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i3$5.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: TextareaModule }, { kind: "directive", type: i3$1.Textarea, selector: "[pTextarea], [pInputTextarea]", inputs: ["pTextareaPT", "pTextareaUnstyled", "autoResize", "pSize", "variant", "fluid", "invalid"], outputs: ["onResize"] }, { kind: "ngmodule", type: ToggleSwitchModule }, { kind: "component", type: i4$2.ToggleSwitch, selector: "p-toggleswitch, p-toggleSwitch, p-toggle-switch", inputs: ["styleClass", "tabindex", "inputId", "readonly", "trueValue", "falseValue", "ariaLabel", "size", "ariaLabelledBy", "autofocus"], outputs: ["onChange"] }, { kind: "component", type: CardRouteStepsFormComponent, selector: "app-card-route-steps-form", inputs: ["value"], outputs: ["valueChange"] }, { kind: "component", type: CropperComponentModal, selector: "dc-cropper-modal", inputs: ["imgStorageSettings", "buttonLabel", "currentStorage"], outputs: ["imageUploaded", "onImageCropped", "onFileSelected"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i3.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
8856
9394
  }
8857
9395
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CardRouteFormComponent, decorators: [{
8858
9396
  type: Component,
@@ -8886,7 +9424,7 @@ const CARD_ROUTES = [
8886
9424
  class CardRoutesComponent {
8887
9425
  static { this.routes = CARD_ROUTES; }
8888
9426
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CardRoutesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
8889
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.5", type: CardRoutesComponent, isStandalone: true, selector: "app-card-routes", ngImport: i0, template: `<router-outlet />`, isInline: true, dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$7.RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
9427
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.5", type: CardRoutesComponent, isStandalone: true, selector: "app-card-routes", ngImport: i0, template: `<router-outlet />`, isInline: true, dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$5.RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
8890
9428
  }
8891
9429
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CardRoutesComponent, decorators: [{
8892
9430
  type: Component,
@@ -8950,5 +9488,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
8950
9488
  * Generated bundle index. Do not edit.
8951
9489
  */
8952
9490
 
8953
- export { ACCDataGenerationComponent, AGENT_CARDS_STATE_SERVICE, AIGenerationService, AgentCardListComponent, AgentCardUI, AgentCardsGenerationService, AudioService, AudioSpeed, BACKGROUND_SERVICE_TOKEN, CONVERSATION_AI_TOKEN, CardRouteService, CardRoutesComponent, CardsCreatorComponent, ChatEngineTestComponent, ChatEventType, ChatMessage, ChatMessageOrchestratorComponent, ChatMonitorService, ChatRole, ConditionOperator, ConditionType, ContextEngineService, ContextType, ConversationDTO, ConversationEvents, ConversationFlowStateService, ConversationMessagesDTO, ConversationPromptBuilderService, ConversationRuleService, ConversationRulesComponent, ConversationStatus, ConversationType, ConversationTypeOptions, DCAgentCardFormComponent, DCChatComponent, DCConversationUserChatSettingsComponent, DcAgentCardConverseComponent, DcAgentCardDetailComponent, DefaultAgentCardsService, DoActionTypeOptions, DynamicFlowService, DynamicFlowTaskTypeOptions, EAccountsPlatform, EAgentType, EDoActionType, EDynamicFlowTaskType, EntityThen, EntityWhatOptions, EntityWhenOptions, EvalResultStringDefinition, GlobalToolsService, MessageContent, MessageContentDisplayer, MessagesStateService, ModelSelectorComponent, PopupService, PromptPreviewComponent, SectionType, SystemPromptType, TextEngineOptions, TextEngines, VIDEO_PLAYER_SERVICE_TOKEN, VideoPlayerNativeService, VideoPlayerService, VoiceTTSOption, VoiceTTSOptions, WordTimestamps, XKillsAgentCardsService, buildObjectTTSRequest, characterCardStringDataDefinition, convertToHTML, createAIModelFormGroup, defaultconvUserSettings, extractAudioAndTranscription, extractJsonFromResponse, getMoodStateLabelsAsString, getMoodStatePrompt, markdownToHtml, matchTranscription, provideAgentCardService, removeEmojis, removeEmojisAndSpecialCharacters, removeSpecialCharacters };
9491
+ export { ACCDataGenerationComponent, AGENT_CARDS_STATE_SERVICE, AIGenerationService, AgentCardListComponent, AgentCardUI, AgentCardsGenerationService, AudioService, AudioSpeed, BACKGROUND_SERVICE_TOKEN, CONVERSATION_AI_TOKEN, CardRouteService, CardRoutesComponent, CardsCreatorComponent, ChatEngineTestComponent, ChatEventType, ChatMessage, ChatMessageOrchestratorComponent, ChatMonitorService, ChatRole, ConditionOperator, ConditionType, ContextEngineService, ContextType, ConversationDTO, ConversationEvents, ConversationFlowStateService, ConversationMessagesDTO, ConversationPromptBuilderService, ConversationRuleService, ConversationRulesComponent, ConversationStatus, ConversationType, ConversationTypeOptions, DCAgentCardFormComponent, DCChatComponent, DCConversationUserChatSettingsComponent, DcAgentCardConverseComponent, DcAgentCardDetailComponent, DefaultAgentCardsService, DoActionTypeOptions, DynamicFlowService, DynamicFlowTaskTypeOptions, EAccountsPlatform, EAgentType, EDoActionType, EDynamicFlowTaskType, EntityThen, EntityWhatOptions, EntityWhenOptions, EvalResultStringDefinition, GlobalToolsService, MessageContent, MessageContentDisplayer, MessagesStateService, ModelSelectorComponent, PolitoNotificationComponent, PopupService, PromptPreviewComponent, SectionType, SystemPromptType, TextEngineOptions, TextEngines, VIDEO_PLAYER_SERVICE_TOKEN, VideoPlayerNativeService, VideoPlayerService, VoiceTTSOption, VoiceTTSOptions, WordTimestamps, XKillsAgentCardsService, buildObjectTTSRequest, characterCardStringDataDefinition, convertToHTML, createAIModelFormGroup, defaultconvUserSettings, extractAudioAndTranscription, extractJsonFromResponse, getMoodStateLabelsAsString, getMoodStatePrompt, markdownToHtml, matchTranscription, provideAgentCardService, removeEmojis, removeEmojisAndSpecialCharacters, removeSpecialCharacters };
8954
9492
  //# sourceMappingURL=dataclouder-ngx-agent-cards.mjs.map