@m6d/cortex-angular 0.7.0 → 0.9.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@m6d/cortex-angular",
3
- "version": "0.7.0",
3
+ "version": "0.9.0",
4
4
  "description": "Reusable AI agent chat UI library for Angular",
5
5
  "license": "MIT",
6
6
  "sideEffects": false,
package/theme.css CHANGED
@@ -63,6 +63,15 @@
63
63
  );
64
64
  --cortex-font-size: 0.8125rem;
65
65
 
66
+ /* These read --cortex-font-size (or the color named) when unset, so they ship
67
+ * unset: declaring one here gives that part its own value.
68
+ *
69
+ * --cortex-font-size-message: 0.875rem; message bubbles and the composer
70
+ * --cortex-font-size-header: 0.875rem; the chat and history titles
71
+ * --cortex-color-send-empty: transparent; the send button with nothing to send
72
+ * --cortex-color-send-empty-text: var(--cortex-color-text-muted);
73
+ */
74
+
66
75
  /* The widget's headings read --cortex-font-display and fall back to `inherit`,
67
76
  * so it ships unset on purpose — declaring it here is how you opt in:
68
77
  *
@@ -1,7 +1,7 @@
1
1
  // Generated by dts-bundle-generator v9.5.1
2
2
 
3
3
  import * as i0 from '@angular/core';
4
- import { Injector, OnInit, Signal, Type } from '@angular/core';
4
+ import { Injector, OnInit, Signal, TemplateRef, Type } from '@angular/core';
5
5
  import { ToolCallPart, UIMessage } from '@tanstack/ai';
6
6
  import { Observable } from 'rxjs';
7
7
 
@@ -84,7 +84,9 @@ export type MediaRenderContext = {
84
84
  * Draws a closed media fence's `source` into `host`, resolves once drawn, and
85
85
  * returns the teardown. A consumer's `mediaRenderers` config entry has this
86
86
  * shape too: one per fence language, replacing the built-in of the same name
87
- * or adding a language of its own.
87
+ * or adding a language of its own. The same source can be drawn twice at once,
88
+ * inline and in its expanded view, so a renderer keeps no state that two
89
+ * drawings would share.
88
90
  */
89
91
  export type MediaRenderer = (host: HTMLElement, source: string, context: MediaRenderContext) => Promise<() => void>;
90
92
  export type MediaRenderers = Partial<Record<string, MediaRenderer>>;
@@ -115,7 +117,7 @@ export type CortexToolComponentInputs = {
115
117
  };
116
118
  /**
117
119
  * The framework-neutral part of the widget's configuration. Each SDK extends it
118
- * with its own `toolComponents` slot, which is the one field whose type is
120
+ * with its own `toolComponents` field, which is the one field whose type is
119
121
  * inherently framework-bound.
120
122
  */
