@m6d/cortex-client 1.5.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,17 +1,17 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, inject, NgZone, Injectable, signal, DestroyRef, Pipe, input, effect, ViewEncapsulation, ChangeDetectionStrategy, Component, computed, forwardRef, afterNextRender, viewChild, model, Injector } from '@angular/core';
2
+ import { InjectionToken, inject, NgZone, Injectable, signal, computed, DestroyRef, ViewEncapsulation, ChangeDetectionStrategy, Component, Pipe, input, effect, forwardRef, afterNextRender, viewChild, model, Injector } from '@angular/core';
3
3
  import * as i1$1 from '@angular/forms';
4
4
  import { FormControl, Validators, FormBuilder, ReactiveFormsModule, NG_VALUE_ACCESSOR, FormsModule } from '@angular/forms';
5
5
  import { TranslatePipe, TranslateService, provideTranslateService, provideTranslateLoader } from '@ngx-translate/core';
6
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
6
7
  import { Chat } from '@ai-sdk/angular';
7
8
  import { DefaultChatTransport, lastAssistantMessageIsCompleteWithToolCalls, isStaticToolUIPart, generateId } from 'ai';
8
- import { Observable, retry, timer, share, Subject, of, defer, finalize, tap, switchMap, map, concatMap } from 'rxjs';
9
+ import { Subject, Observable, retry, timer, share, of, defer, finalize, tap, switchMap, map } from 'rxjs';
9
10
  import { fromPromise } from 'rxjs/internal/observable/innerFrom';
10
- import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
11
11
  import { marked } from 'marked';
12
12
  import DOMPurify from 'dompurify';
13
13
  import * as i1 from '@angular/platform-browser';
14
- import { NgClass, NgTemplateOutlet, NgComponentOutlet } from '@angular/common';
14
+ import { NgClass, NgTemplateOutlet, NgComponentOutlet, DecimalPipe, JsonPipe } from '@angular/common';
15
15
  import hljs from 'highlight.js/lib/core';
16
16
  import javascript from 'highlight.js/lib/languages/javascript';
17
17
  import json from 'highlight.js/lib/languages/json';
@@ -19,19 +19,31 @@ import sql from 'highlight.js/lib/languages/sql';
19
19
 
20
20
  const CORTEX_CLIENT_CONFIG = new InjectionToken('CORTEX_CLIENT_CONFIG');
21
21
 
22
+ function createLatch(count, onComplete) {
23
+ let remaining = count;
24
+ return async () => {
25
+ if (--remaining === 0)
26
+ await onComplete();
27
+ };
28
+ }
29
+
22
30
  class CortexClientWebSocketService {
31
+ openedSubject = new Subject();
23
32
  events$;
24
33
  constructor() {
25
34
  const config = inject(CORTEX_CLIENT_CONFIG);
26
35
  const ngZone = inject(NgZone);
27
36
  this.events$ = new Observable((subscriber) => {
28
- const wsUrl = config.wsUrl ?? deriveWsUrl(config.transport.baseUrl);
37
+ const wsUrl = resolveWsUrl(config.wsUrl, config.transport.baseUrl);
29
38
  let ws;
30
39
  Promise.resolve(config.transport.getAuthHeaders()).then((headers) => {
31
40
  if (subscriber.closed)
32
41
  return;
33
42
  const fullWsUrl = appendTokenToUrl(wsUrl, headers);
34
43
  ws = new WebSocket(fullWsUrl);
44
+ ws.addEventListener('open', () => {
45
+ ngZone.run(() => this.openedSubject.next());
46
+ });
35
47
  ws.addEventListener('message', (event) => {
36
48
  let parsed;
37
49
  try {
@@ -53,12 +65,24 @@ class CortexClientWebSocketService {
53
65
  get events() {
54
66
  return this.events$;
55
67
  }
56
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: CortexClientWebSocketService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
57
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: CortexClientWebSocketService });
68
+ get opened() {
69
+ return this.openedSubject.asObservable();
70
+ }
71
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CortexClientWebSocketService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
72
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CortexClientWebSocketService });
58
73
  }
59
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: CortexClientWebSocketService, decorators: [{
74
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CortexClientWebSocketService, decorators: [{
60
75
  type: Injectable
61
76
  }], ctorParameters: () => [] });
77
+ function resolveWsUrl(wsUrl, baseUrl) {
78
+ const resolvedUrl = wsUrl ?? deriveWsUrl(baseUrl);
79
+ if (!wsUrl)
80
+ return resolvedUrl;
81
+ const agentId = extractAgentId(baseUrl);
82
+ if (!agentId)
83
+ return resolvedUrl;
84
+ return appendAgentIdToUrl(resolvedUrl, agentId);
85
+ }
62
86
  function deriveWsUrl(baseUrl) {
63
87
  const url = typeof baseUrl === 'string' ? baseUrl : baseUrl();
64
88
  const parsed = new URL(url, window.location.origin);
@@ -66,13 +90,36 @@ function deriveWsUrl(baseUrl) {
66
90
  parsed.pathname = parsed.pathname.replace(/\/$/, '') + '/ws';
67
91
  return parsed.toString();
68
92
  }
93
+ function extractAgentId(baseUrl) {
94
+ const url = typeof baseUrl === 'string' ? baseUrl : baseUrl();
95
+ const parsed = new URL(url, window.location.origin);
96
+ const segments = parsed.pathname.split('/').filter(Boolean);
97
+ const agentsIndex = segments.lastIndexOf('agents');
98
+ if (agentsIndex === -1)
99
+ return undefined;
100
+ return segments[agentsIndex + 1];
101
+ }
102
+ function appendAgentIdToUrl(wsUrl, agentId) {
103
+ const parsed = new URL(wsUrl, window.location.origin);
104
+ if (parsed.searchParams.has('agentId') || hasAgentIdInPath(parsed))
105
+ return parsed.toString();
106
+ parsed.searchParams.set('agentId', agentId);
107
+ return parsed.toString();
108
+ }
109
+ function hasAgentIdInPath(url) {
110
+ const segments = url.pathname.split('/').filter(Boolean);
111
+ const agentsIndex = segments.lastIndexOf('agents');
112
+ return agentsIndex !== -1 && Boolean(segments[agentsIndex + 1]);
113
+ }
69
114
  function appendTokenToUrl(wsUrl, headers) {
70
115
  const authHeader = headers['Authorization'] ?? headers['authorization'];
71
116
  if (!authHeader?.startsWith('Bearer '))
72
117
  return wsUrl;
73
- const token = authHeader.slice(7);
74
- const separator = wsUrl.includes('?') ? '&' : '?';
75
- return `${wsUrl}${separator}token=${encodeURIComponent(token)}`;
118
+ const parsed = new URL(wsUrl, window.location.origin);
119
+ if (parsed.searchParams.has('token'))
120
+ return parsed.toString();
121
+ parsed.searchParams.set('token', authHeader.slice(7));
122
+ return parsed.toString();
76
123
  }
77
124
 
78
125
  class CortexChatService {
@@ -80,23 +127,34 @@ class CortexChatService {
80
127
  selectedThread = signal(undefined, ...(ngDevMode ? [{ debugName: "selectedThread" }] : /* istanbul ignore next */ []));
81
128
  chat = signal(undefined, ...(ngDevMode ? [{ debugName: "chat" }] : /* istanbul ignore next */ []));
82
129
  isLoadingMessages = signal(false, ...(ngDevMode ? [{ debugName: "isLoadingMessages" }] : /* istanbul ignore next */ []));
83
- isAgentWorking = signal(false, ...(ngDevMode ? [{ debugName: "isAgentWorking" }] : /* istanbul ignore next */ []));
130
+ isAgentWorking = computed(() => {
131
+ const chat = this.chat();
132
+ if (!chat)
133
+ return false;
134
+ const status = chat.status;
135
+ return status === 'submitted' || status === 'streaming';
136
+ }, ...(ngDevMode ? [{ debugName: "isAgentWorking" }] : /* istanbul ignore next */ []));
84
137
  hasPendingToolCalls = signal(false, ...(ngDevMode ? [{ debugName: "hasPendingToolCalls" }] : /* istanbul ignore next */ []));
85
138
  events = new Subject();
86
139
  activeThreadSelectionId = 0;
140
+ completeLatchThreadId = undefined;
141
+ hasSeenWsOpen = false;
87
142
  config = inject(CORTEX_CLIENT_CONFIG);
88
143
  wsService = inject(CortexClientWebSocketService);
89
144
  destroyRef = inject(DestroyRef);
145
+ completeLatch = undefined;
90
146
  constructor() {
91
147
  this.reloadThreads().subscribe();
92
148
  this.subscribeToWsEvents();
149
+ this.subscribeToWsConnections();
93
150
  }
94
151
  get events$() {
95
152
  return this.events.asObservable();
96
153
  }
97
154
  selectThread(thread, options) {
98
- if (this.selectedThread()?.id === thread.id && this.chat() && !this.isLoadingMessages())
155
+ if (this.selectedThread()?.id === thread.id && this.chat() && !this.isLoadingMessages()) {
99
156
  return of();
157
+ }
100
158
  const selectionId = ++this.activeThreadSelectionId;
101
159
  return (options?.skipLoadingMessages
102
160
  ? of([])
@@ -131,22 +189,26 @@ class CortexChatService {
131
189
  output,
132
190
  });
133
191
  },
134
- onError: () => {
135
- this.isAgentWorking.set(false);
192
+ onError: async () => {
136
193
  this.hasPendingToolCalls.set(false);
137
194
  this.events.next('onError');
195
+ await this.completeLatch?.();
138
196
  },
139
- onFinish: () => {
140
- this.isAgentWorking.set(false);
197
+ onFinish: async () => {
141
198
  this.hasPendingToolCalls.set(this.hasIncompleteToolCalls(chat.messages));
142
199
  this.events.next('onFinish');
200
+ if (this.completeLatch) {
201
+ await this.completeLatch();
202
+ }
203
+ else {
204
+ this.onThreadMessagesUpdated({ threadId: thread.id });
205
+ }
143
206
  },
144
- messages: messages,
207
+ messages,
145
208
  transport: new DefaultChatTransport({
146
209
  api: this.resolveUrl('/chat'),
147
210
  headers: async () => await this.resolveHeaders(),
148
211
  prepareSendMessagesRequest: ({ messages, id, body, ...rest }) => {
149
- this.isAgentWorking.set(true);
150
212
  this.hasPendingToolCalls.set(false);
151
213
  return {
152
214
  ...rest,
@@ -163,15 +225,20 @@ class CortexChatService {
163
225
  this.chat.set(chat);
164
226
  this.selectedThread.set(thread);
165
227
  this.syncConversationState(messages);
228
+ this.resumeChat(thread.id, {
229
+ reloadMessagesFirst: false,
230
+ reloadMessagesAfterResume: false,
231
+ });
166
232
  this.events.next('onThreadSelected');
167
233
  }));
168
234
  }
169
235
  deselectThread() {
170
236
  this.activeThreadSelectionId += 1;
171
- this.abort();
237
+ this.chat()?.stop();
172
238
  this.isLoadingMessages.set(false);
173
- this.isAgentWorking.set(false);
174
239
  this.hasPendingToolCalls.set(false);
240
+ this.completeLatch = undefined;
241
+ this.completeLatchThreadId = undefined;
175
242
  if (!this.selectedThread() && !this.chat())
176
243
  return;
177
244
  this.selectedThread.set(undefined);
@@ -181,38 +248,87 @@ class CortexChatService {
181
248
  if (this.isAgentWorking() || this.hasPendingToolCalls())
182
249
  return of();
183
250
  const ensureThread = this.selectedThread()
184
- ? of(undefined)
251
+ ? of(this.selectedThread().id)
185
252
  : fromPromise(this.fetchJson('/threads', {
186
253
  method: 'POST',
187
254
  body: JSON.stringify({ prompt }),
188
- })).pipe(switchMap((thread) => this.selectThread(thread, { skipLoadingMessages: true }).pipe(map(() => undefined))), tap(() => this.reloadThreads().subscribe()));
189
- return ensureThread.pipe(switchMap(() => fromPromise(this.chat().sendMessage({ text: prompt }))), tap(() => this.events.next('onSend')));
255
+ })).pipe(tap((thread) => this.upsertThread(thread)), switchMap((thread) => this.selectThread(thread, { skipLoadingMessages: true }).pipe(map(() => thread.id))));
256
+ return ensureThread.pipe(tap((threadId) => {
257
+ this.events.next('onSend');
258
+ this.updateThreadRunning(threadId, true);
259
+ this.completeLatchThreadId = threadId;
260
+ this.completeLatch = createLatch(2, () => {
261
+ this.onThreadMessagesUpdated({ threadId });
262
+ this.completeLatch = undefined;
263
+ this.completeLatchThreadId = undefined;
264
+ });
265
+ }), switchMap(() => fromPromise(this.chat().sendMessage({ text: prompt }))));
190
266
  }
191
267
  abort() {
192
268
  const chat = this.chat();
193
269
  if (!chat || !this.isAgentWorking())
194
270
  return;
271
+ const threadId = this.selectedThread()?.id;
272
+ if (threadId) {
273
+ this.updateThreadRunning(threadId, false);
274
+ this.fetchJson(`/chat/${threadId}/abort`, { method: 'POST' }).catch(() => { });
275
+ }
195
276
  chat.stop();
196
- this.isAgentWorking.set(false);
197
277
  this.hasPendingToolCalls.set(false);
198
278
  }
199
279
  deleteThread(threadId) {
200
- if (this.selectedThread()?.id === threadId)
280
+ if (this.selectedThread()?.id === threadId) {
201
281
  this.deselectThread();
202
- return fromPromise(this.fetchJson(`/threads/${threadId}`, { method: 'DELETE' })).pipe(concatMap(() => this.reloadThreads()));
282
+ }
283
+ return fromPromise(this.fetchJson(`/threads/${threadId}`, { method: 'DELETE' })).pipe(tap(() => this.removeThread(threadId)));
203
284
  }
204
285
  subscribeToWsEvents() {
205
- this.wsService.events.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((event) => {
286
+ this.wsService.events.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(async (event) => {
206
287
  switch (event.type) {
288
+ case 'thread:created':
289
+ this.upsertThread(event.payload.thread);
290
+ break;
291
+ case 'thread:deleted':
292
+ this.onThreadDeleted(event.payload);
293
+ break;
207
294
  case 'thread:title-updated':
208
295
  this.onThreadTitleUpdated(event.payload);
209
296
  break;
297
+ case 'thread:run-started':
298
+ await this.onThreadRunStarted(event.payload);
299
+ break;
300
+ case 'thread:run-finished':
301
+ this.onThreadRunFinished(event.payload);
302
+ break;
210
303
  case 'thread:messages-updated':
211
- this.onThreadMessagesUpdated(event.payload);
304
+ this.upsertThread(event.payload.thread);
305
+ if (this.completeLatch && this.completeLatchThreadId === event.payload.threadId) {
306
+ await this.completeLatch();
307
+ }
308
+ else {
309
+ this.onThreadMessagesUpdated(event.payload);
310
+ }
212
311
  break;
213
312
  }
214
313
  });
215
314
  }
315
+ subscribeToWsConnections() {
316
+ this.wsService.opened.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => {
317
+ if (!this.hasSeenWsOpen) {
318
+ this.hasSeenWsOpen = true;
319
+ return;
320
+ }
321
+ this.reloadThreads().subscribe(() => {
322
+ const threadId = this.selectedThread()?.id;
323
+ if (!threadId || this.isAgentWorking())
324
+ return;
325
+ this.resumeChat(threadId, {
326
+ reloadMessagesFirst: true,
327
+ reloadMessagesAfterResume: true,
328
+ });
329
+ });
330
+ });
331
+ }
216
332
  onThreadMessagesUpdated(payload) {
217
333
  const chat = this.chat();
218
334
  if (!chat || this.selectedThread()?.id !== payload.threadId)
@@ -228,24 +344,108 @@ class CortexChatService {
228
344
  this.syncConversationState(messages);
229
345
  });
230
346
  }
347
+ async onThreadRunStarted(payload) {
348
+ this.upsertThread(payload.thread);
349
+ if (this.selectedThread()?.id !== payload.thread.id || this.isAgentWorking())
350
+ return;
351
+ await this.resumeChat(payload.thread.id, {
352
+ reloadMessagesFirst: true,
353
+ reloadMessagesAfterResume: true,
354
+ });
355
+ }
231
356
  onThreadTitleUpdated(payload) {
357
+ this.upsertThread(payload.thread);
358
+ }
359
+ onThreadRunFinished(payload) {
360
+ this.upsertThread(payload.thread);
361
+ }
362
+ onThreadDeleted(payload) {
363
+ this.removeThread(payload.threadId);
364
+ if (this.selectedThread()?.id !== payload.threadId)
365
+ return;
366
+ this.deselectThread();
367
+ }
368
+ upsertThread(thread) {
232
369
  const current = this.threads();
233
- if (current) {
234
- this.threads.set(current.map((t) => (t.id === payload.threadId ? { ...t, title: payload.title } : t)));
370
+ const nextThreads = current ? [...current] : [];
371
+ const existingIndex = nextThreads.findIndex((currentThread) => currentThread.id === thread.id);
372
+ if (existingIndex === -1) {
373
+ nextThreads.push(thread);
374
+ }
375
+ else {
376
+ nextThreads[existingIndex] = { ...nextThreads[existingIndex], ...thread };
235
377
  }
378
+ this.threads.set(this.sortThreads(nextThreads));
236
379
  const selected = this.selectedThread();
237
- if (selected?.id === payload.threadId) {
238
- this.selectedThread.set({ ...selected, title: payload.title });
380
+ if (selected?.id === thread.id) {
381
+ this.selectedThread.set({ ...selected, ...thread });
239
382
  }
240
383
  }
384
+ removeThread(threadId) {
385
+ const current = this.threads();
386
+ if (!current)
387
+ return;
388
+ this.threads.set(current.filter((thread) => thread.id !== threadId));
389
+ }
390
+ updateThreadRunning(threadId, isRunning) {
391
+ const thread = this.threads()?.find((currentThread) => currentThread.id === threadId);
392
+ if (thread) {
393
+ this.upsertThread({ ...thread, isRunning });
394
+ }
395
+ const selected = this.selectedThread();
396
+ if (selected?.id === threadId) {
397
+ this.selectedThread.set({ ...selected, isRunning });
398
+ }
399
+ }
400
+ sortThreads(threads) {
401
+ return [...threads].sort((left, right) => {
402
+ const updatedAtDelta = Date.parse(right.updatedAt) - Date.parse(left.updatedAt);
403
+ if (updatedAtDelta !== 0)
404
+ return updatedAtDelta;
405
+ return Date.parse(right.createdAt) - Date.parse(left.createdAt);
406
+ });
407
+ }
408
+ async resumeChat(threadId, options) {
409
+ const chat = this.chat();
410
+ if (!chat || this.selectedThread()?.id !== threadId)
411
+ return;
412
+ if (options.reloadMessagesFirst) {
413
+ try {
414
+ await this.reloadMessagesForSelectedThread(threadId);
415
+ }
416
+ catch {
417
+ return;
418
+ }
419
+ if (this.chat() !== chat || this.selectedThread()?.id !== threadId)
420
+ return;
421
+ }
422
+ void chat.resumeStream().then(() => {
423
+ if (this.chat() !== chat || this.selectedThread()?.id !== threadId)
424
+ return;
425
+ if (this.isAgentWorking())
426
+ return;
427
+ if (!options.reloadMessagesAfterResume)
428
+ return;
429
+ this.reloadMessagesForSelectedThread(threadId).catch(() => { });
430
+ });
431
+ }
432
+ async reloadMessagesForSelectedThread(threadId) {
433
+ const chat = this.chat();
434
+ if (!chat || this.selectedThread()?.id !== threadId)
435
+ return;
436
+ const messages = await this.fetchJson(`/threads/${threadId}/messages`);
437
+ if (this.chat() !== chat || this.selectedThread()?.id !== threadId)
438
+ return;
439
+ chat.messages = messages;
440
+ this.syncConversationState(messages);
441
+ }
241
442
  reloadThreads() {
242
- return fromPromise(this.fetchJson('/threads')).pipe(tap((threads) => this.threads.set(threads)));
443
+ return fromPromise(this.fetchJson('/threads')).pipe(tap((threads) => this.threads.set(this.sortThreads(threads))));
243
444
  }
244
445
  reloadMessages(threadId) {
245
446
  return fromPromise(this.fetchJson(`/threads/${threadId}/messages`));
246
447
  }
247
448
  syncConversationState(messages) {
248
- this.isAgentWorking.set(false);
249
449
  this.hasPendingToolCalls.set(this.hasIncompleteToolCalls(messages));
250
450
  }
251
451
  hasIncompleteToolCalls(messages) {
@@ -301,10 +501,10 @@ class CortexChatService {
301
501
  const text = await res.text();
302
502
  return text ? JSON.parse(text) : undefined;
303
503
  }
304
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: CortexChatService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
305
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: CortexChatService });
504
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CortexChatService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
505
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CortexChatService });
306
506
  }
307
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: CortexChatService, decorators: [{
507
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CortexChatService, decorators: [{
308
508
  type: Injectable
309
509
  }], ctorParameters: () => [] });
310
510
  /**
@@ -328,6 +528,15 @@ function fixChat(chat) {
328
528
  chat.state.snapshot = deepClone;
329
529
  }
330
530
 
531
+ class MessageAbortedFlagComponent {
532
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MessageAbortedFlagComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
533
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.5", type: MessageAbortedFlagComponent, isStandalone: true, selector: "cortex-message-aborted-flag", host: { classAttribute: "cortex-aborted-flag" }, ngImport: i0, template: "<span class=\"cortex-aborted-flag__line\"></span>\n<span class=\"cortex-aborted-flag__label\">\n <svg class=\"cortex-aborted-flag__icon\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\">\n <path d=\"M6 1.5v5M6 8.75v.5\" stroke=\"currentColor\" stroke-width=\"1.4\" stroke-linecap=\"round\" />\n </svg>\n {{ 'translate_aborted' | translate }}\n</span>\n<span class=\"cortex-aborted-flag__line\"></span>\n", styles: ["@keyframes cortex-aborted-fade-in{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}.cortex-aborted-flag{display:flex;align-items:center;gap:.625rem;padding:.25rem 0;animation:cortex-aborted-fade-in .3s ease-out both;-webkit-user-select:none;user-select:none}.cortex-aborted-flag__line{flex:1;height:1px;background:repeating-linear-gradient(90deg,#e2a36f 0px,#e2a36f 4px,transparent 4px,transparent 8px);opacity:.5}.cortex-aborted-flag__label{display:inline-flex;align-items:center;gap:.3125rem;font-family:SF Mono,Cascadia Code,Fira Code,JetBrains Mono,ui-monospace,monospace;font-size:.625rem;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:#c2824a}.cortex-aborted-flag__icon{color:#c2824a;flex-shrink:0}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
534
+ }
535
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MessageAbortedFlagComponent, decorators: [{
536
+ type: Component,
537
+ args: [{ selector: 'cortex-message-aborted-flag', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [TranslatePipe], host: { class: 'cortex-aborted-flag' }, template: "<span class=\"cortex-aborted-flag__line\"></span>\n<span class=\"cortex-aborted-flag__label\">\n <svg class=\"cortex-aborted-flag__icon\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\">\n <path d=\"M6 1.5v5M6 8.75v.5\" stroke=\"currentColor\" stroke-width=\"1.4\" stroke-linecap=\"round\" />\n </svg>\n {{ 'translate_aborted' | translate }}\n</span>\n<span class=\"cortex-aborted-flag__line\"></span>\n", styles: ["@keyframes cortex-aborted-fade-in{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}.cortex-aborted-flag{display:flex;align-items:center;gap:.625rem;padding:.25rem 0;animation:cortex-aborted-fade-in .3s ease-out both;-webkit-user-select:none;user-select:none}.cortex-aborted-flag__line{flex:1;height:1px;background:repeating-linear-gradient(90deg,#e2a36f 0px,#e2a36f 4px,transparent 4px,transparent 8px);opacity:.5}.cortex-aborted-flag__label{display:inline-flex;align-items:center;gap:.3125rem;font-family:SF Mono,Cascadia Code,Fira Code,JetBrains Mono,ui-monospace,monospace;font-size:.625rem;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:#c2824a}.cortex-aborted-flag__icon{color:#c2824a;flex-shrink:0}\n"] }]
538
+ }] });
539
+
331
540
  class MarkedPipe {
332
541
  sanitizer;
333
542
  constructor(sanitizer) {
@@ -344,10 +553,10 @@ class MarkedPipe {
344
553
  .replace(/<(t[hd])([\s>])/g, '<$1 style="padding:0.5rem 1rem"$2');
345
554
  return this.sanitizer.bypassSecurityTrustHtml(DOMPurify.sanitize(html));
346
555
  }
347
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MarkedPipe, deps: [{ token: i1.DomSanitizer }], target: i0.ɵɵFactoryTarget.Pipe });
348
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.4", ngImport: i0, type: MarkedPipe, isStandalone: true, name: "marked" });
556
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MarkedPipe, deps: [{ token: i1.DomSanitizer }], target: i0.ɵɵFactoryTarget.Pipe });
557
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.5", ngImport: i0, type: MarkedPipe, isStandalone: true, name: "marked" });
349
558
  }
350
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MarkedPipe, decorators: [{
559
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MarkedPipe, decorators: [{
351
560
  type: Pipe,
352
561
  args: [{
353
562
  name: 'marked',
@@ -382,9 +591,15 @@ class StreamTextSmoother {
382
591
  constructor(onUpdate) {
383
592
  this.onUpdate = onUpdate;
384
593
  }
594
+ seed(displayedText) {
595
+ this.fullText = displayedText;
596
+ this.displayedLength = displayedText.length;
597
+ this.onUpdate(displayedText);
598
+ }
385
599
  update(newFullText, done) {
386
600
  this.fullText = newFullText;
387
601
  this.isDone = done;
602
+ this.displayedLength = Math.min(this.displayedLength, this.fullText.length);
388
603
  if (done && this.displayedLength >= this.fullText.length) {
389
604
  this.onUpdate(this.fullText);
390
605
  this.stopAnimation();
@@ -437,23 +652,28 @@ class MessageTextPartComponent {
437
652
  effect(() => {
438
653
  const part = this.textPart();
439
654
  const role = this.role();
655
+ const isStreaming = part.state === 'streaming';
440
656
  if (role !== 'assistant') {
441
657
  this.destroySmoother();
442
658
  this.displayedText.set(part.text);
443
659
  this.isFirstRender = false;
444
660
  return;
445
661
  }
446
- // Historical message already complete on first render — show immediately
447
- if (this.isFirstRender && part.state !== 'streaming') {
662
+ if (!isStreaming) {
663
+ this.destroySmoother();
448
664
  this.displayedText.set(part.text);
449
665
  this.isFirstRender = false;
450
666
  return;
451
667
  }
452
- this.isFirstRender = false;
453
- if (!this.smoother) {
454
- this.smoother = new StreamTextSmoother((text) => this.displayedText.set(text));
668
+ if (this.isFirstRender) {
669
+ this.ensureSmoother();
670
+ this.smoother.seed(part.text);
671
+ this.isFirstRender = false;
672
+ return;
455
673
  }
456
- this.smoother.update(part.text, part.state !== 'streaming');
674
+ this.isFirstRender = false;
675
+ this.ensureSmoother();
676
+ this.smoother.update(part.text, false);
457
677
  });
458
678
  }
459
679
  ngOnDestroy() {
@@ -465,20 +685,27 @@ class MessageTextPartComponent {
465
685
  this.smoother = null;
466
686
  }
467
687
  }
468
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MessageTextPartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
469
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.4", type: MessageTextPartComponent, isStandalone: true, selector: "cortex-message-text-part", inputs: { role: { classPropertyName: "role", publicName: "role", isSignal: true, isRequired: true, transformFunction: null }, textPart: { classPropertyName: "textPart", publicName: "textPart", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div\n class=\"cortex-text-part\"\n [class.cortex-text-part--assistant]=\"role() === 'assistant'\"\n [class.cortex-text-part--user]=\"role() === 'user'\"\n>\n <div\n class=\"cortex-text-bubble\"\n [class.cortex-text-bubble--assistant]=\"role() === 'assistant'\"\n [class.cortex-text-bubble--user]=\"role() === 'user'\"\n [innerHTML]=\"displayedText() | marked\"\n ></div>\n</div>\n", styles: [".cortex-text-part{width:100%;display:flex;flex-direction:column}.cortex-text-part--assistant{align-items:flex-start}.cortex-text-part--user{align-items:flex-end}[dir=rtl] .cortex-text-part--assistant{align-items:flex-start}[dir=rtl] .cortex-text-part--user{align-items:flex-end}.cortex-text-bubble{max-width:80%;font-size:.8125rem;line-height:1.625;padding:1rem;border-radius:1rem;border:1px solid #e2e8f0;color:#334155}.cortex-text-bubble--assistant{background:#f1f5f9;border-bottom-left-radius:0}[dir=rtl] .cortex-text-bubble--assistant{border-bottom-left-radius:1rem;border-bottom-right-radius:0}.cortex-text-bubble--user{background:#f8fafc;border-bottom-right-radius:0}[dir=rtl] .cortex-text-bubble--user{border-bottom-right-radius:1rem;border-bottom-left-radius:0}.cortex-text-bubble h1,.cortex-text-bubble h2,.cortex-text-bubble h3,.cortex-text-bubble h4,.cortex-text-bubble h5,.cortex-text-bubble h6{margin-top:1.25em;margin-bottom:.5em;font-weight:600;line-height:1.3;color:#1e293b}.cortex-text-bubble h1:first-child,.cortex-text-bubble h2:first-child,.cortex-text-bubble h3:first-child,.cortex-text-bubble h4:first-child,.cortex-text-bubble h5:first-child,.cortex-text-bubble h6:first-child{margin-top:0}.cortex-text-bubble h1{font-size:1.25em}.cortex-text-bubble h2{font-size:1.125em}.cortex-text-bubble h3{font-size:1em}.cortex-text-bubble p{margin-top:.75em;margin-bottom:.75em}.cortex-text-bubble p:first-child{margin-top:0}.cortex-text-bubble p:last-child{margin-bottom:0}.cortex-text-bubble ul,.cortex-text-bubble ol{margin-top:.75em;margin-bottom:.75em;padding-inline-start:1.5em}.cortex-text-bubble ul{list-style-type:disc}.cortex-text-bubble ol{list-style-type:decimal}.cortex-text-bubble li{margin-top:.25em;margin-bottom:.25em}.cortex-text-bubble code{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:.875em;background:#e2e8f0;padding:.125em .375em;border-radius:.25rem}.cortex-text-bubble pre{margin-top:.75em;margin-bottom:.75em;padding:.75em 1em;background:#1e293b;border-radius:.5rem;overflow-x:auto;font-size:.8125em;line-height:1.6}.cortex-text-bubble pre code{background:transparent;padding:0;color:#e2e8f0}.cortex-text-bubble blockquote{margin-top:.75em;margin-bottom:.75em;padding-inline-start:1em;border-inline-start:3px solid #cbd5e1;color:#64748b;font-style:italic}.cortex-text-bubble a{color:#2563eb;text-decoration:underline}.cortex-text-bubble a:hover{color:#1d4ed8}.cortex-text-bubble table{width:100%;border-collapse:collapse;margin-top:.75em;margin-bottom:.75em;font-size:.875em}.cortex-text-bubble th,.cortex-text-bubble td{border:1px solid #e2e8f0;padding:.375em .75em;text-align:start}.cortex-text-bubble th{background:#f8fafc;font-weight:600}.cortex-text-bubble hr{margin-top:1.5em;margin-bottom:1.5em;border:none;border-top:1px solid #e2e8f0}.cortex-text-bubble img{max-width:100%;height:auto;border-radius:.375rem}\n"], dependencies: [{ kind: "pipe", type: MarkedPipe, name: "marked" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
688
+ ensureSmoother() {
689
+ if (this.smoother) {
690
+ return;
691
+ }
692
+ this.smoother = new StreamTextSmoother((text) => this.displayedText.set(text));
693
+ this.smoother.seed(this.displayedText());
694
+ }
695
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MessageTextPartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
696
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.5", type: MessageTextPartComponent, isStandalone: true, selector: "cortex-message-text-part", inputs: { role: { classPropertyName: "role", publicName: "role", isSignal: true, isRequired: true, transformFunction: null }, textPart: { classPropertyName: "textPart", publicName: "textPart", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div\n class=\"cortex-text-part\"\n [class.cortex-text-part--assistant]=\"role() === 'assistant'\"\n [class.cortex-text-part--user]=\"role() === 'user'\"\n>\n <div\n class=\"cortex-text-bubble\"\n [class.cortex-text-bubble--assistant]=\"role() === 'assistant'\"\n [class.cortex-text-bubble--user]=\"role() === 'user'\"\n [innerHTML]=\"displayedText() | marked\"\n ></div>\n</div>\n", styles: [".cortex-text-part{width:100%;display:flex;flex-direction:column}.cortex-text-part--assistant{align-items:flex-start}.cortex-text-part--user{align-items:flex-end}[dir=rtl] .cortex-text-part--assistant{align-items:flex-start}[dir=rtl] .cortex-text-part--user{align-items:flex-end}.cortex-text-bubble{max-width:80%;font-size:.8125rem;line-height:1.625;padding:1rem;border-radius:1rem;border:1px solid #e2e8f0;color:#334155}.cortex-text-bubble--assistant{background:#f1f5f9;border-bottom-left-radius:0}[dir=rtl] .cortex-text-bubble--assistant{border-bottom-left-radius:1rem;border-bottom-right-radius:0}.cortex-text-bubble--user{background:#f8fafc;border-bottom-right-radius:0}[dir=rtl] .cortex-text-bubble--user{border-bottom-right-radius:1rem;border-bottom-left-radius:0}.cortex-text-bubble h1,.cortex-text-bubble h2,.cortex-text-bubble h3,.cortex-text-bubble h4,.cortex-text-bubble h5,.cortex-text-bubble h6{margin-top:1.25em;margin-bottom:.5em;font-weight:600;line-height:1.3;color:#1e293b}.cortex-text-bubble h1:first-child,.cortex-text-bubble h2:first-child,.cortex-text-bubble h3:first-child,.cortex-text-bubble h4:first-child,.cortex-text-bubble h5:first-child,.cortex-text-bubble h6:first-child{margin-top:0}.cortex-text-bubble h1{font-size:1.25em}.cortex-text-bubble h2{font-size:1.125em}.cortex-text-bubble h3{font-size:1em}.cortex-text-bubble p{margin-top:.75em;margin-bottom:.75em}.cortex-text-bubble p:first-child{margin-top:0}.cortex-text-bubble p:last-child{margin-bottom:0}.cortex-text-bubble ul,.cortex-text-bubble ol{margin-top:.75em;margin-bottom:.75em;padding-inline-start:1.5em}.cortex-text-bubble ul{list-style-type:disc}.cortex-text-bubble ol{list-style-type:decimal}.cortex-text-bubble li{margin-top:.25em;margin-bottom:.25em}.cortex-text-bubble code{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:.875em;background:#e2e8f0;padding:.125em .375em;border-radius:.25rem}.cortex-text-bubble pre{margin-top:.75em;margin-bottom:.75em;padding:.75em 1em;background:#1e293b;border-radius:.5rem;overflow-x:auto;font-size:.8125em;line-height:1.6}.cortex-text-bubble pre code{background:transparent;padding:0;color:#e2e8f0}.cortex-text-bubble blockquote{margin-top:.75em;margin-bottom:.75em;padding-inline-start:1em;border-inline-start:3px solid #cbd5e1;color:#64748b;font-style:italic}.cortex-text-bubble a{color:#2563eb;text-decoration:underline}.cortex-text-bubble a:hover{color:#1d4ed8}.cortex-text-bubble table{width:100%;border-collapse:collapse;margin-top:.75em;margin-bottom:.75em;font-size:.875em}.cortex-text-bubble th,.cortex-text-bubble td{border:1px solid #e2e8f0;padding:.375em .75em;text-align:start}.cortex-text-bubble th{background:#f8fafc;font-weight:600}.cortex-text-bubble hr{margin-top:1.5em;margin-bottom:1.5em;border:none;border-top:1px solid #e2e8f0}.cortex-text-bubble img{max-width:100%;height:auto;border-radius:.375rem}\n"], dependencies: [{ kind: "pipe", type: MarkedPipe, name: "marked" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
470
697
  }
471
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MessageTextPartComponent, decorators: [{
698
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MessageTextPartComponent, decorators: [{
472
699
  type: Component,
473
700
  args: [{ selector: 'cortex-message-text-part', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [MarkedPipe], template: "<div\n class=\"cortex-text-part\"\n [class.cortex-text-part--assistant]=\"role() === 'assistant'\"\n [class.cortex-text-part--user]=\"role() === 'user'\"\n>\n <div\n class=\"cortex-text-bubble\"\n [class.cortex-text-bubble--assistant]=\"role() === 'assistant'\"\n [class.cortex-text-bubble--user]=\"role() === 'user'\"\n [innerHTML]=\"displayedText() | marked\"\n ></div>\n</div>\n", styles: [".cortex-text-part{width:100%;display:flex;flex-direction:column}.cortex-text-part--assistant{align-items:flex-start}.cortex-text-part--user{align-items:flex-end}[dir=rtl] .cortex-text-part--assistant{align-items:flex-start}[dir=rtl] .cortex-text-part--user{align-items:flex-end}.cortex-text-bubble{max-width:80%;font-size:.8125rem;line-height:1.625;padding:1rem;border-radius:1rem;border:1px solid #e2e8f0;color:#334155}.cortex-text-bubble--assistant{background:#f1f5f9;border-bottom-left-radius:0}[dir=rtl] .cortex-text-bubble--assistant{border-bottom-left-radius:1rem;border-bottom-right-radius:0}.cortex-text-bubble--user{background:#f8fafc;border-bottom-right-radius:0}[dir=rtl] .cortex-text-bubble--user{border-bottom-right-radius:1rem;border-bottom-left-radius:0}.cortex-text-bubble h1,.cortex-text-bubble h2,.cortex-text-bubble h3,.cortex-text-bubble h4,.cortex-text-bubble h5,.cortex-text-bubble h6{margin-top:1.25em;margin-bottom:.5em;font-weight:600;line-height:1.3;color:#1e293b}.cortex-text-bubble h1:first-child,.cortex-text-bubble h2:first-child,.cortex-text-bubble h3:first-child,.cortex-text-bubble h4:first-child,.cortex-text-bubble h5:first-child,.cortex-text-bubble h6:first-child{margin-top:0}.cortex-text-bubble h1{font-size:1.25em}.cortex-text-bubble h2{font-size:1.125em}.cortex-text-bubble h3{font-size:1em}.cortex-text-bubble p{margin-top:.75em;margin-bottom:.75em}.cortex-text-bubble p:first-child{margin-top:0}.cortex-text-bubble p:last-child{margin-bottom:0}.cortex-text-bubble ul,.cortex-text-bubble ol{margin-top:.75em;margin-bottom:.75em;padding-inline-start:1.5em}.cortex-text-bubble ul{list-style-type:disc}.cortex-text-bubble ol{list-style-type:decimal}.cortex-text-bubble li{margin-top:.25em;margin-bottom:.25em}.cortex-text-bubble code{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:.875em;background:#e2e8f0;padding:.125em .375em;border-radius:.25rem}.cortex-text-bubble pre{margin-top:.75em;margin-bottom:.75em;padding:.75em 1em;background:#1e293b;border-radius:.5rem;overflow-x:auto;font-size:.8125em;line-height:1.6}.cortex-text-bubble pre code{background:transparent;padding:0;color:#e2e8f0}.cortex-text-bubble blockquote{margin-top:.75em;margin-bottom:.75em;padding-inline-start:1em;border-inline-start:3px solid #cbd5e1;color:#64748b;font-style:italic}.cortex-text-bubble a{color:#2563eb;text-decoration:underline}.cortex-text-bubble a:hover{color:#1d4ed8}.cortex-text-bubble table{width:100%;border-collapse:collapse;margin-top:.75em;margin-bottom:.75em;font-size:.875em}.cortex-text-bubble th,.cortex-text-bubble td{border:1px solid #e2e8f0;padding:.375em .75em;text-align:start}.cortex-text-bubble th{background:#f8fafc;font-weight:600}.cortex-text-bubble hr{margin-top:1.5em;margin-bottom:1.5em;border:none;border-top:1px solid #e2e8f0}.cortex-text-bubble img{max-width:100%;height:auto;border-radius:.375rem}\n"] }]
474
701
  }], ctorParameters: () => [], propDecorators: { role: [{ type: i0.Input, args: [{ isSignal: true, alias: "role", required: true }] }], textPart: [{ type: i0.Input, args: [{ isSignal: true, alias: "textPart", required: true }] }] } });
475
702
 
476
703
  class MessageReasoningPartComponent {
477
704
  reasoningPart = input.required(...(ngDevMode ? [{ debugName: "reasoningPart" }] : /* istanbul ignore next */ []));
478
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MessageReasoningPartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
479
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: MessageReasoningPartComponent, isStandalone: true, selector: "cortex-message-reasoning-part", inputs: { reasoningPart: { classPropertyName: "reasoningPart", publicName: "reasoningPart", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "@let p = reasoningPart();\n<details class=\"cortex-reasoning-details\">\n <summary class=\"cortex-reasoning-details__summary\">\n <div class=\"cortex-reasoning-details__header\">\n <span class=\"cortex-reasoning-details__icon\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 20 20\" fill=\"none\" aria-hidden=\"true\">\n <path\n d=\"M10 2C6.686 2 4 4.686 4 8c0 1.655.672 3.154 1.757 4.243.362.363.576.858.576 1.371V14.5a1 1 0 0 0 1 1h5.334a1 1 0 0 0 1-1v-.886c0-.513.214-1.008.576-1.371A5.978 5.978 0 0 0 16 8c0-3.314-2.686-6-6-6Z\"\n stroke=\"currentColor\"\n stroke-width=\"1.4\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n <path\n d=\"M7.5 17.5h5M8.5 8a2 2 0 0 1 2-2\"\n stroke=\"currentColor\"\n stroke-width=\"1.4\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </span>\n\n <div class=\"cortex-reasoning-details__title-group\">\n <div class=\"cortex-reasoning-details__title-row\">\n <div class=\"cortex-reasoning-details__title\">Reasoning</div>\n @if (p.state) {\n <span\n class=\"cortex-reasoning-details__badge\"\n [ngClass]=\"{\n 'cortex-reasoning-details__badge--streaming': p.state === 'streaming',\n 'cortex-reasoning-details__badge--done': p.state === 'done',\n }\"\n >\n {{ p.state === 'streaming' ? 'Streaming' : 'Done' }}\n </span>\n }\n </div>\n </div>\n </div>\n\n <span class=\"cortex-reasoning-details__chevron\" aria-hidden=\"true\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 20 20\" fill=\"none\">\n <path\n d=\"m5.75 8.25 4.25 4.25 4.25-4.25\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </span>\n </summary>\n\n <div class=\"cortex-reasoning-details__body\">\n <div class=\"cortex-reasoning-details__content\">\n <pre class=\"cortex-reasoning-details__pre\">{{\n p.text.trim() ? p.text : 'No reasoning provided.'\n }}</pre>\n </div>\n </div>\n</details>\n", styles: [".cortex-reasoning-details{width:100%;border-radius:.5rem;border:1px solid #e2e8f0;background:#f8fafc;overflow:hidden}.cortex-reasoning-details__summary{list-style:none;cursor:pointer;-webkit-user-select:none;user-select:none;padding:.75rem 1rem;display:flex;align-items:center;gap:.75rem}.cortex-reasoning-details__summary::-webkit-details-marker{display:none}.cortex-reasoning-details__header{display:flex;align-items:center;gap:.5rem;min-width:0;flex:1}.cortex-reasoning-details__icon{display:inline-flex;height:1.5rem;width:1.5rem;align-items:center;justify-content:center;border-radius:.25rem;background:#e0e7ff;color:#4f46e5}.cortex-reasoning-details__title-group{min-width:0}.cortex-reasoning-details__title-row{display:flex;align-items:center;gap:.5rem}.cortex-reasoning-details__title{font-weight:500;color:#334155;font-size:.875rem}.cortex-reasoning-details__badge{display:inline-flex;align-items:center;border-radius:.25rem;padding:.125rem .375rem;font-size:.6875rem;font-weight:500}.cortex-reasoning-details__badge--streaming{background:#fef3c7;color:#b45309}.cortex-reasoning-details__badge--done{background:#d1fae5;color:#047857}.cortex-reasoning-details__chevron{margin-inline-start:auto;display:inline-flex;height:1.5rem;width:1.5rem;align-items:center;justify-content:center;border-radius:.25rem;color:#94a3b8;transition:transform .2s}details[open]>summary>.cortex-reasoning-details__chevron{transform:rotate(180deg)}.cortex-reasoning-details__body{padding:0 1rem 1rem}.cortex-reasoning-details__content{margin-top:.25rem;border-radius:.25rem;background:#fff;border:1px solid #e2e8f0;padding:.75rem}.cortex-reasoning-details__pre{margin:0;white-space:pre-wrap;overflow-wrap:break-word;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:.75rem;line-height:1.625;color:#334155}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
705
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MessageReasoningPartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
706
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: MessageReasoningPartComponent, isStandalone: true, selector: "cortex-message-reasoning-part", inputs: { reasoningPart: { classPropertyName: "reasoningPart", publicName: "reasoningPart", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "@let p = reasoningPart();\n<details class=\"cortex-reasoning-details\">\n <summary class=\"cortex-reasoning-details__summary\">\n <div class=\"cortex-reasoning-details__header\">\n <span class=\"cortex-reasoning-details__icon\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 20 20\" fill=\"none\" aria-hidden=\"true\">\n <path\n d=\"M10 2C6.686 2 4 4.686 4 8c0 1.655.672 3.154 1.757 4.243.362.363.576.858.576 1.371V14.5a1 1 0 0 0 1 1h5.334a1 1 0 0 0 1-1v-.886c0-.513.214-1.008.576-1.371A5.978 5.978 0 0 0 16 8c0-3.314-2.686-6-6-6Z\"\n stroke=\"currentColor\"\n stroke-width=\"1.4\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n <path\n d=\"M7.5 17.5h5M8.5 8a2 2 0 0 1 2-2\"\n stroke=\"currentColor\"\n stroke-width=\"1.4\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </span>\n\n <div class=\"cortex-reasoning-details__title-group\">\n <div class=\"cortex-reasoning-details__title-row\">\n <div class=\"cortex-reasoning-details__title\">Reasoning</div>\n @if (p.state) {\n <span\n class=\"cortex-reasoning-details__badge\"\n [ngClass]=\"{\n 'cortex-reasoning-details__badge--streaming': p.state === 'streaming',\n 'cortex-reasoning-details__badge--done': p.state === 'done',\n }\"\n >\n {{ p.state === 'streaming' ? 'Streaming' : 'Done' }}\n </span>\n }\n </div>\n </div>\n </div>\n\n <span class=\"cortex-reasoning-details__chevron\" aria-hidden=\"true\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 20 20\" fill=\"none\">\n <path\n d=\"m5.75 8.25 4.25 4.25 4.25-4.25\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </span>\n </summary>\n\n <div class=\"cortex-reasoning-details__body\">\n <div class=\"cortex-reasoning-details__content\">\n <pre class=\"cortex-reasoning-details__pre\">{{\n p.text.trim() ? p.text : 'No reasoning provided.'\n }}</pre>\n </div>\n </div>\n</details>\n", styles: [".cortex-reasoning-details{width:100%;border-radius:.5rem;border:1px solid #e2e8f0;background:#f8fafc;overflow:hidden}.cortex-reasoning-details__summary{list-style:none;cursor:pointer;-webkit-user-select:none;user-select:none;padding:.75rem 1rem;display:flex;align-items:center;gap:.75rem}.cortex-reasoning-details__summary::-webkit-details-marker{display:none}.cortex-reasoning-details__header{display:flex;align-items:center;gap:.5rem;min-width:0;flex:1}.cortex-reasoning-details__icon{display:inline-flex;height:1.5rem;width:1.5rem;align-items:center;justify-content:center;border-radius:.25rem;background:#e0e7ff;color:#4f46e5}.cortex-reasoning-details__title-group{min-width:0}.cortex-reasoning-details__title-row{display:flex;align-items:center;gap:.5rem}.cortex-reasoning-details__title{font-weight:500;color:#334155;font-size:.875rem}.cortex-reasoning-details__badge{display:inline-flex;align-items:center;border-radius:.25rem;padding:.125rem .375rem;font-size:.6875rem;font-weight:500}.cortex-reasoning-details__badge--streaming{background:#fef3c7;color:#b45309}.cortex-reasoning-details__badge--done{background:#d1fae5;color:#047857}.cortex-reasoning-details__chevron{margin-inline-start:auto;display:inline-flex;height:1.5rem;width:1.5rem;align-items:center;justify-content:center;border-radius:.25rem;color:#94a3b8;transition:transform .2s}details[open]>summary>.cortex-reasoning-details__chevron{transform:rotate(180deg)}.cortex-reasoning-details__body{padding:0 1rem 1rem}.cortex-reasoning-details__content{margin-top:.25rem;border-radius:.25rem;background:#fff;border:1px solid #e2e8f0;padding:.75rem}.cortex-reasoning-details__pre{margin:0;white-space:pre-wrap;overflow-wrap:break-word;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:.75rem;line-height:1.625;color:#334155}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
480
707
  }
481
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MessageReasoningPartComponent, decorators: [{
708
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MessageReasoningPartComponent, decorators: [{
482
709
  type: Component,
483
710
  args: [{ selector: 'cortex-message-reasoning-part', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [NgClass], template: "@let p = reasoningPart();\n<details class=\"cortex-reasoning-details\">\n <summary class=\"cortex-reasoning-details__summary\">\n <div class=\"cortex-reasoning-details__header\">\n <span class=\"cortex-reasoning-details__icon\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 20 20\" fill=\"none\" aria-hidden=\"true\">\n <path\n d=\"M10 2C6.686 2 4 4.686 4 8c0 1.655.672 3.154 1.757 4.243.362.363.576.858.576 1.371V14.5a1 1 0 0 0 1 1h5.334a1 1 0 0 0 1-1v-.886c0-.513.214-1.008.576-1.371A5.978 5.978 0 0 0 16 8c0-3.314-2.686-6-6-6Z\"\n stroke=\"currentColor\"\n stroke-width=\"1.4\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n <path\n d=\"M7.5 17.5h5M8.5 8a2 2 0 0 1 2-2\"\n stroke=\"currentColor\"\n stroke-width=\"1.4\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </span>\n\n <div class=\"cortex-reasoning-details__title-group\">\n <div class=\"cortex-reasoning-details__title-row\">\n <div class=\"cortex-reasoning-details__title\">Reasoning</div>\n @if (p.state) {\n <span\n class=\"cortex-reasoning-details__badge\"\n [ngClass]=\"{\n 'cortex-reasoning-details__badge--streaming': p.state === 'streaming',\n 'cortex-reasoning-details__badge--done': p.state === 'done',\n }\"\n >\n {{ p.state === 'streaming' ? 'Streaming' : 'Done' }}\n </span>\n }\n </div>\n </div>\n </div>\n\n <span class=\"cortex-reasoning-details__chevron\" aria-hidden=\"true\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 20 20\" fill=\"none\">\n <path\n d=\"m5.75 8.25 4.25 4.25 4.25-4.25\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </span>\n </summary>\n\n <div class=\"cortex-reasoning-details__body\">\n <div class=\"cortex-reasoning-details__content\">\n <pre class=\"cortex-reasoning-details__pre\">{{\n p.text.trim() ? p.text : 'No reasoning provided.'\n }}</pre>\n </div>\n </div>\n</details>\n", styles: [".cortex-reasoning-details{width:100%;border-radius:.5rem;border:1px solid #e2e8f0;background:#f8fafc;overflow:hidden}.cortex-reasoning-details__summary{list-style:none;cursor:pointer;-webkit-user-select:none;user-select:none;padding:.75rem 1rem;display:flex;align-items:center;gap:.75rem}.cortex-reasoning-details__summary::-webkit-details-marker{display:none}.cortex-reasoning-details__header{display:flex;align-items:center;gap:.5rem;min-width:0;flex:1}.cortex-reasoning-details__icon{display:inline-flex;height:1.5rem;width:1.5rem;align-items:center;justify-content:center;border-radius:.25rem;background:#e0e7ff;color:#4f46e5}.cortex-reasoning-details__title-group{min-width:0}.cortex-reasoning-details__title-row{display:flex;align-items:center;gap:.5rem}.cortex-reasoning-details__title{font-weight:500;color:#334155;font-size:.875rem}.cortex-reasoning-details__badge{display:inline-flex;align-items:center;border-radius:.25rem;padding:.125rem .375rem;font-size:.6875rem;font-weight:500}.cortex-reasoning-details__badge--streaming{background:#fef3c7;color:#b45309}.cortex-reasoning-details__badge--done{background:#d1fae5;color:#047857}.cortex-reasoning-details__chevron{margin-inline-start:auto;display:inline-flex;height:1.5rem;width:1.5rem;align-items:center;justify-content:center;border-radius:.25rem;color:#94a3b8;transition:transform .2s}details[open]>summary>.cortex-reasoning-details__chevron{transform:rotate(180deg)}.cortex-reasoning-details__body{padding:0 1rem 1rem}.cortex-reasoning-details__content{margin-top:.25rem;border-radius:.25rem;background:#fff;border:1px solid #e2e8f0;padding:.75rem}.cortex-reasoning-details__pre{margin:0;white-space:pre-wrap;overflow-wrap:break-word;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:.75rem;line-height:1.625;color:#334155}\n"] }]
484
711
  }], propDecorators: { reasoningPart: [{ type: i0.Input, args: [{ isSignal: true, alias: "reasoningPart", required: true }] }] } });
@@ -502,10 +729,10 @@ class HighlightPipe {
502
729
  escapeHtml(str) {
503
730
  return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
504
731
  }
505
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: HighlightPipe, deps: [{ token: i1.DomSanitizer }], target: i0.ɵɵFactoryTarget.Pipe });
506
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.4", ngImport: i0, type: HighlightPipe, isStandalone: true, name: "highlight" });
732
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: HighlightPipe, deps: [{ token: i1.DomSanitizer }], target: i0.ɵɵFactoryTarget.Pipe });
733
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.5", ngImport: i0, type: HighlightPipe, isStandalone: true, name: "highlight" });
507
734
  }
508
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: HighlightPipe, decorators: [{
735
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: HighlightPipe, decorators: [{
509
736
  type: Pipe,
510
737
  args: [{ name: 'highlight', standalone: true }]
511
738
  }], ctorParameters: () => [{ type: i1.DomSanitizer }] });
@@ -603,10 +830,10 @@ class JsonTreeComponent {
603
830
  }
604
831
  return value;
605
832
  }
606
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: JsonTreeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
607
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: JsonTreeComponent, isStandalone: true, selector: "cortex-json-tree", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null }, expandDepth: { classPropertyName: "expandDepth", publicName: "expandDepth", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "cortex-json-tree" }, ngImport: i0, template: "<!-- Entry point: parse and render the root value -->\n<ng-container\n *ngTemplateOutlet=\"valueTemplate; context: { $implicit: parsed(data()), path: '$', depth: 0 }\"\n/>\n\n<!-- Recursive value renderer -->\n<ng-template #valueTemplate let-value let-path=\"path\" let-depth=\"depth\">\n @if (isObject(value)) {\n @if (objectLength(value) === 0) {\n <span class=\"jt-bracket\">{{ '{' }}{{ '}' }}</span>\n } @else {\n <span class=\"jt-toggle\" (click)=\"toggle(path, depth); $event.stopPropagation()\" role=\"button\">\n <span class=\"jt-arrow\" [class.jt-arrow--collapsed]=\"isCollapsed(path, depth)\">&#9662;</span>\n <span class=\"jt-bracket\">{{ '{' }}</span>\n </span>\n @if (isCollapsed(path, depth)) {\n <span\n class=\"jt-collapsed-hint\"\n (click)=\"toggle(path, depth); $event.stopPropagation()\"\n role=\"button\"\n >{{ objectLength(value) }}\n {{ objectLength(value) === 1 ? 'property' : 'properties' }}</span\n ><span class=\"jt-bracket\">{{ '}' }}</span>\n } @else {\n <div class=\"jt-indent\">\n @for (entry of objectEntries(value); track entry[0]; let last = $last) {\n <div class=\"jt-line\">\n <span class=\"jt-key\">\"{{ entry[0] }}\"</span><span class=\"jt-colon\">: </span>\n @if (isContainer(entry[1])) {\n <ng-container\n *ngTemplateOutlet=\"\n valueTemplate;\n context: { $implicit: entry[1], path: path + '.' + entry[0], depth: depth + 1 }\n \"\n />\n } @else {\n <span [class]=\"primitiveClass(entry[1])\">{{ formatPrimitive(entry[1]) }}</span>\n }\n @if (!last) {\n <span class=\"jt-comma\">,</span>\n }\n </div>\n }\n </div>\n <span class=\"jt-bracket\">{{ '}' }}</span>\n }\n }\n } @else if (isArray(value)) {\n @if (arrayLength(value) === 0) {\n <span class=\"jt-bracket\">[]</span>\n } @else {\n <span class=\"jt-toggle\" (click)=\"toggle(path, depth); $event.stopPropagation()\" role=\"button\">\n <span class=\"jt-arrow\" [class.jt-arrow--collapsed]=\"isCollapsed(path, depth)\">&#9662;</span>\n <span class=\"jt-bracket\">[</span>\n </span>\n @if (isCollapsed(path, depth)) {\n <span\n class=\"jt-collapsed-hint\"\n (click)=\"toggle(path, depth); $event.stopPropagation()\"\n role=\"button\"\n >{{ arrayLength(value) }} {{ arrayLength(value) === 1 ? 'item' : 'items' }}</span\n ><span class=\"jt-bracket\">]</span>\n } @else {\n <div class=\"jt-indent\">\n @for (item of arrayItems(value); track $index; let last = $last) {\n <div class=\"jt-line\">\n @if (isContainer(item)) {\n <ng-container\n *ngTemplateOutlet=\"\n valueTemplate;\n context: { $implicit: item, path: path + '[' + $index + ']', depth: depth + 1 }\n \"\n />\n } @else {\n <span [class]=\"primitiveClass(item)\">{{ formatPrimitive(item) }}</span>\n }\n @if (!last) {\n <span class=\"jt-comma\">,</span>\n }\n </div>\n }\n </div>\n <span class=\"jt-bracket\">]</span>\n }\n }\n } @else {\n <span [class]=\"primitiveClass(value)\">{{ formatPrimitive(value) }}</span>\n }\n</ng-template>\n", styles: [".cortex-json-tree{display:block;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:.75rem;line-height:1.25rem;-webkit-user-select:text;user-select:text;white-space:pre-wrap;word-break:break-word}.jt-indent{padding-inline-start:1.25em;border-inline-start:1px solid #e2e8f0;margin-inline-start:.3em}.jt-line{position:relative}.jt-toggle{cursor:pointer;-webkit-user-select:none;user-select:none}.jt-toggle:hover .jt-arrow{color:#475569}.jt-arrow{display:inline-block;width:1em;text-align:center;color:#94a3b8;font-size:.7em;transition:transform .15s ease;vertical-align:middle}.jt-arrow--collapsed{transform:rotate(-90deg)}.jt-bracket{color:#64748b}.jt-key{color:#6366f1}.jt-colon{color:#64748b}.jt-comma{color:#94a3b8}.jt-string{color:#059669}.jt-number{color:#2563eb}.jt-boolean{color:#d97706}.jt-null{color:#94a3b8;font-style:italic}.jt-collapsed-hint{display:inline-block;padding:0 .4em;margin:0 .15em;font-size:10px;line-height:1.5;color:#94a3b8;background:#f8fafc;border:1px solid #e2e8f0;border-radius:3px;font-style:italic;cursor:pointer;-webkit-user-select:none;user-select:none;vertical-align:middle}.jt-collapsed-hint:hover{color:#64748b;border-color:#cbd5e1;background:#f1f5f9}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
833
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: JsonTreeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
834
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: JsonTreeComponent, isStandalone: true, selector: "cortex-json-tree", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null }, expandDepth: { classPropertyName: "expandDepth", publicName: "expandDepth", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "cortex-json-tree" }, ngImport: i0, template: "<!-- Entry point: parse and render the root value -->\n<ng-container\n *ngTemplateOutlet=\"valueTemplate; context: { $implicit: parsed(data()), path: '$', depth: 0 }\"\n/>\n\n<!-- Recursive value renderer -->\n<ng-template #valueTemplate let-value let-path=\"path\" let-depth=\"depth\">\n @if (isObject(value)) {\n @if (objectLength(value) === 0) {\n <span class=\"jt-bracket\">{{ '{' }}{{ '}' }}</span>\n } @else {\n <span class=\"jt-toggle\" (click)=\"toggle(path, depth); $event.stopPropagation()\" role=\"button\">\n <span class=\"jt-arrow\" [class.jt-arrow--collapsed]=\"isCollapsed(path, depth)\">&#9662;</span>\n <span class=\"jt-bracket\">{{ '{' }}</span>\n </span>\n @if (isCollapsed(path, depth)) {\n <span\n class=\"jt-collapsed-hint\"\n (click)=\"toggle(path, depth); $event.stopPropagation()\"\n role=\"button\"\n >{{ objectLength(value) }}\n {{ objectLength(value) === 1 ? 'property' : 'properties' }}</span\n ><span class=\"jt-bracket\">{{ '}' }}</span>\n } @else {\n <div class=\"jt-indent\">\n @for (entry of objectEntries(value); track entry[0]; let last = $last) {\n <div class=\"jt-line\">\n <span class=\"jt-key\">\"{{ entry[0] }}\"</span><span class=\"jt-colon\">: </span>\n @if (isContainer(entry[1])) {\n <ng-container\n *ngTemplateOutlet=\"\n valueTemplate;\n context: { $implicit: entry[1], path: path + '.' + entry[0], depth: depth + 1 }\n \"\n />\n } @else {\n <span [class]=\"primitiveClass(entry[1])\">{{ formatPrimitive(entry[1]) }}</span>\n }\n @if (!last) {\n <span class=\"jt-comma\">,</span>\n }\n </div>\n }\n </div>\n <span class=\"jt-bracket\">{{ '}' }}</span>\n }\n }\n } @else if (isArray(value)) {\n @if (arrayLength(value) === 0) {\n <span class=\"jt-bracket\">[]</span>\n } @else {\n <span class=\"jt-toggle\" (click)=\"toggle(path, depth); $event.stopPropagation()\" role=\"button\">\n <span class=\"jt-arrow\" [class.jt-arrow--collapsed]=\"isCollapsed(path, depth)\">&#9662;</span>\n <span class=\"jt-bracket\">[</span>\n </span>\n @if (isCollapsed(path, depth)) {\n <span\n class=\"jt-collapsed-hint\"\n (click)=\"toggle(path, depth); $event.stopPropagation()\"\n role=\"button\"\n >{{ arrayLength(value) }} {{ arrayLength(value) === 1 ? 'item' : 'items' }}</span\n ><span class=\"jt-bracket\">]</span>\n } @else {\n <div class=\"jt-indent\">\n @for (item of arrayItems(value); track $index; let last = $last) {\n <div class=\"jt-line\">\n @if (isContainer(item)) {\n <ng-container\n *ngTemplateOutlet=\"\n valueTemplate;\n context: { $implicit: item, path: path + '[' + $index + ']', depth: depth + 1 }\n \"\n />\n } @else {\n <span [class]=\"primitiveClass(item)\">{{ formatPrimitive(item) }}</span>\n }\n @if (!last) {\n <span class=\"jt-comma\">,</span>\n }\n </div>\n }\n </div>\n <span class=\"jt-bracket\">]</span>\n }\n }\n } @else {\n <span [class]=\"primitiveClass(value)\">{{ formatPrimitive(value) }}</span>\n }\n</ng-template>\n", styles: [".cortex-json-tree{display:block;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:.75rem;line-height:1.25rem;-webkit-user-select:text;user-select:text;white-space:pre-wrap;word-break:break-word}.jt-indent{padding-inline-start:1.25em;border-inline-start:1px solid #e2e8f0;margin-inline-start:.3em}.jt-line{position:relative}.jt-toggle{cursor:pointer;-webkit-user-select:none;user-select:none}.jt-toggle:hover .jt-arrow{color:#475569}.jt-arrow{display:inline-block;width:1em;text-align:center;color:#94a3b8;font-size:.7em;transition:transform .15s ease;vertical-align:middle}.jt-arrow--collapsed{transform:rotate(-90deg)}.jt-bracket{color:#64748b}.jt-key{color:#6366f1}.jt-colon{color:#64748b}.jt-comma{color:#94a3b8}.jt-string{color:#059669}.jt-number{color:#2563eb}.jt-boolean{color:#d97706}.jt-null{color:#94a3b8;font-style:italic}.jt-collapsed-hint{display:inline-block;padding:0 .4em;margin:0 .15em;font-size:10px;line-height:1.5;color:#94a3b8;background:#f8fafc;border:1px solid #e2e8f0;border-radius:3px;font-style:italic;cursor:pointer;-webkit-user-select:none;user-select:none;vertical-align:middle}.jt-collapsed-hint:hover{color:#64748b;border-color:#cbd5e1;background:#f1f5f9}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
608
835
  }
609
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: JsonTreeComponent, decorators: [{
836
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: JsonTreeComponent, decorators: [{
610
837
  type: Component,
611
838
  args: [{ selector: 'cortex-json-tree', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [NgTemplateOutlet], host: { class: 'cortex-json-tree' }, template: "<!-- Entry point: parse and render the root value -->\n<ng-container\n *ngTemplateOutlet=\"valueTemplate; context: { $implicit: parsed(data()), path: '$', depth: 0 }\"\n/>\n\n<!-- Recursive value renderer -->\n<ng-template #valueTemplate let-value let-path=\"path\" let-depth=\"depth\">\n @if (isObject(value)) {\n @if (objectLength(value) === 0) {\n <span class=\"jt-bracket\">{{ '{' }}{{ '}' }}</span>\n } @else {\n <span class=\"jt-toggle\" (click)=\"toggle(path, depth); $event.stopPropagation()\" role=\"button\">\n <span class=\"jt-arrow\" [class.jt-arrow--collapsed]=\"isCollapsed(path, depth)\">&#9662;</span>\n <span class=\"jt-bracket\">{{ '{' }}</span>\n </span>\n @if (isCollapsed(path, depth)) {\n <span\n class=\"jt-collapsed-hint\"\n (click)=\"toggle(path, depth); $event.stopPropagation()\"\n role=\"button\"\n >{{ objectLength(value) }}\n {{ objectLength(value) === 1 ? 'property' : 'properties' }}</span\n ><span class=\"jt-bracket\">{{ '}' }}</span>\n } @else {\n <div class=\"jt-indent\">\n @for (entry of objectEntries(value); track entry[0]; let last = $last) {\n <div class=\"jt-line\">\n <span class=\"jt-key\">\"{{ entry[0] }}\"</span><span class=\"jt-colon\">: </span>\n @if (isContainer(entry[1])) {\n <ng-container\n *ngTemplateOutlet=\"\n valueTemplate;\n context: { $implicit: entry[1], path: path + '.' + entry[0], depth: depth + 1 }\n \"\n />\n } @else {\n <span [class]=\"primitiveClass(entry[1])\">{{ formatPrimitive(entry[1]) }}</span>\n }\n @if (!last) {\n <span class=\"jt-comma\">,</span>\n }\n </div>\n }\n </div>\n <span class=\"jt-bracket\">{{ '}' }}</span>\n }\n }\n } @else if (isArray(value)) {\n @if (arrayLength(value) === 0) {\n <span class=\"jt-bracket\">[]</span>\n } @else {\n <span class=\"jt-toggle\" (click)=\"toggle(path, depth); $event.stopPropagation()\" role=\"button\">\n <span class=\"jt-arrow\" [class.jt-arrow--collapsed]=\"isCollapsed(path, depth)\">&#9662;</span>\n <span class=\"jt-bracket\">[</span>\n </span>\n @if (isCollapsed(path, depth)) {\n <span\n class=\"jt-collapsed-hint\"\n (click)=\"toggle(path, depth); $event.stopPropagation()\"\n role=\"button\"\n >{{ arrayLength(value) }} {{ arrayLength(value) === 1 ? 'item' : 'items' }}</span\n ><span class=\"jt-bracket\">]</span>\n } @else {\n <div class=\"jt-indent\">\n @for (item of arrayItems(value); track $index; let last = $last) {\n <div class=\"jt-line\">\n @if (isContainer(item)) {\n <ng-container\n *ngTemplateOutlet=\"\n valueTemplate;\n context: { $implicit: item, path: path + '[' + $index + ']', depth: depth + 1 }\n \"\n />\n } @else {\n <span [class]=\"primitiveClass(item)\">{{ formatPrimitive(item) }}</span>\n }\n @if (!last) {\n <span class=\"jt-comma\">,</span>\n }\n </div>\n }\n </div>\n <span class=\"jt-bracket\">]</span>\n }\n }\n } @else {\n <span [class]=\"primitiveClass(value)\">{{ formatPrimitive(value) }}</span>\n }\n</ng-template>\n", styles: [".cortex-json-tree{display:block;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:.75rem;line-height:1.25rem;-webkit-user-select:text;user-select:text;white-space:pre-wrap;word-break:break-word}.jt-indent{padding-inline-start:1.25em;border-inline-start:1px solid #e2e8f0;margin-inline-start:.3em}.jt-line{position:relative}.jt-toggle{cursor:pointer;-webkit-user-select:none;user-select:none}.jt-toggle:hover .jt-arrow{color:#475569}.jt-arrow{display:inline-block;width:1em;text-align:center;color:#94a3b8;font-size:.7em;transition:transform .15s ease;vertical-align:middle}.jt-arrow--collapsed{transform:rotate(-90deg)}.jt-bracket{color:#64748b}.jt-key{color:#6366f1}.jt-colon{color:#64748b}.jt-comma{color:#94a3b8}.jt-string{color:#059669}.jt-number{color:#2563eb}.jt-boolean{color:#d97706}.jt-null{color:#94a3b8;font-style:italic}.jt-collapsed-hint{display:inline-block;padding:0 .4em;margin:0 .15em;font-size:10px;line-height:1.5;color:#94a3b8;background:#f8fafc;border:1px solid #e2e8f0;border-radius:3px;font-style:italic;cursor:pointer;-webkit-user-select:none;user-select:none;vertical-align:middle}.jt-collapsed-hint:hover{color:#64748b;border-color:#cbd5e1;background:#f1f5f9}\n"] }]
612
839
  }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: true }] }], expandDepth: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandDepth", required: false }] }] } });
@@ -656,10 +883,10 @@ class MessageToolCallPartComponent {
656
883
  return '';
657
884
  return type.startsWith('tool-') ? type.slice('tool-'.length) : type;
658
885
  }
659
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MessageToolCallPartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
660
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: MessageToolCallPartComponent, isStandalone: true, selector: "cortex-message-tool-call-part", inputs: { toolCallPart: { classPropertyName: "toolCallPart", publicName: "toolCallPart", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<details class=\"cortex-tool-details\">\n <summary class=\"cortex-tool-details__summary\">\n <div class=\"cortex-tool-details__header\">\n <div class=\"cortex-tool-details__icon-box\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 20 20\" class=\"cortex-tool-details__icon-svg\" fill=\"none\">\n <path\n d=\"M6.5 6.5 3.75 10l2.75 3.5M13.5 6.5 16.25 10l-2.75 3.5M11.25 5.75 8.75 14.25\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </div>\n\n <div class=\"cortex-tool-details__info\">\n <div class=\"cortex-tool-details__title-row\">\n <div class=\"cortex-tool-details__name-row\">\n <div class=\"cortex-tool-details__name\" [attr.title]=\"toolCallPart().title || null\">\n {{ toolCallPart().title ?? 'Tool call' }}\n </div>\n @if (toolName()) {\n <span\n class=\"cortex-tool-details__tool-badge\"\n [attr.title]=\"toolCallPart().type || null\"\n >{{ toolName() }}</span\n >\n }\n </div>\n <div class=\"cortex-tool-details__id-line\">\n <span class=\"cortex-tool-details__id-label\">ID</span>\n <span class=\"cortex-tool-details__id-value\"> {{ toolCallPart().toolCallId }}</span>\n @if (toolCallPart().providerExecuted) {\n <span class=\"cortex-tool-details__provider-badge\">\n <span class=\"cortex-tool-details__provider-dot\"></span>\n provider\n </span>\n }\n </div>\n </div>\n\n <div class=\"cortex-tool-details__actions\">\n <span\n class=\"cortex-tool-details__state-badge\"\n [ngClass]=\"{\n 'cortex-tool-details__state-badge--success':\n toolCallPart().state === 'output-available',\n 'cortex-tool-details__state-badge--error': toolCallPart().state === 'output-error',\n 'cortex-tool-details__state-badge--denied': toolCallPart().state === 'output-denied',\n 'cortex-tool-details__state-badge--approval':\n toolCallPart().state === 'approval-requested' ||\n toolCallPart().state === 'approval-responded',\n 'cortex-tool-details__state-badge--pending':\n toolCallPart().state === 'input-streaming' ||\n toolCallPart().state === 'input-available',\n }\"\n >\n @switch (toolCallPart().state) {\n @case ('input-streaming') {\n <span\n class=\"cortex-tool-details__status-dot cortex-tool-details__status-dot--amber cortex-tool-details__status-dot--pulse\"\n ></span>\n Calling\n }\n @case ('input-available') {\n <span\n class=\"cortex-tool-details__status-dot cortex-tool-details__status-dot--amber\"\n ></span>\n Input ready\n }\n @case ('approval-requested') {\n <span\n class=\"cortex-tool-details__status-dot cortex-tool-details__status-dot--violet cortex-tool-details__status-dot--pulse\"\n ></span>\n Needs approval\n }\n @case ('approval-responded') {\n @if (toolCallPart().approval?.approved) {\n <span\n class=\"cortex-tool-details__status-dot cortex-tool-details__status-dot--emerald\"\n ></span>\n Approved\n } @else {\n <span\n class=\"cortex-tool-details__status-dot cortex-tool-details__status-dot--slate\"\n ></span>\n Responded\n }\n }\n @case ('output-available') {\n <span\n class=\"cortex-tool-details__status-dot cortex-tool-details__status-dot--emerald\"\n ></span>\n {{ 'translate_completed' | translate }}\n }\n @case ('output-error') {\n <span\n class=\"cortex-tool-details__status-dot cortex-tool-details__status-dot--red\"\n ></span>\n Error\n }\n @case ('output-denied') {\n <span\n class=\"cortex-tool-details__status-dot cortex-tool-details__status-dot--slate\"\n ></span>\n Denied\n }\n }\n </span>\n\n <span class=\"cortex-tool-details__chevron\" aria-hidden=\"true\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 20 20\" fill=\"none\">\n <path\n d=\"m5.75 8.25 4.25 4.25 4.25-4.25\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </span>\n </div>\n </div>\n </div>\n </summary>\n\n <div class=\"cortex-tool-details__body\">\n <div class=\"cortex-tool-details__panels\">\n @for (snippet of codeSnippets(); track snippet.key) {\n <div class=\"cortex-tool-details__panel\">\n <div class=\"cortex-tool-details__panel-header\">\n <div class=\"cortex-tool-details__panel-label\">{{ snippet.key }}</div>\n <div class=\"cortex-tool-details__panel-lang\">{{ snippet.lang }}</div>\n </div>\n <pre\n dir=\"ltr\"\n class=\"cortex-tool-details__code-pre\"\n ><code class=\"hljs\" [innerHTML]=\"snippet.value | highlight : snippet.lang\"></code></pre>\n </div>\n }\n\n @if (remainingInput(); as remaining) {\n <div class=\"cortex-tool-details__panel\">\n <div class=\"cortex-tool-details__panel-header\">\n <div class=\"cortex-tool-details__panel-label\">Input</div>\n <div class=\"cortex-tool-details__panel-lang\">json</div>\n </div>\n <div dir=\"ltr\" class=\"cortex-tool-details__tree-container\">\n <cortex-json-tree [data]=\"remaining\" [expandDepth]=\"2\" />\n </div>\n </div>\n }\n\n @if (toolCallPart().state === 'output-available') {\n <div class=\"cortex-tool-details__panel cortex-tool-details__panel--success\">\n <div class=\"cortex-tool-details__panel-header cortex-tool-details__panel-header--success\">\n <div class=\"cortex-tool-details__panel-label cortex-tool-details__panel-label--success\">\n Output\n </div>\n <div class=\"cortex-tool-details__panel-lang cortex-tool-details__panel-lang--success\">\n json\n </div>\n </div>\n <div dir=\"ltr\" class=\"cortex-tool-details__tree-container\">\n <cortex-json-tree [data]=\"toolCallPart().output\" [expandDepth]=\"2\" />\n </div>\n </div>\n }\n\n @if (toolCallPart().state === 'output-error') {\n <div class=\"cortex-tool-details__panel cortex-tool-details__panel--error\">\n <div class=\"cortex-tool-details__panel-header cortex-tool-details__panel-header--error\">\n <div class=\"cortex-tool-details__panel-label cortex-tool-details__panel-label--error\">\n Error\n </div>\n <div class=\"cortex-tool-details__panel-lang cortex-tool-details__panel-lang--error\">\n text\n </div>\n </div>\n <pre dir=\"ltr\" class=\"cortex-tool-details__error-pre\">{{ toolCallPart().errorText }}</pre>\n </div>\n }\n\n @if (toolCallPart().state === 'output-denied') {\n <div class=\"cortex-tool-details__panel\">\n <div class=\"cortex-tool-details__panel-header\">\n <div class=\"cortex-tool-details__panel-label\">Denied</div>\n <div class=\"cortex-tool-details__panel-lang\">approval</div>\n </div>\n <div class=\"cortex-tool-details__denied-body\">\n Tool execution was denied.\n @if (toolCallPart().approval?.reason) {\n <div class=\"cortex-tool-details__reason-box\">\n <div class=\"cortex-tool-details__reason-label\">Reason</div>\n <div class=\"cortex-tool-details__reason-text\">\n {{ toolCallPart().approval?.reason }}\n </div>\n </div>\n }\n </div>\n </div>\n }\n\n @if (toolCallPart().state === 'approval-requested') {\n <div class=\"cortex-tool-details__panel cortex-tool-details__panel--approval\">\n <div\n class=\"cortex-tool-details__panel-header cortex-tool-details__panel-header--approval\"\n >\n <div\n class=\"cortex-tool-details__panel-label cortex-tool-details__panel-label--approval\"\n >\n Approval requested\n </div>\n <div class=\"cortex-tool-details__panel-lang cortex-tool-details__panel-lang--approval\">\n {{ toolCallPart().approval?.id }}\n </div>\n </div>\n <div class=\"cortex-tool-details__approval-body\">\n Waiting for approval to execute this tool.\n </div>\n </div>\n }\n\n @if (toolCallPart().state === 'approval-responded') {\n <div class=\"cortex-tool-details__panel cortex-tool-details__panel--approval\">\n <div\n class=\"cortex-tool-details__panel-header cortex-tool-details__panel-header--approval\"\n >\n <div\n class=\"cortex-tool-details__panel-label cortex-tool-details__panel-label--approval\"\n >\n Approval response\n </div>\n <div class=\"cortex-tool-details__panel-lang cortex-tool-details__panel-lang--approval\">\n {{ toolCallPart().approval?.id }}\n </div>\n </div>\n <div class=\"cortex-tool-details__approval-body\">\n @if (toolCallPart().approval?.approved) {\n Approved.\n } @else {\n Response received.\n }\n @if (toolCallPart().approval?.reason) {\n <div\n class=\"cortex-tool-details__reason-box cortex-tool-details__reason-box--approval\"\n >\n <div\n class=\"cortex-tool-details__reason-label cortex-tool-details__reason-label--approval\"\n >\n Reason\n </div>\n <div\n class=\"cortex-tool-details__reason-text cortex-tool-details__reason-text--approval\"\n >\n {{ toolCallPart().approval?.reason }}\n </div>\n </div>\n }\n </div>\n </div>\n }\n </div>\n </div>\n</details>\n", styles: [".cortex-tool-details{width:100%;border-radius:.5rem;border:1px solid #e2e8f0;background:#f8fafc;overflow:hidden}.cortex-tool-details__summary{list-style:none;cursor:pointer;-webkit-user-select:none;user-select:none;padding:.75rem 1rem}.cortex-tool-details__summary::-webkit-details-marker{display:none}details[open]>.cortex-tool-details__summary{border-bottom:1px solid #e2e8f0}.cortex-tool-details__header{display:flex;align-items:flex-start;gap:.75rem}.cortex-tool-details__icon-box{flex-shrink:0;margin-top:.125rem;width:1.75rem;height:1.75rem;border-radius:.25rem;background:#1e293b;color:#fff;display:flex;align-items:center;justify-content:center}.cortex-tool-details__icon-svg{width:1rem;height:1rem}.cortex-tool-details__info{min-width:0;flex:1;display:flex;align-items:center;gap:.5rem}.cortex-tool-details__title-row{min-width:0;flex:1}.cortex-tool-details__name-row{display:flex;align-items:center;gap:.5rem;min-width:0}.cortex-tool-details__name{font-weight:500;color:#1e293b;font-size:.875rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.cortex-tool-details__tool-badge{display:none;align-items:center;border-radius:.25rem;background:#e2e8f0;padding:.125rem .375rem;font-size:.6875rem;font-weight:500;color:#475569;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace}@media(min-width:640px){.cortex-tool-details__tool-badge{display:inline-flex}}.cortex-tool-details__id-line{margin-top:.125rem;font-size:.6875rem;color:#64748b;word-break:break-all}.cortex-tool-details__id-label{font-weight:500;color:#475569}.cortex-tool-details__id-value{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace}.cortex-tool-details__provider-badge{margin-inline-start:.5rem;display:inline-flex;align-items:center;gap:.25rem;color:#047857}.cortex-tool-details__provider-dot{width:.375rem;height:.375rem;border-radius:9999px;background:#10b981}.cortex-tool-details__actions{display:flex;align-items:center;gap:.5rem}.cortex-tool-details__state-badge{display:inline-flex;align-items:center;gap:.375rem;border-radius:.25rem;padding:.25rem .5rem;font-size:.6875rem;font-weight:500;border:1px solid}.cortex-tool-details__state-badge--success{background:#ecfdf5;color:#047857;border-color:#a7f3d0}.cortex-tool-details__state-badge--error{background:#fef2f2;color:#b91c1c;border-color:#fecaca}.cortex-tool-details__state-badge--denied{background:#f1f5f9;color:#475569;border-color:#e2e8f0}.cortex-tool-details__state-badge--approval{background:#f5f3ff;color:#6d28d9;border-color:#ddd6fe}.cortex-tool-details__state-badge--pending{background:#fffbeb;color:#b45309;border-color:#fde68a}.cortex-tool-details__status-dot{width:.375rem;height:.375rem;border-radius:9999px}.cortex-tool-details__status-dot--amber{background:#f59e0b}.cortex-tool-details__status-dot--violet{background:#8b5cf6}.cortex-tool-details__status-dot--emerald{background:#10b981}.cortex-tool-details__status-dot--red{background:#ef4444}.cortex-tool-details__status-dot--slate{background:#64748b}.cortex-tool-details__status-dot--pulse{animation:cortex-tool-status-pulse 2s ease-in-out infinite}@keyframes cortex-tool-status-pulse{0%,to{opacity:1}50%{opacity:.4}}.cortex-tool-details__chevron{display:inline-flex;width:1.5rem;height:1.5rem;align-items:center;justify-content:center;border-radius:.25rem;color:#94a3b8;transition:transform .2s}details[open]>summary .cortex-tool-details__chevron{transform:rotate(180deg)}.cortex-tool-details__body{background:#fff;padding:.75rem 1rem 1rem}.cortex-tool-details__panels{display:grid;gap:.75rem}.cortex-tool-details__panel{border-radius:.5rem;border:1px solid #e2e8f0;overflow:hidden}.cortex-tool-details__panel--success{border-color:#a7f3d0}.cortex-tool-details__panel--error{border-color:#fecaca}.cortex-tool-details__panel--approval{border-color:#ddd6fe}.cortex-tool-details__panel-header{padding:.5rem .75rem;display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid #e2e8f0;background:#f8fafc}.cortex-tool-details__panel-header--success{border-bottom-color:#a7f3d0;background:#ecfdf5}.cortex-tool-details__panel-header--error{border-bottom-color:#fecaca;background:#fef2f2}.cortex-tool-details__panel-header--approval{border-bottom-color:#ddd6fe;background:#f5f3ff}.cortex-tool-details__panel-label{font-size:.6875rem;font-weight:500;color:#475569}.cortex-tool-details__panel-label--success{color:#047857}.cortex-tool-details__panel-label--error{color:#b91c1c}.cortex-tool-details__panel-label--approval{color:#6d28d9}.cortex-tool-details__panel-lang{font-size:.6875rem;color:#94a3b8;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace}.cortex-tool-details__panel-lang--success{color:#059669}.cortex-tool-details__panel-lang--error{color:#dc2626}.cortex-tool-details__panel-lang--approval{color:#7c3aed}.cortex-tool-details__code-pre{margin:0;max-height:20rem;overflow:auto;padding:.75rem;font-size:.75rem;line-height:1.25rem;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;white-space:pre;overflow-wrap:break-word}.cortex-tool-details__tree-container{max-height:16rem;overflow:auto;padding:.75rem}.cortex-tool-details__error-pre{margin:0;max-height:16rem;overflow:auto;padding:.75rem;font-size:.75rem;line-height:1.25rem;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;color:#991b1b;white-space:pre-wrap;overflow-wrap:break-word}.cortex-tool-details__denied-body{padding:.75rem;font-size:.75rem;color:#334155}.cortex-tool-details__approval-body{padding:.75rem;font-size:.75rem;color:#5b21b6}.cortex-tool-details__reason-box{margin-top:.5rem;border-radius:.25rem;background:#f8fafc;border:1px solid #e2e8f0;padding:.5rem}.cortex-tool-details__reason-box--approval{background:#f5f3ff;border-color:#ddd6fe}.cortex-tool-details__reason-label{font-size:.6875rem;font-weight:500;color:#475569}.cortex-tool-details__reason-label--approval{color:#6d28d9}.cortex-tool-details__reason-text{margin-top:.25rem;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:.75rem;color:#334155;overflow-wrap:break-word}.cortex-tool-details__reason-text--approval{color:#5b21b6}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: JsonTreeComponent, selector: "cortex-json-tree", inputs: ["data", "expandDepth"] }, { kind: "pipe", type: HighlightPipe, name: "highlight" }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
886
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MessageToolCallPartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
887
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: MessageToolCallPartComponent, isStandalone: true, selector: "cortex-message-tool-call-part", inputs: { toolCallPart: { classPropertyName: "toolCallPart", publicName: "toolCallPart", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<details class=\"cortex-tool-details\">\n <summary class=\"cortex-tool-details__summary\">\n <div class=\"cortex-tool-details__header\">\n <div class=\"cortex-tool-details__icon-box\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 20 20\" class=\"cortex-tool-details__icon-svg\" fill=\"none\">\n <path\n d=\"M6.5 6.5 3.75 10l2.75 3.5M13.5 6.5 16.25 10l-2.75 3.5M11.25 5.75 8.75 14.25\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </div>\n\n <div class=\"cortex-tool-details__info\">\n <div class=\"cortex-tool-details__title-row\">\n <div class=\"cortex-tool-details__name-row\">\n <div class=\"cortex-tool-details__name\" [attr.title]=\"toolCallPart().title || null\">\n {{ toolCallPart().title ?? 'Tool call' }}\n </div>\n @if (toolName()) {\n <span\n class=\"cortex-tool-details__tool-badge\"\n [attr.title]=\"toolCallPart().type || null\"\n >{{ toolName() }}</span\n >\n }\n </div>\n <div class=\"cortex-tool-details__id-line\">\n <span class=\"cortex-tool-details__id-label\">ID</span>\n <span class=\"cortex-tool-details__id-value\"> {{ toolCallPart().toolCallId }}</span>\n @if (toolCallPart().providerExecuted) {\n <span class=\"cortex-tool-details__provider-badge\">\n <span class=\"cortex-tool-details__provider-dot\"></span>\n provider\n </span>\n }\n </div>\n </div>\n\n <div class=\"cortex-tool-details__actions\">\n <span\n class=\"cortex-tool-details__state-badge\"\n [ngClass]=\"{\n 'cortex-tool-details__state-badge--success':\n toolCallPart().state === 'output-available',\n 'cortex-tool-details__state-badge--error': toolCallPart().state === 'output-error',\n 'cortex-tool-details__state-badge--denied': toolCallPart().state === 'output-denied',\n 'cortex-tool-details__state-badge--approval':\n toolCallPart().state === 'approval-requested' ||\n toolCallPart().state === 'approval-responded',\n 'cortex-tool-details__state-badge--pending':\n toolCallPart().state === 'input-streaming' ||\n toolCallPart().state === 'input-available',\n }\"\n >\n @switch (toolCallPart().state) {\n @case ('input-streaming') {\n <span\n class=\"cortex-tool-details__status-dot cortex-tool-details__status-dot--amber cortex-tool-details__status-dot--pulse\"\n ></span>\n Calling\n }\n @case ('input-available') {\n <span\n class=\"cortex-tool-details__status-dot cortex-tool-details__status-dot--amber\"\n ></span>\n Input ready\n }\n @case ('approval-requested') {\n <span\n class=\"cortex-tool-details__status-dot cortex-tool-details__status-dot--violet cortex-tool-details__status-dot--pulse\"\n ></span>\n Needs approval\n }\n @case ('approval-responded') {\n @if (toolCallPart().approval?.approved) {\n <span\n class=\"cortex-tool-details__status-dot cortex-tool-details__status-dot--emerald\"\n ></span>\n Approved\n } @else {\n <span\n class=\"cortex-tool-details__status-dot cortex-tool-details__status-dot--slate\"\n ></span>\n Responded\n }\n }\n @case ('output-available') {\n <span\n class=\"cortex-tool-details__status-dot cortex-tool-details__status-dot--emerald\"\n ></span>\n {{ 'translate_completed' | translate }}\n }\n @case ('output-error') {\n <span\n class=\"cortex-tool-details__status-dot cortex-tool-details__status-dot--red\"\n ></span>\n Error\n }\n @case ('output-denied') {\n <span\n class=\"cortex-tool-details__status-dot cortex-tool-details__status-dot--slate\"\n ></span>\n Denied\n }\n }\n </span>\n\n <span class=\"cortex-tool-details__chevron\" aria-hidden=\"true\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 20 20\" fill=\"none\">\n <path\n d=\"m5.75 8.25 4.25 4.25 4.25-4.25\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </span>\n </div>\n </div>\n </div>\n </summary>\n\n <div class=\"cortex-tool-details__body\">\n <div class=\"cortex-tool-details__panels\">\n @for (snippet of codeSnippets(); track snippet.key) {\n <div class=\"cortex-tool-details__panel\">\n <div class=\"cortex-tool-details__panel-header\">\n <div class=\"cortex-tool-details__panel-label\">{{ snippet.key }}</div>\n <div class=\"cortex-tool-details__panel-lang\">{{ snippet.lang }}</div>\n </div>\n <pre\n dir=\"ltr\"\n class=\"cortex-tool-details__code-pre\"\n ><code class=\"hljs\" [innerHTML]=\"snippet.value | highlight : snippet.lang\"></code></pre>\n </div>\n }\n\n @if (remainingInput(); as remaining) {\n <div class=\"cortex-tool-details__panel\">\n <div class=\"cortex-tool-details__panel-header\">\n <div class=\"cortex-tool-details__panel-label\">Input</div>\n <div class=\"cortex-tool-details__panel-lang\">json</div>\n </div>\n <div dir=\"ltr\" class=\"cortex-tool-details__tree-container\">\n <cortex-json-tree [data]=\"remaining\" [expandDepth]=\"2\" />\n </div>\n </div>\n }\n\n @if (toolCallPart().state === 'output-available') {\n <div class=\"cortex-tool-details__panel cortex-tool-details__panel--success\">\n <div class=\"cortex-tool-details__panel-header cortex-tool-details__panel-header--success\">\n <div class=\"cortex-tool-details__panel-label cortex-tool-details__panel-label--success\">\n Output\n </div>\n <div class=\"cortex-tool-details__panel-lang cortex-tool-details__panel-lang--success\">\n json\n </div>\n </div>\n <div dir=\"ltr\" class=\"cortex-tool-details__tree-container\">\n <cortex-json-tree [data]=\"toolCallPart().output\" [expandDepth]=\"2\" />\n </div>\n </div>\n }\n\n @if (toolCallPart().state === 'output-error') {\n <div class=\"cortex-tool-details__panel cortex-tool-details__panel--error\">\n <div class=\"cortex-tool-details__panel-header cortex-tool-details__panel-header--error\">\n <div class=\"cortex-tool-details__panel-label cortex-tool-details__panel-label--error\">\n Error\n </div>\n <div class=\"cortex-tool-details__panel-lang cortex-tool-details__panel-lang--error\">\n text\n </div>\n </div>\n <pre dir=\"ltr\" class=\"cortex-tool-details__error-pre\">{{ toolCallPart().errorText }}</pre>\n </div>\n }\n\n @if (toolCallPart().state === 'output-denied') {\n <div class=\"cortex-tool-details__panel\">\n <div class=\"cortex-tool-details__panel-header\">\n <div class=\"cortex-tool-details__panel-label\">Denied</div>\n <div class=\"cortex-tool-details__panel-lang\">approval</div>\n </div>\n <div class=\"cortex-tool-details__denied-body\">\n Tool execution was denied.\n @if (toolCallPart().approval?.reason) {\n <div class=\"cortex-tool-details__reason-box\">\n <div class=\"cortex-tool-details__reason-label\">Reason</div>\n <div class=\"cortex-tool-details__reason-text\">\n {{ toolCallPart().approval?.reason }}\n </div>\n </div>\n }\n </div>\n </div>\n }\n\n @if (toolCallPart().state === 'approval-requested') {\n <div class=\"cortex-tool-details__panel cortex-tool-details__panel--approval\">\n <div\n class=\"cortex-tool-details__panel-header cortex-tool-details__panel-header--approval\"\n >\n <div\n class=\"cortex-tool-details__panel-label cortex-tool-details__panel-label--approval\"\n >\n Approval requested\n </div>\n <div class=\"cortex-tool-details__panel-lang cortex-tool-details__panel-lang--approval\">\n {{ toolCallPart().approval?.id }}\n </div>\n </div>\n <div class=\"cortex-tool-details__approval-body\">\n Waiting for approval to execute this tool.\n </div>\n </div>\n }\n\n @if (toolCallPart().state === 'approval-responded') {\n <div class=\"cortex-tool-details__panel cortex-tool-details__panel--approval\">\n <div\n class=\"cortex-tool-details__panel-header cortex-tool-details__panel-header--approval\"\n >\n <div\n class=\"cortex-tool-details__panel-label cortex-tool-details__panel-label--approval\"\n >\n Approval response\n </div>\n <div class=\"cortex-tool-details__panel-lang cortex-tool-details__panel-lang--approval\">\n {{ toolCallPart().approval?.id }}\n </div>\n </div>\n <div class=\"cortex-tool-details__approval-body\">\n @if (toolCallPart().approval?.approved) {\n Approved.\n } @else {\n Response received.\n }\n @if (toolCallPart().approval?.reason) {\n <div\n class=\"cortex-tool-details__reason-box cortex-tool-details__reason-box--approval\"\n >\n <div\n class=\"cortex-tool-details__reason-label cortex-tool-details__reason-label--approval\"\n >\n Reason\n </div>\n <div\n class=\"cortex-tool-details__reason-text cortex-tool-details__reason-text--approval\"\n >\n {{ toolCallPart().approval?.reason }}\n </div>\n </div>\n }\n </div>\n </div>\n }\n </div>\n </div>\n</details>\n", styles: [".cortex-tool-details{width:100%;border-radius:.5rem;border:1px solid #e2e8f0;background:#f8fafc;overflow:hidden}.cortex-tool-details__summary{list-style:none;cursor:pointer;-webkit-user-select:none;user-select:none;padding:.75rem 1rem}.cortex-tool-details__summary::-webkit-details-marker{display:none}details[open]>.cortex-tool-details__summary{border-bottom:1px solid #e2e8f0}.cortex-tool-details__header{display:flex;align-items:flex-start;gap:.75rem}.cortex-tool-details__icon-box{flex-shrink:0;margin-top:.125rem;width:1.75rem;height:1.75rem;border-radius:.25rem;background:#1e293b;color:#fff;display:flex;align-items:center;justify-content:center}.cortex-tool-details__icon-svg{width:1rem;height:1rem}.cortex-tool-details__info{min-width:0;flex:1;display:flex;align-items:center;gap:.5rem}.cortex-tool-details__title-row{min-width:0;flex:1}.cortex-tool-details__name-row{display:flex;align-items:center;gap:.5rem;min-width:0}.cortex-tool-details__name{font-weight:500;color:#1e293b;font-size:.875rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.cortex-tool-details__tool-badge{display:none;align-items:center;border-radius:.25rem;background:#e2e8f0;padding:.125rem .375rem;font-size:.6875rem;font-weight:500;color:#475569;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace}@media(min-width:640px){.cortex-tool-details__tool-badge{display:inline-flex}}.cortex-tool-details__id-line{margin-top:.125rem;font-size:.6875rem;color:#64748b;word-break:break-all}.cortex-tool-details__id-label{font-weight:500;color:#475569}.cortex-tool-details__id-value{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace}.cortex-tool-details__provider-badge{margin-inline-start:.5rem;display:inline-flex;align-items:center;gap:.25rem;color:#047857}.cortex-tool-details__provider-dot{width:.375rem;height:.375rem;border-radius:9999px;background:#10b981}.cortex-tool-details__actions{display:flex;align-items:center;gap:.5rem}.cortex-tool-details__state-badge{display:inline-flex;align-items:center;gap:.375rem;border-radius:.25rem;padding:.25rem .5rem;font-size:.6875rem;font-weight:500;border:1px solid}.cortex-tool-details__state-badge--success{background:#ecfdf5;color:#047857;border-color:#a7f3d0}.cortex-tool-details__state-badge--error{background:#fef2f2;color:#b91c1c;border-color:#fecaca}.cortex-tool-details__state-badge--denied{background:#f1f5f9;color:#475569;border-color:#e2e8f0}.cortex-tool-details__state-badge--approval{background:#f5f3ff;color:#6d28d9;border-color:#ddd6fe}.cortex-tool-details__state-badge--pending{background:#fffbeb;color:#b45309;border-color:#fde68a}.cortex-tool-details__status-dot{width:.375rem;height:.375rem;border-radius:9999px}.cortex-tool-details__status-dot--amber{background:#f59e0b}.cortex-tool-details__status-dot--violet{background:#8b5cf6}.cortex-tool-details__status-dot--emerald{background:#10b981}.cortex-tool-details__status-dot--red{background:#ef4444}.cortex-tool-details__status-dot--slate{background:#64748b}.cortex-tool-details__status-dot--pulse{animation:cortex-tool-status-pulse 2s ease-in-out infinite}@keyframes cortex-tool-status-pulse{0%,to{opacity:1}50%{opacity:.4}}.cortex-tool-details__chevron{display:inline-flex;width:1.5rem;height:1.5rem;align-items:center;justify-content:center;border-radius:.25rem;color:#94a3b8;transition:transform .2s}details[open]>summary .cortex-tool-details__chevron{transform:rotate(180deg)}.cortex-tool-details__body{background:#fff;padding:.75rem 1rem 1rem}.cortex-tool-details__panels{display:grid;gap:.75rem}.cortex-tool-details__panel{border-radius:.5rem;border:1px solid #e2e8f0;overflow:hidden}.cortex-tool-details__panel--success{border-color:#a7f3d0}.cortex-tool-details__panel--error{border-color:#fecaca}.cortex-tool-details__panel--approval{border-color:#ddd6fe}.cortex-tool-details__panel-header{padding:.5rem .75rem;display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid #e2e8f0;background:#f8fafc}.cortex-tool-details__panel-header--success{border-bottom-color:#a7f3d0;background:#ecfdf5}.cortex-tool-details__panel-header--error{border-bottom-color:#fecaca;background:#fef2f2}.cortex-tool-details__panel-header--approval{border-bottom-color:#ddd6fe;background:#f5f3ff}.cortex-tool-details__panel-label{font-size:.6875rem;font-weight:500;color:#475569}.cortex-tool-details__panel-label--success{color:#047857}.cortex-tool-details__panel-label--error{color:#b91c1c}.cortex-tool-details__panel-label--approval{color:#6d28d9}.cortex-tool-details__panel-lang{font-size:.6875rem;color:#94a3b8;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace}.cortex-tool-details__panel-lang--success{color:#059669}.cortex-tool-details__panel-lang--error{color:#dc2626}.cortex-tool-details__panel-lang--approval{color:#7c3aed}.cortex-tool-details__code-pre{margin:0;max-height:20rem;overflow:auto;padding:.75rem;font-size:.75rem;line-height:1.25rem;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;white-space:pre;overflow-wrap:break-word}.cortex-tool-details__tree-container{max-height:16rem;overflow:auto;padding:.75rem}.cortex-tool-details__error-pre{margin:0;max-height:16rem;overflow:auto;padding:.75rem;font-size:.75rem;line-height:1.25rem;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;color:#991b1b;white-space:pre-wrap;overflow-wrap:break-word}.cortex-tool-details__denied-body{padding:.75rem;font-size:.75rem;color:#334155}.cortex-tool-details__approval-body{padding:.75rem;font-size:.75rem;color:#5b21b6}.cortex-tool-details__reason-box{margin-top:.5rem;border-radius:.25rem;background:#f8fafc;border:1px solid #e2e8f0;padding:.5rem}.cortex-tool-details__reason-box--approval{background:#f5f3ff;border-color:#ddd6fe}.cortex-tool-details__reason-label{font-size:.6875rem;font-weight:500;color:#475569}.cortex-tool-details__reason-label--approval{color:#6d28d9}.cortex-tool-details__reason-text{margin-top:.25rem;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:.75rem;color:#334155;overflow-wrap:break-word}.cortex-tool-details__reason-text--approval{color:#5b21b6}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: JsonTreeComponent, selector: "cortex-json-tree", inputs: ["data", "expandDepth"] }, { kind: "pipe", type: HighlightPipe, name: "highlight" }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
661
888
  }
662
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MessageToolCallPartComponent, decorators: [{
889
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MessageToolCallPartComponent, decorators: [{
663
890
  type: Component,
664
891
  args: [{ selector: 'cortex-message-tool-call-part', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [HighlightPipe, NgClass, TranslatePipe, JsonTreeComponent], template: "<details class=\"cortex-tool-details\">\n <summary class=\"cortex-tool-details__summary\">\n <div class=\"cortex-tool-details__header\">\n <div class=\"cortex-tool-details__icon-box\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 20 20\" class=\"cortex-tool-details__icon-svg\" fill=\"none\">\n <path\n d=\"M6.5 6.5 3.75 10l2.75 3.5M13.5 6.5 16.25 10l-2.75 3.5M11.25 5.75 8.75 14.25\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </div>\n\n <div class=\"cortex-tool-details__info\">\n <div class=\"cortex-tool-details__title-row\">\n <div class=\"cortex-tool-details__name-row\">\n <div class=\"cortex-tool-details__name\" [attr.title]=\"toolCallPart().title || null\">\n {{ toolCallPart().title ?? 'Tool call' }}\n </div>\n @if (toolName()) {\n <span\n class=\"cortex-tool-details__tool-badge\"\n [attr.title]=\"toolCallPart().type || null\"\n >{{ toolName() }}</span\n >\n }\n </div>\n <div class=\"cortex-tool-details__id-line\">\n <span class=\"cortex-tool-details__id-label\">ID</span>\n <span class=\"cortex-tool-details__id-value\"> {{ toolCallPart().toolCallId }}</span>\n @if (toolCallPart().providerExecuted) {\n <span class=\"cortex-tool-details__provider-badge\">\n <span class=\"cortex-tool-details__provider-dot\"></span>\n provider\n </span>\n }\n </div>\n </div>\n\n <div class=\"cortex-tool-details__actions\">\n <span\n class=\"cortex-tool-details__state-badge\"\n [ngClass]=\"{\n 'cortex-tool-details__state-badge--success':\n toolCallPart().state === 'output-available',\n 'cortex-tool-details__state-badge--error': toolCallPart().state === 'output-error',\n 'cortex-tool-details__state-badge--denied': toolCallPart().state === 'output-denied',\n 'cortex-tool-details__state-badge--approval':\n toolCallPart().state === 'approval-requested' ||\n toolCallPart().state === 'approval-responded',\n 'cortex-tool-details__state-badge--pending':\n toolCallPart().state === 'input-streaming' ||\n toolCallPart().state === 'input-available',\n }\"\n >\n @switch (toolCallPart().state) {\n @case ('input-streaming') {\n <span\n class=\"cortex-tool-details__status-dot cortex-tool-details__status-dot--amber cortex-tool-details__status-dot--pulse\"\n ></span>\n Calling\n }\n @case ('input-available') {\n <span\n class=\"cortex-tool-details__status-dot cortex-tool-details__status-dot--amber\"\n ></span>\n Input ready\n }\n @case ('approval-requested') {\n <span\n class=\"cortex-tool-details__status-dot cortex-tool-details__status-dot--violet cortex-tool-details__status-dot--pulse\"\n ></span>\n Needs approval\n }\n @case ('approval-responded') {\n @if (toolCallPart().approval?.approved) {\n <span\n class=\"cortex-tool-details__status-dot cortex-tool-details__status-dot--emerald\"\n ></span>\n Approved\n } @else {\n <span\n class=\"cortex-tool-details__status-dot cortex-tool-details__status-dot--slate\"\n ></span>\n Responded\n }\n }\n @case ('output-available') {\n <span\n class=\"cortex-tool-details__status-dot cortex-tool-details__status-dot--emerald\"\n ></span>\n {{ 'translate_completed' | translate }}\n }\n @case ('output-error') {\n <span\n class=\"cortex-tool-details__status-dot cortex-tool-details__status-dot--red\"\n ></span>\n Error\n }\n @case ('output-denied') {\n <span\n class=\"cortex-tool-details__status-dot cortex-tool-details__status-dot--slate\"\n ></span>\n Denied\n }\n }\n </span>\n\n <span class=\"cortex-tool-details__chevron\" aria-hidden=\"true\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 20 20\" fill=\"none\">\n <path\n d=\"m5.75 8.25 4.25 4.25 4.25-4.25\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </span>\n </div>\n </div>\n </div>\n </summary>\n\n <div class=\"cortex-tool-details__body\">\n <div class=\"cortex-tool-details__panels\">\n @for (snippet of codeSnippets(); track snippet.key) {\n <div class=\"cortex-tool-details__panel\">\n <div class=\"cortex-tool-details__panel-header\">\n <div class=\"cortex-tool-details__panel-label\">{{ snippet.key }}</div>\n <div class=\"cortex-tool-details__panel-lang\">{{ snippet.lang }}</div>\n </div>\n <pre\n dir=\"ltr\"\n class=\"cortex-tool-details__code-pre\"\n ><code class=\"hljs\" [innerHTML]=\"snippet.value | highlight : snippet.lang\"></code></pre>\n </div>\n }\n\n @if (remainingInput(); as remaining) {\n <div class=\"cortex-tool-details__panel\">\n <div class=\"cortex-tool-details__panel-header\">\n <div class=\"cortex-tool-details__panel-label\">Input</div>\n <div class=\"cortex-tool-details__panel-lang\">json</div>\n </div>\n <div dir=\"ltr\" class=\"cortex-tool-details__tree-container\">\n <cortex-json-tree [data]=\"remaining\" [expandDepth]=\"2\" />\n </div>\n </div>\n }\n\n @if (toolCallPart().state === 'output-available') {\n <div class=\"cortex-tool-details__panel cortex-tool-details__panel--success\">\n <div class=\"cortex-tool-details__panel-header cortex-tool-details__panel-header--success\">\n <div class=\"cortex-tool-details__panel-label cortex-tool-details__panel-label--success\">\n Output\n </div>\n <div class=\"cortex-tool-details__panel-lang cortex-tool-details__panel-lang--success\">\n json\n </div>\n </div>\n <div dir=\"ltr\" class=\"cortex-tool-details__tree-container\">\n <cortex-json-tree [data]=\"toolCallPart().output\" [expandDepth]=\"2\" />\n </div>\n </div>\n }\n\n @if (toolCallPart().state === 'output-error') {\n <div class=\"cortex-tool-details__panel cortex-tool-details__panel--error\">\n <div class=\"cortex-tool-details__panel-header cortex-tool-details__panel-header--error\">\n <div class=\"cortex-tool-details__panel-label cortex-tool-details__panel-label--error\">\n Error\n </div>\n <div class=\"cortex-tool-details__panel-lang cortex-tool-details__panel-lang--error\">\n text\n </div>\n </div>\n <pre dir=\"ltr\" class=\"cortex-tool-details__error-pre\">{{ toolCallPart().errorText }}</pre>\n </div>\n }\n\n @if (toolCallPart().state === 'output-denied') {\n <div class=\"cortex-tool-details__panel\">\n <div class=\"cortex-tool-details__panel-header\">\n <div class=\"cortex-tool-details__panel-label\">Denied</div>\n <div class=\"cortex-tool-details__panel-lang\">approval</div>\n </div>\n <div class=\"cortex-tool-details__denied-body\">\n Tool execution was denied.\n @if (toolCallPart().approval?.reason) {\n <div class=\"cortex-tool-details__reason-box\">\n <div class=\"cortex-tool-details__reason-label\">Reason</div>\n <div class=\"cortex-tool-details__reason-text\">\n {{ toolCallPart().approval?.reason }}\n </div>\n </div>\n }\n </div>\n </div>\n }\n\n @if (toolCallPart().state === 'approval-requested') {\n <div class=\"cortex-tool-details__panel cortex-tool-details__panel--approval\">\n <div\n class=\"cortex-tool-details__panel-header cortex-tool-details__panel-header--approval\"\n >\n <div\n class=\"cortex-tool-details__panel-label cortex-tool-details__panel-label--approval\"\n >\n Approval requested\n </div>\n <div class=\"cortex-tool-details__panel-lang cortex-tool-details__panel-lang--approval\">\n {{ toolCallPart().approval?.id }}\n </div>\n </div>\n <div class=\"cortex-tool-details__approval-body\">\n Waiting for approval to execute this tool.\n </div>\n </div>\n }\n\n @if (toolCallPart().state === 'approval-responded') {\n <div class=\"cortex-tool-details__panel cortex-tool-details__panel--approval\">\n <div\n class=\"cortex-tool-details__panel-header cortex-tool-details__panel-header--approval\"\n >\n <div\n class=\"cortex-tool-details__panel-label cortex-tool-details__panel-label--approval\"\n >\n Approval response\n </div>\n <div class=\"cortex-tool-details__panel-lang cortex-tool-details__panel-lang--approval\">\n {{ toolCallPart().approval?.id }}\n </div>\n </div>\n <div class=\"cortex-tool-details__approval-body\">\n @if (toolCallPart().approval?.approved) {\n Approved.\n } @else {\n Response received.\n }\n @if (toolCallPart().approval?.reason) {\n <div\n class=\"cortex-tool-details__reason-box cortex-tool-details__reason-box--approval\"\n >\n <div\n class=\"cortex-tool-details__reason-label cortex-tool-details__reason-label--approval\"\n >\n Reason\n </div>\n <div\n class=\"cortex-tool-details__reason-text cortex-tool-details__reason-text--approval\"\n >\n {{ toolCallPart().approval?.reason }}\n </div>\n </div>\n }\n </div>\n </div>\n }\n </div>\n </div>\n</details>\n", styles: [".cortex-tool-details{width:100%;border-radius:.5rem;border:1px solid #e2e8f0;background:#f8fafc;overflow:hidden}.cortex-tool-details__summary{list-style:none;cursor:pointer;-webkit-user-select:none;user-select:none;padding:.75rem 1rem}.cortex-tool-details__summary::-webkit-details-marker{display:none}details[open]>.cortex-tool-details__summary{border-bottom:1px solid #e2e8f0}.cortex-tool-details__header{display:flex;align-items:flex-start;gap:.75rem}.cortex-tool-details__icon-box{flex-shrink:0;margin-top:.125rem;width:1.75rem;height:1.75rem;border-radius:.25rem;background:#1e293b;color:#fff;display:flex;align-items:center;justify-content:center}.cortex-tool-details__icon-svg{width:1rem;height:1rem}.cortex-tool-details__info{min-width:0;flex:1;display:flex;align-items:center;gap:.5rem}.cortex-tool-details__title-row{min-width:0;flex:1}.cortex-tool-details__name-row{display:flex;align-items:center;gap:.5rem;min-width:0}.cortex-tool-details__name{font-weight:500;color:#1e293b;font-size:.875rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.cortex-tool-details__tool-badge{display:none;align-items:center;border-radius:.25rem;background:#e2e8f0;padding:.125rem .375rem;font-size:.6875rem;font-weight:500;color:#475569;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace}@media(min-width:640px){.cortex-tool-details__tool-badge{display:inline-flex}}.cortex-tool-details__id-line{margin-top:.125rem;font-size:.6875rem;color:#64748b;word-break:break-all}.cortex-tool-details__id-label{font-weight:500;color:#475569}.cortex-tool-details__id-value{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace}.cortex-tool-details__provider-badge{margin-inline-start:.5rem;display:inline-flex;align-items:center;gap:.25rem;color:#047857}.cortex-tool-details__provider-dot{width:.375rem;height:.375rem;border-radius:9999px;background:#10b981}.cortex-tool-details__actions{display:flex;align-items:center;gap:.5rem}.cortex-tool-details__state-badge{display:inline-flex;align-items:center;gap:.375rem;border-radius:.25rem;padding:.25rem .5rem;font-size:.6875rem;font-weight:500;border:1px solid}.cortex-tool-details__state-badge--success{background:#ecfdf5;color:#047857;border-color:#a7f3d0}.cortex-tool-details__state-badge--error{background:#fef2f2;color:#b91c1c;border-color:#fecaca}.cortex-tool-details__state-badge--denied{background:#f1f5f9;color:#475569;border-color:#e2e8f0}.cortex-tool-details__state-badge--approval{background:#f5f3ff;color:#6d28d9;border-color:#ddd6fe}.cortex-tool-details__state-badge--pending{background:#fffbeb;color:#b45309;border-color:#fde68a}.cortex-tool-details__status-dot{width:.375rem;height:.375rem;border-radius:9999px}.cortex-tool-details__status-dot--amber{background:#f59e0b}.cortex-tool-details__status-dot--violet{background:#8b5cf6}.cortex-tool-details__status-dot--emerald{background:#10b981}.cortex-tool-details__status-dot--red{background:#ef4444}.cortex-tool-details__status-dot--slate{background:#64748b}.cortex-tool-details__status-dot--pulse{animation:cortex-tool-status-pulse 2s ease-in-out infinite}@keyframes cortex-tool-status-pulse{0%,to{opacity:1}50%{opacity:.4}}.cortex-tool-details__chevron{display:inline-flex;width:1.5rem;height:1.5rem;align-items:center;justify-content:center;border-radius:.25rem;color:#94a3b8;transition:transform .2s}details[open]>summary .cortex-tool-details__chevron{transform:rotate(180deg)}.cortex-tool-details__body{background:#fff;padding:.75rem 1rem 1rem}.cortex-tool-details__panels{display:grid;gap:.75rem}.cortex-tool-details__panel{border-radius:.5rem;border:1px solid #e2e8f0;overflow:hidden}.cortex-tool-details__panel--success{border-color:#a7f3d0}.cortex-tool-details__panel--error{border-color:#fecaca}.cortex-tool-details__panel--approval{border-color:#ddd6fe}.cortex-tool-details__panel-header{padding:.5rem .75rem;display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid #e2e8f0;background:#f8fafc}.cortex-tool-details__panel-header--success{border-bottom-color:#a7f3d0;background:#ecfdf5}.cortex-tool-details__panel-header--error{border-bottom-color:#fecaca;background:#fef2f2}.cortex-tool-details__panel-header--approval{border-bottom-color:#ddd6fe;background:#f5f3ff}.cortex-tool-details__panel-label{font-size:.6875rem;font-weight:500;color:#475569}.cortex-tool-details__panel-label--success{color:#047857}.cortex-tool-details__panel-label--error{color:#b91c1c}.cortex-tool-details__panel-label--approval{color:#6d28d9}.cortex-tool-details__panel-lang{font-size:.6875rem;color:#94a3b8;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace}.cortex-tool-details__panel-lang--success{color:#059669}.cortex-tool-details__panel-lang--error{color:#dc2626}.cortex-tool-details__panel-lang--approval{color:#7c3aed}.cortex-tool-details__code-pre{margin:0;max-height:20rem;overflow:auto;padding:.75rem;font-size:.75rem;line-height:1.25rem;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;white-space:pre;overflow-wrap:break-word}.cortex-tool-details__tree-container{max-height:16rem;overflow:auto;padding:.75rem}.cortex-tool-details__error-pre{margin:0;max-height:16rem;overflow:auto;padding:.75rem;font-size:.75rem;line-height:1.25rem;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;color:#991b1b;white-space:pre-wrap;overflow-wrap:break-word}.cortex-tool-details__denied-body{padding:.75rem;font-size:.75rem;color:#334155}.cortex-tool-details__approval-body{padding:.75rem;font-size:.75rem;color:#5b21b6}.cortex-tool-details__reason-box{margin-top:.5rem;border-radius:.25rem;background:#f8fafc;border:1px solid #e2e8f0;padding:.5rem}.cortex-tool-details__reason-box--approval{background:#f5f3ff;border-color:#ddd6fe}.cortex-tool-details__reason-label{font-size:.6875rem;font-weight:500;color:#475569}.cortex-tool-details__reason-label--approval{color:#6d28d9}.cortex-tool-details__reason-text{margin-top:.25rem;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:.75rem;color:#334155;overflow-wrap:break-word}.cortex-tool-details__reason-text--approval{color:#5b21b6}\n"] }]
665
892
  }], propDecorators: { toolCallPart: [{ type: i0.Input, args: [{ isSignal: true, alias: "toolCallPart", required: true }] }] } });
@@ -751,10 +978,10 @@ class MessageCaptureFilesPartComponent {
751
978
  message: 'User canceled upload',
752
979
  });
753
980
  }
754
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MessageCaptureFilesPartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
755
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: MessageCaptureFilesPartComponent, isStandalone: true, selector: "cortex-message-capture-files-part", inputs: { message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: true, transformFunction: null }, toolPart: { classPropertyName: "toolPart", publicName: "toolPart", isSignal: true, isRequired: true, transformFunction: null }, setOutput: { classPropertyName: "setOutput", publicName: "setOutput", isSignal: true, isRequired: true, transformFunction: null } }, host: { classAttribute: "cortex-capture-files" }, ngImport: i0, template: "@if (outputData(); as output) {\n <!-- Result state -->\n @if (output.status === 'success') {\n <div class=\"cortex-capture-success\">\n <div class=\"cortex-capture-success__header\">\n <div class=\"cortex-capture-success__icon\">\n <svg viewBox=\"0 0 20 20\" class=\"cortex-capture-success__icon-svg\" fill=\"none\">\n <path\n d=\"M5.5 10.5 L8.5 13.5 L14.5 7\"\n stroke=\"currentColor\"\n stroke-width=\"1.75\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </div>\n <div class=\"cortex-capture-success__title-wrap\">\n <h3 class=\"cortex-capture-success__title\">\n {{ 'translate_files_attached' | translate: { count: requestedFiles().length } }}\n </h3>\n </div>\n </div>\n\n <div class=\"cortex-capture-success__file-list\">\n <ul class=\"cortex-capture-success__files\">\n @for (file of outputData()!.result!; track file.uploadId) {\n <li>\n <button\n type=\"button\"\n (click)=\"downloadFile(file.uploadId)\"\n class=\"cortex-capture-success__download-btn\"\n >\n <svg viewBox=\"0 0 16 16\" class=\"cortex-capture-success__file-icon\" fill=\"none\">\n <path\n d=\"M4 1.5h5.172a2 2 0 0 1 1.414.586l2.328 2.328a2 2 0 0 1 .586 1.414V12.5a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-9a2 2 0 0 1 2-2Z\"\n stroke=\"currentColor\"\n stroke-width=\"1.25\"\n />\n <path\n d=\"M9.5 1.5v2a2 2 0 0 0 2 2h2\"\n stroke=\"currentColor\"\n stroke-width=\"1.25\"\n stroke-linecap=\"round\"\n />\n </svg>\n <span class=\"cortex-capture-success__file-name\">{{\n requestedFiles()[$index]?.label ?? outputData()!.result![$index]?.id\n }}</span>\n <svg viewBox=\"0 0 16 16\" class=\"cortex-capture-success__dl-icon\" fill=\"none\">\n <path\n d=\"M8 3v7m0 0L5.5 7.5M8 10l2.5-2.5M3 13h10\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </button>\n </li>\n }\n </ul>\n </div>\n </div>\n } @else {\n <!-- Canceled state -->\n <div class=\"cortex-capture-canceled-wrap\">\n <div class=\"cortex-capture-canceled\">\n <div class=\"cortex-capture-canceled__icon\">\n <svg viewBox=\"0 0 20 20\" class=\"cortex-capture-canceled__icon-svg\" fill=\"none\">\n <path d=\"M6 10h8\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" />\n </svg>\n </div>\n <span class=\"cortex-capture-canceled__text\">{{\n 'translate_file_upload_skipped' | translate\n }}</span>\n </div>\n </div>\n }\n} @else {\n @if (!hasInvalidInput()) {\n <!-- Upload form -->\n <form [formGroup]=\"form()\" class=\"cortex-capture-form\">\n @if (requestedFiles().length === 1) {\n <!-- Single file: minimal inline -->\n <fieldset [formArray]=\"form().controls.files\">\n <div [formGroupName]=\"0\" class=\"cortex-capture-form__single\">\n <label for=\"capture-file-0\" class=\"cortex-capture-form__label\">\n {{ requestedFiles()[0]!.label }}\n </label>\n <input hidden formControlName=\"id\" />\n <div class=\"cortex-capture-form__row\">\n <cortex-file-input\n id=\"capture-file-0\"\n formControlName=\"file\"\n class=\"cortex-capture-form__input\"\n />\n <button\n (click)=\"cancel()\"\n [disabled]=\"isLoading()\"\n type=\"button\"\n class=\"cortex-capture-form__cancel-link\"\n >\n {{ 'translate_cancel' | translate }}\n </button>\n <button\n (click)=\"submit()\"\n type=\"button\"\n class=\"cortex-capture-form__submit-btn\"\n [disabled]=\"form().invalid || isLoading()\"\n >\n @if (isLoading()) {\n <svg class=\"cortex-capture-form__spinner\" viewBox=\"0 0 16 16\" fill=\"none\">\n <circle\n cx=\"8\"\n cy=\"8\"\n r=\"6\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n class=\"cortex-capture-form__spinner-track\"\n />\n <path\n d=\"M14 8a6 6 0 0 0-6-6\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n />\n </svg>\n {{ 'translate_uploading' | translate }}\n } @else {\n {{ 'translate_submit' | translate }}\n }\n </button>\n </div>\n </div>\n </fieldset>\n } @else {\n <!-- Multi-file: full form -->\n <div class=\"cortex-capture-form__multi\">\n <div class=\"cortex-capture-form__multi-header\">\n <div class=\"cortex-capture-form__multi-header-row\">\n <div class=\"cortex-capture-form__multi-icon\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 20 20\" class=\"cortex-capture-form__multi-icon-svg\" fill=\"none\">\n <path\n d=\"M4 13.5a3.5 3.5 0 0 1-.5-6.97 5.002 5.002 0 0 1 9.78-1.03A4.5 4.5 0 0 1 15.5 14\"\n stroke=\"currentColor\"\n stroke-width=\"1.4\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n <path\n d=\"M10 10v7m0-7-2.5 2.5M10 10l2.5 2.5\"\n stroke=\"currentColor\"\n stroke-width=\"1.4\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </div>\n\n <div class=\"cortex-capture-form__multi-title-wrap\">\n <h3 class=\"cortex-capture-form__multi-title\">\n {{ 'translate_attach_requested_files' | translate }}\n </h3>\n <p class=\"cortex-capture-form__multi-subtitle\">\n {{ 'translate_n_files_required' | translate: { count: requestedFiles().length } }}\n </p>\n </div>\n </div>\n </div>\n\n <fieldset [formArray]=\"form().controls.files\" class=\"cortex-capture-form__multi-fields\">\n @for (file of form().controls.files.value; track $index) {\n <div [formGroupName]=\"$index\" class=\"cortex-capture-form__multi-item\">\n <div class=\"cortex-capture-form__multi-item-header\">\n <label\n [for]=\"'capture-file-' + $index\"\n class=\"cortex-capture-form__multi-item-label\"\n >\n {{ requestedFiles()[$index]!.label }}\n </label>\n <span class=\"cortex-capture-form__required-badge\">\n {{ 'translate_required' | translate }}\n </span>\n </div>\n <input hidden formControlName=\"id\" />\n <cortex-file-input [id]=\"'capture-file-' + $index\" formControlName=\"file\" />\n </div>\n }\n </fieldset>\n\n <div class=\"cortex-capture-form__multi-footer\">\n <button\n (click)=\"cancel()\"\n [disabled]=\"isLoading()\"\n type=\"button\"\n class=\"cortex-capture-form__cancel-btn\"\n >\n {{ 'translate_cancel' | translate }}\n </button>\n <button\n (click)=\"submit()\"\n type=\"button\"\n class=\"cortex-capture-form__submit-btn\"\n [disabled]=\"form().invalid || isLoading()\"\n >\n @if (isLoading()) {\n <svg class=\"cortex-capture-form__spinner\" viewBox=\"0 0 16 16\" fill=\"none\">\n <circle\n cx=\"8\"\n cy=\"8\"\n r=\"6\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n class=\"cortex-capture-form__spinner-track\"\n />\n <path\n d=\"M14 8a6 6 0 0 0-6-6\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n />\n </svg>\n {{ 'translate_uploading' | translate }}\n } @else {\n {{ 'translate_submit_files' | translate }}\n }\n </button>\n </div>\n </div>\n }\n </form>\n }\n}\n", styles: [".cortex-capture-files{display:block;width:100%}.cortex-file-input{display:flex;width:100%;cursor:pointer;align-items:center;border-radius:.5rem;border:1px solid #cbd5e1;background:#f8fafc;transition:border-color .15s}.cortex-file-input:hover{border-color:#94a3b8}.cortex-file-input:focus-within{box-shadow:0 0 0 2px #cbd5e1}.cortex-file-input__btn{margin:.25rem;flex-shrink:0;cursor:pointer;border-radius:.375rem;border:0;background:#1e293b;padding:.375rem .75rem;font-size:.6875rem;font-weight:600;letter-spacing:.025em;color:#f1f5f9}.cortex-file-input__btn:hover{background:#334155}.cortex-file-input__name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding:0 .75rem;font-size:.75rem;color:#475569}.cortex-file-input__hidden{display:none}.cortex-capture-success{overflow:hidden;border-radius:1rem;border:1px solid #a7f3d0;background:linear-gradient(to bottom,#ecfdf5cc,#fff)}.cortex-capture-success__header{display:flex;align-items:center;gap:.75rem;padding:.75rem 1rem}@media(min-width:640px){.cortex-capture-success__header{padding:.75rem 1.25rem}}.cortex-capture-success__icon{display:inline-flex;width:2rem;height:2rem;flex-shrink:0;align-items:center;justify-content:center;border-radius:.5rem;border:1px solid #a7f3d0;background:#d1fae5;color:#059669}.cortex-capture-success__icon-svg{width:1rem;height:1rem}.cortex-capture-success__title-wrap{min-width:0}.cortex-capture-success__title{font-size:.8125rem;font-weight:600;letter-spacing:-.01em;color:#065f46;margin:0}.cortex-capture-success__file-list{border-top:1px solid #d1fae5;padding:.625rem 1rem}@media(min-width:640px){.cortex-capture-success__file-list{padding:.625rem 1.25rem}}.cortex-capture-success__files{display:flex;flex-wrap:wrap;gap:.5rem;list-style:none;margin:0;padding:0}.cortex-capture-success__download-btn{display:inline-flex;cursor:pointer;align-items:center;gap:.375rem;border-radius:.5rem;border:1px solid #d1fae5;background:#fff;padding:.375rem .625rem;font-size:.75rem;font-weight:500;color:#047857;box-shadow:0 1px 2px #0000000d;transition:all .15s}.cortex-capture-success__download-btn:hover{border-color:#a7f3d0;background:#ecfdf5;box-shadow:0 1px 3px #0000001a}.cortex-capture-success__download-btn:active{transform:scale(.97)}.cortex-capture-success__file-icon{width:.875rem;height:.875rem;flex-shrink:0;color:#6ee7b7}.cortex-capture-success__file-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:180px}.cortex-capture-success__dl-icon{width:.75rem;height:.75rem;flex-shrink:0;color:#86efac}.cortex-capture-canceled-wrap{display:flex;justify-content:center}.cortex-capture-canceled{display:inline-flex;align-items:center;gap:.625rem;border-radius:.5rem;border:1px solid #e2e8f0;background:#f8fafc;padding:.625rem 1rem}.cortex-capture-canceled__icon{display:inline-flex;width:1.5rem;height:1.5rem;flex-shrink:0;align-items:center;justify-content:center;border-radius:.375rem;border:1px solid #e2e8f0;background:#f1f5f9;color:#94a3b8}.cortex-capture-canceled__icon-svg{width:.75rem;height:.75rem}.cortex-capture-canceled__text{font-size:.8125rem;font-weight:500;color:#94a3b8}.cortex-capture-form{width:100%}.cortex-capture-form__single{border-radius:.75rem;border:1px solid #e2e8f0;background:#f8fafc;padding:.75rem}.cortex-capture-form__label{display:block;margin-bottom:.375rem;font-size:.75rem;color:#64748b}.cortex-capture-form__row{display:flex;align-items:center;gap:.5rem}.cortex-capture-form__input{min-width:0;flex:1}.cortex-capture-form__cancel-link{flex-shrink:0;font-size:.75rem;font-weight:500;color:#94a3b8;background:none;border:0;cursor:pointer;transition:color .15s}.cortex-capture-form__cancel-link:hover{color:#475569}.cortex-capture-form__submit-btn{display:inline-flex;flex-shrink:0;align-items:center;border-radius:.375rem;background:#1e293b;padding:.375rem .75rem;font-size:.75rem;font-weight:500;color:#f1f5f9;border:0;cursor:pointer;transition:background-color .15s}.cortex-capture-form__submit-btn:hover{background:#334155}.cortex-capture-form__submit-btn:active{background:#0f172a}.cortex-capture-form__submit-btn:disabled{cursor:not-allowed;background:#cbd5e1}.cortex-capture-form__spinner{width:.75rem;height:.75rem;margin-inline-end:.375rem;animation:cortex-capture-spin .8s linear infinite}.cortex-capture-form__spinner-track{opacity:.25}@keyframes cortex-capture-spin{to{transform:rotate(360deg)}}.cortex-capture-form__multi{overflow:hidden;border-radius:1rem;border:1px solid #e2e8f0;background:linear-gradient(to bottom,#fff,#f8fafc)}.cortex-capture-form__multi-header{border-bottom:1px solid #e2e8f0;background:#ffffffd9;padding:.75rem 1rem}@media(min-width:640px){.cortex-capture-form__multi-header{padding:.75rem 1.25rem}}.cortex-capture-form__multi-header-row{display:flex;align-items:flex-start;gap:.75rem}.cortex-capture-form__multi-icon{margin-top:.125rem;display:inline-flex;width:2rem;height:2rem;flex-shrink:0;align-items:center;justify-content:center;border-radius:.5rem;border:1px solid #e2e8f0;background:#f1f5f9;color:#475569}.cortex-capture-form__multi-icon-svg{width:1rem;height:1rem}.cortex-capture-form__multi-title-wrap{min-width:0}.cortex-capture-form__multi-title{font-size:.8125rem;font-weight:600;letter-spacing:-.01em;color:#1e293b;margin:0}.cortex-capture-form__multi-subtitle{margin-top:.125rem;font-size:.6875rem;color:#64748b;margin-bottom:0}.cortex-capture-form__multi-fields{display:grid;gap:.75rem;padding:1rem;border:0}@media(min-width:640px){.cortex-capture-form__multi-fields{padding:1.25rem}}.cortex-capture-form__multi-item{border-radius:.75rem;border:1px solid #e2e8f0;background:#fff;padding:.75rem;transition:border-color .15s}.cortex-capture-form__multi-item:hover{border-color:#cbd5e1}.cortex-capture-form__multi-item-header{margin-bottom:.5rem;display:flex;align-items:center;justify-content:space-between;gap:.5rem}.cortex-capture-form__multi-item-label{display:block;font-size:.75rem;font-weight:500;line-height:1;color:#334155}.cortex-capture-form__required-badge{display:inline-flex;align-items:center;border-radius:.25rem;border:1px solid #e2e8f0;background:#f8fafc;padding:.125rem .375rem;font-size:.625rem;font-weight:500;text-transform:uppercase;letter-spacing:.05em;color:#64748b}.cortex-capture-form__multi-footer{display:flex;align-items:center;justify-content:flex-end;gap:.5rem;border-top:1px solid #e2e8f0;background:#ffffffe6;padding:.75rem 1rem}@media(min-width:640px){.cortex-capture-form__multi-footer{padding:.75rem 1.25rem}}.cortex-capture-form__cancel-btn{display:inline-flex;align-items:center;border-radius:.375rem;border:1px solid #cbd5e1;background:#fff;padding:.375rem .75rem;font-size:.75rem;font-weight:500;color:#475569;cursor:pointer;transition:background-color .15s}.cortex-capture-form__cancel-btn:hover{background:#f8fafc}.cortex-capture-form__cancel-btn:active{background:#f1f5f9}\n"], dependencies: [{ kind: "ngmodule", type: i0.forwardRef(() => ReactiveFormsModule) }, { kind: "directive", type: i0.forwardRef(() => i1$1.ɵNgNoValidate), selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i0.forwardRef(() => 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: i0.forwardRef(() => i1$1.NgControlStatus), selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i0.forwardRef(() => i1$1.NgControlStatusGroup), selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i0.forwardRef(() => i1$1.FormGroupDirective), selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i0.forwardRef(() => i1$1.FormArrayDirective), selector: "[formArray]", inputs: ["formArray"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i0.forwardRef(() => i1$1.FormControlName), selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i0.forwardRef(() => i1$1.FormGroupName), selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "component", type: i0.forwardRef(() => FileInputComponent), selector: "cortex-file-input", inputs: ["allowedMimeTypes"] }, { kind: "pipe", type: i0.forwardRef(() => TranslatePipe), name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
981
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MessageCaptureFilesPartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
982
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: MessageCaptureFilesPartComponent, isStandalone: true, selector: "cortex-message-capture-files-part", inputs: { message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: true, transformFunction: null }, toolPart: { classPropertyName: "toolPart", publicName: "toolPart", isSignal: true, isRequired: true, transformFunction: null }, setOutput: { classPropertyName: "setOutput", publicName: "setOutput", isSignal: true, isRequired: true, transformFunction: null } }, host: { classAttribute: "cortex-capture-files" }, ngImport: i0, template: "@if (outputData(); as output) {\n <!-- Result state -->\n @if (output.status === 'success') {\n <div class=\"cortex-capture-success\">\n <div class=\"cortex-capture-success__header\">\n <div class=\"cortex-capture-success__icon\">\n <svg viewBox=\"0 0 20 20\" class=\"cortex-capture-success__icon-svg\" fill=\"none\">\n <path\n d=\"M5.5 10.5 L8.5 13.5 L14.5 7\"\n stroke=\"currentColor\"\n stroke-width=\"1.75\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </div>\n <div class=\"cortex-capture-success__title-wrap\">\n <h3 class=\"cortex-capture-success__title\">\n {{ 'translate_files_attached' | translate: { count: requestedFiles().length } }}\n </h3>\n </div>\n </div>\n\n <div class=\"cortex-capture-success__file-list\">\n <ul class=\"cortex-capture-success__files\">\n @for (file of outputData()!.result!; track file.uploadId) {\n <li>\n <button\n type=\"button\"\n (click)=\"downloadFile(file.uploadId)\"\n class=\"cortex-capture-success__download-btn\"\n >\n <svg viewBox=\"0 0 16 16\" class=\"cortex-capture-success__file-icon\" fill=\"none\">\n <path\n d=\"M4 1.5h5.172a2 2 0 0 1 1.414.586l2.328 2.328a2 2 0 0 1 .586 1.414V12.5a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-9a2 2 0 0 1 2-2Z\"\n stroke=\"currentColor\"\n stroke-width=\"1.25\"\n />\n <path\n d=\"M9.5 1.5v2a2 2 0 0 0 2 2h2\"\n stroke=\"currentColor\"\n stroke-width=\"1.25\"\n stroke-linecap=\"round\"\n />\n </svg>\n <span class=\"cortex-capture-success__file-name\">{{\n requestedFiles()[$index]?.label ?? outputData()!.result![$index]?.id\n }}</span>\n <svg viewBox=\"0 0 16 16\" class=\"cortex-capture-success__dl-icon\" fill=\"none\">\n <path\n d=\"M8 3v7m0 0L5.5 7.5M8 10l2.5-2.5M3 13h10\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </button>\n </li>\n }\n </ul>\n </div>\n </div>\n } @else {\n <!-- Canceled state -->\n <div class=\"cortex-capture-canceled-wrap\">\n <div class=\"cortex-capture-canceled\">\n <div class=\"cortex-capture-canceled__icon\">\n <svg viewBox=\"0 0 20 20\" class=\"cortex-capture-canceled__icon-svg\" fill=\"none\">\n <path d=\"M6 10h8\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" />\n </svg>\n </div>\n <span class=\"cortex-capture-canceled__text\">{{\n 'translate_file_upload_skipped' | translate\n }}</span>\n </div>\n </div>\n }\n} @else {\n @if (!hasInvalidInput()) {\n <!-- Upload form -->\n <form [formGroup]=\"form()\" class=\"cortex-capture-form\">\n @if (requestedFiles().length === 1) {\n <!-- Single file: minimal inline -->\n <fieldset [formArray]=\"form().controls.files\">\n <div [formGroupName]=\"0\" class=\"cortex-capture-form__single\">\n <label for=\"capture-file-0\" class=\"cortex-capture-form__label\">\n {{ requestedFiles()[0]!.label }}\n </label>\n <input hidden formControlName=\"id\" />\n <div class=\"cortex-capture-form__row\">\n <cortex-file-input\n id=\"capture-file-0\"\n formControlName=\"file\"\n class=\"cortex-capture-form__input\"\n />\n <button\n (click)=\"cancel()\"\n [disabled]=\"isLoading()\"\n type=\"button\"\n class=\"cortex-capture-form__cancel-link\"\n >\n {{ 'translate_cancel' | translate }}\n </button>\n <button\n (click)=\"submit()\"\n type=\"button\"\n class=\"cortex-capture-form__submit-btn\"\n [disabled]=\"form().invalid || isLoading()\"\n >\n @if (isLoading()) {\n <svg class=\"cortex-capture-form__spinner\" viewBox=\"0 0 16 16\" fill=\"none\">\n <circle\n cx=\"8\"\n cy=\"8\"\n r=\"6\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n class=\"cortex-capture-form__spinner-track\"\n />\n <path\n d=\"M14 8a6 6 0 0 0-6-6\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n />\n </svg>\n {{ 'translate_uploading' | translate }}\n } @else {\n {{ 'translate_submit' | translate }}\n }\n </button>\n </div>\n </div>\n </fieldset>\n } @else {\n <!-- Multi-file: full form -->\n <div class=\"cortex-capture-form__multi\">\n <div class=\"cortex-capture-form__multi-header\">\n <div class=\"cortex-capture-form__multi-header-row\">\n <div class=\"cortex-capture-form__multi-icon\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 20 20\" class=\"cortex-capture-form__multi-icon-svg\" fill=\"none\">\n <path\n d=\"M4 13.5a3.5 3.5 0 0 1-.5-6.97 5.002 5.002 0 0 1 9.78-1.03A4.5 4.5 0 0 1 15.5 14\"\n stroke=\"currentColor\"\n stroke-width=\"1.4\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n <path\n d=\"M10 10v7m0-7-2.5 2.5M10 10l2.5 2.5\"\n stroke=\"currentColor\"\n stroke-width=\"1.4\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </div>\n\n <div class=\"cortex-capture-form__multi-title-wrap\">\n <h3 class=\"cortex-capture-form__multi-title\">\n {{ 'translate_attach_requested_files' | translate }}\n </h3>\n <p class=\"cortex-capture-form__multi-subtitle\">\n {{ 'translate_n_files_required' | translate: { count: requestedFiles().length } }}\n </p>\n </div>\n </div>\n </div>\n\n <fieldset [formArray]=\"form().controls.files\" class=\"cortex-capture-form__multi-fields\">\n @for (file of form().controls.files.value; track $index) {\n <div [formGroupName]=\"$index\" class=\"cortex-capture-form__multi-item\">\n <div class=\"cortex-capture-form__multi-item-header\">\n <label\n [for]=\"'capture-file-' + $index\"\n class=\"cortex-capture-form__multi-item-label\"\n >\n {{ requestedFiles()[$index]!.label }}\n </label>\n <span class=\"cortex-capture-form__required-badge\">\n {{ 'translate_required' | translate }}\n </span>\n </div>\n <input hidden formControlName=\"id\" />\n <cortex-file-input [id]=\"'capture-file-' + $index\" formControlName=\"file\" />\n </div>\n }\n </fieldset>\n\n <div class=\"cortex-capture-form__multi-footer\">\n <button\n (click)=\"cancel()\"\n [disabled]=\"isLoading()\"\n type=\"button\"\n class=\"cortex-capture-form__cancel-btn\"\n >\n {{ 'translate_cancel' | translate }}\n </button>\n <button\n (click)=\"submit()\"\n type=\"button\"\n class=\"cortex-capture-form__submit-btn\"\n [disabled]=\"form().invalid || isLoading()\"\n >\n @if (isLoading()) {\n <svg class=\"cortex-capture-form__spinner\" viewBox=\"0 0 16 16\" fill=\"none\">\n <circle\n cx=\"8\"\n cy=\"8\"\n r=\"6\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n class=\"cortex-capture-form__spinner-track\"\n />\n <path\n d=\"M14 8a6 6 0 0 0-6-6\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n />\n </svg>\n {{ 'translate_uploading' | translate }}\n } @else {\n {{ 'translate_submit_files' | translate }}\n }\n </button>\n </div>\n </div>\n }\n </form>\n }\n}\n", styles: [".cortex-capture-files{display:block;width:100%}.cortex-file-input{display:flex;width:100%;cursor:pointer;align-items:center;border-radius:.5rem;border:1px solid #cbd5e1;background:#f8fafc;transition:border-color .15s}.cortex-file-input:hover{border-color:#94a3b8}.cortex-file-input:focus-within{box-shadow:0 0 0 2px #cbd5e1}.cortex-file-input__btn{margin:.25rem;flex-shrink:0;cursor:pointer;border-radius:.375rem;border:0;background:#1e293b;padding:.375rem .75rem;font-size:.6875rem;font-weight:600;letter-spacing:.025em;color:#f1f5f9}.cortex-file-input__btn:hover{background:#334155}.cortex-file-input__name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding:0 .75rem;font-size:.75rem;color:#475569}.cortex-file-input__hidden{display:none}.cortex-capture-success{overflow:hidden;border-radius:1rem;border:1px solid #a7f3d0;background:linear-gradient(to bottom,#ecfdf5cc,#fff)}.cortex-capture-success__header{display:flex;align-items:center;gap:.75rem;padding:.75rem 1rem}@media(min-width:640px){.cortex-capture-success__header{padding:.75rem 1.25rem}}.cortex-capture-success__icon{display:inline-flex;width:2rem;height:2rem;flex-shrink:0;align-items:center;justify-content:center;border-radius:.5rem;border:1px solid #a7f3d0;background:#d1fae5;color:#059669}.cortex-capture-success__icon-svg{width:1rem;height:1rem}.cortex-capture-success__title-wrap{min-width:0}.cortex-capture-success__title{font-size:.8125rem;font-weight:600;letter-spacing:-.01em;color:#065f46;margin:0}.cortex-capture-success__file-list{border-top:1px solid #d1fae5;padding:.625rem 1rem}@media(min-width:640px){.cortex-capture-success__file-list{padding:.625rem 1.25rem}}.cortex-capture-success__files{display:flex;flex-wrap:wrap;gap:.5rem;list-style:none;margin:0;padding:0}.cortex-capture-success__download-btn{display:inline-flex;cursor:pointer;align-items:center;gap:.375rem;border-radius:.5rem;border:1px solid #d1fae5;background:#fff;padding:.375rem .625rem;font-size:.75rem;font-weight:500;color:#047857;box-shadow:0 1px 2px #0000000d;transition:all .15s}.cortex-capture-success__download-btn:hover{border-color:#a7f3d0;background:#ecfdf5;box-shadow:0 1px 3px #0000001a}.cortex-capture-success__download-btn:active{transform:scale(.97)}.cortex-capture-success__file-icon{width:.875rem;height:.875rem;flex-shrink:0;color:#6ee7b7}.cortex-capture-success__file-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:180px}.cortex-capture-success__dl-icon{width:.75rem;height:.75rem;flex-shrink:0;color:#86efac}.cortex-capture-canceled-wrap{display:flex;justify-content:center}.cortex-capture-canceled{display:inline-flex;align-items:center;gap:.625rem;border-radius:.5rem;border:1px solid #e2e8f0;background:#f8fafc;padding:.625rem 1rem}.cortex-capture-canceled__icon{display:inline-flex;width:1.5rem;height:1.5rem;flex-shrink:0;align-items:center;justify-content:center;border-radius:.375rem;border:1px solid #e2e8f0;background:#f1f5f9;color:#94a3b8}.cortex-capture-canceled__icon-svg{width:.75rem;height:.75rem}.cortex-capture-canceled__text{font-size:.8125rem;font-weight:500;color:#94a3b8}.cortex-capture-form{width:100%}.cortex-capture-form__single{border-radius:.75rem;border:1px solid #e2e8f0;background:#f8fafc;padding:.75rem}.cortex-capture-form__label{display:block;margin-bottom:.375rem;font-size:.75rem;color:#64748b}.cortex-capture-form__row{display:flex;align-items:center;gap:.5rem}.cortex-capture-form__input{min-width:0;flex:1}.cortex-capture-form__cancel-link{flex-shrink:0;font-size:.75rem;font-weight:500;color:#94a3b8;background:none;border:0;cursor:pointer;transition:color .15s}.cortex-capture-form__cancel-link:hover{color:#475569}.cortex-capture-form__submit-btn{display:inline-flex;flex-shrink:0;align-items:center;border-radius:.375rem;background:#1e293b;padding:.375rem .75rem;font-size:.75rem;font-weight:500;color:#f1f5f9;border:0;cursor:pointer;transition:background-color .15s}.cortex-capture-form__submit-btn:hover{background:#334155}.cortex-capture-form__submit-btn:active{background:#0f172a}.cortex-capture-form__submit-btn:disabled{cursor:not-allowed;background:#cbd5e1}.cortex-capture-form__spinner{width:.75rem;height:.75rem;margin-inline-end:.375rem;animation:cortex-capture-spin .8s linear infinite}.cortex-capture-form__spinner-track{opacity:.25}@keyframes cortex-capture-spin{to{transform:rotate(360deg)}}.cortex-capture-form__multi{overflow:hidden;border-radius:1rem;border:1px solid #e2e8f0;background:linear-gradient(to bottom,#fff,#f8fafc)}.cortex-capture-form__multi-header{border-bottom:1px solid #e2e8f0;background:#ffffffd9;padding:.75rem 1rem}@media(min-width:640px){.cortex-capture-form__multi-header{padding:.75rem 1.25rem}}.cortex-capture-form__multi-header-row{display:flex;align-items:flex-start;gap:.75rem}.cortex-capture-form__multi-icon{margin-top:.125rem;display:inline-flex;width:2rem;height:2rem;flex-shrink:0;align-items:center;justify-content:center;border-radius:.5rem;border:1px solid #e2e8f0;background:#f1f5f9;color:#475569}.cortex-capture-form__multi-icon-svg{width:1rem;height:1rem}.cortex-capture-form__multi-title-wrap{min-width:0}.cortex-capture-form__multi-title{font-size:.8125rem;font-weight:600;letter-spacing:-.01em;color:#1e293b;margin:0}.cortex-capture-form__multi-subtitle{margin-top:.125rem;font-size:.6875rem;color:#64748b;margin-bottom:0}.cortex-capture-form__multi-fields{display:grid;gap:.75rem;padding:1rem;border:0}@media(min-width:640px){.cortex-capture-form__multi-fields{padding:1.25rem}}.cortex-capture-form__multi-item{border-radius:.75rem;border:1px solid #e2e8f0;background:#fff;padding:.75rem;transition:border-color .15s}.cortex-capture-form__multi-item:hover{border-color:#cbd5e1}.cortex-capture-form__multi-item-header{margin-bottom:.5rem;display:flex;align-items:center;justify-content:space-between;gap:.5rem}.cortex-capture-form__multi-item-label{display:block;font-size:.75rem;font-weight:500;line-height:1;color:#334155}.cortex-capture-form__required-badge{display:inline-flex;align-items:center;border-radius:.25rem;border:1px solid #e2e8f0;background:#f8fafc;padding:.125rem .375rem;font-size:.625rem;font-weight:500;text-transform:uppercase;letter-spacing:.05em;color:#64748b}.cortex-capture-form__multi-footer{display:flex;align-items:center;justify-content:flex-end;gap:.5rem;border-top:1px solid #e2e8f0;background:#ffffffe6;padding:.75rem 1rem}@media(min-width:640px){.cortex-capture-form__multi-footer{padding:.75rem 1.25rem}}.cortex-capture-form__cancel-btn{display:inline-flex;align-items:center;border-radius:.375rem;border:1px solid #cbd5e1;background:#fff;padding:.375rem .75rem;font-size:.75rem;font-weight:500;color:#475569;cursor:pointer;transition:background-color .15s}.cortex-capture-form__cancel-btn:hover{background:#f8fafc}.cortex-capture-form__cancel-btn:active{background:#f1f5f9}\n"], dependencies: [{ kind: "ngmodule", type: i0.forwardRef(() => ReactiveFormsModule) }, { kind: "directive", type: i0.forwardRef(() => i1$1.ɵNgNoValidate), selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i0.forwardRef(() => 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: i0.forwardRef(() => i1$1.NgControlStatus), selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i0.forwardRef(() => i1$1.NgControlStatusGroup), selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i0.forwardRef(() => i1$1.FormGroupDirective), selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i0.forwardRef(() => i1$1.FormArrayDirective), selector: "[formArray]", inputs: ["formArray"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i0.forwardRef(() => i1$1.FormControlName), selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i0.forwardRef(() => i1$1.FormGroupName), selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "component", type: i0.forwardRef(() => FileInputComponent), selector: "cortex-file-input", inputs: ["allowedMimeTypes"] }, { kind: "pipe", type: i0.forwardRef(() => TranslatePipe), name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
756
983
  }
757
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MessageCaptureFilesPartComponent, decorators: [{
984
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MessageCaptureFilesPartComponent, decorators: [{
758
985
  type: Component,
759
986
  args: [{ selector: 'cortex-message-capture-files-part', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [ReactiveFormsModule, forwardRef(() => FileInputComponent), TranslatePipe], host: { class: 'cortex-capture-files' }, template: "@if (outputData(); as output) {\n <!-- Result state -->\n @if (output.status === 'success') {\n <div class=\"cortex-capture-success\">\n <div class=\"cortex-capture-success__header\">\n <div class=\"cortex-capture-success__icon\">\n <svg viewBox=\"0 0 20 20\" class=\"cortex-capture-success__icon-svg\" fill=\"none\">\n <path\n d=\"M5.5 10.5 L8.5 13.5 L14.5 7\"\n stroke=\"currentColor\"\n stroke-width=\"1.75\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </div>\n <div class=\"cortex-capture-success__title-wrap\">\n <h3 class=\"cortex-capture-success__title\">\n {{ 'translate_files_attached' | translate: { count: requestedFiles().length } }}\n </h3>\n </div>\n </div>\n\n <div class=\"cortex-capture-success__file-list\">\n <ul class=\"cortex-capture-success__files\">\n @for (file of outputData()!.result!; track file.uploadId) {\n <li>\n <button\n type=\"button\"\n (click)=\"downloadFile(file.uploadId)\"\n class=\"cortex-capture-success__download-btn\"\n >\n <svg viewBox=\"0 0 16 16\" class=\"cortex-capture-success__file-icon\" fill=\"none\">\n <path\n d=\"M4 1.5h5.172a2 2 0 0 1 1.414.586l2.328 2.328a2 2 0 0 1 .586 1.414V12.5a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-9a2 2 0 0 1 2-2Z\"\n stroke=\"currentColor\"\n stroke-width=\"1.25\"\n />\n <path\n d=\"M9.5 1.5v2a2 2 0 0 0 2 2h2\"\n stroke=\"currentColor\"\n stroke-width=\"1.25\"\n stroke-linecap=\"round\"\n />\n </svg>\n <span class=\"cortex-capture-success__file-name\">{{\n requestedFiles()[$index]?.label ?? outputData()!.result![$index]?.id\n }}</span>\n <svg viewBox=\"0 0 16 16\" class=\"cortex-capture-success__dl-icon\" fill=\"none\">\n <path\n d=\"M8 3v7m0 0L5.5 7.5M8 10l2.5-2.5M3 13h10\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </button>\n </li>\n }\n </ul>\n </div>\n </div>\n } @else {\n <!-- Canceled state -->\n <div class=\"cortex-capture-canceled-wrap\">\n <div class=\"cortex-capture-canceled\">\n <div class=\"cortex-capture-canceled__icon\">\n <svg viewBox=\"0 0 20 20\" class=\"cortex-capture-canceled__icon-svg\" fill=\"none\">\n <path d=\"M6 10h8\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" />\n </svg>\n </div>\n <span class=\"cortex-capture-canceled__text\">{{\n 'translate_file_upload_skipped' | translate\n }}</span>\n </div>\n </div>\n }\n} @else {\n @if (!hasInvalidInput()) {\n <!-- Upload form -->\n <form [formGroup]=\"form()\" class=\"cortex-capture-form\">\n @if (requestedFiles().length === 1) {\n <!-- Single file: minimal inline -->\n <fieldset [formArray]=\"form().controls.files\">\n <div [formGroupName]=\"0\" class=\"cortex-capture-form__single\">\n <label for=\"capture-file-0\" class=\"cortex-capture-form__label\">\n {{ requestedFiles()[0]!.label }}\n </label>\n <input hidden formControlName=\"id\" />\n <div class=\"cortex-capture-form__row\">\n <cortex-file-input\n id=\"capture-file-0\"\n formControlName=\"file\"\n class=\"cortex-capture-form__input\"\n />\n <button\n (click)=\"cancel()\"\n [disabled]=\"isLoading()\"\n type=\"button\"\n class=\"cortex-capture-form__cancel-link\"\n >\n {{ 'translate_cancel' | translate }}\n </button>\n <button\n (click)=\"submit()\"\n type=\"button\"\n class=\"cortex-capture-form__submit-btn\"\n [disabled]=\"form().invalid || isLoading()\"\n >\n @if (isLoading()) {\n <svg class=\"cortex-capture-form__spinner\" viewBox=\"0 0 16 16\" fill=\"none\">\n <circle\n cx=\"8\"\n cy=\"8\"\n r=\"6\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n class=\"cortex-capture-form__spinner-track\"\n />\n <path\n d=\"M14 8a6 6 0 0 0-6-6\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n />\n </svg>\n {{ 'translate_uploading' | translate }}\n } @else {\n {{ 'translate_submit' | translate }}\n }\n </button>\n </div>\n </div>\n </fieldset>\n } @else {\n <!-- Multi-file: full form -->\n <div class=\"cortex-capture-form__multi\">\n <div class=\"cortex-capture-form__multi-header\">\n <div class=\"cortex-capture-form__multi-header-row\">\n <div class=\"cortex-capture-form__multi-icon\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 20 20\" class=\"cortex-capture-form__multi-icon-svg\" fill=\"none\">\n <path\n d=\"M4 13.5a3.5 3.5 0 0 1-.5-6.97 5.002 5.002 0 0 1 9.78-1.03A4.5 4.5 0 0 1 15.5 14\"\n stroke=\"currentColor\"\n stroke-width=\"1.4\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n <path\n d=\"M10 10v7m0-7-2.5 2.5M10 10l2.5 2.5\"\n stroke=\"currentColor\"\n stroke-width=\"1.4\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </div>\n\n <div class=\"cortex-capture-form__multi-title-wrap\">\n <h3 class=\"cortex-capture-form__multi-title\">\n {{ 'translate_attach_requested_files' | translate }}\n </h3>\n <p class=\"cortex-capture-form__multi-subtitle\">\n {{ 'translate_n_files_required' | translate: { count: requestedFiles().length } }}\n </p>\n </div>\n </div>\n </div>\n\n <fieldset [formArray]=\"form().controls.files\" class=\"cortex-capture-form__multi-fields\">\n @for (file of form().controls.files.value; track $index) {\n <div [formGroupName]=\"$index\" class=\"cortex-capture-form__multi-item\">\n <div class=\"cortex-capture-form__multi-item-header\">\n <label\n [for]=\"'capture-file-' + $index\"\n class=\"cortex-capture-form__multi-item-label\"\n >\n {{ requestedFiles()[$index]!.label }}\n </label>\n <span class=\"cortex-capture-form__required-badge\">\n {{ 'translate_required' | translate }}\n </span>\n </div>\n <input hidden formControlName=\"id\" />\n <cortex-file-input [id]=\"'capture-file-' + $index\" formControlName=\"file\" />\n </div>\n }\n </fieldset>\n\n <div class=\"cortex-capture-form__multi-footer\">\n <button\n (click)=\"cancel()\"\n [disabled]=\"isLoading()\"\n type=\"button\"\n class=\"cortex-capture-form__cancel-btn\"\n >\n {{ 'translate_cancel' | translate }}\n </button>\n <button\n (click)=\"submit()\"\n type=\"button\"\n class=\"cortex-capture-form__submit-btn\"\n [disabled]=\"form().invalid || isLoading()\"\n >\n @if (isLoading()) {\n <svg class=\"cortex-capture-form__spinner\" viewBox=\"0 0 16 16\" fill=\"none\">\n <circle\n cx=\"8\"\n cy=\"8\"\n r=\"6\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n class=\"cortex-capture-form__spinner-track\"\n />\n <path\n d=\"M14 8a6 6 0 0 0-6-6\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n />\n </svg>\n {{ 'translate_uploading' | translate }}\n } @else {\n {{ 'translate_submit_files' | translate }}\n }\n </button>\n </div>\n </div>\n }\n </form>\n }\n}\n", styles: [".cortex-capture-files{display:block;width:100%}.cortex-file-input{display:flex;width:100%;cursor:pointer;align-items:center;border-radius:.5rem;border:1px solid #cbd5e1;background:#f8fafc;transition:border-color .15s}.cortex-file-input:hover{border-color:#94a3b8}.cortex-file-input:focus-within{box-shadow:0 0 0 2px #cbd5e1}.cortex-file-input__btn{margin:.25rem;flex-shrink:0;cursor:pointer;border-radius:.375rem;border:0;background:#1e293b;padding:.375rem .75rem;font-size:.6875rem;font-weight:600;letter-spacing:.025em;color:#f1f5f9}.cortex-file-input__btn:hover{background:#334155}.cortex-file-input__name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding:0 .75rem;font-size:.75rem;color:#475569}.cortex-file-input__hidden{display:none}.cortex-capture-success{overflow:hidden;border-radius:1rem;border:1px solid #a7f3d0;background:linear-gradient(to bottom,#ecfdf5cc,#fff)}.cortex-capture-success__header{display:flex;align-items:center;gap:.75rem;padding:.75rem 1rem}@media(min-width:640px){.cortex-capture-success__header{padding:.75rem 1.25rem}}.cortex-capture-success__icon{display:inline-flex;width:2rem;height:2rem;flex-shrink:0;align-items:center;justify-content:center;border-radius:.5rem;border:1px solid #a7f3d0;background:#d1fae5;color:#059669}.cortex-capture-success__icon-svg{width:1rem;height:1rem}.cortex-capture-success__title-wrap{min-width:0}.cortex-capture-success__title{font-size:.8125rem;font-weight:600;letter-spacing:-.01em;color:#065f46;margin:0}.cortex-capture-success__file-list{border-top:1px solid #d1fae5;padding:.625rem 1rem}@media(min-width:640px){.cortex-capture-success__file-list{padding:.625rem 1.25rem}}.cortex-capture-success__files{display:flex;flex-wrap:wrap;gap:.5rem;list-style:none;margin:0;padding:0}.cortex-capture-success__download-btn{display:inline-flex;cursor:pointer;align-items:center;gap:.375rem;border-radius:.5rem;border:1px solid #d1fae5;background:#fff;padding:.375rem .625rem;font-size:.75rem;font-weight:500;color:#047857;box-shadow:0 1px 2px #0000000d;transition:all .15s}.cortex-capture-success__download-btn:hover{border-color:#a7f3d0;background:#ecfdf5;box-shadow:0 1px 3px #0000001a}.cortex-capture-success__download-btn:active{transform:scale(.97)}.cortex-capture-success__file-icon{width:.875rem;height:.875rem;flex-shrink:0;color:#6ee7b7}.cortex-capture-success__file-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:180px}.cortex-capture-success__dl-icon{width:.75rem;height:.75rem;flex-shrink:0;color:#86efac}.cortex-capture-canceled-wrap{display:flex;justify-content:center}.cortex-capture-canceled{display:inline-flex;align-items:center;gap:.625rem;border-radius:.5rem;border:1px solid #e2e8f0;background:#f8fafc;padding:.625rem 1rem}.cortex-capture-canceled__icon{display:inline-flex;width:1.5rem;height:1.5rem;flex-shrink:0;align-items:center;justify-content:center;border-radius:.375rem;border:1px solid #e2e8f0;background:#f1f5f9;color:#94a3b8}.cortex-capture-canceled__icon-svg{width:.75rem;height:.75rem}.cortex-capture-canceled__text{font-size:.8125rem;font-weight:500;color:#94a3b8}.cortex-capture-form{width:100%}.cortex-capture-form__single{border-radius:.75rem;border:1px solid #e2e8f0;background:#f8fafc;padding:.75rem}.cortex-capture-form__label{display:block;margin-bottom:.375rem;font-size:.75rem;color:#64748b}.cortex-capture-form__row{display:flex;align-items:center;gap:.5rem}.cortex-capture-form__input{min-width:0;flex:1}.cortex-capture-form__cancel-link{flex-shrink:0;font-size:.75rem;font-weight:500;color:#94a3b8;background:none;border:0;cursor:pointer;transition:color .15s}.cortex-capture-form__cancel-link:hover{color:#475569}.cortex-capture-form__submit-btn{display:inline-flex;flex-shrink:0;align-items:center;border-radius:.375rem;background:#1e293b;padding:.375rem .75rem;font-size:.75rem;font-weight:500;color:#f1f5f9;border:0;cursor:pointer;transition:background-color .15s}.cortex-capture-form__submit-btn:hover{background:#334155}.cortex-capture-form__submit-btn:active{background:#0f172a}.cortex-capture-form__submit-btn:disabled{cursor:not-allowed;background:#cbd5e1}.cortex-capture-form__spinner{width:.75rem;height:.75rem;margin-inline-end:.375rem;animation:cortex-capture-spin .8s linear infinite}.cortex-capture-form__spinner-track{opacity:.25}@keyframes cortex-capture-spin{to{transform:rotate(360deg)}}.cortex-capture-form__multi{overflow:hidden;border-radius:1rem;border:1px solid #e2e8f0;background:linear-gradient(to bottom,#fff,#f8fafc)}.cortex-capture-form__multi-header{border-bottom:1px solid #e2e8f0;background:#ffffffd9;padding:.75rem 1rem}@media(min-width:640px){.cortex-capture-form__multi-header{padding:.75rem 1.25rem}}.cortex-capture-form__multi-header-row{display:flex;align-items:flex-start;gap:.75rem}.cortex-capture-form__multi-icon{margin-top:.125rem;display:inline-flex;width:2rem;height:2rem;flex-shrink:0;align-items:center;justify-content:center;border-radius:.5rem;border:1px solid #e2e8f0;background:#f1f5f9;color:#475569}.cortex-capture-form__multi-icon-svg{width:1rem;height:1rem}.cortex-capture-form__multi-title-wrap{min-width:0}.cortex-capture-form__multi-title{font-size:.8125rem;font-weight:600;letter-spacing:-.01em;color:#1e293b;margin:0}.cortex-capture-form__multi-subtitle{margin-top:.125rem;font-size:.6875rem;color:#64748b;margin-bottom:0}.cortex-capture-form__multi-fields{display:grid;gap:.75rem;padding:1rem;border:0}@media(min-width:640px){.cortex-capture-form__multi-fields{padding:1.25rem}}.cortex-capture-form__multi-item{border-radius:.75rem;border:1px solid #e2e8f0;background:#fff;padding:.75rem;transition:border-color .15s}.cortex-capture-form__multi-item:hover{border-color:#cbd5e1}.cortex-capture-form__multi-item-header{margin-bottom:.5rem;display:flex;align-items:center;justify-content:space-between;gap:.5rem}.cortex-capture-form__multi-item-label{display:block;font-size:.75rem;font-weight:500;line-height:1;color:#334155}.cortex-capture-form__required-badge{display:inline-flex;align-items:center;border-radius:.25rem;border:1px solid #e2e8f0;background:#f8fafc;padding:.125rem .375rem;font-size:.625rem;font-weight:500;text-transform:uppercase;letter-spacing:.05em;color:#64748b}.cortex-capture-form__multi-footer{display:flex;align-items:center;justify-content:flex-end;gap:.5rem;border-top:1px solid #e2e8f0;background:#ffffffe6;padding:.75rem 1rem}@media(min-width:640px){.cortex-capture-form__multi-footer{padding:.75rem 1.25rem}}.cortex-capture-form__cancel-btn{display:inline-flex;align-items:center;border-radius:.375rem;border:1px solid #cbd5e1;background:#fff;padding:.375rem .75rem;font-size:.75rem;font-weight:500;color:#475569;cursor:pointer;transition:background-color .15s}.cortex-capture-form__cancel-btn:hover{background:#f8fafc}.cortex-capture-form__cancel-btn:active{background:#f1f5f9}\n"] }]
760
987
  }], propDecorators: { message: [{ type: i0.Input, args: [{ isSignal: true, alias: "message", required: true }] }], toolPart: [{ type: i0.Input, args: [{ isSignal: true, alias: "toolPart", required: true }] }], setOutput: [{ type: i0.Input, args: [{ isSignal: true, alias: "setOutput", required: true }] }] } });
@@ -808,8 +1035,8 @@ class FileInputComponent {
808
1035
  this.value.set(value);
809
1036
  this.onChange?.(value);
810
1037
  }
811
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: FileInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
812
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.4", type: FileInputComponent, isStandalone: true, selector: "cortex-file-input", inputs: { allowedMimeTypes: { classPropertyName: "allowedMimeTypes", publicName: "allowedMimeTypes", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
1038
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: FileInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1039
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.5", type: FileInputComponent, isStandalone: true, selector: "cortex-file-input", inputs: { allowedMimeTypes: { classPropertyName: "allowedMimeTypes", publicName: "allowedMimeTypes", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
813
1040
  {
814
1041
  provide: NG_VALUE_ACCESSOR,
815
1042
  multi: true,
@@ -825,7 +1052,7 @@ class FileInputComponent {
825
1052
  <input #fileInput (change)="loadFile($event)" type="file" class="cortex-file-input__hidden" />
826
1053
  </div>`, isInline: true, styles: [".cortex-capture-files{display:block;width:100%}.cortex-file-input{display:flex;width:100%;cursor:pointer;align-items:center;border-radius:.5rem;border:1px solid #cbd5e1;background:#f8fafc;transition:border-color .15s}.cortex-file-input:hover{border-color:#94a3b8}.cortex-file-input:focus-within{box-shadow:0 0 0 2px #cbd5e1}.cortex-file-input__btn{margin:.25rem;flex-shrink:0;cursor:pointer;border-radius:.375rem;border:0;background:#1e293b;padding:.375rem .75rem;font-size:.6875rem;font-weight:600;letter-spacing:.025em;color:#f1f5f9}.cortex-file-input__btn:hover{background:#334155}.cortex-file-input__name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding:0 .75rem;font-size:.75rem;color:#475569}.cortex-file-input__hidden{display:none}.cortex-capture-success{overflow:hidden;border-radius:1rem;border:1px solid #a7f3d0;background:linear-gradient(to bottom,#ecfdf5cc,#fff)}.cortex-capture-success__header{display:flex;align-items:center;gap:.75rem;padding:.75rem 1rem}@media(min-width:640px){.cortex-capture-success__header{padding:.75rem 1.25rem}}.cortex-capture-success__icon{display:inline-flex;width:2rem;height:2rem;flex-shrink:0;align-items:center;justify-content:center;border-radius:.5rem;border:1px solid #a7f3d0;background:#d1fae5;color:#059669}.cortex-capture-success__icon-svg{width:1rem;height:1rem}.cortex-capture-success__title-wrap{min-width:0}.cortex-capture-success__title{font-size:.8125rem;font-weight:600;letter-spacing:-.01em;color:#065f46;margin:0}.cortex-capture-success__file-list{border-top:1px solid #d1fae5;padding:.625rem 1rem}@media(min-width:640px){.cortex-capture-success__file-list{padding:.625rem 1.25rem}}.cortex-capture-success__files{display:flex;flex-wrap:wrap;gap:.5rem;list-style:none;margin:0;padding:0}.cortex-capture-success__download-btn{display:inline-flex;cursor:pointer;align-items:center;gap:.375rem;border-radius:.5rem;border:1px solid #d1fae5;background:#fff;padding:.375rem .625rem;font-size:.75rem;font-weight:500;color:#047857;box-shadow:0 1px 2px #0000000d;transition:all .15s}.cortex-capture-success__download-btn:hover{border-color:#a7f3d0;background:#ecfdf5;box-shadow:0 1px 3px #0000001a}.cortex-capture-success__download-btn:active{transform:scale(.97)}.cortex-capture-success__file-icon{width:.875rem;height:.875rem;flex-shrink:0;color:#6ee7b7}.cortex-capture-success__file-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:180px}.cortex-capture-success__dl-icon{width:.75rem;height:.75rem;flex-shrink:0;color:#86efac}.cortex-capture-canceled-wrap{display:flex;justify-content:center}.cortex-capture-canceled{display:inline-flex;align-items:center;gap:.625rem;border-radius:.5rem;border:1px solid #e2e8f0;background:#f8fafc;padding:.625rem 1rem}.cortex-capture-canceled__icon{display:inline-flex;width:1.5rem;height:1.5rem;flex-shrink:0;align-items:center;justify-content:center;border-radius:.375rem;border:1px solid #e2e8f0;background:#f1f5f9;color:#94a3b8}.cortex-capture-canceled__icon-svg{width:.75rem;height:.75rem}.cortex-capture-canceled__text{font-size:.8125rem;font-weight:500;color:#94a3b8}.cortex-capture-form{width:100%}.cortex-capture-form__single{border-radius:.75rem;border:1px solid #e2e8f0;background:#f8fafc;padding:.75rem}.cortex-capture-form__label{display:block;margin-bottom:.375rem;font-size:.75rem;color:#64748b}.cortex-capture-form__row{display:flex;align-items:center;gap:.5rem}.cortex-capture-form__input{min-width:0;flex:1}.cortex-capture-form__cancel-link{flex-shrink:0;font-size:.75rem;font-weight:500;color:#94a3b8;background:none;border:0;cursor:pointer;transition:color .15s}.cortex-capture-form__cancel-link:hover{color:#475569}.cortex-capture-form__submit-btn{display:inline-flex;flex-shrink:0;align-items:center;border-radius:.375rem;background:#1e293b;padding:.375rem .75rem;font-size:.75rem;font-weight:500;color:#f1f5f9;border:0;cursor:pointer;transition:background-color .15s}.cortex-capture-form__submit-btn:hover{background:#334155}.cortex-capture-form__submit-btn:active{background:#0f172a}.cortex-capture-form__submit-btn:disabled{cursor:not-allowed;background:#cbd5e1}.cortex-capture-form__spinner{width:.75rem;height:.75rem;margin-inline-end:.375rem;animation:cortex-capture-spin .8s linear infinite}.cortex-capture-form__spinner-track{opacity:.25}@keyframes cortex-capture-spin{to{transform:rotate(360deg)}}.cortex-capture-form__multi{overflow:hidden;border-radius:1rem;border:1px solid #e2e8f0;background:linear-gradient(to bottom,#fff,#f8fafc)}.cortex-capture-form__multi-header{border-bottom:1px solid #e2e8f0;background:#ffffffd9;padding:.75rem 1rem}@media(min-width:640px){.cortex-capture-form__multi-header{padding:.75rem 1.25rem}}.cortex-capture-form__multi-header-row{display:flex;align-items:flex-start;gap:.75rem}.cortex-capture-form__multi-icon{margin-top:.125rem;display:inline-flex;width:2rem;height:2rem;flex-shrink:0;align-items:center;justify-content:center;border-radius:.5rem;border:1px solid #e2e8f0;background:#f1f5f9;color:#475569}.cortex-capture-form__multi-icon-svg{width:1rem;height:1rem}.cortex-capture-form__multi-title-wrap{min-width:0}.cortex-capture-form__multi-title{font-size:.8125rem;font-weight:600;letter-spacing:-.01em;color:#1e293b;margin:0}.cortex-capture-form__multi-subtitle{margin-top:.125rem;font-size:.6875rem;color:#64748b;margin-bottom:0}.cortex-capture-form__multi-fields{display:grid;gap:.75rem;padding:1rem;border:0}@media(min-width:640px){.cortex-capture-form__multi-fields{padding:1.25rem}}.cortex-capture-form__multi-item{border-radius:.75rem;border:1px solid #e2e8f0;background:#fff;padding:.75rem;transition:border-color .15s}.cortex-capture-form__multi-item:hover{border-color:#cbd5e1}.cortex-capture-form__multi-item-header{margin-bottom:.5rem;display:flex;align-items:center;justify-content:space-between;gap:.5rem}.cortex-capture-form__multi-item-label{display:block;font-size:.75rem;font-weight:500;line-height:1;color:#334155}.cortex-capture-form__required-badge{display:inline-flex;align-items:center;border-radius:.25rem;border:1px solid #e2e8f0;background:#f8fafc;padding:.125rem .375rem;font-size:.625rem;font-weight:500;text-transform:uppercase;letter-spacing:.05em;color:#64748b}.cortex-capture-form__multi-footer{display:flex;align-items:center;justify-content:flex-end;gap:.5rem;border-top:1px solid #e2e8f0;background:#ffffffe6;padding:.75rem 1rem}@media(min-width:640px){.cortex-capture-form__multi-footer{padding:.75rem 1.25rem}}.cortex-capture-form__cancel-btn{display:inline-flex;align-items:center;border-radius:.375rem;border:1px solid #cbd5e1;background:#fff;padding:.375rem .75rem;font-size:.75rem;font-weight:500;color:#475569;cursor:pointer;transition:background-color .15s}.cortex-capture-form__cancel-btn:hover{background:#f8fafc}.cortex-capture-form__cancel-btn:active{background:#f1f5f9}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
827
1054
  }
828
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: FileInputComponent, decorators: [{
1055
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: FileInputComponent, decorators: [{
829
1056
  type: Component,
830
1057
  args: [{ selector: 'cortex-file-input', template: `<div class="cortex-file-input">
831
1058
  <button type="button" (click)="fileInput.click()" class="cortex-file-input__btn">
@@ -931,10 +1158,10 @@ class MessageToolCallAnimatedComponent {
931
1158
  return Math.abs(hash) % STATUS_COUNT;
932
1159
  }, ...(ngDevMode ? [{ debugName: "stableIndex" }] : /* istanbul ignore next */ []));
933
1160
  chatService = inject(CortexChatService);
934
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MessageToolCallAnimatedComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
935
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: MessageToolCallAnimatedComponent, isStandalone: true, selector: "cortex-message-tool-call-animated", inputs: { message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: true, transformFunction: null }, toolCallPart: { classPropertyName: "toolCallPart", publicName: "toolCallPart", isSignal: true, isRequired: true, transformFunction: null } }, host: { classAttribute: "cortex-tool-call-animated" }, ngImport: i0, template: "@if (customComponent(); as custom) {\n <ng-container\n *ngComponentOutlet=\"\n custom;\n inputs: { toolCallPart: toolCallPart(), message: message(), setOutput: setOutput() };\n injector: config.injector\n \"\n />\n} @else {\n @switch (toolCallPart().type) {\n @case ('tool-captureFiles') {\n <cortex-message-capture-files-part\n [toolPart]=\"toolCallPart()\"\n [message]=\"message()\"\n [setOutput]=\"setOutput()\"\n />\n }\n @default {\n @let state = animState();\n @let active = isActive();\n\n <div class=\"cortex-tool-pill-wrap\">\n <div\n class=\"cortex-tool-pill\"\n [class.cortex-tool-pill--active]=\"active\"\n [class.cortex-tool-pill--complete]=\"state === 'complete'\"\n [class.cortex-tool-pill--error]=\"state === 'error'\"\n [class.cortex-tool-pill--denied]=\"state === 'denied'\"\n >\n <!-- Icon box -->\n <div\n class=\"cortex-tool-pill__icon\"\n [class.cortex-tool-pill__icon--active]=\"active\"\n [class.cortex-tool-pill__icon--complete]=\"state === 'complete'\"\n [class.cortex-tool-pill__icon--error]=\"state === 'error'\"\n [class.cortex-tool-pill__icon--denied]=\"state === 'denied'\"\n >\n <!-- Spinner -->\n <div\n class=\"cortex-tool-pill__spinner\"\n [class.cortex-tool-pill__spinner--visible]=\"active\"\n ></div>\n <!-- Check -->\n <svg\n class=\"cortex-tool-pill__svg\"\n [class.cortex-tool-pill__svg--visible]=\"state === 'complete'\"\n [class.cortex-tool-pill__svg--check]=\"state === 'complete'\"\n viewBox=\"0 0 20 20\"\n fill=\"none\"\n >\n <path\n d=\"M5.5 10.5 L8.5 13.5 L14.5 7\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n <!-- Error -->\n <svg\n class=\"cortex-tool-pill__svg\"\n [class.cortex-tool-pill__svg--visible]=\"state === 'error'\"\n [class.cortex-tool-pill__svg--error]=\"state === 'error'\"\n viewBox=\"0 0 20 20\"\n fill=\"none\"\n >\n <path\n d=\"M6.5 6.5 L13.5 13.5 M13.5 6.5 L6.5 13.5\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n />\n </svg>\n <!-- Denied -->\n <svg\n class=\"cortex-tool-pill__svg\"\n [class.cortex-tool-pill__svg--visible]=\"state === 'denied'\"\n [class.cortex-tool-pill__svg--denied]=\"state === 'denied'\"\n viewBox=\"0 0 20 20\"\n fill=\"none\"\n >\n <path\n d=\"M6 10 L14 10\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n />\n </svg>\n </div>\n\n <!-- Title -->\n <span\n class=\"cortex-tool-pill__title\"\n [class.cortex-tool-pill__title--active]=\"active\"\n [class.cortex-tool-pill__title--complete]=\"state === 'complete'\"\n [class.cortex-tool-pill__title--error]=\"state === 'error'\"\n [class.cortex-tool-pill__title--denied]=\"state === 'denied'\"\n >\n {{ displayTitleKey() | translate }}\n </span>\n\n <!-- Bottom bar -->\n <div class=\"cortex-tool-pill__bar-track\">\n <div\n class=\"cortex-tool-pill__bar\"\n [class.cortex-tool-pill__bar--active]=\"active\"\n [class.cortex-tool-pill__bar--complete]=\"state === 'complete'\"\n [class.cortex-tool-pill__bar--error]=\"state === 'error'\"\n [class.cortex-tool-pill__bar--denied]=\"state === 'denied'\"\n ></div>\n </div>\n </div>\n </div>\n }\n }\n}\n", styles: [".cortex-tool-call-animated{display:block;width:100%}.cortex-tool-pill-wrap{display:flex;justify-content:center}.cortex-tool-pill{display:inline-flex;align-items:center;gap:.625rem;padding:.625rem 1rem;border-radius:.5rem;border:1px solid;position:relative;overflow:hidden;transition:background-color .3s,border-color .3s}.cortex-tool-pill--active{border-color:#c7d2fe;background:#eef2ff}.cortex-tool-pill--complete{border-color:#a7f3d0;background:#ecfdf5}.cortex-tool-pill--error{border-color:#fecaca;background:#fef2f2}.cortex-tool-pill--denied{border-color:#e2e8f0;background:#f8fafc;opacity:.6}.cortex-tool-pill__icon{position:relative;width:1.5rem;height:1.5rem;display:flex;align-items:center;justify-content:center;border-radius:.375rem;border:1px solid;flex-shrink:0;transition:background-color .3s,border-color .3s}.cortex-tool-pill__icon--active{background:#e0e7ff;border-color:#c7d2fe}.cortex-tool-pill__icon--complete{background:#d1fae5;border-color:#a7f3d0}.cortex-tool-pill__icon--error{background:#fee2e2;border-color:#fecaca}.cortex-tool-pill__icon--denied{background:#f1f5f9;border-color:#e2e8f0}.cortex-tool-pill__spinner{position:absolute;width:.75rem;height:.75rem;border:1.5px solid #c7d2fe;border-top-color:#6366f1;border-radius:9999px;opacity:0;transition:opacity .2s}.cortex-tool-pill__spinner--visible{opacity:1;animation:cortex-tool-spin .8s linear infinite}@keyframes cortex-tool-spin{to{transform:rotate(360deg)}}.cortex-tool-pill__svg{position:absolute;width:.75rem;height:.75rem;opacity:0;transform:scale(.6);transition:opacity .2s,transform .2s}.cortex-tool-pill__svg--visible{opacity:1;transform:scale(1)}.cortex-tool-pill__svg--check{color:#059669}.cortex-tool-pill__svg--error{color:#dc2626}.cortex-tool-pill__svg--denied{color:#94a3b8}.cortex-tool-pill__title{font-size:.8125rem;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:color .3s}.cortex-tool-pill__title--active{color:#4338ca}.cortex-tool-pill__title--complete{color:#047857}.cortex-tool-pill__title--error{color:#dc2626}.cortex-tool-pill__title--denied{color:#94a3b8}.cortex-tool-pill__bar-track{position:absolute;bottom:0;left:0;right:0;height:2px;overflow:hidden}.cortex-tool-pill__bar{height:100%;width:100%;transform-origin:left}.cortex-tool-pill__bar--active{background:#818cf8;animation:cortex-bar-slide 1.5s ease-in-out infinite}.cortex-tool-pill__bar--complete{background:#34d399;animation:cortex-bar-fill .3s ease-out both}.cortex-tool-pill__bar--error{background:#f87171;animation:cortex-bar-fill .3s ease-out both}.cortex-tool-pill__bar--denied{opacity:0}@keyframes cortex-bar-slide{0%{transform:translate(-100%)}to{transform:translate(100%)}}@keyframes cortex-bar-fill{0%{transform:scaleX(0)}to{transform:scaleX(1)}}\n"], dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "component", type: MessageCaptureFilesPartComponent, selector: "cortex-message-capture-files-part", inputs: ["message", "toolPart", "setOutput"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1161
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MessageToolCallAnimatedComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1162
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: MessageToolCallAnimatedComponent, isStandalone: true, selector: "cortex-message-tool-call-animated", inputs: { message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: true, transformFunction: null }, toolCallPart: { classPropertyName: "toolCallPart", publicName: "toolCallPart", isSignal: true, isRequired: true, transformFunction: null } }, host: { classAttribute: "cortex-tool-call-animated" }, ngImport: i0, template: "@if (customComponent(); as custom) {\n <ng-container\n *ngComponentOutlet=\"\n custom;\n inputs: { toolCallPart: toolCallPart(), message: message(), setOutput: setOutput() };\n injector: config.injector\n \"\n />\n} @else {\n @switch (toolCallPart().type) {\n @case ('tool-captureFiles') {\n <cortex-message-capture-files-part\n [toolPart]=\"toolCallPart()\"\n [message]=\"message()\"\n [setOutput]=\"setOutput()\"\n />\n }\n @default {\n @let state = animState();\n @let active = isActive();\n\n <div class=\"cortex-tool-pill-wrap\">\n <div\n class=\"cortex-tool-pill\"\n [class.cortex-tool-pill--active]=\"active\"\n [class.cortex-tool-pill--complete]=\"state === 'complete'\"\n [class.cortex-tool-pill--error]=\"state === 'error'\"\n [class.cortex-tool-pill--denied]=\"state === 'denied'\"\n >\n <!-- Icon box -->\n <div\n class=\"cortex-tool-pill__icon\"\n [class.cortex-tool-pill__icon--active]=\"active\"\n [class.cortex-tool-pill__icon--complete]=\"state === 'complete'\"\n [class.cortex-tool-pill__icon--error]=\"state === 'error'\"\n [class.cortex-tool-pill__icon--denied]=\"state === 'denied'\"\n >\n <!-- Spinner -->\n <div\n class=\"cortex-tool-pill__spinner\"\n [class.cortex-tool-pill__spinner--visible]=\"active\"\n ></div>\n <!-- Check -->\n <svg\n class=\"cortex-tool-pill__svg\"\n [class.cortex-tool-pill__svg--visible]=\"state === 'complete'\"\n [class.cortex-tool-pill__svg--check]=\"state === 'complete'\"\n viewBox=\"0 0 20 20\"\n fill=\"none\"\n >\n <path\n d=\"M5.5 10.5 L8.5 13.5 L14.5 7\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n <!-- Error -->\n <svg\n class=\"cortex-tool-pill__svg\"\n [class.cortex-tool-pill__svg--visible]=\"state === 'error'\"\n [class.cortex-tool-pill__svg--error]=\"state === 'error'\"\n viewBox=\"0 0 20 20\"\n fill=\"none\"\n >\n <path\n d=\"M6.5 6.5 L13.5 13.5 M13.5 6.5 L6.5 13.5\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n />\n </svg>\n <!-- Denied -->\n <svg\n class=\"cortex-tool-pill__svg\"\n [class.cortex-tool-pill__svg--visible]=\"state === 'denied'\"\n [class.cortex-tool-pill__svg--denied]=\"state === 'denied'\"\n viewBox=\"0 0 20 20\"\n fill=\"none\"\n >\n <path\n d=\"M6 10 L14 10\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n />\n </svg>\n </div>\n\n <!-- Title -->\n <span\n class=\"cortex-tool-pill__title\"\n [class.cortex-tool-pill__title--active]=\"active\"\n [class.cortex-tool-pill__title--complete]=\"state === 'complete'\"\n [class.cortex-tool-pill__title--error]=\"state === 'error'\"\n [class.cortex-tool-pill__title--denied]=\"state === 'denied'\"\n >\n {{ displayTitleKey() | translate }}\n </span>\n\n <!-- Bottom bar -->\n <div class=\"cortex-tool-pill__bar-track\">\n <div\n class=\"cortex-tool-pill__bar\"\n [class.cortex-tool-pill__bar--active]=\"active\"\n [class.cortex-tool-pill__bar--complete]=\"state === 'complete'\"\n [class.cortex-tool-pill__bar--error]=\"state === 'error'\"\n [class.cortex-tool-pill__bar--denied]=\"state === 'denied'\"\n ></div>\n </div>\n </div>\n </div>\n }\n }\n}\n", styles: [".cortex-tool-call-animated{display:block;width:100%}.cortex-tool-pill-wrap{display:flex;justify-content:center}.cortex-tool-pill{display:inline-flex;align-items:center;gap:.625rem;padding:.625rem 1rem;border-radius:.5rem;border:1px solid;position:relative;overflow:hidden;transition:background-color .3s,border-color .3s}.cortex-tool-pill--active{border-color:#c7d2fe;background:#eef2ff}.cortex-tool-pill--complete{border-color:#a7f3d0;background:#ecfdf5}.cortex-tool-pill--error{border-color:#fecaca;background:#fef2f2}.cortex-tool-pill--denied{border-color:#e2e8f0;background:#f8fafc;opacity:.6}.cortex-tool-pill__icon{position:relative;width:1.5rem;height:1.5rem;display:flex;align-items:center;justify-content:center;border-radius:.375rem;border:1px solid;flex-shrink:0;transition:background-color .3s,border-color .3s}.cortex-tool-pill__icon--active{background:#e0e7ff;border-color:#c7d2fe}.cortex-tool-pill__icon--complete{background:#d1fae5;border-color:#a7f3d0}.cortex-tool-pill__icon--error{background:#fee2e2;border-color:#fecaca}.cortex-tool-pill__icon--denied{background:#f1f5f9;border-color:#e2e8f0}.cortex-tool-pill__spinner{position:absolute;width:.75rem;height:.75rem;border:1.5px solid #c7d2fe;border-top-color:#6366f1;border-radius:9999px;opacity:0;transition:opacity .2s}.cortex-tool-pill__spinner--visible{opacity:1;animation:cortex-tool-spin .8s linear infinite}@keyframes cortex-tool-spin{to{transform:rotate(360deg)}}.cortex-tool-pill__svg{position:absolute;width:.75rem;height:.75rem;opacity:0;transform:scale(.6);transition:opacity .2s,transform .2s}.cortex-tool-pill__svg--visible{opacity:1;transform:scale(1)}.cortex-tool-pill__svg--check{color:#059669}.cortex-tool-pill__svg--error{color:#dc2626}.cortex-tool-pill__svg--denied{color:#94a3b8}.cortex-tool-pill__title{font-size:.8125rem;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:color .3s}.cortex-tool-pill__title--active{color:#4338ca}.cortex-tool-pill__title--complete{color:#047857}.cortex-tool-pill__title--error{color:#dc2626}.cortex-tool-pill__title--denied{color:#94a3b8}.cortex-tool-pill__bar-track{position:absolute;bottom:0;left:0;right:0;height:2px;overflow:hidden}.cortex-tool-pill__bar{height:100%;width:100%;transform-origin:left}.cortex-tool-pill__bar--active{background:#818cf8;animation:cortex-bar-slide 1.5s ease-in-out infinite}.cortex-tool-pill__bar--complete{background:#34d399;animation:cortex-bar-fill .3s ease-out both}.cortex-tool-pill__bar--error{background:#f87171;animation:cortex-bar-fill .3s ease-out both}.cortex-tool-pill__bar--denied{opacity:0}@keyframes cortex-bar-slide{0%{transform:translate(-100%)}to{transform:translate(100%)}}@keyframes cortex-bar-fill{0%{transform:scaleX(0)}to{transform:scaleX(1)}}\n"], dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "component", type: MessageCaptureFilesPartComponent, selector: "cortex-message-capture-files-part", inputs: ["message", "toolPart", "setOutput"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
936
1163
  }
937
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MessageToolCallAnimatedComponent, decorators: [{
1164
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MessageToolCallAnimatedComponent, decorators: [{
938
1165
  type: Component,
939
1166
  args: [{ selector: 'cortex-message-tool-call-animated', imports: [NgComponentOutlet, MessageCaptureFilesPartComponent, TranslatePipe], host: { class: 'cortex-tool-call-animated' }, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (customComponent(); as custom) {\n <ng-container\n *ngComponentOutlet=\"\n custom;\n inputs: { toolCallPart: toolCallPart(), message: message(), setOutput: setOutput() };\n injector: config.injector\n \"\n />\n} @else {\n @switch (toolCallPart().type) {\n @case ('tool-captureFiles') {\n <cortex-message-capture-files-part\n [toolPart]=\"toolCallPart()\"\n [message]=\"message()\"\n [setOutput]=\"setOutput()\"\n />\n }\n @default {\n @let state = animState();\n @let active = isActive();\n\n <div class=\"cortex-tool-pill-wrap\">\n <div\n class=\"cortex-tool-pill\"\n [class.cortex-tool-pill--active]=\"active\"\n [class.cortex-tool-pill--complete]=\"state === 'complete'\"\n [class.cortex-tool-pill--error]=\"state === 'error'\"\n [class.cortex-tool-pill--denied]=\"state === 'denied'\"\n >\n <!-- Icon box -->\n <div\n class=\"cortex-tool-pill__icon\"\n [class.cortex-tool-pill__icon--active]=\"active\"\n [class.cortex-tool-pill__icon--complete]=\"state === 'complete'\"\n [class.cortex-tool-pill__icon--error]=\"state === 'error'\"\n [class.cortex-tool-pill__icon--denied]=\"state === 'denied'\"\n >\n <!-- Spinner -->\n <div\n class=\"cortex-tool-pill__spinner\"\n [class.cortex-tool-pill__spinner--visible]=\"active\"\n ></div>\n <!-- Check -->\n <svg\n class=\"cortex-tool-pill__svg\"\n [class.cortex-tool-pill__svg--visible]=\"state === 'complete'\"\n [class.cortex-tool-pill__svg--check]=\"state === 'complete'\"\n viewBox=\"0 0 20 20\"\n fill=\"none\"\n >\n <path\n d=\"M5.5 10.5 L8.5 13.5 L14.5 7\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n <!-- Error -->\n <svg\n class=\"cortex-tool-pill__svg\"\n [class.cortex-tool-pill__svg--visible]=\"state === 'error'\"\n [class.cortex-tool-pill__svg--error]=\"state === 'error'\"\n viewBox=\"0 0 20 20\"\n fill=\"none\"\n >\n <path\n d=\"M6.5 6.5 L13.5 13.5 M13.5 6.5 L6.5 13.5\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n />\n </svg>\n <!-- Denied -->\n <svg\n class=\"cortex-tool-pill__svg\"\n [class.cortex-tool-pill__svg--visible]=\"state === 'denied'\"\n [class.cortex-tool-pill__svg--denied]=\"state === 'denied'\"\n viewBox=\"0 0 20 20\"\n fill=\"none\"\n >\n <path\n d=\"M6 10 L14 10\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n />\n </svg>\n </div>\n\n <!-- Title -->\n <span\n class=\"cortex-tool-pill__title\"\n [class.cortex-tool-pill__title--active]=\"active\"\n [class.cortex-tool-pill__title--complete]=\"state === 'complete'\"\n [class.cortex-tool-pill__title--error]=\"state === 'error'\"\n [class.cortex-tool-pill__title--denied]=\"state === 'denied'\"\n >\n {{ displayTitleKey() | translate }}\n </span>\n\n <!-- Bottom bar -->\n <div class=\"cortex-tool-pill__bar-track\">\n <div\n class=\"cortex-tool-pill__bar\"\n [class.cortex-tool-pill__bar--active]=\"active\"\n [class.cortex-tool-pill__bar--complete]=\"state === 'complete'\"\n [class.cortex-tool-pill__bar--error]=\"state === 'error'\"\n [class.cortex-tool-pill__bar--denied]=\"state === 'denied'\"\n ></div>\n </div>\n </div>\n </div>\n }\n }\n}\n", styles: [".cortex-tool-call-animated{display:block;width:100%}.cortex-tool-pill-wrap{display:flex;justify-content:center}.cortex-tool-pill{display:inline-flex;align-items:center;gap:.625rem;padding:.625rem 1rem;border-radius:.5rem;border:1px solid;position:relative;overflow:hidden;transition:background-color .3s,border-color .3s}.cortex-tool-pill--active{border-color:#c7d2fe;background:#eef2ff}.cortex-tool-pill--complete{border-color:#a7f3d0;background:#ecfdf5}.cortex-tool-pill--error{border-color:#fecaca;background:#fef2f2}.cortex-tool-pill--denied{border-color:#e2e8f0;background:#f8fafc;opacity:.6}.cortex-tool-pill__icon{position:relative;width:1.5rem;height:1.5rem;display:flex;align-items:center;justify-content:center;border-radius:.375rem;border:1px solid;flex-shrink:0;transition:background-color .3s,border-color .3s}.cortex-tool-pill__icon--active{background:#e0e7ff;border-color:#c7d2fe}.cortex-tool-pill__icon--complete{background:#d1fae5;border-color:#a7f3d0}.cortex-tool-pill__icon--error{background:#fee2e2;border-color:#fecaca}.cortex-tool-pill__icon--denied{background:#f1f5f9;border-color:#e2e8f0}.cortex-tool-pill__spinner{position:absolute;width:.75rem;height:.75rem;border:1.5px solid #c7d2fe;border-top-color:#6366f1;border-radius:9999px;opacity:0;transition:opacity .2s}.cortex-tool-pill__spinner--visible{opacity:1;animation:cortex-tool-spin .8s linear infinite}@keyframes cortex-tool-spin{to{transform:rotate(360deg)}}.cortex-tool-pill__svg{position:absolute;width:.75rem;height:.75rem;opacity:0;transform:scale(.6);transition:opacity .2s,transform .2s}.cortex-tool-pill__svg--visible{opacity:1;transform:scale(1)}.cortex-tool-pill__svg--check{color:#059669}.cortex-tool-pill__svg--error{color:#dc2626}.cortex-tool-pill__svg--denied{color:#94a3b8}.cortex-tool-pill__title{font-size:.8125rem;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:color .3s}.cortex-tool-pill__title--active{color:#4338ca}.cortex-tool-pill__title--complete{color:#047857}.cortex-tool-pill__title--error{color:#dc2626}.cortex-tool-pill__title--denied{color:#94a3b8}.cortex-tool-pill__bar-track{position:absolute;bottom:0;left:0;right:0;height:2px;overflow:hidden}.cortex-tool-pill__bar{height:100%;width:100%;transform-origin:left}.cortex-tool-pill__bar--active{background:#818cf8;animation:cortex-bar-slide 1.5s ease-in-out infinite}.cortex-tool-pill__bar--complete{background:#34d399;animation:cortex-bar-fill .3s ease-out both}.cortex-tool-pill__bar--error{background:#f87171;animation:cortex-bar-fill .3s ease-out both}.cortex-tool-pill__bar--denied{opacity:0}@keyframes cortex-bar-slide{0%{transform:translate(-100%)}to{transform:translate(100%)}}@keyframes cortex-bar-fill{0%{transform:scaleX(0)}to{transform:scaleX(1)}}\n"] }]
940
1167
  }], propDecorators: { message: [{ type: i0.Input, args: [{ isSignal: true, alias: "message", required: true }] }], toolCallPart: [{ type: i0.Input, args: [{ isSignal: true, alias: "toolCallPart", required: true }] }] } });
@@ -982,10 +1209,10 @@ class SubtleActivityComponent {
982
1209
  if (this.enterTimeout)
983
1210
  clearTimeout(this.enterTimeout);
984
1211
  }
985
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: SubtleActivityComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
986
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.4", type: SubtleActivityComponent, isStandalone: true, selector: "cortex-subtle-activity", inputs: { labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: true, transformFunction: null } }, host: { classAttribute: "cortex-subtle-activity" }, ngImport: i0, template: "<div class=\"cortex-subtle-activity__dots\">\n <span class=\"cortex-subtle-activity__dot\"></span>\n <span class=\"cortex-subtle-activity__dot cortex-subtle-activity__dot--d1\"></span>\n <span class=\"cortex-subtle-activity__dot cortex-subtle-activity__dot--d2\"></span>\n</div>\n\n<div class=\"cortex-subtle-activity__label-mask\">\n <span\n class=\"cortex-subtle-activity__label\"\n [class.cortex-subtle-activity__label--idle]=\"labelState() === 'idle'\"\n [class.cortex-subtle-activity__label--exiting]=\"labelState() === 'exiting'\"\n [class.cortex-subtle-activity__label--enter-start]=\"labelState() === 'enter-start'\"\n [class.cortex-subtle-activity__label--entering]=\"labelState() === 'entering'\"\n >\n {{ labels()[currentIndex()] | translate }}\n </span>\n</div>\n", styles: [".cortex-subtle-activity{display:flex;align-items:center;gap:.375rem;padding:.25rem 0;width:fit-content}.cortex-subtle-activity__dots{display:flex;align-items:center;gap:3px}.cortex-subtle-activity__dot{width:3px;height:3px;border-radius:9999px;background:#a5b4fc;animation:cortex-subtle-dot-pulse 1.4s ease-in-out infinite}.cortex-subtle-activity__dot--d1{animation-delay:.2s}.cortex-subtle-activity__dot--d2{animation-delay:.4s}@keyframes cortex-subtle-dot-pulse{0%,to{opacity:.3;transform:scale(.8)}40%{opacity:1;transform:scale(1.3)}}.cortex-subtle-activity__label-mask{overflow:hidden;position:relative;height:1.1em}.cortex-subtle-activity__label{display:block;font-size:.75rem;color:#94a3b8;white-space:nowrap;line-height:1.1em}.cortex-subtle-activity__label--idle,.cortex-subtle-activity__label--entering{opacity:1;transform:translateY(0);transition:opacity .3s ease,transform .3s ease}.cortex-subtle-activity__label--exiting{opacity:0;transform:translateY(-6px);transition:opacity .3s ease,transform .3s ease}.cortex-subtle-activity__label--enter-start{opacity:0;transform:translateY(6px);transition:none}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1212
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SubtleActivityComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1213
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.5", type: SubtleActivityComponent, isStandalone: true, selector: "cortex-subtle-activity", inputs: { labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: true, transformFunction: null } }, host: { classAttribute: "cortex-subtle-activity" }, ngImport: i0, template: "<div class=\"cortex-subtle-activity__dots\">\n <span class=\"cortex-subtle-activity__dot\"></span>\n <span class=\"cortex-subtle-activity__dot cortex-subtle-activity__dot--d1\"></span>\n <span class=\"cortex-subtle-activity__dot cortex-subtle-activity__dot--d2\"></span>\n</div>\n\n<div class=\"cortex-subtle-activity__label-mask\">\n <span\n class=\"cortex-subtle-activity__label\"\n [class.cortex-subtle-activity__label--idle]=\"labelState() === 'idle'\"\n [class.cortex-subtle-activity__label--exiting]=\"labelState() === 'exiting'\"\n [class.cortex-subtle-activity__label--enter-start]=\"labelState() === 'enter-start'\"\n [class.cortex-subtle-activity__label--entering]=\"labelState() === 'entering'\"\n >\n {{ labels()[currentIndex()] | translate }}\n </span>\n</div>\n", styles: [".cortex-subtle-activity{display:flex;align-items:center;gap:.375rem;padding:.25rem 0;width:fit-content}.cortex-subtle-activity__dots{display:flex;align-items:center;gap:3px}.cortex-subtle-activity__dot{width:3px;height:3px;border-radius:9999px;background:#a5b4fc;animation:cortex-subtle-dot-pulse 1.4s ease-in-out infinite}.cortex-subtle-activity__dot--d1{animation-delay:.2s}.cortex-subtle-activity__dot--d2{animation-delay:.4s}@keyframes cortex-subtle-dot-pulse{0%,to{opacity:.3;transform:scale(.8)}40%{opacity:1;transform:scale(1.3)}}.cortex-subtle-activity__label-mask{overflow:hidden;position:relative;height:1.1em}.cortex-subtle-activity__label{display:block;font-size:.75rem;color:#94a3b8;white-space:nowrap;line-height:1.1em}.cortex-subtle-activity__label--idle,.cortex-subtle-activity__label--entering{opacity:1;transform:translateY(0);transition:opacity .3s ease,transform .3s ease}.cortex-subtle-activity__label--exiting{opacity:0;transform:translateY(-6px);transition:opacity .3s ease,transform .3s ease}.cortex-subtle-activity__label--enter-start{opacity:0;transform:translateY(6px);transition:none}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
987
1214
  }
988
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: SubtleActivityComponent, decorators: [{
1215
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SubtleActivityComponent, decorators: [{
989
1216
  type: Component,
990
1217
  args: [{ selector: 'cortex-subtle-activity', imports: [TranslatePipe], host: { class: 'cortex-subtle-activity' }, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"cortex-subtle-activity__dots\">\n <span class=\"cortex-subtle-activity__dot\"></span>\n <span class=\"cortex-subtle-activity__dot cortex-subtle-activity__dot--d1\"></span>\n <span class=\"cortex-subtle-activity__dot cortex-subtle-activity__dot--d2\"></span>\n</div>\n\n<div class=\"cortex-subtle-activity__label-mask\">\n <span\n class=\"cortex-subtle-activity__label\"\n [class.cortex-subtle-activity__label--idle]=\"labelState() === 'idle'\"\n [class.cortex-subtle-activity__label--exiting]=\"labelState() === 'exiting'\"\n [class.cortex-subtle-activity__label--enter-start]=\"labelState() === 'enter-start'\"\n [class.cortex-subtle-activity__label--entering]=\"labelState() === 'entering'\"\n >\n {{ labels()[currentIndex()] | translate }}\n </span>\n</div>\n", styles: [".cortex-subtle-activity{display:flex;align-items:center;gap:.375rem;padding:.25rem 0;width:fit-content}.cortex-subtle-activity__dots{display:flex;align-items:center;gap:3px}.cortex-subtle-activity__dot{width:3px;height:3px;border-radius:9999px;background:#a5b4fc;animation:cortex-subtle-dot-pulse 1.4s ease-in-out infinite}.cortex-subtle-activity__dot--d1{animation-delay:.2s}.cortex-subtle-activity__dot--d2{animation-delay:.4s}@keyframes cortex-subtle-dot-pulse{0%,to{opacity:.3;transform:scale(.8)}40%{opacity:1;transform:scale(1.3)}}.cortex-subtle-activity__label-mask{overflow:hidden;position:relative;height:1.1em}.cortex-subtle-activity__label{display:block;font-size:.75rem;color:#94a3b8;white-space:nowrap;line-height:1.1em}.cortex-subtle-activity__label--idle,.cortex-subtle-activity__label--entering{opacity:1;transform:translateY(0);transition:opacity .3s ease,transform .3s ease}.cortex-subtle-activity__label--exiting{opacity:0;transform:translateY(-6px);transition:opacity .3s ease,transform .3s ease}.cortex-subtle-activity__label--enter-start{opacity:0;transform:translateY(6px);transition:none}\n"] }]
991
1218
  }], ctorParameters: () => [], propDecorators: { labels: [{ type: i0.Input, args: [{ isSignal: true, alias: "labels", required: true }] }] } });
@@ -1005,10 +1232,10 @@ const LABELS$3 = [
1005
1232
  class MessageReasoningAnimatedComponent {
1006
1233
  reasoningPart = input.required(...(ngDevMode ? [{ debugName: "reasoningPart" }] : /* istanbul ignore next */ []));
1007
1234
  labels = LABELS$3;
1008
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MessageReasoningAnimatedComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1009
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.4", type: MessageReasoningAnimatedComponent, isStandalone: true, selector: "cortex-message-reasoning-animated", inputs: { reasoningPart: { classPropertyName: "reasoningPart", publicName: "reasoningPart", isSignal: true, isRequired: true, transformFunction: null } }, host: { classAttribute: "cortex-reasoning-animated" }, ngImport: i0, template: "<cortex-subtle-activity [labels]=\"labels\" />\n", styles: [".cortex-reasoning-animated{display:block}\n"], dependencies: [{ kind: "component", type: SubtleActivityComponent, selector: "cortex-subtle-activity", inputs: ["labels"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1235
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MessageReasoningAnimatedComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1236
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.5", type: MessageReasoningAnimatedComponent, isStandalone: true, selector: "cortex-message-reasoning-animated", inputs: { reasoningPart: { classPropertyName: "reasoningPart", publicName: "reasoningPart", isSignal: true, isRequired: true, transformFunction: null } }, host: { classAttribute: "cortex-reasoning-animated" }, ngImport: i0, template: "<cortex-subtle-activity [labels]=\"labels\" />\n", styles: [".cortex-reasoning-animated{display:block}\n"], dependencies: [{ kind: "component", type: SubtleActivityComponent, selector: "cortex-subtle-activity", inputs: ["labels"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1010
1237
  }
1011
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MessageReasoningAnimatedComponent, decorators: [{
1238
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MessageReasoningAnimatedComponent, decorators: [{
1012
1239
  type: Component,
1013
1240
  args: [{ selector: 'cortex-message-reasoning-animated', imports: [SubtleActivityComponent], host: { class: 'cortex-reasoning-animated' }, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<cortex-subtle-activity [labels]=\"labels\" />\n", styles: [".cortex-reasoning-animated{display:block}\n"] }]
1014
1241
  }], propDecorators: { reasoningPart: [{ type: i0.Input, args: [{ isSignal: true, alias: "reasoningPart", required: true }] }] } });
@@ -1027,10 +1254,10 @@ const LABELS$2 = [
1027
1254
  ];
1028
1255
  class ToolCallEndpointAnimatedComponent {
1029
1256
  labels = LABELS$2;
1030
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ToolCallEndpointAnimatedComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1031
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.4", type: ToolCallEndpointAnimatedComponent, isStandalone: true, selector: "cortex-tool-call-endpoint-animated", ngImport: i0, template: '<cortex-subtle-activity [labels]="labels" />', isInline: true, dependencies: [{ kind: "component", type: SubtleActivityComponent, selector: "cortex-subtle-activity", inputs: ["labels"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1257
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ToolCallEndpointAnimatedComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1258
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.5", type: ToolCallEndpointAnimatedComponent, isStandalone: true, selector: "cortex-tool-call-endpoint-animated", ngImport: i0, template: '<cortex-subtle-activity [labels]="labels" />', isInline: true, dependencies: [{ kind: "component", type: SubtleActivityComponent, selector: "cortex-subtle-activity", inputs: ["labels"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1032
1259
  }
1033
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ToolCallEndpointAnimatedComponent, decorators: [{
1260
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ToolCallEndpointAnimatedComponent, decorators: [{
1034
1261
  type: Component,
1035
1262
  args: [{
1036
1263
  selector: 'cortex-tool-call-endpoint-animated',
@@ -1055,10 +1282,10 @@ const LABELS$1 = [
1055
1282
  ];
1056
1283
  class ToolQueryGraphAnimatedComponent {
1057
1284
  labels = LABELS$1;
1058
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ToolQueryGraphAnimatedComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1059
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.4", type: ToolQueryGraphAnimatedComponent, isStandalone: true, selector: "cortex-tool-query-graph-animated", ngImport: i0, template: '<cortex-subtle-activity [labels]="labels" />', isInline: true, dependencies: [{ kind: "component", type: SubtleActivityComponent, selector: "cortex-subtle-activity", inputs: ["labels"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1285
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ToolQueryGraphAnimatedComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1286
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.5", type: ToolQueryGraphAnimatedComponent, isStandalone: true, selector: "cortex-tool-query-graph-animated", ngImport: i0, template: '<cortex-subtle-activity [labels]="labels" />', isInline: true, dependencies: [{ kind: "component", type: SubtleActivityComponent, selector: "cortex-subtle-activity", inputs: ["labels"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1060
1287
  }
1061
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ToolQueryGraphAnimatedComponent, decorators: [{
1288
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ToolQueryGraphAnimatedComponent, decorators: [{
1062
1289
  type: Component,
1063
1290
  args: [{
1064
1291
  selector: 'cortex-tool-query-graph-animated',
@@ -1083,10 +1310,10 @@ const LABELS = [
1083
1310
  ];
1084
1311
  class ToolExecuteCodeAnimatedComponent {
1085
1312
  labels = LABELS;
1086
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ToolExecuteCodeAnimatedComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1087
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.4", type: ToolExecuteCodeAnimatedComponent, isStandalone: true, selector: "cortex-tool-execute-code-animated", ngImport: i0, template: '<cortex-subtle-activity [labels]="labels" />', isInline: true, dependencies: [{ kind: "component", type: SubtleActivityComponent, selector: "cortex-subtle-activity", inputs: ["labels"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1313
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ToolExecuteCodeAnimatedComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1314
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.5", type: ToolExecuteCodeAnimatedComponent, isStandalone: true, selector: "cortex-tool-execute-code-animated", ngImport: i0, template: '<cortex-subtle-activity [labels]="labels" />', isInline: true, dependencies: [{ kind: "component", type: SubtleActivityComponent, selector: "cortex-subtle-activity", inputs: ["labels"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1088
1315
  }
1089
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ToolExecuteCodeAnimatedComponent, decorators: [{
1316
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ToolExecuteCodeAnimatedComponent, decorators: [{
1090
1317
  type: Component,
1091
1318
  args: [{
1092
1319
  selector: 'cortex-tool-execute-code-animated',
@@ -1103,10 +1330,10 @@ class MessagePartComponent {
1103
1330
  debugMode = input(false, ...(ngDevMode ? [{ debugName: "debugMode" }] : /* istanbul ignore next */ []));
1104
1331
  animate = input(false, ...(ngDevMode ? [{ debugName: "animate" }] : /* istanbul ignore next */ []));
1105
1332
  isStaticToolUIPart = isStaticToolUIPart;
1106
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MessagePartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1107
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: MessagePartComponent, isStandalone: true, selector: "cortex-message-part", inputs: { message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: true, transformFunction: null }, part: { classPropertyName: "part", publicName: "part", isSignal: true, isRequired: true, transformFunction: null }, debugMode: { classPropertyName: "debugMode", publicName: "debugMode", isSignal: true, isRequired: false, transformFunction: null }, animate: { classPropertyName: "animate", publicName: "animate", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.cortex-message-part--animated": "animate()" }, classAttribute: "cortex-message-part" }, ngImport: i0, template: "@let myPart = part();\n@switch (myPart.type) {\n @case ('text') {\n <cortex-message-text-part [textPart]=\"myPart\" [role]=\"message().role\" />\n }\n @case ('reasoning') {\n @if (debugMode()) {\n <cortex-message-reasoning-part [reasoningPart]=\"myPart\" />\n } @else {\n <cortex-message-reasoning-animated [reasoningPart]=\"myPart\" />\n }\n }\n @default {\n @if (isStaticToolUIPart(myPart)) {\n @if (debugMode()) {\n <cortex-message-tool-call-part [toolCallPart]=\"myPart\" />\n } @else {\n @switch (myPart.type) {\n @case ('tool-callEndpoint') {\n <cortex-tool-call-endpoint-animated />\n }\n @case ('tool-queryGraph') {\n <cortex-tool-query-graph-animated />\n }\n @case ('tool-executeCode') {\n <cortex-tool-execute-code-animated />\n }\n @default {\n <cortex-message-tool-call-animated [toolCallPart]=\"myPart\" [message]=\"message()\" />\n }\n }\n }\n } @else {\n <p class=\"cortex-unhandled-type\">Unhandled type: {{ part().type }}</p>\n }\n }\n}\n", styles: [".cortex-message-part{display:block}.cortex-message-part:empty{display:none}.cortex-message-part--animated{animation:cortex-part-fade-in-up .2s cubic-bezier(.34,1.56,.64,1) both}@keyframes cortex-part-fade-in-up{0%{opacity:0;transform:translateY(30px)}to{opacity:1;transform:translateY(0)}}.cortex-unhandled-type{text-align:center;font-size:.75rem;color:#94a3b8}\n"], dependencies: [{ kind: "component", type: MessageTextPartComponent, selector: "cortex-message-text-part", inputs: ["role", "textPart"] }, { kind: "component", type: MessageReasoningPartComponent, selector: "cortex-message-reasoning-part", inputs: ["reasoningPart"] }, { kind: "component", type: MessageToolCallPartComponent, selector: "cortex-message-tool-call-part", inputs: ["toolCallPart"] }, { kind: "component", type: MessageToolCallAnimatedComponent, selector: "cortex-message-tool-call-animated", inputs: ["message", "toolCallPart"] }, { kind: "component", type: MessageReasoningAnimatedComponent, selector: "cortex-message-reasoning-animated", inputs: ["reasoningPart"] }, { kind: "component", type: ToolCallEndpointAnimatedComponent, selector: "cortex-tool-call-endpoint-animated" }, { kind: "component", type: ToolQueryGraphAnimatedComponent, selector: "cortex-tool-query-graph-animated" }, { kind: "component", type: ToolExecuteCodeAnimatedComponent, selector: "cortex-tool-execute-code-animated" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1333
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MessagePartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1334
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: MessagePartComponent, isStandalone: true, selector: "cortex-message-part", inputs: { message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: true, transformFunction: null }, part: { classPropertyName: "part", publicName: "part", isSignal: true, isRequired: true, transformFunction: null }, debugMode: { classPropertyName: "debugMode", publicName: "debugMode", isSignal: true, isRequired: false, transformFunction: null }, animate: { classPropertyName: "animate", publicName: "animate", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.cortex-message-part--animated": "animate()" }, classAttribute: "cortex-message-part" }, ngImport: i0, template: "@let myPart = part();\n@switch (myPart.type) {\n @case ('text') {\n <cortex-message-text-part [textPart]=\"myPart\" [role]=\"message().role\" />\n }\n @case ('reasoning') {\n @if (debugMode()) {\n <cortex-message-reasoning-part [reasoningPart]=\"myPart\" />\n } @else {\n <cortex-message-reasoning-animated [reasoningPart]=\"myPart\" />\n }\n }\n @default {\n @if (isStaticToolUIPart(myPart)) {\n @if (debugMode()) {\n <cortex-message-tool-call-part [toolCallPart]=\"myPart\" />\n } @else {\n @switch (myPart.type) {\n @case ('tool-callEndpoint') {\n <cortex-tool-call-endpoint-animated />\n }\n @case ('tool-queryGraph') {\n <cortex-tool-query-graph-animated />\n }\n @case ('tool-executeCode') {\n <cortex-tool-execute-code-animated />\n }\n @default {\n <cortex-message-tool-call-animated [toolCallPart]=\"myPart\" [message]=\"message()\" />\n }\n }\n }\n } @else {\n <p class=\"cortex-unhandled-type\">Unhandled type: {{ part().type }}</p>\n }\n }\n}\n", styles: [".cortex-message-part{display:block}.cortex-message-part:empty{display:none}.cortex-message-part--animated{animation:cortex-part-fade-in-up .2s cubic-bezier(.34,1.56,.64,1) both}@keyframes cortex-part-fade-in-up{0%{opacity:0;transform:translateY(30px)}to{opacity:1;transform:translateY(0)}}.cortex-unhandled-type{text-align:center;font-size:.75rem;color:#94a3b8}\n"], dependencies: [{ kind: "component", type: MessageTextPartComponent, selector: "cortex-message-text-part", inputs: ["role", "textPart"] }, { kind: "component", type: MessageReasoningPartComponent, selector: "cortex-message-reasoning-part", inputs: ["reasoningPart"] }, { kind: "component", type: MessageToolCallPartComponent, selector: "cortex-message-tool-call-part", inputs: ["toolCallPart"] }, { kind: "component", type: MessageToolCallAnimatedComponent, selector: "cortex-message-tool-call-animated", inputs: ["message", "toolCallPart"] }, { kind: "component", type: MessageReasoningAnimatedComponent, selector: "cortex-message-reasoning-animated", inputs: ["reasoningPart"] }, { kind: "component", type: ToolCallEndpointAnimatedComponent, selector: "cortex-tool-call-endpoint-animated" }, { kind: "component", type: ToolQueryGraphAnimatedComponent, selector: "cortex-tool-query-graph-animated" }, { kind: "component", type: ToolExecuteCodeAnimatedComponent, selector: "cortex-tool-execute-code-animated" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1108
1335
  }
1109
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MessagePartComponent, decorators: [{
1336
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MessagePartComponent, decorators: [{
1110
1337
  type: Component,
1111
1338
  args: [{ selector: 'cortex-message-part', imports: [
1112
1339
  MessageTextPartComponent,
@@ -1123,6 +1350,27 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
1123
1350
  }, template: "@let myPart = part();\n@switch (myPart.type) {\n @case ('text') {\n <cortex-message-text-part [textPart]=\"myPart\" [role]=\"message().role\" />\n }\n @case ('reasoning') {\n @if (debugMode()) {\n <cortex-message-reasoning-part [reasoningPart]=\"myPart\" />\n } @else {\n <cortex-message-reasoning-animated [reasoningPart]=\"myPart\" />\n }\n }\n @default {\n @if (isStaticToolUIPart(myPart)) {\n @if (debugMode()) {\n <cortex-message-tool-call-part [toolCallPart]=\"myPart\" />\n } @else {\n @switch (myPart.type) {\n @case ('tool-callEndpoint') {\n <cortex-tool-call-endpoint-animated />\n }\n @case ('tool-queryGraph') {\n <cortex-tool-query-graph-animated />\n }\n @case ('tool-executeCode') {\n <cortex-tool-execute-code-animated />\n }\n @default {\n <cortex-message-tool-call-animated [toolCallPart]=\"myPart\" [message]=\"message()\" />\n }\n }\n }\n } @else {\n <p class=\"cortex-unhandled-type\">Unhandled type: {{ part().type }}</p>\n }\n }\n}\n", styles: [".cortex-message-part{display:block}.cortex-message-part:empty{display:none}.cortex-message-part--animated{animation:cortex-part-fade-in-up .2s cubic-bezier(.34,1.56,.64,1) both}@keyframes cortex-part-fade-in-up{0%{opacity:0;transform:translateY(30px)}to{opacity:1;transform:translateY(0)}}.cortex-unhandled-type{text-align:center;font-size:.75rem;color:#94a3b8}\n"] }]
1124
1351
  }], propDecorators: { message: [{ type: i0.Input, args: [{ isSignal: true, alias: "message", required: true }] }], part: [{ type: i0.Input, args: [{ isSignal: true, alias: "part", required: true }] }], debugMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "debugMode", required: false }] }], animate: [{ type: i0.Input, args: [{ isSignal: true, alias: "animate", required: false }] }] } });
1125
1352
 
1353
+ class MessageTokenUsageComponent {
1354
+ usage = input.required(...(ngDevMode ? [{ debugName: "usage" }] : /* istanbul ignore next */ []));
1355
+ modelId = input(...(ngDevMode ? [undefined, { debugName: "modelId" }] : /* istanbul ignore next */ []));
1356
+ expanded = signal(false, ...(ngDevMode ? [{ debugName: "expanded" }] : /* istanbul ignore next */ []));
1357
+ cacheRatio = computed(() => {
1358
+ const u = this.usage();
1359
+ if (u.input.total === 0)
1360
+ return 0;
1361
+ return Math.round((u.input.cacheRead / u.input.total) * 100);
1362
+ }, ...(ngDevMode ? [{ debugName: "cacheRatio" }] : /* istanbul ignore next */ []));
1363
+ toggle() {
1364
+ this.expanded.update((v) => !v);
1365
+ }
1366
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MessageTokenUsageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1367
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: MessageTokenUsageComponent, isStandalone: true, selector: "cortex-message-token-usage", inputs: { usage: { classPropertyName: "usage", publicName: "usage", isSignal: true, isRequired: true, transformFunction: null }, modelId: { classPropertyName: "modelId", publicName: "modelId", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.cortex-token-usage--expanded": "expanded()" }, classAttribute: "cortex-token-usage" }, ngImport: i0, template: "<button class=\"cortex-token-usage__summary\" (click)=\"toggle()\">\n <span class=\"cortex-token-usage__total\">\n <span class=\"cortex-token-usage__total-number\">{{ usage().total | number }}</span>\n <span class=\"cortex-token-usage__total-label\">tokens</span>\n </span>\n\n @if (modelId(); as id) {\n <span class=\"cortex-token-usage__model\">{{ id }}</span>\n }\n\n <span class=\"cortex-token-usage__pills\">\n <span class=\"cortex-token-usage__pill\">\n <span class=\"cortex-token-usage__dot cortex-token-usage__dot--input\"></span>\n {{ usage().input.total | number }}\n </span>\n <span class=\"cortex-token-usage__pill\">\n <span class=\"cortex-token-usage__dot cortex-token-usage__dot--output\"></span>\n {{ usage().output.total | number }}\n </span>\n </span>\n\n <svg class=\"cortex-token-usage__chevron\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\">\n <path\n d=\"M3 4.5L6 7.5L9 4.5\"\n stroke=\"currentColor\"\n stroke-width=\"1.25\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n</button>\n\n<div class=\"cortex-token-usage__details\">\n <div class=\"cortex-token-usage__details-inner\">\n <div class=\"cortex-token-usage__section\">\n <div class=\"cortex-token-usage__section-header\">\n <span class=\"cortex-token-usage__dot cortex-token-usage__dot--input\"></span>\n <span class=\"cortex-token-usage__section-label\">Input</span>\n <span class=\"cortex-token-usage__section-total\">{{ usage().input.total | number }}</span>\n </div>\n <div class=\"cortex-token-usage__rows\">\n @if (usage().input.noCache) {\n <div class=\"cortex-token-usage__row\">\n <span class=\"cortex-token-usage__row-label\">Fresh</span>\n <span class=\"cortex-token-usage__row-value\">{{ usage().input.noCache | number }}</span>\n </div>\n }\n @if (usage().input.cacheRead) {\n <div class=\"cortex-token-usage__row\">\n <span class=\"cortex-token-usage__row-label\">Cache read</span>\n <span class=\"cortex-token-usage__row-value\">{{\n usage().input.cacheRead | number\n }}</span>\n </div>\n }\n @if (usage().input.cacheWrite) {\n <div class=\"cortex-token-usage__row\">\n <span class=\"cortex-token-usage__row-label\">Cache write</span>\n <span class=\"cortex-token-usage__row-value\">{{\n usage().input.cacheWrite | number\n }}</span>\n </div>\n }\n @if (cacheRatio() > 0) {\n <div class=\"cortex-token-usage__row cortex-token-usage__row--highlight\">\n <span class=\"cortex-token-usage__row-label\">Cache hit</span>\n <span class=\"cortex-token-usage__row-value\">{{ cacheRatio() }}%</span>\n </div>\n }\n </div>\n </div>\n\n <div class=\"cortex-token-usage__divider\"></div>\n\n <div class=\"cortex-token-usage__section\">\n <div class=\"cortex-token-usage__section-header\">\n <span class=\"cortex-token-usage__dot cortex-token-usage__dot--output\"></span>\n <span class=\"cortex-token-usage__section-label\">Output</span>\n <span class=\"cortex-token-usage__section-total\">{{ usage().output.total | number }}</span>\n </div>\n <div class=\"cortex-token-usage__rows\">\n @if (usage().output.text) {\n <div class=\"cortex-token-usage__row\">\n <span class=\"cortex-token-usage__row-label\">Text</span>\n <span class=\"cortex-token-usage__row-value\">{{ usage().output.text | number }}</span>\n </div>\n }\n @if (usage().output.reasoning) {\n <div class=\"cortex-token-usage__row\">\n <span class=\"cortex-token-usage__row-label\">Reasoning</span>\n <span class=\"cortex-token-usage__row-value\">{{\n usage().output.reasoning | number\n }}</span>\n </div>\n }\n </div>\n </div>\n </div>\n</div>\n", styles: [".cortex-token-usage{direction:ltr;display:flex;flex-direction:column;margin-top:.25rem;font-family:SF Mono,Cascadia Code,Fira Code,JetBrains Mono,ui-monospace,monospace;font-size:.6875rem;line-height:1.4;color:#94a3b8;-webkit-user-select:none;user-select:none}html[dir=rtl] .cortex-token-usage__summary{align-self:end}html[dir=ltr] .cortex-token-usage__summary{align-self:start}.cortex-token-usage__summary{display:inline-flex;align-items:center;gap:.625rem;padding:.25rem .5rem;border:1px solid transparent;border-radius:6px;background:transparent;cursor:pointer;transition:background .2s ease,border-color .2s ease;font:inherit;color:inherit;letter-spacing:.01em}.cortex-token-usage__summary:hover{background:#f8fafc;border-color:#e2e8f0}.cortex-token-usage__total-number{font-weight:600;font-variant-numeric:tabular-nums;color:#64748b}.cortex-token-usage__total-label{margin-inline-start:.1875rem;color:#94a3b8;font-weight:400;letter-spacing:.04em;text-transform:lowercase}.cortex-token-usage__model{color:#94a3b8;font-weight:400;font-size:.625rem;letter-spacing:.02em}.cortex-token-usage__pills{display:inline-flex;align-items:center;gap:.375rem}.cortex-token-usage__pill{display:inline-flex;align-items:center;gap:.25rem;font-variant-numeric:tabular-nums;color:#94a3b8}.cortex-token-usage__dot{width:5px;height:5px;border-radius:50%;flex-shrink:0}.cortex-token-usage__dot--input{background:#f59e0b;box-shadow:0 0 0 1px #f59e0b33}.cortex-token-usage__dot--output{background:#6366f1;box-shadow:0 0 0 1px #6366f133}.cortex-token-usage__chevron{color:#cbd5e1;transition:transform .25s cubic-bezier(.4,0,.2,1);flex-shrink:0}.cortex-token-usage--expanded .cortex-token-usage__chevron{transform:rotate(180deg)}.cortex-token-usage__details{display:grid;grid-template-rows:0fr;transition:grid-template-rows .3s cubic-bezier(.4,0,.2,1),opacity .2s ease,margin .2s ease;opacity:0;margin-top:0;margin-inline-start:.5rem;padding-inline-start:.625rem;border-inline-start:1px solid transparent}.cortex-token-usage__details-inner{overflow:hidden}.cortex-token-usage--expanded .cortex-token-usage__details{grid-template-rows:1fr;opacity:1;margin-top:.25rem;border-inline-start-color:#e2e8f0}.cortex-token-usage__section{padding:.375rem 0}.cortex-token-usage__section-header{display:flex;align-items:center;gap:.375rem;margin-bottom:.25rem}.cortex-token-usage__section-label{font-weight:500;color:#64748b;letter-spacing:.03em;text-transform:uppercase;font-size:.625rem}.cortex-token-usage__section-total{margin-inline-start:auto;font-weight:600;font-variant-numeric:tabular-nums;color:#64748b}.cortex-token-usage__rows{display:flex;flex-direction:column;gap:.125rem}.cortex-token-usage__row{display:flex;align-items:baseline;justify-content:space-between;padding:.0625rem 0;padding-inline-start:calc(5px + .375rem)}.cortex-token-usage__row-label{color:#94a3b8}.cortex-token-usage__row-value{font-variant-numeric:tabular-nums;color:#64748b;font-weight:500}.cortex-token-usage__row--highlight .cortex-token-usage__row-value{color:#10b981;font-weight:600}.cortex-token-usage__divider{height:1px;background:#f1f5f9}\n"], dependencies: [{ kind: "pipe", type: DecimalPipe, name: "number" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1368
+ }
1369
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MessageTokenUsageComponent, decorators: [{
1370
+ type: Component,
1371
+ args: [{ selector: 'cortex-message-token-usage', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [DecimalPipe], host: { class: 'cortex-token-usage', '[class.cortex-token-usage--expanded]': 'expanded()' }, template: "<button class=\"cortex-token-usage__summary\" (click)=\"toggle()\">\n <span class=\"cortex-token-usage__total\">\n <span class=\"cortex-token-usage__total-number\">{{ usage().total | number }}</span>\n <span class=\"cortex-token-usage__total-label\">tokens</span>\n </span>\n\n @if (modelId(); as id) {\n <span class=\"cortex-token-usage__model\">{{ id }}</span>\n }\n\n <span class=\"cortex-token-usage__pills\">\n <span class=\"cortex-token-usage__pill\">\n <span class=\"cortex-token-usage__dot cortex-token-usage__dot--input\"></span>\n {{ usage().input.total | number }}\n </span>\n <span class=\"cortex-token-usage__pill\">\n <span class=\"cortex-token-usage__dot cortex-token-usage__dot--output\"></span>\n {{ usage().output.total | number }}\n </span>\n </span>\n\n <svg class=\"cortex-token-usage__chevron\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\">\n <path\n d=\"M3 4.5L6 7.5L9 4.5\"\n stroke=\"currentColor\"\n stroke-width=\"1.25\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n</button>\n\n<div class=\"cortex-token-usage__details\">\n <div class=\"cortex-token-usage__details-inner\">\n <div class=\"cortex-token-usage__section\">\n <div class=\"cortex-token-usage__section-header\">\n <span class=\"cortex-token-usage__dot cortex-token-usage__dot--input\"></span>\n <span class=\"cortex-token-usage__section-label\">Input</span>\n <span class=\"cortex-token-usage__section-total\">{{ usage().input.total | number }}</span>\n </div>\n <div class=\"cortex-token-usage__rows\">\n @if (usage().input.noCache) {\n <div class=\"cortex-token-usage__row\">\n <span class=\"cortex-token-usage__row-label\">Fresh</span>\n <span class=\"cortex-token-usage__row-value\">{{ usage().input.noCache | number }}</span>\n </div>\n }\n @if (usage().input.cacheRead) {\n <div class=\"cortex-token-usage__row\">\n <span class=\"cortex-token-usage__row-label\">Cache read</span>\n <span class=\"cortex-token-usage__row-value\">{{\n usage().input.cacheRead | number\n }}</span>\n </div>\n }\n @if (usage().input.cacheWrite) {\n <div class=\"cortex-token-usage__row\">\n <span class=\"cortex-token-usage__row-label\">Cache write</span>\n <span class=\"cortex-token-usage__row-value\">{{\n usage().input.cacheWrite | number\n }}</span>\n </div>\n }\n @if (cacheRatio() > 0) {\n <div class=\"cortex-token-usage__row cortex-token-usage__row--highlight\">\n <span class=\"cortex-token-usage__row-label\">Cache hit</span>\n <span class=\"cortex-token-usage__row-value\">{{ cacheRatio() }}%</span>\n </div>\n }\n </div>\n </div>\n\n <div class=\"cortex-token-usage__divider\"></div>\n\n <div class=\"cortex-token-usage__section\">\n <div class=\"cortex-token-usage__section-header\">\n <span class=\"cortex-token-usage__dot cortex-token-usage__dot--output\"></span>\n <span class=\"cortex-token-usage__section-label\">Output</span>\n <span class=\"cortex-token-usage__section-total\">{{ usage().output.total | number }}</span>\n </div>\n <div class=\"cortex-token-usage__rows\">\n @if (usage().output.text) {\n <div class=\"cortex-token-usage__row\">\n <span class=\"cortex-token-usage__row-label\">Text</span>\n <span class=\"cortex-token-usage__row-value\">{{ usage().output.text | number }}</span>\n </div>\n }\n @if (usage().output.reasoning) {\n <div class=\"cortex-token-usage__row\">\n <span class=\"cortex-token-usage__row-label\">Reasoning</span>\n <span class=\"cortex-token-usage__row-value\">{{\n usage().output.reasoning | number\n }}</span>\n </div>\n }\n </div>\n </div>\n </div>\n</div>\n", styles: [".cortex-token-usage{direction:ltr;display:flex;flex-direction:column;margin-top:.25rem;font-family:SF Mono,Cascadia Code,Fira Code,JetBrains Mono,ui-monospace,monospace;font-size:.6875rem;line-height:1.4;color:#94a3b8;-webkit-user-select:none;user-select:none}html[dir=rtl] .cortex-token-usage__summary{align-self:end}html[dir=ltr] .cortex-token-usage__summary{align-self:start}.cortex-token-usage__summary{display:inline-flex;align-items:center;gap:.625rem;padding:.25rem .5rem;border:1px solid transparent;border-radius:6px;background:transparent;cursor:pointer;transition:background .2s ease,border-color .2s ease;font:inherit;color:inherit;letter-spacing:.01em}.cortex-token-usage__summary:hover{background:#f8fafc;border-color:#e2e8f0}.cortex-token-usage__total-number{font-weight:600;font-variant-numeric:tabular-nums;color:#64748b}.cortex-token-usage__total-label{margin-inline-start:.1875rem;color:#94a3b8;font-weight:400;letter-spacing:.04em;text-transform:lowercase}.cortex-token-usage__model{color:#94a3b8;font-weight:400;font-size:.625rem;letter-spacing:.02em}.cortex-token-usage__pills{display:inline-flex;align-items:center;gap:.375rem}.cortex-token-usage__pill{display:inline-flex;align-items:center;gap:.25rem;font-variant-numeric:tabular-nums;color:#94a3b8}.cortex-token-usage__dot{width:5px;height:5px;border-radius:50%;flex-shrink:0}.cortex-token-usage__dot--input{background:#f59e0b;box-shadow:0 0 0 1px #f59e0b33}.cortex-token-usage__dot--output{background:#6366f1;box-shadow:0 0 0 1px #6366f133}.cortex-token-usage__chevron{color:#cbd5e1;transition:transform .25s cubic-bezier(.4,0,.2,1);flex-shrink:0}.cortex-token-usage--expanded .cortex-token-usage__chevron{transform:rotate(180deg)}.cortex-token-usage__details{display:grid;grid-template-rows:0fr;transition:grid-template-rows .3s cubic-bezier(.4,0,.2,1),opacity .2s ease,margin .2s ease;opacity:0;margin-top:0;margin-inline-start:.5rem;padding-inline-start:.625rem;border-inline-start:1px solid transparent}.cortex-token-usage__details-inner{overflow:hidden}.cortex-token-usage--expanded .cortex-token-usage__details{grid-template-rows:1fr;opacity:1;margin-top:.25rem;border-inline-start-color:#e2e8f0}.cortex-token-usage__section{padding:.375rem 0}.cortex-token-usage__section-header{display:flex;align-items:center;gap:.375rem;margin-bottom:.25rem}.cortex-token-usage__section-label{font-weight:500;color:#64748b;letter-spacing:.03em;text-transform:uppercase;font-size:.625rem}.cortex-token-usage__section-total{margin-inline-start:auto;font-weight:600;font-variant-numeric:tabular-nums;color:#64748b}.cortex-token-usage__rows{display:flex;flex-direction:column;gap:.125rem}.cortex-token-usage__row{display:flex;align-items:baseline;justify-content:space-between;padding:.0625rem 0;padding-inline-start:calc(5px + .375rem)}.cortex-token-usage__row-label{color:#94a3b8}.cortex-token-usage__row-value{font-variant-numeric:tabular-nums;color:#64748b;font-weight:500}.cortex-token-usage__row--highlight .cortex-token-usage__row-value{color:#10b981;font-weight:600}.cortex-token-usage__divider{height:1px;background:#f1f5f9}\n"] }]
1372
+ }], propDecorators: { usage: [{ type: i0.Input, args: [{ isSignal: true, alias: "usage", required: true }] }], modelId: [{ type: i0.Input, args: [{ isSignal: true, alias: "modelId", required: false }] }] } });
1373
+
1126
1374
  class MessageComponent {
1127
1375
  message = input.required(...(ngDevMode ? [{ debugName: "message" }] : /* istanbul ignore next */ []));
1128
1376
  debugMode = input(false, ...(ngDevMode ? [{ debugName: "debugMode" }] : /* istanbul ignore next */ []));
@@ -1138,31 +1386,59 @@ class MessageComponent {
1138
1386
  constructor() {
1139
1387
  effect(() => {
1140
1388
  const parts = this.message().parts;
1141
- this.parts.set(parts);
1142
- const originalPush = parts.push;
1143
- parts.push = (...items) => {
1144
- const newParts = items;
1145
- newParts.forEach((x) => (x.__id = generateId()));
1146
- this.parts.update((x) => [...x, ...newParts]);
1147
- newParts.forEach((part) => {
1148
- Object.keys(part).forEach((prop) => {
1149
- let value = part[prop];
1150
- Object.defineProperty(part, prop, {
1151
- get: () => value,
1152
- set: (newValue) => {
1153
- value = newValue;
1154
- this.parts.update((existingParts) => {
1155
- return existingParts.map((x) => {
1156
- return x.__id === part.__id ? { ...x, [prop]: newValue } : x;
1157
- });
1158
- });
1159
- },
1160
- configurable: true,
1389
+ this.parts.set(parts.map((part) => this.trackPart(part)));
1390
+ this.wrapPush(parts);
1391
+ });
1392
+ }
1393
+ trackPart(part) {
1394
+ const trackedPart = part;
1395
+ if (trackedPart.__cortexTracked) {
1396
+ return trackedPart;
1397
+ }
1398
+ trackedPart.__id = trackedPart.__id ?? generateId();
1399
+ Object.defineProperty(trackedPart, '__cortexTracked', {
1400
+ value: true,
1401
+ configurable: true,
1402
+ });
1403
+ Object.keys(trackedPart).forEach((prop) => {
1404
+ if (prop === '__id') {
1405
+ return;
1406
+ }
1407
+ const descriptor = Object.getOwnPropertyDescriptor(trackedPart, prop);
1408
+ if (!descriptor?.configurable || descriptor.get || descriptor.set) {
1409
+ return;
1410
+ }
1411
+ let value = trackedPart[prop];
1412
+ Object.defineProperty(trackedPart, prop, {
1413
+ get: () => value,
1414
+ set: (newValue) => {
1415
+ value = newValue;
1416
+ this.parts.update((existingParts) => {
1417
+ return existingParts.map((existingPart) => {
1418
+ return existingPart.__id === trackedPart.__id
1419
+ ? { ...existingPart, [prop]: newValue }
1420
+ : existingPart;
1161
1421
  });
1162
1422
  });
1163
- });
1164
- return originalPush.apply(parts, newParts);
1165
- };
1423
+ },
1424
+ configurable: true,
1425
+ });
1426
+ });
1427
+ return trackedPart;
1428
+ }
1429
+ wrapPush(parts) {
1430
+ if (parts.__cortexPushWrapped) {
1431
+ return;
1432
+ }
1433
+ const originalPush = parts.push;
1434
+ parts.push = (...items) => {
1435
+ const newParts = items.map((part) => this.trackPart(part));
1436
+ this.parts.update((existingParts) => [...existingParts, ...newParts]);
1437
+ return originalPush.apply(parts, newParts);
1438
+ };
1439
+ Object.defineProperty(parts, '__cortexPushWrapped', {
1440
+ value: true,
1441
+ configurable: true,
1166
1442
  });
1167
1443
  }
1168
1444
  isHiddenInAnimatedMode(part) {
@@ -1176,12 +1452,17 @@ class MessageComponent {
1176
1452
  }
1177
1453
  return false;
1178
1454
  }
1179
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MessageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1180
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: MessageComponent, isStandalone: true, selector: "cortex-message", inputs: { message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: true, transformFunction: null }, debugMode: { classPropertyName: "debugMode", publicName: "debugMode", isSignal: true, isRequired: false, transformFunction: null }, animate: { classPropertyName: "animate", publicName: "animate", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "cortex-message" }, ngImport: i0, template: "@if (visibleParts().length) {\n <div class=\"cortex-message-parts\">\n @for (part of visibleParts(); track $index) {\n <cortex-message-part\n [part]=\"part\"\n [message]=\"message()\"\n [debugMode]=\"debugMode()\"\n [animate]=\"animate()\"\n />\n }\n </div>\n}\n", styles: [".cortex-message:empty{display:none}.cortex-message-parts{width:100%;display:flex;flex-direction:column;gap:.5rem}\n"], dependencies: [{ kind: "component", type: MessagePartComponent, selector: "cortex-message-part", inputs: ["message", "part", "debugMode", "animate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1455
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MessageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1456
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: MessageComponent, isStandalone: true, selector: "cortex-message", inputs: { message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: true, transformFunction: null }, debugMode: { classPropertyName: "debugMode", publicName: "debugMode", isSignal: true, isRequired: false, transformFunction: null }, animate: { classPropertyName: "animate", publicName: "animate", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "cortex-message" }, ngImport: i0, template: "@if (visibleParts().length) {\n <div class=\"cortex-message-parts\">\n @for (part of visibleParts(); track $index) {\n <cortex-message-part\n [part]=\"part\"\n [message]=\"message()\"\n [debugMode]=\"debugMode()\"\n [animate]=\"animate()\"\n />\n }\n\n @if (message().metadata?.isAborted) {\n <cortex-message-aborted-flag />\n }\n\n @if (debugMode() && message().metadata?.tokenUsage; as usage) {\n <cortex-message-token-usage [usage]=\"usage\" [modelId]=\"message().metadata?.modelId\" />\n }\n </div>\n}\n", styles: [".cortex-message:empty{display:none}.cortex-message-parts{width:100%;display:flex;flex-direction:column;gap:.5rem}\n"], dependencies: [{ kind: "component", type: MessageAbortedFlagComponent, selector: "cortex-message-aborted-flag" }, { kind: "component", type: MessagePartComponent, selector: "cortex-message-part", inputs: ["message", "part", "debugMode", "animate"] }, { kind: "component", type: MessageTokenUsageComponent, selector: "cortex-message-token-usage", inputs: ["usage", "modelId"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1181
1457
  }
1182
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MessageComponent, decorators: [{
1458
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MessageComponent, decorators: [{
1183
1459
  type: Component,
1184
- args: [{ selector: 'cortex-message', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [MessagePartComponent], host: { class: 'cortex-message' }, template: "@if (visibleParts().length) {\n <div class=\"cortex-message-parts\">\n @for (part of visibleParts(); track $index) {\n <cortex-message-part\n [part]=\"part\"\n [message]=\"message()\"\n [debugMode]=\"debugMode()\"\n [animate]=\"animate()\"\n />\n }\n </div>\n}\n", styles: [".cortex-message:empty{display:none}.cortex-message-parts{width:100%;display:flex;flex-direction:column;gap:.5rem}\n"] }]
1460
+ args: [{ selector: 'cortex-message', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [
1461
+ MessageAbortedFlagComponent,
1462
+ MessagePartComponent,
1463
+ MessageTokenUsageComponent,
1464
+ JsonPipe,
1465
+ ], host: { class: 'cortex-message' }, template: "@if (visibleParts().length) {\n <div class=\"cortex-message-parts\">\n @for (part of visibleParts(); track $index) {\n <cortex-message-part\n [part]=\"part\"\n [message]=\"message()\"\n [debugMode]=\"debugMode()\"\n [animate]=\"animate()\"\n />\n }\n\n @if (message().metadata?.isAborted) {\n <cortex-message-aborted-flag />\n }\n\n @if (debugMode() && message().metadata?.tokenUsage; as usage) {\n <cortex-message-token-usage [usage]=\"usage\" [modelId]=\"message().metadata?.modelId\" />\n }\n </div>\n}\n", styles: [".cortex-message:empty{display:none}.cortex-message-parts{width:100%;display:flex;flex-direction:column;gap:.5rem}\n"] }]
1185
1466
  }], ctorParameters: () => [], propDecorators: { message: [{ type: i0.Input, args: [{ isSignal: true, alias: "message", required: true }] }], debugMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "debugMode", required: false }] }], animate: [{ type: i0.Input, args: [{ isSignal: true, alias: "animate", required: false }] }] } });
1186
1467
 
1187
1468
  class MessageListComponent {
@@ -1190,6 +1471,8 @@ class MessageListComponent {
1190
1471
  messagesContainer = viewChild('messagesContainer', ...(ngDevMode ? [{ debugName: "messagesContainer" }] : /* istanbul ignore next */ []));
1191
1472
  shouldScrollToBottom = true;
1192
1473
  isNearBottom = true;
1474
+ mutationObserver = undefined;
1475
+ scrollToBottomQueued = false;
1193
1476
  animateNewParts = signal(false, ...(ngDevMode ? [{ debugName: "animateNewParts" }] : /* istanbul ignore next */ []));
1194
1477
  constructor(chatService, destroyRef) {
1195
1478
  this.chatService = chatService;
@@ -1199,10 +1482,7 @@ class MessageListComponent {
1199
1482
  if (!this.shouldScrollToBottom && !this.isNearBottom) {
1200
1483
  return;
1201
1484
  }
1202
- queueMicrotask(() => {
1203
- this.scrollToBottom();
1204
- this.shouldScrollToBottom = false;
1205
- });
1485
+ this.scheduleScrollToBottom();
1206
1486
  });
1207
1487
  chatService.events$.pipe(takeUntilDestroyed(destroyRef)).subscribe((event) => {
1208
1488
  if (event === 'onThreadSelected') {
@@ -1213,13 +1493,14 @@ class MessageListComponent {
1213
1493
  if (event === 'onSend')
1214
1494
  this.shouldScrollToBottom = true;
1215
1495
  });
1496
+ destroyRef.onDestroy(() => {
1497
+ this.mutationObserver?.disconnect();
1498
+ });
1216
1499
  }
1217
1500
  ngAfterViewInit() {
1218
- queueMicrotask(() => {
1219
- this.scrollToBottom();
1220
- this.shouldScrollToBottom = false;
1221
- this.animateNewParts.set(true);
1222
- });
1501
+ this.observeMessageMutations();
1502
+ this.scheduleScrollToBottom();
1503
+ queueMicrotask(() => this.animateNewParts.set(true));
1223
1504
  }
1224
1505
  onScroll() {
1225
1506
  const el = this.messagesContainer()?.nativeElement;
@@ -1233,10 +1514,38 @@ class MessageListComponent {
1233
1514
  el.scrollTop = el.scrollHeight;
1234
1515
  }
1235
1516
  }
1236
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MessageListComponent, deps: [{ token: CortexChatService }, { token: i0.DestroyRef }], target: i0.ɵɵFactoryTarget.Component });
1237
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: MessageListComponent, isStandalone: true, selector: "cortex-message-list", inputs: { debugMode: { classPropertyName: "debugMode", publicName: "debugMode", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "messagesContainer", first: true, predicate: ["messagesContainer"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"cortex-message-list\" #messagesContainer (scroll)=\"onScroll()\">\n @for (message of chatService.chat()?.messages; track message.id) {\n <cortex-message [message]=\"message\" [debugMode]=\"debugMode()\" [animate]=\"animateNewParts()\" />\n }\n</div>\n", styles: [".cortex-message-list{height:100%;overflow-y:auto;width:100%;display:flex;flex-direction:column;gap:.5rem;padding:1rem}\n"], dependencies: [{ kind: "component", type: MessageComponent, selector: "cortex-message", inputs: ["message", "debugMode", "animate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1517
+ scheduleScrollToBottom() {
1518
+ if (this.scrollToBottomQueued) {
1519
+ return;
1520
+ }
1521
+ this.scrollToBottomQueued = true;
1522
+ queueMicrotask(() => {
1523
+ this.scrollToBottomQueued = false;
1524
+ this.scrollToBottom();
1525
+ this.shouldScrollToBottom = false;
1526
+ });
1527
+ }
1528
+ observeMessageMutations() {
1529
+ const el = this.messagesContainer()?.nativeElement;
1530
+ if (!el || typeof MutationObserver === 'undefined') {
1531
+ return;
1532
+ }
1533
+ this.mutationObserver = new MutationObserver(() => {
1534
+ if (!this.shouldScrollToBottom && !this.isNearBottom) {
1535
+ return;
1536
+ }
1537
+ this.scheduleScrollToBottom();
1538
+ });
1539
+ this.mutationObserver.observe(el, {
1540
+ childList: true,
1541
+ subtree: true,
1542
+ characterData: true,
1543
+ });
1544
+ }
1545
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MessageListComponent, deps: [{ token: CortexChatService }, { token: i0.DestroyRef }], target: i0.ɵɵFactoryTarget.Component });
1546
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: MessageListComponent, isStandalone: true, selector: "cortex-message-list", inputs: { debugMode: { classPropertyName: "debugMode", publicName: "debugMode", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "messagesContainer", first: true, predicate: ["messagesContainer"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"cortex-message-list\" #messagesContainer (scroll)=\"onScroll()\">\n @for (message of chatService.chat()?.messages; track message.id) {\n <cortex-message [message]=\"message\" [debugMode]=\"debugMode()\" [animate]=\"animateNewParts()\" />\n }\n</div>\n", styles: [".cortex-message-list{height:100%;overflow-y:auto;width:100%;display:flex;flex-direction:column;gap:.5rem;padding:1rem}\n"], dependencies: [{ kind: "component", type: MessageComponent, selector: "cortex-message", inputs: ["message", "debugMode", "animate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1238
1547
  }
1239
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MessageListComponent, decorators: [{
1548
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MessageListComponent, decorators: [{
1240
1549
  type: Component,
1241
1550
  args: [{ selector: 'cortex-message-list', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [MessageComponent], template: "<div class=\"cortex-message-list\" #messagesContainer (scroll)=\"onScroll()\">\n @for (message of chatService.chat()?.messages; track message.id) {\n <cortex-message [message]=\"message\" [debugMode]=\"debugMode()\" [animate]=\"animateNewParts()\" />\n }\n</div>\n", styles: [".cortex-message-list{height:100%;overflow-y:auto;width:100%;display:flex;flex-direction:column;gap:.5rem;padding:1rem}\n"] }]
1242
1551
  }], ctorParameters: () => [{ type: CortexChatService }, { type: i0.DestroyRef }], propDecorators: { debugMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "debugMode", required: false }] }], messagesContainer: [{ type: i0.ViewChild, args: ['messagesContainer', { isSignal: true }] }] } });
@@ -1244,6 +1553,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
1244
1553
  var translate_new$1 = "New";
1245
1554
  var translate_threads$1 = "Threads";
1246
1555
  var translate_n_conversations$1 = "{{count}} conversations";
1556
+ var translate_no_threads_yet$1 = "No threads yet";
1557
+ var translate_start_a_new_conversation$1 = "Start a new conversation";
1247
1558
  var translate_untitled$1 = "Untitled";
1248
1559
  var translate_new_chat$1 = "New Chat";
1249
1560
  var translate_normal$1 = "Normal";
@@ -1327,10 +1638,14 @@ var translate_reasoning_6$1 = "Mulling it over...";
1327
1638
  var translate_reasoning_7$1 = "Finding the best approach...";
1328
1639
  var translate_reasoning_8$1 = "Organizing my thoughts...";
1329
1640
  var translate_reasoning_9$1 = "Almost there...";
1641
+ var translate_running$1 = "Running";
1642
+ var translate_aborted$1 = "Aborted";
1330
1643
  var en = {
1331
1644
  translate_new: translate_new$1,
1332
1645
  translate_threads: translate_threads$1,
1333
1646
  translate_n_conversations: translate_n_conversations$1,
1647
+ translate_no_threads_yet: translate_no_threads_yet$1,
1648
+ translate_start_a_new_conversation: translate_start_a_new_conversation$1,
1334
1649
  translate_untitled: translate_untitled$1,
1335
1650
  translate_new_chat: translate_new_chat$1,
1336
1651
  translate_normal: translate_normal$1,
@@ -1413,12 +1728,16 @@ var en = {
1413
1728
  translate_reasoning_6: translate_reasoning_6$1,
1414
1729
  translate_reasoning_7: translate_reasoning_7$1,
1415
1730
  translate_reasoning_8: translate_reasoning_8$1,
1416
- translate_reasoning_9: translate_reasoning_9$1
1731
+ translate_reasoning_9: translate_reasoning_9$1,
1732
+ translate_running: translate_running$1,
1733
+ translate_aborted: translate_aborted$1
1417
1734
  };
1418
1735
 
1419
1736
  var translate_new = "جديد";
1420
1737
  var translate_threads = "المحادثات";
1421
1738
  var translate_n_conversations = "{{count}} محادثات";
1739
+ var translate_no_threads_yet = "لا توجد محادثات بعد";
1740
+ var translate_start_a_new_conversation = "ابدأ محادثة جديدة";
1422
1741
  var translate_untitled = "بدون عنوان";
1423
1742
  var translate_new_chat = "محادثة جديدة";
1424
1743
  var translate_normal = "عادي";
@@ -1502,10 +1821,14 @@ var translate_reasoning_6 = "جارٍ التمعن في الأمر...";
1502
1821
  var translate_reasoning_7 = "جارٍ إيجاد أفضل طريقة...";
1503
1822
  var translate_reasoning_8 = "جارٍ تنظيم أفكاري...";
1504
1823
  var translate_reasoning_9 = "أوشك على الانتهاء...";
1824
+ var translate_running = "قيد التنفيذ";
1825
+ var translate_aborted = "تم الإلغاء";
1505
1826
  var ar = {
1506
1827
  translate_new: translate_new,
1507
1828
  translate_threads: translate_threads,
1508
1829
  translate_n_conversations: translate_n_conversations,
1830
+ translate_no_threads_yet: translate_no_threads_yet,
1831
+ translate_start_a_new_conversation: translate_start_a_new_conversation,
1509
1832
  translate_untitled: translate_untitled,
1510
1833
  translate_new_chat: translate_new_chat,
1511
1834
  translate_normal: translate_normal,
@@ -1588,7 +1911,9 @@ var ar = {
1588
1911
  translate_reasoning_6: translate_reasoning_6,
1589
1912
  translate_reasoning_7: translate_reasoning_7,
1590
1913
  translate_reasoning_8: translate_reasoning_8,
1591
- translate_reasoning_9: translate_reasoning_9
1914
+ translate_reasoning_9: translate_reasoning_9,
1915
+ translate_running: translate_running,
1916
+ translate_aborted: translate_aborted
1592
1917
  };
1593
1918
 
1594
1919
  const translations = { en, ar };
@@ -1600,10 +1925,10 @@ class CortexClientTranslateLoader {
1600
1925
 
1601
1926
  class CortexClientConfigRef {
1602
1927
  config;
1603
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: CortexClientConfigRef, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1604
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: CortexClientConfigRef });
1928
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CortexClientConfigRef, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1929
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CortexClientConfigRef });
1605
1930
  }
1606
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: CortexClientConfigRef, decorators: [{
1931
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CortexClientConfigRef, decorators: [{
1607
1932
  type: Injectable
1608
1933
  }] });
1609
1934
  class CortexChatWidgetComponent {
@@ -1650,8 +1975,8 @@ class CortexChatWidgetComponent {
1650
1975
  this.chatService.deselectThread();
1651
1976
  this.screen.set('chat');
1652
1977
  }
1653
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: CortexChatWidgetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1654
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: CortexChatWidgetComponent, isStandalone: true, selector: "cortex-chat-widget", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null }, text: { classPropertyName: "text", publicName: "text", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { text: "textChange" }, host: { classAttribute: "cortex-widget" }, providers: [
1978
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CortexChatWidgetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1979
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: CortexChatWidgetComponent, isStandalone: true, selector: "cortex-chat-widget", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null }, text: { classPropertyName: "text", publicName: "text", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { text: "textChange" }, host: { classAttribute: "cortex-widget" }, providers: [
1655
1980
  CortexClientConfigRef,
1656
1981
  {
1657
1982
  provide: CORTEX_CLIENT_CONFIG,
@@ -1663,9 +1988,9 @@ class CortexChatWidgetComponent {
1663
1988
  fallbackLang: 'en',
1664
1989
  loader: provideTranslateLoader(CortexClientTranslateLoader),
1665
1990
  }),
1666
- ], ngImport: i0, template: "<div class=\"cortex-widget__container\">\n <!-- SCREEN 1: THREADS -->\n <div\n class=\"cortex-widget__screen\"\n [class.cortex-widget__screen--active]=\"screen() === 'threads'\"\n [class.cortex-widget__screen--left]=\"screen() !== 'threads'\"\n >\n <!-- Threads header -->\n <div class=\"cortex-widget__threads-header\">\n <div>\n <h2 class=\"cortex-widget__threads-title\">\n {{ 'translate_threads' | translate }}\n </h2>\n <p class=\"cortex-widget__threads-count\">\n {{\n 'translate_n_conversations' | translate: { count: chatService.threads()?.length ?? 0 }\n }}\n </p>\n </div>\n <button (click)=\"newChat()\" class=\"cortex-widget__new-chat-btn\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path\n d=\"M8 3v10M3 8h10\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n />\n </svg>\n {{ 'translate_new' | translate }}\n </button>\n </div>\n\n <!-- Threads list -->\n <div class=\"cortex-widget__threads-list\">\n <!-- Threads loading skeleton -->\n @if (chatService.threads() === undefined) {\n @for (i of [1, 2, 3, 4]; track i) {\n <div class=\"cortex-widget__thread-skeleton\">\n <div class=\"cortex-skeleton cortex-widget__thread-skeleton-icon\"></div>\n <div class=\"cortex-widget__thread-skeleton-lines\">\n <div\n class=\"cortex-skeleton cortex-widget__thread-skeleton-line\"\n [style.width]=\"40 + i * 12 + '%'\"\n ></div>\n </div>\n </div>\n }\n } @else {\n @for (thread of chatService.threads(); track thread.id) {\n <button\n (click)=\"selectThread(thread)\"\n class=\"cortex-widget__thread-item\"\n [class.cortex-widget__thread-item--active]=\"\n thread.id === chatService.selectedThread()?.id\n \"\n >\n <!-- Thread icon -->\n <div\n class=\"cortex-widget__thread-icon\"\n [class.cortex-widget__thread-icon--active]=\"\n thread.id === chatService.selectedThread()?.id\n \"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path\n d=\"M2.5 4.5h11M2.5 8h7M2.5 11.5h9\"\n stroke=\"currentColor\"\n stroke-width=\"1.3\"\n stroke-linecap=\"round\"\n />\n </svg>\n </div>\n\n <!-- Thread info -->\n <div class=\"cortex-widget__thread-info\">\n <p\n class=\"cortex-widget__thread-title\"\n [class.cortex-widget__thread-title--active]=\"\n thread.id === chatService.selectedThread()?.id\n \"\n >\n {{ thread.title ?? ('translate_untitled' | translate) }}\n </p>\n </div>\n\n <!-- Delete button -->\n <button\n (click)=\"$event.stopPropagation(); chatService.deleteThread(thread.id).subscribe()\"\n class=\"cortex-widget__thread-delete\"\n [class.cortex-widget__thread-delete--active]=\"\n thread.id === chatService.selectedThread()?.id\n \"\n >\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path\n d=\"M4 4l8 8M12 4l-8 8\"\n stroke=\"currentColor\"\n stroke-width=\"1.3\"\n stroke-linecap=\"round\"\n />\n </svg>\n </button>\n\n <!-- Arrow -->\n <svg\n class=\"cortex-widget__thread-arrow\"\n [class.cortex-widget__thread-arrow--active]=\"\n thread.id === chatService.selectedThread()?.id\n \"\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n >\n <path\n d=\"M6 4l4 4-4 4\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </button>\n }\n\n @if (!chatService.threads()?.length) {\n <div class=\"cortex-widget__threads-empty\">\n <div class=\"cortex-widget__threads-empty-icon\">\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n class=\"cortex-widget__threads-empty-svg\"\n >\n <path\n d=\"M2.5 4.5h11M2.5 8h7M2.5 11.5h9\"\n stroke=\"currentColor\"\n stroke-width=\"1.3\"\n stroke-linecap=\"round\"\n />\n </svg>\n </div>\n <p class=\"cortex-widget__threads-empty-title\">No threads yet</p>\n <p class=\"cortex-widget__threads-empty-subtitle\">Start a new conversation</p>\n </div>\n }\n }\n </div>\n </div>\n\n <!-- SCREEN 2: CHAT -->\n <div\n class=\"cortex-widget__screen\"\n [class.cortex-widget__screen--active]=\"screen() === 'chat'\"\n [class.cortex-widget__screen--right]=\"screen() !== 'chat'\"\n >\n <!-- Chat header -->\n <div class=\"cortex-widget__chat-header\">\n <!-- Back button -->\n <button (click)=\"goBack()\" class=\"cortex-widget__back-btn\">\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n class=\"cortex-widget__back-icon\"\n >\n <path\n d=\"M10 3L5 8l5 5\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </button>\n\n <!-- Title -->\n <div class=\"cortex-widget__chat-title-wrap\">\n <p class=\"cortex-widget__chat-title\">\n {{ chatService.selectedThread()?.title ?? ('translate_new_chat' | translate) }}\n </p>\n </div>\n\n <!-- Debug toggle -->\n <button\n (click)=\"toggleDebugMode()\"\n class=\"cortex-widget__debug-btn\"\n [class.cortex-widget__debug-btn--on]=\"debugMode()\"\n [class.cortex-widget__debug-btn--off]=\"!debugMode()\"\n >\n {{ debugMode() ? ('translate_debug' | translate) : ('translate_normal' | translate) }}\n </button>\n </div>\n\n <!-- Messages loading skeleton -->\n @if (chatService.isLoadingMessages() && !chatService.isAgentWorking()) {\n <div class=\"cortex-widget__messages-skeleton\">\n <!-- User message skeleton -->\n <div class=\"cortex-widget__msg-skel cortex-widget__msg-skel--user\">\n <div class=\"cortex-widget__msg-skel-bubble cortex-widget__msg-skel-bubble--user\">\n <div class=\"cortex-skeleton cortex-widget__msg-skel-line\" style=\"width: 13rem\"></div>\n <div class=\"cortex-skeleton cortex-widget__msg-skel-line\" style=\"width: 9rem\"></div>\n </div>\n </div>\n <!-- Assistant message skeleton -->\n <div class=\"cortex-widget__msg-skel cortex-widget__msg-skel--assistant\">\n <div class=\"cortex-widget__msg-skel-bubble cortex-widget__msg-skel-bubble--assistant\">\n <div class=\"cortex-skeleton cortex-widget__msg-skel-line\" style=\"width: 16rem\"></div>\n <div class=\"cortex-skeleton cortex-widget__msg-skel-line\" style=\"width: 18rem\"></div>\n <div class=\"cortex-skeleton cortex-widget__msg-skel-line\" style=\"width: 12rem\"></div>\n </div>\n </div>\n <!-- User message skeleton -->\n <div class=\"cortex-widget__msg-skel cortex-widget__msg-skel--user\">\n <div class=\"cortex-widget__msg-skel-bubble cortex-widget__msg-skel-bubble--user\">\n <div class=\"cortex-skeleton cortex-widget__msg-skel-line\" style=\"width: 11rem\"></div>\n </div>\n </div>\n <!-- Assistant message skeleton -->\n <div class=\"cortex-widget__msg-skel cortex-widget__msg-skel--assistant\">\n <div class=\"cortex-widget__msg-skel-bubble cortex-widget__msg-skel-bubble--assistant\">\n <div class=\"cortex-skeleton cortex-widget__msg-skel-line\" style=\"width: 14rem\"></div>\n <div class=\"cortex-skeleton cortex-widget__msg-skel-line\" style=\"width: 15rem\"></div>\n </div>\n </div>\n </div>\n } @else {\n <!-- Messages area -->\n <cortex-message-list class=\"cortex-widget__messages\" [debugMode]=\"debugMode()\" />\n }\n\n <!-- Agent working indicator -->\n @if (chatService.isAgentWorking() && !chatService.hasPendingToolCalls()) {\n <div class=\"cortex-widget__working\">\n <div class=\"cortex-widget__working-dots\">\n <span class=\"cortex-working-dot\"></span>\n <span class=\"cortex-working-dot\"></span>\n <span class=\"cortex-working-dot\"></span>\n </div>\n <span class=\"cortex-widget__working-text\">{{ 'translate_thinking' | translate }}</span>\n </div>\n }\n\n <!-- Chat input (hidden during pending tool calls) -->\n @if (!chatService.hasPendingToolCalls()) {\n <div class=\"cortex-widget__input-area\">\n <div\n class=\"cortex-widget__input-box\"\n [class.cortex-widget__input-box--disabled]=\"chatService.isAgentWorking()\"\n [class.cortex-widget__input-box--enabled]=\"!chatService.isAgentWorking()\"\n >\n <textarea\n (keydown)=\"onKeydown($event)\"\n [(ngModel)]=\"text\"\n [placeholder]=\"\n chatService.isAgentWorking() ? '' : ('translate_type_a_message' | translate)\n \"\n [disabled]=\"chatService.isAgentWorking()\"\n rows=\"1\"\n class=\"cortex-widget__textarea\"\n [class.cortex-widget__textarea--disabled]=\"chatService.isAgentWorking()\"\n ></textarea>\n @if (chatService.isAgentWorking()) {\n <!-- Stop button -->\n <button (click)=\"chatService.abort()\" class=\"cortex-stop-btn\">\n <!-- Pulsing ring -->\n <span class=\"cortex-stop-btn__ring\"></span>\n <!-- Stop icon (rounded square) -->\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n class=\"cortex-stop-btn__icon\"\n >\n <rect x=\"1\" y=\"1\" width=\"10\" height=\"10\" rx=\"2.5\" fill=\"currentColor\" />\n </svg>\n </button>\n } @else {\n <!-- Send button -->\n <button\n (click)=\"send()\"\n class=\"cortex-widget__send-btn\"\n [class.cortex-widget__send-btn--empty]=\"!text().trim()\"\n [class.cortex-widget__send-btn--ready]=\"!!text().trim()\"\n >\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n class=\"cortex-widget__send-icon\"\n >\n <path\n d=\"M3 8h10M9 4l4 4-4 4\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </button>\n }\n </div>\n </div>\n }\n </div>\n</div>\n", styles: [".cortex-widget{display:block}.cortex-widget__container{width:100%;height:100%;position:relative;overflow:hidden}.cortex-widget__screen{position:absolute;inset:0;display:flex;flex-direction:column;transition:transform .3s ease-out}.cortex-widget__screen--active{transform:translate(0)}.cortex-widget__screen--left{transform:translate(-100%)}[dir=rtl] .cortex-widget__screen--left,.cortex-widget__screen--right{transform:translate(100%)}[dir=rtl] .cortex-widget__screen--right{transform:translate(-100%)}.cortex-widget__threads-header{flex-shrink:0;padding:1.25rem 1.25rem 1rem;display:flex;align-items:center;justify-content:space-between}.cortex-widget__threads-title{font-size:.9375rem;font-weight:600;color:#1e293b;letter-spacing:-.01em;margin:0}.cortex-widget__threads-count{font-size:.6875rem;color:#94a3b8;margin-top:.125rem;margin-bottom:0}.cortex-widget__new-chat-btn{display:inline-flex;align-items:center;gap:.375rem;font-size:.75rem;font-weight:500;color:#f1f5f9;background:#1e293b;padding:.375rem .75rem;border-radius:.375rem;border:0;cursor:pointer;transition:background-color .15s}.cortex-widget__new-chat-btn:hover{background:#334155}.cortex-widget__new-chat-btn:active{background:#0f172a}.cortex-widget__threads-list{flex:1;overflow-y:auto;padding:0 .75rem .75rem}.cortex-widget__thread-skeleton{display:flex;align-items:center;gap:.75rem;padding:.75rem;margin-bottom:.125rem}.cortex-widget__thread-skeleton-icon{flex-shrink:0;width:2rem;height:2rem}.cortex-widget__thread-skeleton-lines{flex:1;display:flex;flex-direction:column;gap:.375rem}.cortex-widget__thread-skeleton-line{height:.875rem}@keyframes cortex-skeleton-shimmer{0%{background-position:-200% 0}to{background-position:200% 0}}.cortex-skeleton{background:linear-gradient(90deg,#e2e8f0,#f1f5f9,#e2e8f0 80%);background-size:200% 100%;animation:cortex-skeleton-shimmer 1.8s ease-in-out infinite;border-radius:6px}.cortex-widget__thread-item{width:100%;text-align:start;padding:.75rem;border-radius:.5rem;display:flex;align-items:center;gap:.75rem;transition:background-color .15s;cursor:pointer;margin-bottom:.125rem;border:0;background:transparent;color:#475569}.cortex-widget__thread-item:hover{background:#f1f5f9}.cortex-widget__thread-item:active{background:#e8ecf1}.cortex-widget__thread-item--active{background:#e2e8f0;color:#f1f5f9}.cortex-widget__thread-icon{flex-shrink:0;width:2rem;height:2rem;border-radius:.375rem;display:flex;align-items:center;justify-content:center;font-size:.6875rem;font-weight:600;background:#e2e8f0;color:#64748b}[dir=rtl] .cortex-widget__thread-icon{transform:rotate(180deg)}.cortex-widget__thread-icon--active{background:#334155;color:#cbd5e1}.cortex-widget__thread-info{min-width:0;flex:1}.cortex-widget__thread-title{font-size:.8125rem;font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:1.25;margin:0;color:#334155}.cortex-widget__thread-title--active{color:#f1f5f9}.cortex-widget__thread-delete{flex-shrink:0;opacity:0;width:1.75rem;height:1.75rem;border-radius:.375rem;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:opacity .15s;background:transparent;border:0;color:#94a3b8}.cortex-widget__thread-item:hover>.cortex-widget__thread-delete{opacity:1}.cortex-widget__thread-delete:hover{background:#e2e8f0}.cortex-widget__thread-delete--active:hover{background:#475569}.cortex-widget__thread-arrow{flex-shrink:0;transition:color .15s;color:#cbd5e1}[dir=rtl] .cortex-widget__thread-arrow{transform:rotate(180deg)}.cortex-widget__thread-item:hover>.cortex-widget__thread-arrow{color:#94a3b8}.cortex-widget__thread-arrow--active{color:#64748b}.cortex-widget__threads-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:4rem 0;text-align:center}.cortex-widget__threads-empty-icon{width:2.5rem;height:2.5rem;border-radius:.5rem;background:#e2e8f0;display:flex;align-items:center;justify-content:center;margin-bottom:.75rem}.cortex-widget__threads-empty-svg{color:#94a3b8}.cortex-widget__threads-empty-title{font-size:.8125rem;color:#94a3b8;font-weight:500;margin:0}.cortex-widget__threads-empty-subtitle{font-size:.6875rem;color:#a5afbd;margin-top:.25rem;margin-bottom:0}.cortex-widget__chat-header{flex-shrink:0;height:3rem;padding:0 1rem;display:flex;align-items:center;gap:.75rem;border-bottom:1px solid #e2e8f0;background:#fff}.cortex-widget__back-btn{flex-shrink:0;width:2rem;height:2rem;border-radius:.375rem;display:flex;align-items:center;justify-content:center;color:#94a3b8;background:transparent;border:0;cursor:pointer;transition:color .15s,background-color .15s}.cortex-widget__back-btn:hover{color:#475569;background:#f1f5f9}[dir=rtl] .cortex-widget__back-icon{transform:rotate(180deg)}.cortex-widget__chat-title-wrap{min-width:0;flex:1}.cortex-widget__chat-title{font-size:.8125rem;font-weight:500;color:#334155;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin:0}.cortex-widget__debug-btn{flex-shrink:0;font-size:.6875rem;font-weight:500;padding:.25rem .625rem;border-radius:.375rem;border:0;cursor:pointer;transition:background-color .15s}.cortex-widget__debug-btn--on{background:#fef3c7;color:#d97706}.cortex-widget__debug-btn--on:hover{background:#fde68a}.cortex-widget__debug-btn--off{background:#f1f5f9;color:#94a3b8}.cortex-widget__debug-btn--off:hover{background:#e2e8f0}.cortex-widget__messages-skeleton{flex:1;overflow:hidden;padding:1rem;display:flex;flex-direction:column;gap:.5rem}.cortex-widget__msg-skel{width:100%;display:flex;flex-direction:column}.cortex-widget__msg-skel--user{align-items:flex-end}.cortex-widget__msg-skel--assistant{align-items:flex-start}.cortex-widget__msg-skel-bubble{max-width:80%;padding:1rem;border-radius:1rem;border:1px solid #e2e8f0;display:flex;flex-direction:column;gap:.5rem}.cortex-widget__msg-skel-bubble--user{background:#f8fafc;border-bottom-right-radius:0}.cortex-widget__msg-skel-bubble--assistant{background:#f1f5f9;border-bottom-left-radius:0}.cortex-widget__msg-skel-line{height:.75rem}.cortex-widget__messages{flex:1;overflow:hidden}@keyframes cortex-working-slide-in{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}@keyframes cortex-dot-wave{0%,60%,to{transform:translateY(0) scale(1);opacity:.45}30%{transform:translateY(-5px) scale(1.2);opacity:1}}@keyframes cortex-working-shimmer{0%{background-position:-200% center}to{background-position:200% center}}.cortex-widget__working{flex-shrink:0;padding:.5rem 1rem;display:flex;align-items:center;gap:.5rem;animation:cortex-working-slide-in .25s ease-out both}.cortex-widget__working-dots{display:flex;align-items:center;gap:4px}.cortex-working-dot{display:block;width:6px;height:6px;border-radius:9999px;background:#22c55e;animation:cortex-dot-wave 1.4s ease-in-out infinite}.cortex-working-dot:nth-child(2){animation-delay:.15s}.cortex-working-dot:nth-child(3){animation-delay:.3s}.cortex-widget__working-text{font-size:.75rem;font-weight:500;letter-spacing:.01em;color:#16a34a}.cortex-widget__input-area{flex-shrink:0;padding:.75rem;background:#fff;border-top:1px solid #e2e8f0}.cortex-widget__input-box{display:flex;align-items:flex-end;gap:.5rem;border-radius:.75rem;border:1px solid #e2e8f0;padding:.375rem;transition:border-color .15s,background-color .15s}.cortex-widget__input-box--disabled{background:#f1f5f9}.cortex-widget__input-box--enabled{background:#f8fafc}.cortex-widget__input-box--enabled:focus-within{border-color:#cbd5e1;background:#fff}.cortex-widget__textarea{flex:1;background:transparent;resize:none;border:0;outline:none;font-size:.8125rem;padding:.375rem .5rem;min-height:28px;max-height:120px;line-height:1.375;color:#334155}.cortex-widget__textarea::placeholder{color:#a5afbd}.cortex-widget__textarea--disabled{color:#94a3b8;cursor:not-allowed}.cortex-widget__textarea:disabled{cursor:not-allowed;border:0}@keyframes cortex-stop-pulse-ring{0%{opacity:.45;transform:scale(1)}50%{opacity:.15;transform:scale(1.12)}to{opacity:.45;transform:scale(1)}}@keyframes cortex-stop-fade-in{0%{opacity:0;transform:scale(.7)}to{opacity:1;transform:scale(1)}}.cortex-stop-btn{flex-shrink:0;width:2rem;height:2rem;border-radius:.5rem;display:flex;align-items:center;justify-content:center;cursor:pointer;position:relative;background:#e11d48;color:#fff;border:0;animation:cortex-stop-fade-in .2s ease-out both;transition:background .15s ease}.cortex-stop-btn:hover{background:#be123c}.cortex-stop-btn:active{transform:scale(.92)}.cortex-stop-btn__ring{position:absolute;inset:0;border-radius:.5rem;background:#e11d48;animation:cortex-stop-pulse-ring 2s ease-in-out infinite;pointer-events:none}.cortex-stop-btn__icon{position:relative;z-index:1}.cortex-widget__send-btn{flex-shrink:0;width:2rem;height:2rem;border-radius:.5rem;display:flex;align-items:center;justify-content:center;border:0;transition:background-color .15s}.cortex-widget__send-btn--empty{background:#e2e8f0;color:#94a3b8}.cortex-widget__send-btn--ready{background:#1e293b;color:#fff;cursor:pointer}.cortex-widget__send-btn--ready:hover{background:#334155}[dir=rtl] .cortex-widget__send-icon{transform:rotate(180deg)}\n"], dependencies: [{ kind: "component", type: MessageListComponent, selector: "cortex-message-list", inputs: ["debugMode"] }, { 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: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1991
+ ], ngImport: i0, template: "<div class=\"cortex-widget__container\">\n <!-- SCREEN 1: THREADS -->\n <div\n class=\"cortex-widget__screen\"\n [class.cortex-widget__screen--active]=\"screen() === 'threads'\"\n [class.cortex-widget__screen--left]=\"screen() !== 'threads'\"\n >\n <!-- Threads header -->\n <div class=\"cortex-widget__threads-header\">\n <div>\n <h2 class=\"cortex-widget__threads-title\">\n {{ 'translate_threads' | translate }}\n </h2>\n <p class=\"cortex-widget__threads-count\">\n {{\n 'translate_n_conversations' | translate: { count: chatService.threads()?.length ?? 0 }\n }}\n </p>\n </div>\n <button (click)=\"newChat()\" class=\"cortex-widget__new-chat-btn\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path\n d=\"M8 3v10M3 8h10\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n />\n </svg>\n {{ 'translate_new' | translate }}\n </button>\n </div>\n\n <!-- Threads list -->\n <div class=\"cortex-widget__threads-list\">\n <!-- Threads loading skeleton -->\n @if (chatService.threads() === undefined) {\n @for (i of [1, 2, 3, 4]; track i) {\n <div class=\"cortex-widget__thread-skeleton\">\n <div class=\"cortex-skeleton cortex-widget__thread-skeleton-icon\"></div>\n <div class=\"cortex-widget__thread-skeleton-lines\">\n <div\n class=\"cortex-skeleton cortex-widget__thread-skeleton-line\"\n [style.width]=\"40 + i * 12 + '%'\"\n ></div>\n </div>\n </div>\n }\n } @else {\n @for (thread of chatService.threads(); track thread.id) {\n <button\n (click)=\"selectThread(thread)\"\n class=\"cortex-widget__thread-item\"\n [class.cortex-widget__thread-item--active]=\"\n thread.id === chatService.selectedThread()?.id\n \"\n >\n <!-- Thread icon -->\n <div\n class=\"cortex-widget__thread-icon\"\n [class.cortex-widget__thread-icon--active]=\"\n thread.id === chatService.selectedThread()?.id\n \"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path\n d=\"M2.5 4.5h11M2.5 8h7M2.5 11.5h9\"\n stroke=\"currentColor\"\n stroke-width=\"1.3\"\n stroke-linecap=\"round\"\n />\n </svg>\n </div>\n\n <!-- Thread info -->\n <div class=\"cortex-widget__thread-info\">\n <div class=\"cortex-widget__thread-title-row\">\n <p\n class=\"cortex-widget__thread-title\"\n [class.cortex-widget__thread-title--active]=\"\n thread.id === chatService.selectedThread()?.id\n \"\n >\n {{ thread.title ?? ('translate_untitled' | translate) }}\n </p>\n\n @if (thread.isRunning) {\n <span\n class=\"cortex-widget__thread-running\"\n [class.cortex-widget__thread-running--active]=\"\n thread.id === chatService.selectedThread()?.id\n \"\n >\n <span class=\"cortex-widget__thread-running-dot\"></span>\n {{ 'translate_running' | translate }}\n </span>\n }\n </div>\n </div>\n\n <!-- Delete button -->\n <button\n (click)=\"$event.stopPropagation(); chatService.deleteThread(thread.id).subscribe()\"\n class=\"cortex-widget__thread-delete\"\n [class.cortex-widget__thread-delete--active]=\"\n thread.id === chatService.selectedThread()?.id\n \"\n >\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path\n d=\"M4 4l8 8M12 4l-8 8\"\n stroke=\"currentColor\"\n stroke-width=\"1.3\"\n stroke-linecap=\"round\"\n />\n </svg>\n </button>\n\n <!-- Arrow -->\n <svg\n class=\"cortex-widget__thread-arrow\"\n [class.cortex-widget__thread-arrow--active]=\"\n thread.id === chatService.selectedThread()?.id\n \"\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n >\n <path\n d=\"M6 4l4 4-4 4\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </button>\n }\n\n @if (!chatService.threads()?.length) {\n <div class=\"cortex-widget__threads-empty\">\n <div class=\"cortex-widget__threads-empty-icon\">\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n class=\"cortex-widget__threads-empty-svg\"\n >\n <path\n d=\"M2.5 4.5h11M2.5 8h7M2.5 11.5h9\"\n stroke=\"currentColor\"\n stroke-width=\"1.3\"\n stroke-linecap=\"round\"\n />\n </svg>\n </div>\n <p class=\"cortex-widget__threads-empty-title\">\n {{ 'translate_no_threads_yet' | translate }}\n </p>\n <p class=\"cortex-widget__threads-empty-subtitle\">\n {{ 'translate_start_a_new_conversation' | translate }}\n </p>\n </div>\n }\n }\n </div>\n </div>\n\n <!-- SCREEN 2: CHAT -->\n <div\n class=\"cortex-widget__screen\"\n [class.cortex-widget__screen--active]=\"screen() === 'chat'\"\n [class.cortex-widget__screen--right]=\"screen() !== 'chat'\"\n >\n <!-- Chat header -->\n <div class=\"cortex-widget__chat-header\">\n <!-- Back button -->\n <button (click)=\"goBack()\" class=\"cortex-widget__back-btn\">\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n class=\"cortex-widget__back-icon\"\n >\n <path\n d=\"M10 3L5 8l5 5\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </button>\n\n <!-- Title -->\n <div class=\"cortex-widget__chat-title-wrap\">\n <p class=\"cortex-widget__chat-title\">\n {{ chatService.selectedThread()?.title ?? ('translate_new_chat' | translate) }}\n </p>\n </div>\n\n <!-- Debug toggle -->\n @if (config().showDebugButton) {\n <button\n (click)=\"toggleDebugMode()\"\n class=\"cortex-widget__debug-btn\"\n [class.cortex-widget__debug-btn--on]=\"debugMode()\"\n [class.cortex-widget__debug-btn--off]=\"!debugMode()\"\n >\n {{ debugMode() ? ('translate_debug' | translate) : ('translate_normal' | translate) }}\n </button>\n }\n </div>\n\n <!-- Messages loading skeleton -->\n @if (chatService.isLoadingMessages() && !chatService.isAgentWorking()) {\n <div class=\"cortex-widget__messages-skeleton\">\n <!-- User message skeleton -->\n <div class=\"cortex-widget__msg-skel cortex-widget__msg-skel--user\">\n <div class=\"cortex-widget__msg-skel-bubble cortex-widget__msg-skel-bubble--user\">\n <div class=\"cortex-skeleton cortex-widget__msg-skel-line\" style=\"width: 13rem\"></div>\n <div class=\"cortex-skeleton cortex-widget__msg-skel-line\" style=\"width: 9rem\"></div>\n </div>\n </div>\n <!-- Assistant message skeleton -->\n <div class=\"cortex-widget__msg-skel cortex-widget__msg-skel--assistant\">\n <div class=\"cortex-widget__msg-skel-bubble cortex-widget__msg-skel-bubble--assistant\">\n <div class=\"cortex-skeleton cortex-widget__msg-skel-line\" style=\"width: 16rem\"></div>\n <div class=\"cortex-skeleton cortex-widget__msg-skel-line\" style=\"width: 18rem\"></div>\n <div class=\"cortex-skeleton cortex-widget__msg-skel-line\" style=\"width: 12rem\"></div>\n </div>\n </div>\n <!-- User message skeleton -->\n <div class=\"cortex-widget__msg-skel cortex-widget__msg-skel--user\">\n <div class=\"cortex-widget__msg-skel-bubble cortex-widget__msg-skel-bubble--user\">\n <div class=\"cortex-skeleton cortex-widget__msg-skel-line\" style=\"width: 11rem\"></div>\n </div>\n </div>\n <!-- Assistant message skeleton -->\n <div class=\"cortex-widget__msg-skel cortex-widget__msg-skel--assistant\">\n <div class=\"cortex-widget__msg-skel-bubble cortex-widget__msg-skel-bubble--assistant\">\n <div class=\"cortex-skeleton cortex-widget__msg-skel-line\" style=\"width: 14rem\"></div>\n <div class=\"cortex-skeleton cortex-widget__msg-skel-line\" style=\"width: 15rem\"></div>\n </div>\n </div>\n </div>\n } @else {\n <!-- Messages area -->\n <cortex-message-list class=\"cortex-widget__messages\" [debugMode]=\"debugMode()\" />\n }\n\n <!-- Agent working indicator -->\n @if (chatService.isAgentWorking() && !chatService.hasPendingToolCalls()) {\n <div class=\"cortex-widget__working\">\n <div class=\"cortex-widget__working-dots\">\n <span class=\"cortex-working-dot\"></span>\n <span class=\"cortex-working-dot\"></span>\n <span class=\"cortex-working-dot\"></span>\n </div>\n <span class=\"cortex-widget__working-text\">{{ 'translate_thinking' | translate }}</span>\n </div>\n }\n\n <!-- Chat input (hidden during pending tool calls) -->\n @if (!chatService.hasPendingToolCalls()) {\n <div class=\"cortex-widget__input-area\">\n <div\n class=\"cortex-widget__input-box\"\n [class.cortex-widget__input-box--disabled]=\"chatService.isAgentWorking()\"\n [class.cortex-widget__input-box--enabled]=\"!chatService.isAgentWorking()\"\n >\n <textarea\n (keydown)=\"onKeydown($event)\"\n [(ngModel)]=\"text\"\n [placeholder]=\"\n chatService.isAgentWorking() ? '' : ('translate_type_a_message' | translate)\n \"\n [disabled]=\"chatService.isAgentWorking()\"\n rows=\"1\"\n class=\"cortex-widget__textarea\"\n [class.cortex-widget__textarea--disabled]=\"chatService.isAgentWorking()\"\n ></textarea>\n @if (chatService.isAgentWorking()) {\n <!-- Stop button -->\n <button (click)=\"chatService.abort()\" class=\"cortex-stop-btn\">\n <!-- Pulsing ring -->\n <span class=\"cortex-stop-btn__ring\"></span>\n <!-- Stop icon (rounded square) -->\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n class=\"cortex-stop-btn__icon\"\n >\n <rect x=\"1\" y=\"1\" width=\"10\" height=\"10\" rx=\"2.5\" fill=\"currentColor\" />\n </svg>\n </button>\n } @else {\n <!-- Send button -->\n <button\n (click)=\"send()\"\n class=\"cortex-widget__send-btn\"\n [class.cortex-widget__send-btn--empty]=\"!text().trim()\"\n [class.cortex-widget__send-btn--ready]=\"!!text().trim()\"\n >\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n class=\"cortex-widget__send-icon\"\n >\n <path\n d=\"M3 8h10M9 4l4 4-4 4\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </button>\n }\n </div>\n </div>\n }\n </div>\n</div>\n", styles: [".cortex-widget{display:block}.cortex-widget__container{width:100%;height:100%;position:relative;overflow:hidden}.cortex-widget__screen{position:absolute;inset:0;display:flex;flex-direction:column;transition:transform .3s ease-out}.cortex-widget__screen--active{transform:translate(0)}.cortex-widget__screen--left{transform:translate(-100%)}[dir=rtl] .cortex-widget__screen--left,.cortex-widget__screen--right{transform:translate(100%)}[dir=rtl] .cortex-widget__screen--right{transform:translate(-100%)}.cortex-widget__threads-header{flex-shrink:0;padding:1.25rem 1.25rem 1rem;display:flex;align-items:center;justify-content:space-between}.cortex-widget__threads-title{font-size:.9375rem;font-weight:600;color:#1e293b;letter-spacing:-.01em;margin:0}.cortex-widget__threads-count{font-size:.6875rem;color:#94a3b8;margin-top:.125rem;margin-bottom:0}.cortex-widget__new-chat-btn{display:inline-flex;align-items:center;gap:.375rem;font-size:.75rem;font-weight:500;color:#f1f5f9;background:#1e293b;padding:.375rem .75rem;border-radius:.375rem;border:0;cursor:pointer;transition:background-color .15s}.cortex-widget__new-chat-btn:hover{background:#334155}.cortex-widget__new-chat-btn:active{background:#0f172a}.cortex-widget__threads-list{flex:1;overflow-y:auto;padding:0 .75rem .75rem}.cortex-widget__thread-skeleton{display:flex;align-items:center;gap:.75rem;padding:.75rem;margin-bottom:.125rem}.cortex-widget__thread-skeleton-icon{flex-shrink:0;width:2rem;height:2rem}.cortex-widget__thread-skeleton-lines{flex:1;display:flex;flex-direction:column;gap:.375rem}.cortex-widget__thread-skeleton-line{height:.875rem}@keyframes cortex-skeleton-shimmer{0%{background-position:-200% 0}to{background-position:200% 0}}.cortex-skeleton{background:linear-gradient(90deg,#e2e8f0,#f1f5f9,#e2e8f0 80%);background-size:200% 100%;animation:cortex-skeleton-shimmer 1.8s ease-in-out infinite;border-radius:6px}.cortex-widget__thread-item{width:100%;text-align:start;padding:.75rem;border-radius:.5rem;display:flex;align-items:center;gap:.75rem;transition:background-color .15s;cursor:pointer;margin-bottom:.125rem;border:0;background:transparent;color:#475569}.cortex-widget__thread-item:hover{background:#f1f5f9}.cortex-widget__thread-item:active{background:#e8ecf1}.cortex-widget__thread-item--active{background:#e2e8f0;color:#f1f5f9}.cortex-widget__thread-icon{flex-shrink:0;width:2rem;height:2rem;border-radius:.375rem;display:flex;align-items:center;justify-content:center;font-size:.6875rem;font-weight:600;background:#e2e8f0;color:#64748b}[dir=rtl] .cortex-widget__thread-icon{transform:rotate(180deg)}.cortex-widget__thread-icon--active{background:#334155;color:#cbd5e1}.cortex-widget__thread-info{min-width:0;flex:1}.cortex-widget__thread-title-row{display:flex;align-items:center;gap:.5rem;min-width:0}.cortex-widget__thread-title{font-size:.8125rem;font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:1.25;margin:0;color:#334155}.cortex-widget__thread-title--active{color:#f1f5f9}.cortex-widget__thread-running{flex-shrink:0;display:inline-flex;align-items:center;gap:.3125rem;padding:.2rem .45rem;border-radius:999px;background:#0e74901a;color:#0f766e;font-size:.625rem;font-weight:700;letter-spacing:.02em;text-transform:uppercase}.cortex-widget__thread-running--active{background:#f1f5f929;color:#e2e8f0}.cortex-widget__thread-running-dot{width:.375rem;height:.375rem;border-radius:999px;background:currentColor;box-shadow:0 0 .45rem currentColor;animation:cortex-thread-running-pulse 1.4s ease-in-out infinite}@keyframes cortex-thread-running-pulse{0%,to{opacity:.45;transform:scale(.9)}50%{opacity:1;transform:scale(1)}}.cortex-widget__thread-delete{flex-shrink:0;opacity:0;width:1.75rem;height:1.75rem;border-radius:.375rem;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:opacity .15s;background:transparent;border:0;color:#94a3b8}.cortex-widget__thread-item:hover>.cortex-widget__thread-delete{opacity:1}.cortex-widget__thread-delete:hover{background:#e2e8f0}.cortex-widget__thread-delete--active:hover{background:#475569}.cortex-widget__thread-arrow{flex-shrink:0;transition:color .15s;color:#cbd5e1}[dir=rtl] .cortex-widget__thread-arrow{transform:rotate(180deg)}.cortex-widget__thread-item:hover>.cortex-widget__thread-arrow{color:#94a3b8}.cortex-widget__thread-arrow--active{color:#64748b}.cortex-widget__threads-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:4rem 0;text-align:center}.cortex-widget__threads-empty-icon{width:2.5rem;height:2.5rem;border-radius:.5rem;background:#e2e8f0;display:flex;align-items:center;justify-content:center;margin-bottom:.75rem}.cortex-widget__threads-empty-svg{color:#94a3b8}.cortex-widget__threads-empty-title{font-size:.8125rem;color:#94a3b8;font-weight:500;margin:0}.cortex-widget__threads-empty-subtitle{font-size:.6875rem;color:#a5afbd;margin-top:.25rem;margin-bottom:0}.cortex-widget__chat-header{flex-shrink:0;height:3rem;padding:0 1rem;display:flex;align-items:center;gap:.75rem;border-bottom:1px solid #e2e8f0;background:#fff}.cortex-widget__back-btn{flex-shrink:0;width:2rem;height:2rem;border-radius:.375rem;display:flex;align-items:center;justify-content:center;color:#94a3b8;background:transparent;border:0;cursor:pointer;transition:color .15s,background-color .15s}.cortex-widget__back-btn:hover{color:#475569;background:#f1f5f9}[dir=rtl] .cortex-widget__back-icon{transform:rotate(180deg)}.cortex-widget__chat-title-wrap{min-width:0;flex:1}.cortex-widget__chat-title{font-size:.8125rem;font-weight:500;color:#334155;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin:0}.cortex-widget__debug-btn{flex-shrink:0;font-size:.6875rem;font-weight:500;padding:.25rem .625rem;border-radius:.375rem;border:0;cursor:pointer;transition:background-color .15s}.cortex-widget__debug-btn--on{background:#fef3c7;color:#d97706}.cortex-widget__debug-btn--on:hover{background:#fde68a}.cortex-widget__debug-btn--off{background:#f1f5f9;color:#94a3b8}.cortex-widget__debug-btn--off:hover{background:#e2e8f0}.cortex-widget__messages-skeleton{flex:1;overflow:hidden;padding:1rem;display:flex;flex-direction:column;gap:.5rem}.cortex-widget__msg-skel{width:100%;display:flex;flex-direction:column}.cortex-widget__msg-skel--user{align-items:flex-end}.cortex-widget__msg-skel--assistant{align-items:flex-start}.cortex-widget__msg-skel-bubble{max-width:80%;padding:1rem;border-radius:1rem;border:1px solid #e2e8f0;display:flex;flex-direction:column;gap:.5rem}.cortex-widget__msg-skel-bubble--user{background:#f8fafc;border-bottom-right-radius:0}.cortex-widget__msg-skel-bubble--assistant{background:#f1f5f9;border-bottom-left-radius:0}.cortex-widget__msg-skel-line{height:.75rem}.cortex-widget__messages{flex:1;overflow:hidden}@keyframes cortex-working-slide-in{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}@keyframes cortex-dot-wave{0%,60%,to{transform:translateY(0) scale(1);opacity:.45}30%{transform:translateY(-5px) scale(1.2);opacity:1}}@keyframes cortex-working-shimmer{0%{background-position:-200% center}to{background-position:200% center}}.cortex-widget__working{flex-shrink:0;padding:.5rem 1rem;display:flex;align-items:center;gap:.5rem;animation:cortex-working-slide-in .25s ease-out both}.cortex-widget__working-dots{display:flex;align-items:center;gap:4px}.cortex-working-dot{display:block;width:6px;height:6px;border-radius:9999px;background:#22c55e;animation:cortex-dot-wave 1.4s ease-in-out infinite}.cortex-working-dot:nth-child(2){animation-delay:.15s}.cortex-working-dot:nth-child(3){animation-delay:.3s}.cortex-widget__working-text{font-size:.75rem;font-weight:500;letter-spacing:.01em;color:#16a34a}.cortex-widget__input-area{flex-shrink:0;padding:.75rem;background:#fff;border-top:1px solid #e2e8f0}.cortex-widget__input-box{display:flex;align-items:flex-end;gap:.5rem;border-radius:.75rem;border:1px solid #e2e8f0;padding:.375rem;transition:border-color .15s,background-color .15s}.cortex-widget__input-box--disabled{background:#f1f5f9}.cortex-widget__input-box--enabled{background:#f8fafc}.cortex-widget__input-box--enabled:focus-within{border-color:#cbd5e1;background:#fff}.cortex-widget__textarea{flex:1;background:transparent;resize:none;border:0;outline:none;font-size:.8125rem;padding:.375rem .5rem;min-height:28px;max-height:120px;line-height:1.375;color:#334155}.cortex-widget__textarea::placeholder{color:#a5afbd}.cortex-widget__textarea--disabled{color:#94a3b8;cursor:not-allowed}.cortex-widget__textarea:disabled{cursor:not-allowed;border:0}@keyframes cortex-stop-pulse-ring{0%{opacity:.45;transform:scale(1)}50%{opacity:.15;transform:scale(1.12)}to{opacity:.45;transform:scale(1)}}@keyframes cortex-stop-fade-in{0%{opacity:0;transform:scale(.7)}to{opacity:1;transform:scale(1)}}.cortex-stop-btn{flex-shrink:0;width:2rem;height:2rem;border-radius:.5rem;display:flex;align-items:center;justify-content:center;cursor:pointer;position:relative;background:#e11d48;color:#fff;border:0;animation:cortex-stop-fade-in .2s ease-out both;transition:background .15s ease}.cortex-stop-btn:hover{background:#be123c}.cortex-stop-btn:active{transform:scale(.92)}.cortex-stop-btn__ring{position:absolute;inset:0;border-radius:.5rem;background:#e11d48;animation:cortex-stop-pulse-ring 2s ease-in-out infinite;pointer-events:none}.cortex-stop-btn__icon{position:relative;z-index:1}.cortex-widget__send-btn{flex-shrink:0;width:2rem;height:2rem;border-radius:.5rem;display:flex;align-items:center;justify-content:center;border:0;transition:background-color .15s}.cortex-widget__send-btn--empty{background:#e2e8f0;color:#94a3b8}.cortex-widget__send-btn--ready{background:#1e293b;color:#fff;cursor:pointer}.cortex-widget__send-btn--ready:hover{background:#334155}[dir=rtl] .cortex-widget__send-icon{transform:rotate(180deg)}\n"], dependencies: [{ kind: "component", type: MessageListComponent, selector: "cortex-message-list", inputs: ["debugMode"] }, { 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: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1667
1992
  }
1668
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: CortexChatWidgetComponent, decorators: [{
1993
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CortexChatWidgetComponent, decorators: [{
1669
1994
  type: Component,
1670
1995
  args: [{ selector: 'cortex-chat-widget', imports: [MessageListComponent, FormsModule, TranslatePipe], providers: [
1671
1996
  CortexClientConfigRef,
@@ -1679,7 +2004,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
1679
2004
  fallbackLang: 'en',
1680
2005
  loader: provideTranslateLoader(CortexClientTranslateLoader),
1681
2006
  }),
1682
- ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: { class: 'cortex-widget' }, template: "<div class=\"cortex-widget__container\">\n <!-- SCREEN 1: THREADS -->\n <div\n class=\"cortex-widget__screen\"\n [class.cortex-widget__screen--active]=\"screen() === 'threads'\"\n [class.cortex-widget__screen--left]=\"screen() !== 'threads'\"\n >\n <!-- Threads header -->\n <div class=\"cortex-widget__threads-header\">\n <div>\n <h2 class=\"cortex-widget__threads-title\">\n {{ 'translate_threads' | translate }}\n </h2>\n <p class=\"cortex-widget__threads-count\">\n {{\n 'translate_n_conversations' | translate: { count: chatService.threads()?.length ?? 0 }\n }}\n </p>\n </div>\n <button (click)=\"newChat()\" class=\"cortex-widget__new-chat-btn\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path\n d=\"M8 3v10M3 8h10\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n />\n </svg>\n {{ 'translate_new' | translate }}\n </button>\n </div>\n\n <!-- Threads list -->\n <div class=\"cortex-widget__threads-list\">\n <!-- Threads loading skeleton -->\n @if (chatService.threads() === undefined) {\n @for (i of [1, 2, 3, 4]; track i) {\n <div class=\"cortex-widget__thread-skeleton\">\n <div class=\"cortex-skeleton cortex-widget__thread-skeleton-icon\"></div>\n <div class=\"cortex-widget__thread-skeleton-lines\">\n <div\n class=\"cortex-skeleton cortex-widget__thread-skeleton-line\"\n [style.width]=\"40 + i * 12 + '%'\"\n ></div>\n </div>\n </div>\n }\n } @else {\n @for (thread of chatService.threads(); track thread.id) {\n <button\n (click)=\"selectThread(thread)\"\n class=\"cortex-widget__thread-item\"\n [class.cortex-widget__thread-item--active]=\"\n thread.id === chatService.selectedThread()?.id\n \"\n >\n <!-- Thread icon -->\n <div\n class=\"cortex-widget__thread-icon\"\n [class.cortex-widget__thread-icon--active]=\"\n thread.id === chatService.selectedThread()?.id\n \"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path\n d=\"M2.5 4.5h11M2.5 8h7M2.5 11.5h9\"\n stroke=\"currentColor\"\n stroke-width=\"1.3\"\n stroke-linecap=\"round\"\n />\n </svg>\n </div>\n\n <!-- Thread info -->\n <div class=\"cortex-widget__thread-info\">\n <p\n class=\"cortex-widget__thread-title\"\n [class.cortex-widget__thread-title--active]=\"\n thread.id === chatService.selectedThread()?.id\n \"\n >\n {{ thread.title ?? ('translate_untitled' | translate) }}\n </p>\n </div>\n\n <!-- Delete button -->\n <button\n (click)=\"$event.stopPropagation(); chatService.deleteThread(thread.id).subscribe()\"\n class=\"cortex-widget__thread-delete\"\n [class.cortex-widget__thread-delete--active]=\"\n thread.id === chatService.selectedThread()?.id\n \"\n >\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path\n d=\"M4 4l8 8M12 4l-8 8\"\n stroke=\"currentColor\"\n stroke-width=\"1.3\"\n stroke-linecap=\"round\"\n />\n </svg>\n </button>\n\n <!-- Arrow -->\n <svg\n class=\"cortex-widget__thread-arrow\"\n [class.cortex-widget__thread-arrow--active]=\"\n thread.id === chatService.selectedThread()?.id\n \"\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n >\n <path\n d=\"M6 4l4 4-4 4\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </button>\n }\n\n @if (!chatService.threads()?.length) {\n <div class=\"cortex-widget__threads-empty\">\n <div class=\"cortex-widget__threads-empty-icon\">\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n class=\"cortex-widget__threads-empty-svg\"\n >\n <path\n d=\"M2.5 4.5h11M2.5 8h7M2.5 11.5h9\"\n stroke=\"currentColor\"\n stroke-width=\"1.3\"\n stroke-linecap=\"round\"\n />\n </svg>\n </div>\n <p class=\"cortex-widget__threads-empty-title\">No threads yet</p>\n <p class=\"cortex-widget__threads-empty-subtitle\">Start a new conversation</p>\n </div>\n }\n }\n </div>\n </div>\n\n <!-- SCREEN 2: CHAT -->\n <div\n class=\"cortex-widget__screen\"\n [class.cortex-widget__screen--active]=\"screen() === 'chat'\"\n [class.cortex-widget__screen--right]=\"screen() !== 'chat'\"\n >\n <!-- Chat header -->\n <div class=\"cortex-widget__chat-header\">\n <!-- Back button -->\n <button (click)=\"goBack()\" class=\"cortex-widget__back-btn\">\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n class=\"cortex-widget__back-icon\"\n >\n <path\n d=\"M10 3L5 8l5 5\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </button>\n\n <!-- Title -->\n <div class=\"cortex-widget__chat-title-wrap\">\n <p class=\"cortex-widget__chat-title\">\n {{ chatService.selectedThread()?.title ?? ('translate_new_chat' | translate) }}\n </p>\n </div>\n\n <!-- Debug toggle -->\n <button\n (click)=\"toggleDebugMode()\"\n class=\"cortex-widget__debug-btn\"\n [class.cortex-widget__debug-btn--on]=\"debugMode()\"\n [class.cortex-widget__debug-btn--off]=\"!debugMode()\"\n >\n {{ debugMode() ? ('translate_debug' | translate) : ('translate_normal' | translate) }}\n </button>\n </div>\n\n <!-- Messages loading skeleton -->\n @if (chatService.isLoadingMessages() && !chatService.isAgentWorking()) {\n <div class=\"cortex-widget__messages-skeleton\">\n <!-- User message skeleton -->\n <div class=\"cortex-widget__msg-skel cortex-widget__msg-skel--user\">\n <div class=\"cortex-widget__msg-skel-bubble cortex-widget__msg-skel-bubble--user\">\n <div class=\"cortex-skeleton cortex-widget__msg-skel-line\" style=\"width: 13rem\"></div>\n <div class=\"cortex-skeleton cortex-widget__msg-skel-line\" style=\"width: 9rem\"></div>\n </div>\n </div>\n <!-- Assistant message skeleton -->\n <div class=\"cortex-widget__msg-skel cortex-widget__msg-skel--assistant\">\n <div class=\"cortex-widget__msg-skel-bubble cortex-widget__msg-skel-bubble--assistant\">\n <div class=\"cortex-skeleton cortex-widget__msg-skel-line\" style=\"width: 16rem\"></div>\n <div class=\"cortex-skeleton cortex-widget__msg-skel-line\" style=\"width: 18rem\"></div>\n <div class=\"cortex-skeleton cortex-widget__msg-skel-line\" style=\"width: 12rem\"></div>\n </div>\n </div>\n <!-- User message skeleton -->\n <div class=\"cortex-widget__msg-skel cortex-widget__msg-skel--user\">\n <div class=\"cortex-widget__msg-skel-bubble cortex-widget__msg-skel-bubble--user\">\n <div class=\"cortex-skeleton cortex-widget__msg-skel-line\" style=\"width: 11rem\"></div>\n </div>\n </div>\n <!-- Assistant message skeleton -->\n <div class=\"cortex-widget__msg-skel cortex-widget__msg-skel--assistant\">\n <div class=\"cortex-widget__msg-skel-bubble cortex-widget__msg-skel-bubble--assistant\">\n <div class=\"cortex-skeleton cortex-widget__msg-skel-line\" style=\"width: 14rem\"></div>\n <div class=\"cortex-skeleton cortex-widget__msg-skel-line\" style=\"width: 15rem\"></div>\n </div>\n </div>\n </div>\n } @else {\n <!-- Messages area -->\n <cortex-message-list class=\"cortex-widget__messages\" [debugMode]=\"debugMode()\" />\n }\n\n <!-- Agent working indicator -->\n @if (chatService.isAgentWorking() && !chatService.hasPendingToolCalls()) {\n <div class=\"cortex-widget__working\">\n <div class=\"cortex-widget__working-dots\">\n <span class=\"cortex-working-dot\"></span>\n <span class=\"cortex-working-dot\"></span>\n <span class=\"cortex-working-dot\"></span>\n </div>\n <span class=\"cortex-widget__working-text\">{{ 'translate_thinking' | translate }}</span>\n </div>\n }\n\n <!-- Chat input (hidden during pending tool calls) -->\n @if (!chatService.hasPendingToolCalls()) {\n <div class=\"cortex-widget__input-area\">\n <div\n class=\"cortex-widget__input-box\"\n [class.cortex-widget__input-box--disabled]=\"chatService.isAgentWorking()\"\n [class.cortex-widget__input-box--enabled]=\"!chatService.isAgentWorking()\"\n >\n <textarea\n (keydown)=\"onKeydown($event)\"\n [(ngModel)]=\"text\"\n [placeholder]=\"\n chatService.isAgentWorking() ? '' : ('translate_type_a_message' | translate)\n \"\n [disabled]=\"chatService.isAgentWorking()\"\n rows=\"1\"\n class=\"cortex-widget__textarea\"\n [class.cortex-widget__textarea--disabled]=\"chatService.isAgentWorking()\"\n ></textarea>\n @if (chatService.isAgentWorking()) {\n <!-- Stop button -->\n <button (click)=\"chatService.abort()\" class=\"cortex-stop-btn\">\n <!-- Pulsing ring -->\n <span class=\"cortex-stop-btn__ring\"></span>\n <!-- Stop icon (rounded square) -->\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n class=\"cortex-stop-btn__icon\"\n >\n <rect x=\"1\" y=\"1\" width=\"10\" height=\"10\" rx=\"2.5\" fill=\"currentColor\" />\n </svg>\n </button>\n } @else {\n <!-- Send button -->\n <button\n (click)=\"send()\"\n class=\"cortex-widget__send-btn\"\n [class.cortex-widget__send-btn--empty]=\"!text().trim()\"\n [class.cortex-widget__send-btn--ready]=\"!!text().trim()\"\n >\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n class=\"cortex-widget__send-icon\"\n >\n <path\n d=\"M3 8h10M9 4l4 4-4 4\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </button>\n }\n </div>\n </div>\n }\n </div>\n</div>\n", styles: [".cortex-widget{display:block}.cortex-widget__container{width:100%;height:100%;position:relative;overflow:hidden}.cortex-widget__screen{position:absolute;inset:0;display:flex;flex-direction:column;transition:transform .3s ease-out}.cortex-widget__screen--active{transform:translate(0)}.cortex-widget__screen--left{transform:translate(-100%)}[dir=rtl] .cortex-widget__screen--left,.cortex-widget__screen--right{transform:translate(100%)}[dir=rtl] .cortex-widget__screen--right{transform:translate(-100%)}.cortex-widget__threads-header{flex-shrink:0;padding:1.25rem 1.25rem 1rem;display:flex;align-items:center;justify-content:space-between}.cortex-widget__threads-title{font-size:.9375rem;font-weight:600;color:#1e293b;letter-spacing:-.01em;margin:0}.cortex-widget__threads-count{font-size:.6875rem;color:#94a3b8;margin-top:.125rem;margin-bottom:0}.cortex-widget__new-chat-btn{display:inline-flex;align-items:center;gap:.375rem;font-size:.75rem;font-weight:500;color:#f1f5f9;background:#1e293b;padding:.375rem .75rem;border-radius:.375rem;border:0;cursor:pointer;transition:background-color .15s}.cortex-widget__new-chat-btn:hover{background:#334155}.cortex-widget__new-chat-btn:active{background:#0f172a}.cortex-widget__threads-list{flex:1;overflow-y:auto;padding:0 .75rem .75rem}.cortex-widget__thread-skeleton{display:flex;align-items:center;gap:.75rem;padding:.75rem;margin-bottom:.125rem}.cortex-widget__thread-skeleton-icon{flex-shrink:0;width:2rem;height:2rem}.cortex-widget__thread-skeleton-lines{flex:1;display:flex;flex-direction:column;gap:.375rem}.cortex-widget__thread-skeleton-line{height:.875rem}@keyframes cortex-skeleton-shimmer{0%{background-position:-200% 0}to{background-position:200% 0}}.cortex-skeleton{background:linear-gradient(90deg,#e2e8f0,#f1f5f9,#e2e8f0 80%);background-size:200% 100%;animation:cortex-skeleton-shimmer 1.8s ease-in-out infinite;border-radius:6px}.cortex-widget__thread-item{width:100%;text-align:start;padding:.75rem;border-radius:.5rem;display:flex;align-items:center;gap:.75rem;transition:background-color .15s;cursor:pointer;margin-bottom:.125rem;border:0;background:transparent;color:#475569}.cortex-widget__thread-item:hover{background:#f1f5f9}.cortex-widget__thread-item:active{background:#e8ecf1}.cortex-widget__thread-item--active{background:#e2e8f0;color:#f1f5f9}.cortex-widget__thread-icon{flex-shrink:0;width:2rem;height:2rem;border-radius:.375rem;display:flex;align-items:center;justify-content:center;font-size:.6875rem;font-weight:600;background:#e2e8f0;color:#64748b}[dir=rtl] .cortex-widget__thread-icon{transform:rotate(180deg)}.cortex-widget__thread-icon--active{background:#334155;color:#cbd5e1}.cortex-widget__thread-info{min-width:0;flex:1}.cortex-widget__thread-title{font-size:.8125rem;font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:1.25;margin:0;color:#334155}.cortex-widget__thread-title--active{color:#f1f5f9}.cortex-widget__thread-delete{flex-shrink:0;opacity:0;width:1.75rem;height:1.75rem;border-radius:.375rem;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:opacity .15s;background:transparent;border:0;color:#94a3b8}.cortex-widget__thread-item:hover>.cortex-widget__thread-delete{opacity:1}.cortex-widget__thread-delete:hover{background:#e2e8f0}.cortex-widget__thread-delete--active:hover{background:#475569}.cortex-widget__thread-arrow{flex-shrink:0;transition:color .15s;color:#cbd5e1}[dir=rtl] .cortex-widget__thread-arrow{transform:rotate(180deg)}.cortex-widget__thread-item:hover>.cortex-widget__thread-arrow{color:#94a3b8}.cortex-widget__thread-arrow--active{color:#64748b}.cortex-widget__threads-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:4rem 0;text-align:center}.cortex-widget__threads-empty-icon{width:2.5rem;height:2.5rem;border-radius:.5rem;background:#e2e8f0;display:flex;align-items:center;justify-content:center;margin-bottom:.75rem}.cortex-widget__threads-empty-svg{color:#94a3b8}.cortex-widget__threads-empty-title{font-size:.8125rem;color:#94a3b8;font-weight:500;margin:0}.cortex-widget__threads-empty-subtitle{font-size:.6875rem;color:#a5afbd;margin-top:.25rem;margin-bottom:0}.cortex-widget__chat-header{flex-shrink:0;height:3rem;padding:0 1rem;display:flex;align-items:center;gap:.75rem;border-bottom:1px solid #e2e8f0;background:#fff}.cortex-widget__back-btn{flex-shrink:0;width:2rem;height:2rem;border-radius:.375rem;display:flex;align-items:center;justify-content:center;color:#94a3b8;background:transparent;border:0;cursor:pointer;transition:color .15s,background-color .15s}.cortex-widget__back-btn:hover{color:#475569;background:#f1f5f9}[dir=rtl] .cortex-widget__back-icon{transform:rotate(180deg)}.cortex-widget__chat-title-wrap{min-width:0;flex:1}.cortex-widget__chat-title{font-size:.8125rem;font-weight:500;color:#334155;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin:0}.cortex-widget__debug-btn{flex-shrink:0;font-size:.6875rem;font-weight:500;padding:.25rem .625rem;border-radius:.375rem;border:0;cursor:pointer;transition:background-color .15s}.cortex-widget__debug-btn--on{background:#fef3c7;color:#d97706}.cortex-widget__debug-btn--on:hover{background:#fde68a}.cortex-widget__debug-btn--off{background:#f1f5f9;color:#94a3b8}.cortex-widget__debug-btn--off:hover{background:#e2e8f0}.cortex-widget__messages-skeleton{flex:1;overflow:hidden;padding:1rem;display:flex;flex-direction:column;gap:.5rem}.cortex-widget__msg-skel{width:100%;display:flex;flex-direction:column}.cortex-widget__msg-skel--user{align-items:flex-end}.cortex-widget__msg-skel--assistant{align-items:flex-start}.cortex-widget__msg-skel-bubble{max-width:80%;padding:1rem;border-radius:1rem;border:1px solid #e2e8f0;display:flex;flex-direction:column;gap:.5rem}.cortex-widget__msg-skel-bubble--user{background:#f8fafc;border-bottom-right-radius:0}.cortex-widget__msg-skel-bubble--assistant{background:#f1f5f9;border-bottom-left-radius:0}.cortex-widget__msg-skel-line{height:.75rem}.cortex-widget__messages{flex:1;overflow:hidden}@keyframes cortex-working-slide-in{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}@keyframes cortex-dot-wave{0%,60%,to{transform:translateY(0) scale(1);opacity:.45}30%{transform:translateY(-5px) scale(1.2);opacity:1}}@keyframes cortex-working-shimmer{0%{background-position:-200% center}to{background-position:200% center}}.cortex-widget__working{flex-shrink:0;padding:.5rem 1rem;display:flex;align-items:center;gap:.5rem;animation:cortex-working-slide-in .25s ease-out both}.cortex-widget__working-dots{display:flex;align-items:center;gap:4px}.cortex-working-dot{display:block;width:6px;height:6px;border-radius:9999px;background:#22c55e;animation:cortex-dot-wave 1.4s ease-in-out infinite}.cortex-working-dot:nth-child(2){animation-delay:.15s}.cortex-working-dot:nth-child(3){animation-delay:.3s}.cortex-widget__working-text{font-size:.75rem;font-weight:500;letter-spacing:.01em;color:#16a34a}.cortex-widget__input-area{flex-shrink:0;padding:.75rem;background:#fff;border-top:1px solid #e2e8f0}.cortex-widget__input-box{display:flex;align-items:flex-end;gap:.5rem;border-radius:.75rem;border:1px solid #e2e8f0;padding:.375rem;transition:border-color .15s,background-color .15s}.cortex-widget__input-box--disabled{background:#f1f5f9}.cortex-widget__input-box--enabled{background:#f8fafc}.cortex-widget__input-box--enabled:focus-within{border-color:#cbd5e1;background:#fff}.cortex-widget__textarea{flex:1;background:transparent;resize:none;border:0;outline:none;font-size:.8125rem;padding:.375rem .5rem;min-height:28px;max-height:120px;line-height:1.375;color:#334155}.cortex-widget__textarea::placeholder{color:#a5afbd}.cortex-widget__textarea--disabled{color:#94a3b8;cursor:not-allowed}.cortex-widget__textarea:disabled{cursor:not-allowed;border:0}@keyframes cortex-stop-pulse-ring{0%{opacity:.45;transform:scale(1)}50%{opacity:.15;transform:scale(1.12)}to{opacity:.45;transform:scale(1)}}@keyframes cortex-stop-fade-in{0%{opacity:0;transform:scale(.7)}to{opacity:1;transform:scale(1)}}.cortex-stop-btn{flex-shrink:0;width:2rem;height:2rem;border-radius:.5rem;display:flex;align-items:center;justify-content:center;cursor:pointer;position:relative;background:#e11d48;color:#fff;border:0;animation:cortex-stop-fade-in .2s ease-out both;transition:background .15s ease}.cortex-stop-btn:hover{background:#be123c}.cortex-stop-btn:active{transform:scale(.92)}.cortex-stop-btn__ring{position:absolute;inset:0;border-radius:.5rem;background:#e11d48;animation:cortex-stop-pulse-ring 2s ease-in-out infinite;pointer-events:none}.cortex-stop-btn__icon{position:relative;z-index:1}.cortex-widget__send-btn{flex-shrink:0;width:2rem;height:2rem;border-radius:.5rem;display:flex;align-items:center;justify-content:center;border:0;transition:background-color .15s}.cortex-widget__send-btn--empty{background:#e2e8f0;color:#94a3b8}.cortex-widget__send-btn--ready{background:#1e293b;color:#fff;cursor:pointer}.cortex-widget__send-btn--ready:hover{background:#334155}[dir=rtl] .cortex-widget__send-icon{transform:rotate(180deg)}\n"] }]
2007
+ ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: { class: 'cortex-widget' }, template: "<div class=\"cortex-widget__container\">\n <!-- SCREEN 1: THREADS -->\n <div\n class=\"cortex-widget__screen\"\n [class.cortex-widget__screen--active]=\"screen() === 'threads'\"\n [class.cortex-widget__screen--left]=\"screen() !== 'threads'\"\n >\n <!-- Threads header -->\n <div class=\"cortex-widget__threads-header\">\n <div>\n <h2 class=\"cortex-widget__threads-title\">\n {{ 'translate_threads' | translate }}\n </h2>\n <p class=\"cortex-widget__threads-count\">\n {{\n 'translate_n_conversations' | translate: { count: chatService.threads()?.length ?? 0 }\n }}\n </p>\n </div>\n <button (click)=\"newChat()\" class=\"cortex-widget__new-chat-btn\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path\n d=\"M8 3v10M3 8h10\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n />\n </svg>\n {{ 'translate_new' | translate }}\n </button>\n </div>\n\n <!-- Threads list -->\n <div class=\"cortex-widget__threads-list\">\n <!-- Threads loading skeleton -->\n @if (chatService.threads() === undefined) {\n @for (i of [1, 2, 3, 4]; track i) {\n <div class=\"cortex-widget__thread-skeleton\">\n <div class=\"cortex-skeleton cortex-widget__thread-skeleton-icon\"></div>\n <div class=\"cortex-widget__thread-skeleton-lines\">\n <div\n class=\"cortex-skeleton cortex-widget__thread-skeleton-line\"\n [style.width]=\"40 + i * 12 + '%'\"\n ></div>\n </div>\n </div>\n }\n } @else {\n @for (thread of chatService.threads(); track thread.id) {\n <button\n (click)=\"selectThread(thread)\"\n class=\"cortex-widget__thread-item\"\n [class.cortex-widget__thread-item--active]=\"\n thread.id === chatService.selectedThread()?.id\n \"\n >\n <!-- Thread icon -->\n <div\n class=\"cortex-widget__thread-icon\"\n [class.cortex-widget__thread-icon--active]=\"\n thread.id === chatService.selectedThread()?.id\n \"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path\n d=\"M2.5 4.5h11M2.5 8h7M2.5 11.5h9\"\n stroke=\"currentColor\"\n stroke-width=\"1.3\"\n stroke-linecap=\"round\"\n />\n </svg>\n </div>\n\n <!-- Thread info -->\n <div class=\"cortex-widget__thread-info\">\n <div class=\"cortex-widget__thread-title-row\">\n <p\n class=\"cortex-widget__thread-title\"\n [class.cortex-widget__thread-title--active]=\"\n thread.id === chatService.selectedThread()?.id\n \"\n >\n {{ thread.title ?? ('translate_untitled' | translate) }}\n </p>\n\n @if (thread.isRunning) {\n <span\n class=\"cortex-widget__thread-running\"\n [class.cortex-widget__thread-running--active]=\"\n thread.id === chatService.selectedThread()?.id\n \"\n >\n <span class=\"cortex-widget__thread-running-dot\"></span>\n {{ 'translate_running' | translate }}\n </span>\n }\n </div>\n </div>\n\n <!-- Delete button -->\n <button\n (click)=\"$event.stopPropagation(); chatService.deleteThread(thread.id).subscribe()\"\n class=\"cortex-widget__thread-delete\"\n [class.cortex-widget__thread-delete--active]=\"\n thread.id === chatService.selectedThread()?.id\n \"\n >\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path\n d=\"M4 4l8 8M12 4l-8 8\"\n stroke=\"currentColor\"\n stroke-width=\"1.3\"\n stroke-linecap=\"round\"\n />\n </svg>\n </button>\n\n <!-- Arrow -->\n <svg\n class=\"cortex-widget__thread-arrow\"\n [class.cortex-widget__thread-arrow--active]=\"\n thread.id === chatService.selectedThread()?.id\n \"\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n >\n <path\n d=\"M6 4l4 4-4 4\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </button>\n }\n\n @if (!chatService.threads()?.length) {\n <div class=\"cortex-widget__threads-empty\">\n <div class=\"cortex-widget__threads-empty-icon\">\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n class=\"cortex-widget__threads-empty-svg\"\n >\n <path\n d=\"M2.5 4.5h11M2.5 8h7M2.5 11.5h9\"\n stroke=\"currentColor\"\n stroke-width=\"1.3\"\n stroke-linecap=\"round\"\n />\n </svg>\n </div>\n <p class=\"cortex-widget__threads-empty-title\">\n {{ 'translate_no_threads_yet' | translate }}\n </p>\n <p class=\"cortex-widget__threads-empty-subtitle\">\n {{ 'translate_start_a_new_conversation' | translate }}\n </p>\n </div>\n }\n }\n </div>\n </div>\n\n <!-- SCREEN 2: CHAT -->\n <div\n class=\"cortex-widget__screen\"\n [class.cortex-widget__screen--active]=\"screen() === 'chat'\"\n [class.cortex-widget__screen--right]=\"screen() !== 'chat'\"\n >\n <!-- Chat header -->\n <div class=\"cortex-widget__chat-header\">\n <!-- Back button -->\n <button (click)=\"goBack()\" class=\"cortex-widget__back-btn\">\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n class=\"cortex-widget__back-icon\"\n >\n <path\n d=\"M10 3L5 8l5 5\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </button>\n\n <!-- Title -->\n <div class=\"cortex-widget__chat-title-wrap\">\n <p class=\"cortex-widget__chat-title\">\n {{ chatService.selectedThread()?.title ?? ('translate_new_chat' | translate) }}\n </p>\n </div>\n\n <!-- Debug toggle -->\n @if (config().showDebugButton) {\n <button\n (click)=\"toggleDebugMode()\"\n class=\"cortex-widget__debug-btn\"\n [class.cortex-widget__debug-btn--on]=\"debugMode()\"\n [class.cortex-widget__debug-btn--off]=\"!debugMode()\"\n >\n {{ debugMode() ? ('translate_debug' | translate) : ('translate_normal' | translate) }}\n </button>\n }\n </div>\n\n <!-- Messages loading skeleton -->\n @if (chatService.isLoadingMessages() && !chatService.isAgentWorking()) {\n <div class=\"cortex-widget__messages-skeleton\">\n <!-- User message skeleton -->\n <div class=\"cortex-widget__msg-skel cortex-widget__msg-skel--user\">\n <div class=\"cortex-widget__msg-skel-bubble cortex-widget__msg-skel-bubble--user\">\n <div class=\"cortex-skeleton cortex-widget__msg-skel-line\" style=\"width: 13rem\"></div>\n <div class=\"cortex-skeleton cortex-widget__msg-skel-line\" style=\"width: 9rem\"></div>\n </div>\n </div>\n <!-- Assistant message skeleton -->\n <div class=\"cortex-widget__msg-skel cortex-widget__msg-skel--assistant\">\n <div class=\"cortex-widget__msg-skel-bubble cortex-widget__msg-skel-bubble--assistant\">\n <div class=\"cortex-skeleton cortex-widget__msg-skel-line\" style=\"width: 16rem\"></div>\n <div class=\"cortex-skeleton cortex-widget__msg-skel-line\" style=\"width: 18rem\"></div>\n <div class=\"cortex-skeleton cortex-widget__msg-skel-line\" style=\"width: 12rem\"></div>\n </div>\n </div>\n <!-- User message skeleton -->\n <div class=\"cortex-widget__msg-skel cortex-widget__msg-skel--user\">\n <div class=\"cortex-widget__msg-skel-bubble cortex-widget__msg-skel-bubble--user\">\n <div class=\"cortex-skeleton cortex-widget__msg-skel-line\" style=\"width: 11rem\"></div>\n </div>\n </div>\n <!-- Assistant message skeleton -->\n <div class=\"cortex-widget__msg-skel cortex-widget__msg-skel--assistant\">\n <div class=\"cortex-widget__msg-skel-bubble cortex-widget__msg-skel-bubble--assistant\">\n <div class=\"cortex-skeleton cortex-widget__msg-skel-line\" style=\"width: 14rem\"></div>\n <div class=\"cortex-skeleton cortex-widget__msg-skel-line\" style=\"width: 15rem\"></div>\n </div>\n </div>\n </div>\n } @else {\n <!-- Messages area -->\n <cortex-message-list class=\"cortex-widget__messages\" [debugMode]=\"debugMode()\" />\n }\n\n <!-- Agent working indicator -->\n @if (chatService.isAgentWorking() && !chatService.hasPendingToolCalls()) {\n <div class=\"cortex-widget__working\">\n <div class=\"cortex-widget__working-dots\">\n <span class=\"cortex-working-dot\"></span>\n <span class=\"cortex-working-dot\"></span>\n <span class=\"cortex-working-dot\"></span>\n </div>\n <span class=\"cortex-widget__working-text\">{{ 'translate_thinking' | translate }}</span>\n </div>\n }\n\n <!-- Chat input (hidden during pending tool calls) -->\n @if (!chatService.hasPendingToolCalls()) {\n <div class=\"cortex-widget__input-area\">\n <div\n class=\"cortex-widget__input-box\"\n [class.cortex-widget__input-box--disabled]=\"chatService.isAgentWorking()\"\n [class.cortex-widget__input-box--enabled]=\"!chatService.isAgentWorking()\"\n >\n <textarea\n (keydown)=\"onKeydown($event)\"\n [(ngModel)]=\"text\"\n [placeholder]=\"\n chatService.isAgentWorking() ? '' : ('translate_type_a_message' | translate)\n \"\n [disabled]=\"chatService.isAgentWorking()\"\n rows=\"1\"\n class=\"cortex-widget__textarea\"\n [class.cortex-widget__textarea--disabled]=\"chatService.isAgentWorking()\"\n ></textarea>\n @if (chatService.isAgentWorking()) {\n <!-- Stop button -->\n <button (click)=\"chatService.abort()\" class=\"cortex-stop-btn\">\n <!-- Pulsing ring -->\n <span class=\"cortex-stop-btn__ring\"></span>\n <!-- Stop icon (rounded square) -->\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n class=\"cortex-stop-btn__icon\"\n >\n <rect x=\"1\" y=\"1\" width=\"10\" height=\"10\" rx=\"2.5\" fill=\"currentColor\" />\n </svg>\n </button>\n } @else {\n <!-- Send button -->\n <button\n (click)=\"send()\"\n class=\"cortex-widget__send-btn\"\n [class.cortex-widget__send-btn--empty]=\"!text().trim()\"\n [class.cortex-widget__send-btn--ready]=\"!!text().trim()\"\n >\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n class=\"cortex-widget__send-icon\"\n >\n <path\n d=\"M3 8h10M9 4l4 4-4 4\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </button>\n }\n </div>\n </div>\n }\n </div>\n</div>\n", styles: [".cortex-widget{display:block}.cortex-widget__container{width:100%;height:100%;position:relative;overflow:hidden}.cortex-widget__screen{position:absolute;inset:0;display:flex;flex-direction:column;transition:transform .3s ease-out}.cortex-widget__screen--active{transform:translate(0)}.cortex-widget__screen--left{transform:translate(-100%)}[dir=rtl] .cortex-widget__screen--left,.cortex-widget__screen--right{transform:translate(100%)}[dir=rtl] .cortex-widget__screen--right{transform:translate(-100%)}.cortex-widget__threads-header{flex-shrink:0;padding:1.25rem 1.25rem 1rem;display:flex;align-items:center;justify-content:space-between}.cortex-widget__threads-title{font-size:.9375rem;font-weight:600;color:#1e293b;letter-spacing:-.01em;margin:0}.cortex-widget__threads-count{font-size:.6875rem;color:#94a3b8;margin-top:.125rem;margin-bottom:0}.cortex-widget__new-chat-btn{display:inline-flex;align-items:center;gap:.375rem;font-size:.75rem;font-weight:500;color:#f1f5f9;background:#1e293b;padding:.375rem .75rem;border-radius:.375rem;border:0;cursor:pointer;transition:background-color .15s}.cortex-widget__new-chat-btn:hover{background:#334155}.cortex-widget__new-chat-btn:active{background:#0f172a}.cortex-widget__threads-list{flex:1;overflow-y:auto;padding:0 .75rem .75rem}.cortex-widget__thread-skeleton{display:flex;align-items:center;gap:.75rem;padding:.75rem;margin-bottom:.125rem}.cortex-widget__thread-skeleton-icon{flex-shrink:0;width:2rem;height:2rem}.cortex-widget__thread-skeleton-lines{flex:1;display:flex;flex-direction:column;gap:.375rem}.cortex-widget__thread-skeleton-line{height:.875rem}@keyframes cortex-skeleton-shimmer{0%{background-position:-200% 0}to{background-position:200% 0}}.cortex-skeleton{background:linear-gradient(90deg,#e2e8f0,#f1f5f9,#e2e8f0 80%);background-size:200% 100%;animation:cortex-skeleton-shimmer 1.8s ease-in-out infinite;border-radius:6px}.cortex-widget__thread-item{width:100%;text-align:start;padding:.75rem;border-radius:.5rem;display:flex;align-items:center;gap:.75rem;transition:background-color .15s;cursor:pointer;margin-bottom:.125rem;border:0;background:transparent;color:#475569}.cortex-widget__thread-item:hover{background:#f1f5f9}.cortex-widget__thread-item:active{background:#e8ecf1}.cortex-widget__thread-item--active{background:#e2e8f0;color:#f1f5f9}.cortex-widget__thread-icon{flex-shrink:0;width:2rem;height:2rem;border-radius:.375rem;display:flex;align-items:center;justify-content:center;font-size:.6875rem;font-weight:600;background:#e2e8f0;color:#64748b}[dir=rtl] .cortex-widget__thread-icon{transform:rotate(180deg)}.cortex-widget__thread-icon--active{background:#334155;color:#cbd5e1}.cortex-widget__thread-info{min-width:0;flex:1}.cortex-widget__thread-title-row{display:flex;align-items:center;gap:.5rem;min-width:0}.cortex-widget__thread-title{font-size:.8125rem;font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:1.25;margin:0;color:#334155}.cortex-widget__thread-title--active{color:#f1f5f9}.cortex-widget__thread-running{flex-shrink:0;display:inline-flex;align-items:center;gap:.3125rem;padding:.2rem .45rem;border-radius:999px;background:#0e74901a;color:#0f766e;font-size:.625rem;font-weight:700;letter-spacing:.02em;text-transform:uppercase}.cortex-widget__thread-running--active{background:#f1f5f929;color:#e2e8f0}.cortex-widget__thread-running-dot{width:.375rem;height:.375rem;border-radius:999px;background:currentColor;box-shadow:0 0 .45rem currentColor;animation:cortex-thread-running-pulse 1.4s ease-in-out infinite}@keyframes cortex-thread-running-pulse{0%,to{opacity:.45;transform:scale(.9)}50%{opacity:1;transform:scale(1)}}.cortex-widget__thread-delete{flex-shrink:0;opacity:0;width:1.75rem;height:1.75rem;border-radius:.375rem;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:opacity .15s;background:transparent;border:0;color:#94a3b8}.cortex-widget__thread-item:hover>.cortex-widget__thread-delete{opacity:1}.cortex-widget__thread-delete:hover{background:#e2e8f0}.cortex-widget__thread-delete--active:hover{background:#475569}.cortex-widget__thread-arrow{flex-shrink:0;transition:color .15s;color:#cbd5e1}[dir=rtl] .cortex-widget__thread-arrow{transform:rotate(180deg)}.cortex-widget__thread-item:hover>.cortex-widget__thread-arrow{color:#94a3b8}.cortex-widget__thread-arrow--active{color:#64748b}.cortex-widget__threads-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:4rem 0;text-align:center}.cortex-widget__threads-empty-icon{width:2.5rem;height:2.5rem;border-radius:.5rem;background:#e2e8f0;display:flex;align-items:center;justify-content:center;margin-bottom:.75rem}.cortex-widget__threads-empty-svg{color:#94a3b8}.cortex-widget__threads-empty-title{font-size:.8125rem;color:#94a3b8;font-weight:500;margin:0}.cortex-widget__threads-empty-subtitle{font-size:.6875rem;color:#a5afbd;margin-top:.25rem;margin-bottom:0}.cortex-widget__chat-header{flex-shrink:0;height:3rem;padding:0 1rem;display:flex;align-items:center;gap:.75rem;border-bottom:1px solid #e2e8f0;background:#fff}.cortex-widget__back-btn{flex-shrink:0;width:2rem;height:2rem;border-radius:.375rem;display:flex;align-items:center;justify-content:center;color:#94a3b8;background:transparent;border:0;cursor:pointer;transition:color .15s,background-color .15s}.cortex-widget__back-btn:hover{color:#475569;background:#f1f5f9}[dir=rtl] .cortex-widget__back-icon{transform:rotate(180deg)}.cortex-widget__chat-title-wrap{min-width:0;flex:1}.cortex-widget__chat-title{font-size:.8125rem;font-weight:500;color:#334155;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin:0}.cortex-widget__debug-btn{flex-shrink:0;font-size:.6875rem;font-weight:500;padding:.25rem .625rem;border-radius:.375rem;border:0;cursor:pointer;transition:background-color .15s}.cortex-widget__debug-btn--on{background:#fef3c7;color:#d97706}.cortex-widget__debug-btn--on:hover{background:#fde68a}.cortex-widget__debug-btn--off{background:#f1f5f9;color:#94a3b8}.cortex-widget__debug-btn--off:hover{background:#e2e8f0}.cortex-widget__messages-skeleton{flex:1;overflow:hidden;padding:1rem;display:flex;flex-direction:column;gap:.5rem}.cortex-widget__msg-skel{width:100%;display:flex;flex-direction:column}.cortex-widget__msg-skel--user{align-items:flex-end}.cortex-widget__msg-skel--assistant{align-items:flex-start}.cortex-widget__msg-skel-bubble{max-width:80%;padding:1rem;border-radius:1rem;border:1px solid #e2e8f0;display:flex;flex-direction:column;gap:.5rem}.cortex-widget__msg-skel-bubble--user{background:#f8fafc;border-bottom-right-radius:0}.cortex-widget__msg-skel-bubble--assistant{background:#f1f5f9;border-bottom-left-radius:0}.cortex-widget__msg-skel-line{height:.75rem}.cortex-widget__messages{flex:1;overflow:hidden}@keyframes cortex-working-slide-in{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}@keyframes cortex-dot-wave{0%,60%,to{transform:translateY(0) scale(1);opacity:.45}30%{transform:translateY(-5px) scale(1.2);opacity:1}}@keyframes cortex-working-shimmer{0%{background-position:-200% center}to{background-position:200% center}}.cortex-widget__working{flex-shrink:0;padding:.5rem 1rem;display:flex;align-items:center;gap:.5rem;animation:cortex-working-slide-in .25s ease-out both}.cortex-widget__working-dots{display:flex;align-items:center;gap:4px}.cortex-working-dot{display:block;width:6px;height:6px;border-radius:9999px;background:#22c55e;animation:cortex-dot-wave 1.4s ease-in-out infinite}.cortex-working-dot:nth-child(2){animation-delay:.15s}.cortex-working-dot:nth-child(3){animation-delay:.3s}.cortex-widget__working-text{font-size:.75rem;font-weight:500;letter-spacing:.01em;color:#16a34a}.cortex-widget__input-area{flex-shrink:0;padding:.75rem;background:#fff;border-top:1px solid #e2e8f0}.cortex-widget__input-box{display:flex;align-items:flex-end;gap:.5rem;border-radius:.75rem;border:1px solid #e2e8f0;padding:.375rem;transition:border-color .15s,background-color .15s}.cortex-widget__input-box--disabled{background:#f1f5f9}.cortex-widget__input-box--enabled{background:#f8fafc}.cortex-widget__input-box--enabled:focus-within{border-color:#cbd5e1;background:#fff}.cortex-widget__textarea{flex:1;background:transparent;resize:none;border:0;outline:none;font-size:.8125rem;padding:.375rem .5rem;min-height:28px;max-height:120px;line-height:1.375;color:#334155}.cortex-widget__textarea::placeholder{color:#a5afbd}.cortex-widget__textarea--disabled{color:#94a3b8;cursor:not-allowed}.cortex-widget__textarea:disabled{cursor:not-allowed;border:0}@keyframes cortex-stop-pulse-ring{0%{opacity:.45;transform:scale(1)}50%{opacity:.15;transform:scale(1.12)}to{opacity:.45;transform:scale(1)}}@keyframes cortex-stop-fade-in{0%{opacity:0;transform:scale(.7)}to{opacity:1;transform:scale(1)}}.cortex-stop-btn{flex-shrink:0;width:2rem;height:2rem;border-radius:.5rem;display:flex;align-items:center;justify-content:center;cursor:pointer;position:relative;background:#e11d48;color:#fff;border:0;animation:cortex-stop-fade-in .2s ease-out both;transition:background .15s ease}.cortex-stop-btn:hover{background:#be123c}.cortex-stop-btn:active{transform:scale(.92)}.cortex-stop-btn__ring{position:absolute;inset:0;border-radius:.5rem;background:#e11d48;animation:cortex-stop-pulse-ring 2s ease-in-out infinite;pointer-events:none}.cortex-stop-btn__icon{position:relative;z-index:1}.cortex-widget__send-btn{flex-shrink:0;width:2rem;height:2rem;border-radius:.5rem;display:flex;align-items:center;justify-content:center;border:0;transition:background-color .15s}.cortex-widget__send-btn--empty{background:#e2e8f0;color:#94a3b8}.cortex-widget__send-btn--ready{background:#1e293b;color:#fff;cursor:pointer}.cortex-widget__send-btn--ready:hover{background:#334155}[dir=rtl] .cortex-widget__send-icon{transform:rotate(180deg)}\n"] }]
1683
2008
  }], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: true }] }], text: [{ type: i0.Input, args: [{ isSignal: true, alias: "text", required: false }] }, { type: i0.Output, args: ["textChange"] }] } });
1684
2009
 
1685
2010
  /*