@m6d/cortex-angular 0.13.0 → 0.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,14 +2,20 @@
2
2
 
3
3
  import * as i0 from '@angular/core';
4
4
  import { Injector, OnInit, Signal, TemplateRef, Type } from '@angular/core';
5
- import { ToolCallPart, UIMessage } from '@tanstack/ai';
6
- import { Observable } from 'rxjs';
5
+ import { MessagePart, ToolCallPart, UIMessage } from '@tanstack/ai';
7
6
 
8
7
  declare const LOCALES: readonly [
9
8
  "en",
10
9
  "ar"
11
10
  ];
12
11
  export type Locale = (typeof LOCALES)[number];
12
+ declare const MESSAGE_ROLES: readonly [
13
+ "system",
14
+ "user",
15
+ "assistant",
16
+ "trigger"
17
+ ];
18
+ export type MessageRole = (typeof MESSAGE_ROLES)[number];
13
19
  declare const ATTACHMENT_STATUSES: readonly [
14
20
  "pending",
15
21
  "described",
@@ -55,18 +61,54 @@ export type ThreadSummary = {
55
61
  export type CreateThreadRequest = {
56
62
  variables?: Record<string, string | number | boolean>;
57
63
  };
64
+ export type TokenUsage = {
65
+ input: {
66
+ noCache: number;
67
+ cacheRead: number;
68
+ cacheWrite: number;
69
+ total: number;
70
+ };
71
+ output: {
72
+ reasoning: number;
73
+ text: number;
74
+ total: number;
75
+ };
76
+ total: number;
77
+ };
58
78
  /**
59
79
  * What Cortex offers this agent's clients, fetched once at widget startup.
60
80
  * The widget hides UI for anything absent; Cortex enforces each.
61
81
  */
62
82
  export type AgentCapabilities = {
63
83
  attachments: boolean;
64
- /** False when the agent's `message` trigger is off: the widget hides its composer. */
84
+ /**
85
+ * False when this caller may not send to the chat: the agent's `message`
86
+ * trigger is off, or the caller only reads (`readOnly`). The widget hides
87
+ * its composer and answers no tool call.
88
+ */
65
89
  messages: boolean;
90
+ /** True when the caller only reads, as an operator inspecting a user's thread does. */
91
+ readOnly: boolean;
66
92
  /** Prompt chips on the blank-chat landing per locale; clicking one sends its `prompt` as the first message. */
67
93
  suggestions: Suggestions;
68
94
  /** Headline of the blank-chat landing per locale; "" falls back to the widget's built-in copy. */
69
95
  greeting: Greeting;
96
+ /**
97
+ * Whether this caller gets the debug view: tool inputs and outputs, reasoning,
98
+ * model calls. Cortex sends anyone else only what the widget's normal UI draws.
99
+ */
100
+ debug: boolean;
101
+ };
102
+ export type MessageMetadata = {
103
+ /** ISO time Cortex stored the message; stamped from the row when a transcript is served. */
104
+ createdAt?: string;
105
+ modelId?: string;
106
+ providerMetadata?: unknown;
107
+ isAborted?: boolean;
108
+ tokenUsage?: TokenUsage;
109
+ attachments?: AttachmentSummary[];
110
+ /** Set on `trigger` messages: the firing that wrote them. */
111
+ trigger?: TriggerFiringSummary;
70
112
  };
71
113
  /**
72
114
  * One landing-page chip: the widget shows `title` and sends `prompt` as the
@@ -79,6 +121,52 @@ export type Suggestion = {
79
121
  /** The manifest's suggestion and greeting schemas are built from these. */
80
122
  export type Suggestions = Record<Locale, Suggestion[]>;
81
123
  export type Greeting = Record<Locale, string>;
124
+ export type TriggerFiringSummary = {
125
+ name: string;
126
+ firingId: string;
127
+ firedAt: string;
128
+ payload: unknown;
129
+ };
130
+ /**
131
+ * A stored message as it is persisted and served: the SDK's parts plus the
132
+ * envelope Cortex derives for the UIs, carried in the SDK message's own
133
+ * `metadata` bag so it travels with the message over the stream and the
134
+ * transcript alike.
135
+ *
136
+ * `TPart` stays generic so this file keeps its zero dependencies — both
137
+ * sides substitute the SDK's `MessagePart`.
138
+ */
139
+ export type CortexMessage<TPart = unknown> = {
140
+ id: string;
141
+ /** `trigger` rows carry a firing's instructions; the UIs render them as an event, not a bubble. */
142
+ role: MessageRole;
143
+ parts: TPart[];
144
+ metadata?: MessageMetadata;
145
+ };
146
+ declare const TRIGGER_DROP_REASONS: readonly [
147
+ "busy",
148
+ "approval_pending",
149
+ "budget",
150
+ "rate_limited"
151
+ ];
152
+ export type TriggerDropReason = (typeof TRIGGER_DROP_REASONS)[number];
153
+ /**
154
+ * Body of a `POST /chat` the thread did not take: 409 while a run holds the
155
+ * thread or a call on it waits for a decision, or when the answers it
156
+ * carried fit no open call, were already applied, or answer a call whose
157
+ * origin is out of reach (`no_turn`); 429 once the agent's request bucket is
158
+ * spent, with `Retry-After`.
159
+ */
160
+ export type ChatDropped = {
161
+ outcome: "dropped";
162
+ reason: Exclude<TriggerDropReason, "budget"> | "no_turn";
163
+ };
164
+ /**
165
+ * The drop a widget tells its user about by name: a call on the thread waits
166
+ * for approval, so the message goes back to the composer. Any other drop
167
+ * shows as a failed turn.
168
+ */
169
+ export type SendRefusal = Extract<ChatDropped["reason"], "approval_pending">;
82
170
  export type CortexHeaders = Record<string, string>;
83
171
  /**
84
172
  * How the widget reaches Cortex. `baseUrl` may be a thunk so a consumer with
@@ -165,7 +253,11 @@ export type CortexConfig = {
165
253
  * or a map keyed by locale (`{ en: 'Support', ar: 'الدعم' }`).
166
254
  */
167
255
  agentName?: Localized<string>;
168
- showDebugButton?: boolean;
256
+ /**
257
+ * A thread to open when the widget mounts, by id, once the thread list holds
258
+ * it: a deep link into one conversation, such as the console's inspector.
259
+ */
260
+ thread?: string;
169
261
  /**
170
262
  * Render embedded tool pages served from this page's own origin with their
171
263
  * full identity — which, same-origin, means no effective sandbox at all: such
@@ -193,12 +285,13 @@ export type CortexHeaderContext = {
193
285
  /** How many conversations the history lists; undefined while the first load is out. */
194
286
  threadCount: number | undefined;
195
287
  isWorking: boolean;
196
- /** Whether the consumer enabled the debug switch, and whether it is on. */
288
+ /** Whether Cortex offers this caller the debug view, and whether it is on. */
197
289
  debug: {
198
290
  shown: boolean;
199
291
  on: boolean;
200
292
  };
201
- newChat: () => void;
293
+ /** Absent until the handshake says the caller may write; an operator inspecting a thread only reads. */
294
+ newChat?: () => void;
202
295
  /** Shows the history: the history screen, or in full mode the sidebar where it is hidden. */
203
296
  openHistory: () => void;
204
297
  /** Returns to the open chat from wherever `openHistory` went. */
@@ -236,8 +329,9 @@ export type CortexThreadListContext = {
236
329
  /** The open thread's id; undefined on a new chat. */
237
330
  selectedThreadId: string | undefined;
238
331
  openThread: (thread: ThreadSummary) => void;
239
- deleteThread: (threadId: string) => void;
240
- newChat: () => void;
332
+ /** Both absent until the handshake says the caller may write; an operator inspecting a thread only reads. */
333
+ deleteThread?: (threadId: string) => void;
334
+ newChat?: () => void;
241
335
  };
242
336
  /** Each part of the widget a consumer can draw itself, with the context it receives. */
243
337
  export type CortexSlotContexts<View> = {
@@ -245,8 +339,11 @@ export type CortexSlotContexts<View> = {
245
339
  landing: LandingContext<View>;
246
340
  threadList: CortexThreadListContext;
247
341
  };
248
- /** Why Cortex dropped a message instead of running it: a call on the thread waits for approval. */
249
- export type SendRefusal = "approval_pending";
342
+ /**
343
+ * Why Cortex left a read unanswered: it could not be reached (or failed),
344
+ * it refused the caller's sign-in (401), or it serves no such agent (404).
345
+ */
346
+ export type Unanswered = "unreachable" | "refused" | "missing";
250
347
  /** Why the composer refused a file before uploading it: the attachment policy's reason, or one file too many. */
251
348
  export type AttachmentRefusal = Exclude<ReturnType<typeof checkAttachmentPolicy>, "ok"> | "count";
252
349
  export type QueuedAttachment = {
@@ -259,21 +356,86 @@ export type QueuedAttachment = {
259
356
  attachmentId?: string;
260
357
  summary?: AttachmentSummary;
261
358
  };
262
- /**
263
- * Why Cortex left a read unanswered: it could not be reached (or failed),
264
- * it refused the caller's sign-in (401), or it serves no such agent (404).
265
- */
266
- export type Unanswered = "unreachable" | "refused" | "missing";
267
359
  /**
268
360
  * A turn shown as failed, with Cortex's reason when it gave one (a message
269
361
  * that never got out has none). The reason may name the model provider's
270
- * answer, so a widget shows it only where its debug view is offered. A
271
- * message Cortex refused names why instead.
362
+ * answer, so the widget's state keeps it only where Cortex sends the debug
363
+ * view. A message Cortex refused names why instead.
272
364
  */
273
365
  export type TurnFailure = {
274
366
  reason: string | undefined;
275
367
  refusal?: SendRefusal;
276
368
  };
369
+ /** The open conversation, as a widget draws it. */
370
+ export type ChatSessionState = {
371
+ /** Each carries Cortex's envelope (usage, model id, attachments, time) in its `metadata`. */
372
+ messages: UIMessage[];
373
+ isAgentWorking: boolean;
374
+ isLoadingMessages: boolean;
375
+ /**
376
+ * A call is owed an answer. Only while no stream is open: mid-turn an open
377
+ * call is a tool Cortex is running. Read off the transcript, so the composer
378
+ * comes back the moment an answer settles its call, long before the
379
+ * continuation it sends ends.
380
+ */
381
+ hasPendingToolCalls: boolean;
382
+ /** A call waits for the user to approve or deny it: no message may go out until it is decided. */
383
+ awaitsApproval: boolean;
384
+ /** The last turn failed: Cortex said its run failed, or the message never got out. */
385
+ turnFailure: TurnFailure | undefined;
386
+ };
387
+ /** Everything a widget draws, the same for every framework. */
388
+ export type CortexWidgetState = {
389
+ /** Newest first; undefined until the first list read lands or Cortex refuses it. */
390
+ threads: ThreadSummary[] | undefined;
391
+ /** The open thread, as the list has it now; undefined on a blank chat. */
392
+ selected: ThreadSummary | undefined;
393
+ /**
394
+ * The open thread's conversation; blank while none is open. A failed
395
+ * turn's reason may name the model provider's answer, so it is here only
396
+ * where Cortex sends this caller the debug view.
397
+ */
398
+ session: ChatSessionState;
399
+ /** What Cortex offers this agent's clients; undefined until the handshake answers. */
400
+ capabilities: AgentCapabilities | undefined;
401
+ /** Why the handshake has not answered yet, once a try has failed. */
402
+ unanswered: Unanswered | undefined;
403
+ /** The files held for the next message. */
404
+ attachments: QueuedAttachment[];
405
+ /** A thread is being created for the message on its way out; the composer waits for it. */
406
+ creating: boolean;
407
+ screen: "chat" | "threads";
408
+ /** Full mode's history sidebar, slid in on a narrow viewport. */
409
+ sidebarOpen: boolean;
410
+ /** The reader's debug toggle; on only while the handshake offers the debug view. */
411
+ debugMode: boolean;
412
+ /**
413
+ * What the header, landing and history are drawn from: one object until
414
+ * one of its fields changes, which a streamed chunk does only as the turn
415
+ * starts and stops working, so a framework redraws them only then.
416
+ */
417
+ parts: Pick<CortexWidgetState, "threads" | "selected" | "capabilities" | "debugMode"> & {
418
+ isWorking: boolean;
419
+ };
420
+ };
421
+ export type CortexAngularConfig = CortexConfig & {
422
+ toolComponents?: Record<string, Type<CortexToolComponentInputs>>;
423
+ injector?: Injector;
424
+ };
425
+ /** The landing's context, its composer a template to place with `ngTemplateOutlet`. */
426
+ export type CortexLandingContext = LandingContext<TemplateRef<unknown>>;
427
+ /** Each part of the widget a consumer can draw itself, with the context it receives. */
428
+ export type CortexAngularSlotContexts = CortexSlotContexts<TemplateRef<unknown>>;
429
+ declare const LOCALES$1: readonly [
430
+ "en",
431
+ "ar"
432
+ ];
433
+ type Locale$1 = (typeof LOCALES$1)[number];
434
+ declare const TOOL_SURFACES: readonly [
435
+ "inline",
436
+ "modal"
437
+ ];
438
+ export type ToolSurface = (typeof TOOL_SURFACES)[number];
277
439
  declare const ATTACHMENT_STATUSES$1: readonly [
278
440
  "pending",
279
441
  "described",
@@ -295,228 +457,211 @@ export type AttachmentSummary$1 = {
295
457
  origin: AttachmentOrigin$1;
296
458
  description: string | null;
297
459
  };
298
- export type CortexAngularConfig = CortexConfig & {
299
- toolComponents?: Record<string, Type<CortexToolComponentInputs>>;
300
- injector?: Injector;
460
+ /**
461
+ * Response of `POST /chat/:threadId/abort`. `aborted: false` means there was no
462
+ * live run to abort — the turn had already committed — so the caller must not
463
+ * present the turn as aborted and should read the settled state back instead.
464
+ */
465
+ export type AbortRunResult$1 = {
466
+ aborted: boolean;
301
467
  };
302
- /** The landing's context, its composer a template to place with `ngTemplateOutlet`. */
303
- export type CortexLandingContext = LandingContext<TemplateRef<unknown>>;
304
- /** Each part of the widget a consumer can draw itself, with the context it receives. */
305
- export type CortexAngularSlotContexts = CortexSlotContexts<TemplateRef<unknown>>;
306
- declare class AttachmentQueueService {
307
- readonly items: import("@angular/core").WritableSignal<QueuedAttachment[]>;
308
- private readonly flags;
309
- readonly uploading: import("@angular/core").Signal<boolean>;
310
- readonly busy: import("@angular/core").Signal<boolean>;
311
- readonly hasReady: import("@angular/core").Signal<boolean>;
312
- private readonly chatService;
313
- readonly store: {
314
- getState: () => QueuedAttachment[];
315
- subscribe: (listener: () => void) => () => void;
316
- accept: (files: File[]) => void;
317
- remove: (localId: string) => void;
318
- clear: (threadId: string | undefined) => void;
319
- consumeReady: () => {
320
- status: "ready";
321
- summary: AttachmentSummary$1;
322
- localId: string;
323
- filename: string;
324
- refusal?: "type" | "size" | "name" | "count";
325
- threadId?: string;
326
- attachmentId?: string;
327
- }[];
328
- restoreConsumed: (threadId: string | undefined) => void;
329
- discardConsumed: () => void;
468
+ type TokenUsage$1 = {
469
+ input: {
470
+ noCache: number;
471
+ cacheRead: number;
472
+ cacheWrite: number;
473
+ total: number;
330
474
  };
331
- constructor();
332
- static ɵfac: i0.ɵɵFactoryDeclaration<AttachmentQueueService, never>;
333
- static ɵprov: i0.ɵɵInjectableDeclaration<any>;
334
- }
335
- declare class CortexChatService {
475
+ output: {
476
+ reasoning: number;
477
+ text: number;
478
+ total: number;
479
+ };
480
+ total: number;
481
+ };
482
+ /**
483
+ * What Cortex offers this agent's clients, fetched once at widget startup.
484
+ * The widget hides UI for anything absent; Cortex enforces each.
485
+ */
486
+ export type AgentCapabilities$1 = {
487
+ attachments: boolean;
336
488
  /**
337
- * Selection is the Thread handed to `selectThread`, resolved against the live
338
- * list: the row there receives the title and isRunning updates Cortex
339
- * pushes, so the selection follows them without hand-syncing. The snapshot
340
- * only answers for a thread the list has not caught up with yet.
489
+ * False when this caller may not send to the chat: the agent's `message`
490
+ * trigger is off, or the caller only reads (`readOnly`). The widget hides
491
+ * its composer and answers no tool call.
341
492
  */
342
- readonly selectedThread: import("@angular/core").Signal<ThreadSummary | undefined>;
343
- private readonly chat;
344
- /** The open conversation's transcript; empty while nothing is selected. */
345
- readonly messages: import("@angular/core").Signal<import("@tanstack/ai-client").UIMessage<readonly import("@tanstack/ai").AnyClientTool[], any>[]>;
346
- readonly isLoadingMessages: import("@angular/core").WritableSignal<boolean>;
347
- readonly isAgentWorking: import("@angular/core").Signal<boolean>;
493
+ messages: boolean;
494
+ /** True when the caller only reads, as an operator inspecting a user's thread does. */
495
+ readOnly: boolean;
496
+ /** Prompt chips on the blank-chat landing per locale; clicking one sends its `prompt` as the first message. */
497
+ suggestions: Suggestions$1;
498
+ /** Headline of the blank-chat landing per locale; "" falls back to the widget's built-in copy. */
499
+ greeting: Greeting$1;
348
500
  /**
349
- * Derived, never hand-synced: a call only counts as owed while the stream is
350
- * idle — mid-turn an unsettled call is just a tool Cortex is executing. Reading
351
- * straight from the SDK's signals is what brings the composer back the
352
- * instant `addToolResult` settles the call part — the SDK's delivery promise
353
- * only resolves once the continuation turn ends, far too late to gate UI on.
501
+ * Whether this caller gets the debug view: tool inputs and outputs, reasoning,
502
+ * model calls. Cortex sends anyone else only what the widget's normal UI draws.
354
503
  */
355
- readonly hasPendingToolCalls: import("@angular/core").Signal<boolean>;
356
- /** A call waits for the user to approve or deny it: no message may go out until it is decided. */
357
- readonly awaitsApproval: import("@angular/core").Signal<boolean>;
358
- /** The last turn failed: Cortex said its run failed, or the message never got out. */
359
- readonly turnFailure: import("@angular/core").WritableSignal<TurnFailure | undefined>;
360
- /** The text of a message Cortex refused, handed back to the composer until a message goes out. */
361
- readonly returnedDraft: import("@angular/core").WritableSignal<string | undefined>;
362
- /** What Cortex offers this agent's clients; undefined until the handshake answers. */
363
- readonly capabilities: import("@angular/core").WritableSignal<AgentCapabilities | undefined>;
364
- /** Why the handshake has not answered yet, once a try has failed. */
365
- readonly unanswered: import("@angular/core").WritableSignal<Unanswered | undefined>;
366
- private readonly events;
367
- private readonly selectedThreadSnapshot;
368
- private readonly config;
369
- private readonly api;
370
- private readonly threadService;
371
- private readonly wsService;
372
- private readonly destroyRef;
373
- private readonly environmentInjector;
374
- /** Owns the current thread's chat client; destroying it stops and disposes it. */
375
- private chatInjector;
376
- /** The turn in flight on the current chat client; replaced with it on every mount. */
377
- private lifecycle;
378
- private pendingThreadCreation;
379
- private refreshing;
380
- private stopCapabilities;
504
+ debug: boolean;
505
+ };
506
+ type Suggestion$1 = {
507
+ title: string;
508
+ prompt: string;
509
+ };
510
+ type Suggestions$1 = Record<Locale$1, Suggestion$1[]>;
511
+ type Greeting$1 = Record<Locale$1, string>;
512
+ /**
513
+ * Response of `POST /chat/:threadId/tools/:toolCallId/initiate` for a pending
514
+ * call stamped with an embed. The payload is for the widget only; it never
515
+ * reaches the LLM.
516
+ */
517
+ export type ClientToolInitiateResult$1 = {
518
+ embedUrl: string;
519
+ surface: ToolSurface;
520
+ embedOrigin: string;
521
+ };
522
+ /**
523
+ * One model call of the turn that wrote a message, raw, in the order the
524
+ * turn ran them: `GET /threads/:threadId/messages/:messageId/llm-requests`
525
+ * answers a list, for the request inspector.
526
+ */
527
+ export type LlmRequest$1 = {
528
+ id: string;
529
+ prompt: string;
530
+ output: string | null;
531
+ tokenUsage: TokenUsage$1 | null;
532
+ };
533
+ /** A message as Cortex serves it: SDK parts plus Cortex's metadata envelope. */
534
+ export type CortexChatMessage = CortexMessage<MessagePart>;
535
+ declare class CortexChatService {
536
+ readonly widget: {
537
+ api: {
538
+ getCapabilities(): Promise<AgentCapabilities$1>;
539
+ listThreads(): Promise<ThreadSummary[]>;
540
+ createThread(): Promise<ThreadSummary>;
541
+ deleteThread(threadId: string): Promise<void>;
542
+ listMessages(threadId: string): Promise<CortexChatMessage[]>;
543
+ listLlmRequests(threadId: string, messageId: string): Promise<LlmRequest$1[]>;
544
+ abortStream(threadId: string): Promise<AbortRunResult$1>;
545
+ initiateToolCall(threadId: string, toolCallId: string): Promise<ClientToolInitiateResult$1>;
546
+ uploadAttachment(threadId: string, file: File): Promise<AttachmentSummary$1>;
547
+ deleteAttachment(id: string): Promise<void>;
548
+ downloadAttachment(id: string): Promise<{
549
+ blob: Blob;
550
+ name: string;
551
+ }>;
552
+ resolveHeaders: () => Promise<{
553
+ [x: string]: string;
554
+ }>;
555
+ resolveUrl: (path: string) => string;
556
+ };
557
+ getState: () => CortexWidgetState;
558
+ getDraft: () => string;
559
+ subscribe: (listener: () => void) => () => void;
560
+ start: () => void;
561
+ stop: () => void;
562
+ setDraft: (text: string) => void;
563
+ submit: (text: string) => Promise<{
564
+ readonly sent: false;
565
+ readonly text: string;
566
+ } | {
567
+ readonly sent: true;
568
+ }>;
569
+ sendDraft: (launch: (text: string) => void) => void;
570
+ abort: () => Promise<void>;
571
+ addToolResult: (toolCallId: string, toolName: string, output: unknown) => Promise<void>;
572
+ respondToApproval: (call: import("@tanstack/ai").ToolCallPart, approved: boolean) => Promise<void>;
573
+ openThread: (thread: ThreadSummary) => void;
574
+ newChat: () => void;
575
+ deleteThread: (threadId: string) => Promise<void>;
576
+ attachFiles: (files: File[]) => void;
577
+ removeAttachment: (localId: string) => void;
578
+ openHistory: () => void;
579
+ closeHistory: () => void;
580
+ toggleDebug: () => void;
581
+ };
582
+ private readonly snapshot;
583
+ private readonly text;
584
+ readonly state: import("@angular/core").Signal<CortexWidgetState>;
585
+ readonly draft: import("@angular/core").Signal<string>;
586
+ readonly selectedThread: import("@angular/core").Signal<ThreadSummary | undefined>;
587
+ readonly messages: import("@angular/core").Signal<import("@tanstack/ai").UIMessage<unknown>[]>;
588
+ readonly isAgentWorking: import("@angular/core").Signal<boolean>;
589
+ readonly debugMode: import("@angular/core").Signal<boolean>;
590
+ readonly turnFailure: import("@angular/core").Signal<TurnFailure | undefined>;
591
+ /** What the header, landing and history are drawn from: a streamed chunk leaves it as it was. */
592
+ readonly parts: import("@angular/core").Signal<Pick<CortexWidgetState, "threads" | "capabilities" | "debugMode" | "selected"> & {
593
+ isWorking: boolean;
594
+ }>;
381
595
  constructor();
382
- /**
383
- * Kicked off by the widget once its `config` input is bound. This cannot happen in
384
- * the constructor: the widget builds its children during its creation pass, which
385
- * Angular runs before it binds inputs, so the transport is not knowable yet.
386
- */
387
- start(): void;
388
- /**
389
- * Capability-gated controls stay hidden until the handshake answers, so it
390
- * is asked until it does, and afresh after every reconnect: the old answer
391
- * may be stale (a trigger toggled while the socket was down), so it is
392
- * forgotten first. Why it has not answered is shown until an answer arrives.
393
- */
394
- private loadCapabilities;
395
- get events$(): Observable<"onError" | "onFinish" | "onThreadSelected" | "onSend">;
396
- selectThread(thread: ThreadSummary, options?: {
397
- skipLoadingMessages?: boolean;
398
- }): Observable<ThreadSummary>;
399
- deselectThread(): void;
400
- /**
401
- * The id of the thread the next message belongs to, creating it when the widget is
402
- * still on a blank chat.
403
- */
404
- ensureThread(): Observable<string>;
405
- send(prompt: string, attachments?: AttachmentSummary[]): Observable<void>;
406
- /** Answers a tool call on behalf of a tool component or the client tool
407
- * embed. Returns the delivery, which fails when the answer did not reach
408
- * Cortex, so the caller can ask for it again instead of stranding the call. */
409
- addToolResult(toolCallId: string, toolName: string, output: unknown): Promise<void>;
410
- /** The user's decision on a call the run parked on; the run resumes once delivered. */
411
- respondToApproval(approvalId: string, approved: boolean): Promise<void>;
412
- abort(): Promise<void>;
413
- deleteThread(threadId: string): Observable<void>;
414
- /**
415
- * Points the widget at a thread with a chat client of its own. Cortex owns
416
- * the transcript: on mount the client asks it for the transcript and for
417
- * whatever run is still generating, so selecting a thread, reloading the page
418
- * and a second tab all re-attach through one path.
419
- */
420
- private mountChat;
421
- /**
422
- * Re-mounts the current thread's chat so its hydration re-reads the transcript
423
- * and re-attaches to whatever run is live now. This is how a run another tab
424
- * started, and a websocket that dropped and came back, land in this widget.
425
- * A caller passes the thread when it holds fresher state than the list.
426
- */
427
- private reattach;
428
- private createConnection;
429
- private refreshMessages;
430
- private readBackMessages;
431
- private subscribeToWsEvents;
432
- /**
433
- * Only what these events mean for the open conversation — their list-shaped
434
- * side is CortexThreadService's, which absorbs them on its own subscription.
435
- */
436
- private onWsEvent;
437
- private subscribeToWsConnections;
438
596
  static ɵfac: i0.ɵɵFactoryDeclaration<CortexChatService, never>;
439
597
  static ɵprov: i0.ɵɵInjectableDeclaration<any>;
440
598
  }
441
599
  /** The chat widget: the thread list, the open conversation and its composer, for the agent `config` points at. */
442
600
  export declare class CortexChatWidgetComponent implements OnInit {
443
601
  readonly config: import("@angular/core").InputSignal<CortexAngularConfig>;
444
- protected readonly debugMode: import("@angular/core").WritableSignal<boolean>;
445
- protected readonly screen: import("@angular/core").WritableSignal<"chat" | "threads">;
446
- protected readonly sidebarOpen: import("@angular/core").WritableSignal<boolean>;
447
- protected readonly viewMode: import("@angular/core").Signal<CortexViewMode>;
448
- private readonly composer;
602
+ protected readonly direction: import("@angular/core").Signal<"ltr" | "rtl">;
449
603
  private readonly landingComposer;
450
604
  /** The consumer's own parts by slot; each replaces the widget's default and gets the same context. */
451
605
  private readonly slotDirectives;
452
606
  protected readonly slots: import("@angular/core").Signal<Map<keyof CortexAngularSlotContexts, TemplateRef<{
453
607
  $implicit: CortexHeaderContext | CortexThreadListContext | LandingContext<TemplateRef<unknown>>;
454
608
  }>>>;
455
- /** Why the handshake has not answered, worded for the composer's place. */
456
- protected readonly unansweredNotice: import("@angular/core").Signal<"translate_access_refused" | "translate_agent_unreachable" | "translate_agent_missing" | undefined>;
457
- protected readonly chatHeader: import("@angular/core").Signal<{
458
- screen: "chat" | "threads";
459
- viewMode: CortexViewMode;
460
- title: string | null;
461
- agentName: string | undefined;
462
- threadCount: number | undefined;
463
- isWorking: boolean;
464
- debug: {
465
- shown: boolean;
466
- on: boolean;
609
+ protected chat: CortexChatService;
610
+ protected readonly parts: import("@angular/core").Signal<{
611
+ chatHeader: {
612
+ screen: "chat" | "threads";
613
+ viewMode: CortexViewMode;
614
+ title: string | null;
615
+ agentName: string | undefined;
616
+ threadCount: number | undefined;
617
+ isWorking: boolean;
618
+ debug: {
619
+ shown: boolean;
620
+ on: boolean;
621
+ };
622
+ newChat: (() => void) | undefined;
623
+ openHistory: () => void;
624
+ closeHistory: () => void;
625
+ toggleDebug: () => void;
467
626
  };
468
- newChat: () => void;
469
- openHistory: () => void;
470
- closeHistory: () => void;
471
- toggleDebug: () => void;
472
- }>;
473
- protected readonly threadsHeader: import("@angular/core").Signal<{
474
- screen: "chat" | "threads";
475
- viewMode: CortexViewMode;
476
- title: string | null;
477
- agentName: string | undefined;
478
- threadCount: number | undefined;
479
- isWorking: boolean;
480
- debug: {
481
- shown: boolean;
482
- on: boolean;
627
+ threadsHeader: {
628
+ screen: "chat" | "threads";
629
+ viewMode: CortexViewMode;
630
+ title: string | null;
631
+ agentName: string | undefined;
632
+ threadCount: number | undefined;
633
+ isWorking: boolean;
634
+ debug: {
635
+ shown: boolean;
636
+ on: boolean;
637
+ };
638
+ newChat: (() => void) | undefined;
639
+ openHistory: () => void;
640
+ closeHistory: () => void;
641
+ toggleDebug: () => void;
642
+ };
643
+ landing: {
644
+ threads: ThreadSummary[] | undefined;
645
+ composer: TemplateRef<unknown>;
646
+ openThread: (thread: ThreadSummary) => void;
647
+ openHistory: () => void;
648
+ greeting: string;
649
+ suggestions: Suggestion[];
650
+ send: (prompt: string) => void;
651
+ };
652
+ threadList: {
653
+ newChat?: (() => void) | undefined;
654
+ deleteThread?: ((threadId: string) => undefined) | undefined;
655
+ threads: ThreadSummary[] | undefined;
656
+ selectedThreadId: string | undefined;
657
+ openThread: (thread: ThreadSummary) => void;
483
658
  };
484
- newChat: () => void;
485
- openHistory: () => void;
486
- closeHistory: () => void;
487
- toggleDebug: () => void;
488
- }>;
489
- protected readonly landing: import("@angular/core").Signal<{
490
- threads: ThreadSummary[] | undefined;
491
- composer: TemplateRef<unknown>;
492
- openThread: (thread: ThreadSummary) => void;
493
- openHistory: () => void;
494
- greeting: string;
495
- suggestions: Suggestion[];
496
- send: (prompt: string) => void;
497
- }>;
498
- protected readonly threadList: import("@angular/core").Signal<{
499
- threads: ThreadSummary[] | undefined;
500
- selectedThreadId: string | undefined;
501
- openThread: (thread: ThreadSummary) => void;
502
- deleteThread: (threadId: string) => import("rxjs").Subscription;
503
- newChat: () => void;
504
659
  }>;
505
- protected chatService: CortexChatService;
506
- protected queue: AttachmentQueueService;
507
- private threadService;
660
+ protected readonly composerSlot: import("@angular/core").Signal<"translate_access_refused" | "translate_agent_unreachable" | "translate_agent_missing" | "composer" | "translate_read_only" | "translate_messages_disabled" | undefined>;
508
661
  private readonly injector;
509
- private readonly destroyRef;
510
662
  ngOnInit(): void;
511
- private headerContext;
512
- protected closeSidebar(): void;
513
- private toggleDebugMode;
514
- private selectThread;
515
- private openHistory;
516
- private closeHistory;
517
663
  protected onWidgetDragOver(event: DragEvent): void;
518
664
  protected onWidgetDrop(event: DragEvent): void;
519
- private newChat;
520
665
  static ɵfac: i0.ɵɵFactoryDeclaration<CortexChatWidgetComponent, never>;
521
666
  static ɵcmp: i0.ɵɵComponentDeclaration<CortexChatWidgetComponent, "cortex-chat-widget", never, {
522
667
  "config": {