121
123
  export type CortexConfig = {
@@ -156,6 +158,71 @@ export type CortexConfig = {
156
158
  trustSameOriginEmbeds?: boolean;
157
159
  hooks?: CortexHooks;
158
160
  };
161
+ /**
162
+ * What the header receives, the host's own or the widget's: where the widget
163
+ * is, what to show, and the actions the default header offers. One header
164
+ * serves both screens; `screen` says which is showing.
165
+ */
166
+ export type CortexHeaderContext = {
167
+ screen: "chat" | "threads";
168
+ viewMode: CortexViewMode;
169
+ /** The open thread's title; null on a new chat. */
170
+ title: string | null;
171
+ /** `agentName` in the widget's locale. */
172
+ agentName: string | undefined;
173
+ /** How many conversations the history lists; 0 while it loads. */
174
+ threadCount: number;
175
+ isWorking: boolean;
176
+ /** Whether the host enabled the debug switch, and whether it is on. */
177
+ debug: {
178
+ shown: boolean;
179
+ on: boolean;
180
+ };
181
+ newChat: () => void;
182
+ /** Shows the history: the history screen, or in full mode the sidebar where it is hidden. */
183
+ openHistory: () => void;
184
+ /** Returns to the open chat from wherever `openHistory` went. */
185
+ closeHistory: () => void;
186
+ toggleDebug: () => void;
187
+ };
188
+ /**
189
+ * What the blank-chat landing receives, the host's own or the widget's. The
190
+ * composer arrives ready to place as the SDK's own view type (`View`), so a
191
+ * custom landing keeps the widget's attachments and send rules. Each SDK
192
+ * exports it as `CortexLandingContext` with its view type filled in.
193
+ */
194
+ export type LandingContext<View> = {
195
+ /** The agent's greeting in the widget's locale, or the built-in one. */
196
+ greeting: string;
197
+ /** Empty until the handshake answers, and for an agent that takes no messages. */
198
+ suggestions: Suggestion[];
199
+ /** Newest first; undefined while the first load is out. */
200
+ threads: ThreadSummary[] | undefined;
201
+ /** The composer, or the notice an agent that takes no messages shows instead; empty until the handshake answers. */
202
+ composer: View;
203
+ /**
204
+ * Sends a first message, which opens a thread and swaps the landing for it.
205
+ * Does nothing until the handshake answers, or for an agent that takes no messages.
206
+ */
207
+ send: (prompt: string) => void;
208
+ openThread: (thread: ThreadSummary) => void;
209
+ };
210
+ /** What the history's list receives, the host's own or the widget's. Its header is the header slot. */
211
+ export type CortexThreadListContext = {
212
+ /** Newest first; undefined while the first load is out. */
213
+ threads: ThreadSummary[] | undefined;
214
+ /** The open thread's id; undefined on a new chat. */
215
+ selectedThreadId: string | undefined;
216
+ openThread: (thread: ThreadSummary) => void;
217
+ deleteThread: (threadId: string) => void;
218
+ newChat: () => void;
219
+ };
220
+ /** Each part of the widget a host can draw itself, with the context it receives. */
221
+ export type CortexSlotContexts<View> = {
222
+ header: CortexHeaderContext;
223
+ landing: LandingContext<View>;
224
+ threadList: CortexThreadListContext;
225
+ };
159
226
  export type QueuedAttachment = {
160
227
  localId: string;
161
228
  filename: string;
@@ -189,6 +256,10 @@ export type CortexAngularConfig = CortexConfig & {
189
256
  toolComponents?: Record<string, Type<CortexToolComponentInputs>>;
190
257
  injector?: Injector;
191
258
  };
259
+ /** The landing's context, its composer a template to place with `ngTemplateOutlet`. */
260
+ export type CortexLandingContext = LandingContext<TemplateRef<unknown>>;
261
+ /** Each part of the widget a host can draw itself, with the context it receives. */
262
+ export type CortexAngularSlotContexts = CortexSlotContexts<TemplateRef<unknown>>;
192
263
  declare class AttachmentQueueService {
193
264
  readonly items: import("@angular/core").WritableSignal<QueuedAttachment[]>;
194
265
  private readonly flags;
@@ -319,24 +390,78 @@ declare class CortexChatService {
319
390
  export declare class CortexChatWidgetComponent implements OnInit {
320
391
  readonly config: import("@angular/core").InputSignal<CortexAngularConfig>;
321
392
  protected readonly debugMode: import("@angular/core").WritableSignal<boolean>;
322
- protected readonly screen: import("@angular/core").WritableSignal<"threads" | "chat">;
393
+ protected readonly screen: import("@angular/core").WritableSignal<"chat" | "threads">;
323
394
  protected readonly sidebarOpen: import("@angular/core").WritableSignal<boolean>;
324
395
  protected readonly viewMode: import("@angular/core").Signal<CortexViewMode>;
325
396
  private readonly composer;
397
+ private readonly landingComposer;
398
+ /** The host's own parts by slot; each replaces the widget's default and gets the same context. */
399
+ private readonly slotDirectives;
400
+ protected readonly slots: import("@angular/core").Signal<Map<keyof CortexAngularSlotContexts, TemplateRef<{
401
+ $implicit: CortexHeaderContext | CortexThreadListContext | LandingContext<TemplateRef<unknown>>;
402
+ }>>>;
403
+ protected readonly chatHeader: import("@angular/core").Signal<{
404
+ screen: "chat" | "threads";
405
+ viewMode: CortexViewMode;
406
+ title: string | null;
407
+ agentName: string | undefined;
408
+ threadCount: number;
409
+ isWorking: boolean;
410
+ debug: {
411
+ shown: boolean;
412
+ on: boolean;
413
+ };
414
+ newChat: () => void;
415
+ openHistory: () => void;
416
+ closeHistory: () => void;
417
+ toggleDebug: () => void;
418
+ }>;
419
+ protected readonly threadsHeader: import("@angular/core").Signal<{
420
+ screen: "chat" | "threads";
421
+ viewMode: CortexViewMode;
422
+ title: string | null;
423
+ agentName: string | undefined;
424
+ threadCount: number;
425
+ isWorking: boolean;
426
+ debug: {
427
+ shown: boolean;
428
+ on: boolean;
429
+ };
430
+ newChat: () => void;
431
+ openHistory: () => void;
432
+ closeHistory: () => void;
433
+ toggleDebug: () => void;
434
+ }>;
435
+ protected readonly landing: import("@angular/core").Signal<{
436
+ threads: ThreadSummary[] | undefined;
437
+ composer: TemplateRef<unknown>;
438
+ openThread: (thread: ThreadSummary) => void;
439
+ greeting: string;
440
+ suggestions: Suggestion[];
441
+ send: (prompt: string) => void;
442
+ }>;
443
+ protected readonly threadList: import("@angular/core").Signal<{
444
+ threads: ThreadSummary[] | undefined;
445
+ selectedThreadId: string | undefined;
446
+ openThread: (thread: ThreadSummary) => void;
447
+ deleteThread: (threadId: string) => import("rxjs").Subscription;
448
+ newChat: () => void;
449
+ }>;
326
450
  protected chatService: CortexChatService;
327
451
  protected queue: AttachmentQueueService;
452
+ private threadService;
328
453
  private readonly injector;
329
454
  private readonly destroyRef;
330
455
  ngOnInit(): void;
331
- protected toggleSidebar(): void;
456
+ private headerContext;
332
457
  protected closeSidebar(): void;
333
- protected toggleDebugMode(): void;
334
- protected selectThread(thread: ThreadSummary): void;
335
- protected openHistory(): void;
336
- protected closeHistory(): void;
458
+ private toggleDebugMode;
459
+ private selectThread;
460
+ private openHistory;
461
+ private closeHistory;
337
462
  protected onWidgetDragOver(event: DragEvent): void;
338
463
  protected onWidgetDrop(event: DragEvent): void;
339
- protected newChat(): void;
464
+ private newChat;
340
465
  static ɵfac: i0.ɵɵFactoryDeclaration<CortexChatWidgetComponent, never>;
341
466
  static ɵcmp: i0.ɵɵComponentDeclaration<CortexChatWidgetComponent, "cortex-chat-widget", never, {
342
467
  "config": {
@@ -344,6 +469,42 @@ export declare class CortexChatWidgetComponent implements OnInit {
344
469
  "required": true;
345
470
  "isSignal": true;
346
471
  };
472
+ }, {}, [
473
+ "slotDirectives"
474
+ ], never, true, never>;
475
+ }
476
+ export type SlotName = keyof CortexAngularSlotContexts;
477
+ export type SlotTemplateContext<Slot extends SlotName> = {
478
+ $implicit: CortexAngularSlotContexts[Slot];
479
+ };
480
+ /**
481
+ * Marks the host's own part of `<cortex-chat-widget>`, named by `cortexSlot`:
482
+ * `header`, `landing` or `threadList`. It replaces the widget's default and
483
+ * receives the context the default is drawn from; `header` serves both the
484
+ * chat and the history screen.
485
+ *
486
+ * <cortex-chat-widget [config]="config">
487
+ * <ng-template cortexSlot="header" let-chat>
488
+ * <div class="cortex-widget__chat-header">{{ chat.title ?? chat.agentName }}</div>
489
+ * </ng-template>
490
+ * </cortex-chat-widget>
491
+ */
492
+ export declare class CortexSlotDirective<Slot extends SlotName> {
493
+ readonly slot: import("@angular/core").InputSignal<Slot>;
494
+ private readonly template;
495
+ /** The slot this template fills, paired with the template, for the widget's lookup by slot name. */
496
+ entry(): readonly [
497
+ Slot,
498
+ TemplateRef<SlotTemplateContext<Slot>>
499
+ ];
500
+ static ngTemplateContextGuard<Slot extends SlotName>(_directive: CortexSlotDirective<Slot>, _context: unknown): _context is SlotTemplateContext<Slot>;
501
+ static ɵfac: i0.ɵɵFactoryDeclaration<CortexSlotDirective<any>, never>;
502
+ static ɵdir: i0.ɵɵDirectiveDeclaration<CortexSlotDirective<any>, "ng-template[cortexSlot]", never, {
503
+ "slot": {
504
+ "alias": "cortexSlot";
505
+ "required": true;
506
+ "isSignal": true;
507
+ };
347
508
  }, {}, never, never, true, never>;
348
509
  }
349
510