@threadplane/chat 0.0.51 → 0.0.53

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": "@threadplane/chat",
3
- "version": "0.0.51",
3
+ "version": "0.0.53",
4
4
  "exports": {
5
5
  "./chat.css": "./chat.css",
6
6
  "./themes/default-dark.css": "./themes/default-dark.css",
@@ -25,7 +25,7 @@
25
25
  },
26
26
  "dependencies": {
27
27
  "@cacheplane/partial-json": ">=0.1.1 <0.3.0",
28
- "@cacheplane/partial-markdown": "^0.3.0",
28
+ "@cacheplane/partial-markdown": "^0.4.1",
29
29
  "tslib": "^2.3.0",
30
30
  "@threadplane/telemetry": "*"
31
31
  },
@@ -41,7 +41,13 @@
41
41
  "@json-render/core": "^0.16.0",
42
42
  "@langchain/core": "^1.1.33",
43
43
  "rxjs": "~7.8.0",
44
- "marked": "^15.0.0 || ^16.0.0"
44
+ "marked": "^15.0.0 || ^16.0.0",
45
+ "katex": "^0.16.0 || ^0.17.0"
46
+ },
47
+ "peerDependenciesMeta": {
48
+ "katex": {
49
+ "optional": true
50
+ }
45
51
  },
46
52
  "license": "PolyForm-Noncommercial-1.0.0 OR LicenseRef-Threadplane-Commercial",
47
53
  "repository": {
@@ -12,9 +12,9 @@ import * as _threadplane_chat from '@threadplane/chat';
12
12
  import { PartialJsonParser } from '@cacheplane/partial-json';
13
13
  import { BaseMessage } from '@langchain/core/messages';
14
14
  import * as _cacheplane_partial_markdown from '@cacheplane/partial-markdown';
15
- import { CitationDefinition, MarkdownDocumentNode, MarkdownNode, MarkdownParagraphNode, MarkdownHeadingNode, MarkdownBlockquoteNode, MarkdownListNode, MarkdownListItemNode, MarkdownCodeBlockNode, MarkdownThematicBreakNode, MarkdownTextNode, MarkdownEmphasisNode, MarkdownStrongNode, MarkdownStrikethroughNode, MarkdownInlineCodeNode, MarkdownLinkNode, MarkdownAutolinkNode, MarkdownImageNode, MarkdownSoftBreakNode, MarkdownHardBreakNode, MarkdownCitationReferenceNode, MarkdownTableNode, MarkdownTableRowNode, MarkdownTableCellNode } from '@cacheplane/partial-markdown';
15
+ import { CitationDefinition, MarkdownDocumentNode, MarkdownNode, MarkdownParagraphNode, MarkdownHeadingNode, MarkdownBlockquoteNode, MarkdownListNode, MarkdownListItemNode, MarkdownCodeBlockNode, MarkdownThematicBreakNode, MarkdownTextNode, MarkdownEmphasisNode, MarkdownStrongNode, MarkdownStrikethroughNode, MarkdownInlineCodeNode, MarkdownMathInlineNode, MarkdownMathDisplayNode, MarkdownHtmlInlineNode, MarkdownHtmlBlockNode, MarkdownLinkNode, MarkdownAutolinkNode, MarkdownImageNode, MarkdownSoftBreakNode, MarkdownHardBreakNode, MarkdownCitationReferenceNode, MarkdownTableNode, MarkdownTableRowNode, MarkdownTableCellNode } from '@cacheplane/partial-markdown';
16
+ import { SafeHtml, DomSanitizer } from '@angular/platform-browser';
16
17
  import { NavigationExtras } from '@angular/router';
17
- import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
18
18
 
19
19
  /** Precise authored function tool — what `action()` returns. Carries the schema
20
20
  * `S` and the handler's resolved return type `R`. */
@@ -52,6 +52,12 @@ type ClientToolDef = AnyFunctionToolDef | ViewToolDef | AskToolDef;
52
52
  /** A frozen, name-keyed registry of client tools. */
53
53
  type ClientToolRegistry = Readonly<Record<string, ClientToolDef>>;
54
54
 
55
+ /**
56
+ * Application-wide options for {@link provideChat}. Every field is optional;
57
+ * the values are exposed to all chat components in the tree via the
58
+ * `CHAT_CONFIG` injection token, so you set them once at bootstrap instead of
59
+ * threading props through every component.
60
+ */
55
61
  interface ChatConfig {
56
62
  /** Shared render registry for consumers that read CHAT_CONFIG. */
57
63
  renderRegistry?: AngularRegistry;
@@ -198,15 +204,55 @@ interface Message {
198
204
  */
199
205
  toolCallIds?: string[];
200
206
  }
207
+ /**
208
+ * Type guard narrowing a {@link Message} to `role: 'user'`.
209
+ *
210
+ * @param m The message to test.
211
+ * @returns `true` (and narrows `m`) when the message was sent by the user.
212
+ * @example
213
+ * ```ts
214
+ * const userTurns = agent.messages().filter(isUserMessage);
215
+ * ```
216
+ */
201
217
  declare function isUserMessage(m: Message): m is Message & {
202
218
  role: 'user';
203
219
  };
220
+ /**
221
+ * Type guard narrowing a {@link Message} to `role: 'assistant'`.
222
+ *
223
+ * @param m The message to test.
224
+ * @returns `true` (and narrows `m`) when the message came from the assistant.
225
+ * @example
226
+ * ```ts
227
+ * const reply = agent.messages().findLast(isAssistantMessage);
228
+ * ```
229
+ */
204
230
  declare function isAssistantMessage(m: Message): m is Message & {
205
231
  role: 'assistant';
206
232
  };
233
+ /**
234
+ * Type guard narrowing a {@link Message} to `role: 'tool'` (a tool result turn).
235
+ *
236
+ * @param m The message to test.
237
+ * @returns `true` (and narrows `m`) when the message is a tool result.
238
+ * @example
239
+ * ```ts
240
+ * if (isToolMessage(m)) console.log(m.toolCallId);
241
+ * ```
242
+ */
207
243
  declare function isToolMessage(m: Message): m is Message & {
208
244
  role: 'tool';
209
245
  };
246
+ /**
247
+ * Type guard narrowing a {@link Message} to `role: 'system'`.
248
+ *
249
+ * @param m The message to test.
250
+ * @returns `true` (and narrows `m`) when the message is a system message.
251
+ * @example
252
+ * ```ts
253
+ * const visible = agent.messages().filter((m) => !isSystemMessage(m));
254
+ * ```
255
+ */
210
256
  declare function isSystemMessage(m: Message): m is Message & {
211
257
  role: 'system';
212
258
  };
@@ -714,6 +760,18 @@ declare class ChatInputComponent {
714
760
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<ChatInputComponent, "chat-input", never, { "agent": { "alias": "agent"; "required": true; "isSignal": true; }; "submitOnEnter": { "alias": "submitOnEnter"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "showStopButton": { "alias": "showStopButton"; "required": false; "isSignal": true; }; }, { "submitted": "submitted"; "stopped": "stopped"; }, never, ["[chatInputBanner]", "[chatInputAttachments]", "[chatInputLeading]", "[chatInputModelSelect]", "[chatInputTrailing]", "[chatInputFooter]"], true, never>;
715
761
  }
716
762
 
763
+ /**
764
+ * Whether the agent should show a "typing" indicator — it is loading and has
765
+ * not yet started streaming the assistant's reply.
766
+ *
767
+ * @param agent The agent to inspect.
768
+ * @returns `true` while the agent is awaiting a response but no assistant text
769
+ * has streamed yet; `false` once tokens arrive or the agent is idle.
770
+ * @example
771
+ * ```ts
772
+ * \@if (isTyping(agent)) { <chat-typing-indicator [agent]="agent" /> }
773
+ * ```
774
+ */
717
775
  declare function isTyping(agent: Agent): boolean;
718
776
  declare class ChatTypingIndicatorComponent {
719
777
  readonly agent: _angular_core.InputSignal<Agent<Record<string, unknown>>>;
@@ -810,6 +868,19 @@ declare class ChatScrollBubbleComponent {
810
868
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<ChatScrollBubbleComponent, "chat-scroll-bubble", never, { "mode": { "alias": "mode"; "required": true; "isSignal": true; }; }, { "clicked": "clicked"; }, never, never, true, never>;
811
869
  }
812
870
 
871
+ /**
872
+ * Coerce an unknown error value into a human-readable message string — reads
873
+ * `.message` from `Error`s, returns strings as-is, and `String()`-casts the
874
+ * rest. Useful when rendering an agent's `error` outside the built-in
875
+ * `chat-error` component.
876
+ *
877
+ * @param error Any caught/agent error value.
878
+ * @returns The message text, or `null` when `error` is nullish.
879
+ * @example
880
+ * ```ts
881
+ * const msg = extractErrorMessage(agent.error());
882
+ * ```
883
+ */
813
884
  declare function extractErrorMessage(error: unknown): string | null;
814
885
  declare class ChatErrorComponent {
815
886
  readonly agent: _angular_core.InputSignal<Agent<Record<string, unknown>>>;
@@ -817,6 +888,18 @@ declare class ChatErrorComponent {
817
888
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<ChatErrorComponent, "chat-error", never, { "agent": { "alias": "agent"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
818
889
  }
819
890
 
891
+ /**
892
+ * Read the agent's current human-in-the-loop interrupt, if any.
893
+ *
894
+ * @param agent The agent to inspect.
895
+ * @returns The pending {@link AgentInterrupt}, or `undefined` when the agent is
896
+ * not currently waiting on an interrupt.
897
+ * @example
898
+ * ```ts
899
+ * const interrupt = getInterrupt(agent);
900
+ * if (interrupt) agent.resume('approved');
901
+ * ```
902
+ */
820
903
  declare function getInterrupt(agent: Agent): AgentInterrupt | undefined;
821
904
  declare class ChatInterruptComponent {
822
905
  readonly agent: _angular_core.InputSignal<Agent<Record<string, unknown>>>;
@@ -886,6 +969,8 @@ interface Group {
886
969
  name: string;
887
970
  calls: ToolCall[];
888
971
  templateRef?: ChatToolCallTemplateDirective;
972
+ /** Present when this group anchors a subagent spawned by its (single) task call. */
973
+ subagent?: Subagent;
889
974
  }
890
975
  declare class ChatToolCallsComponent {
891
976
  readonly agent: _angular_core.InputSignal<Agent<Record<string, unknown>>>;
@@ -1347,6 +1432,21 @@ interface ParseTreeStore {
1347
1432
  readonly spec: Signal<Spec | null>;
1348
1433
  readonly elementStates: Signal<Map<string, ElementAccumulationState>>;
1349
1434
  }
1435
+ /**
1436
+ * Create a {@link ParseTreeStore} — feeds streamed JSON chunks through a
1437
+ * partial-JSON parser and exposes the progressively-materialized spec and
1438
+ * per-element accumulation state as signals, so a generative-UI surface can
1439
+ * render while the spec is still arriving.
1440
+ *
1441
+ * @param parser The partial-JSON parser used to incrementally materialize chunks.
1442
+ * @returns A {@link ParseTreeStore}; call `push(chunk)` as bytes stream in.
1443
+ * @example
1444
+ * ```ts
1445
+ * const store = createParseTreeStore(parser);
1446
+ * store.push('{"type":"Car');
1447
+ * store.spec(); // best-effort Spec | null
1448
+ * ```
1449
+ */
1350
1450
  declare function createParseTreeStore(parser: PartialJsonParser): ParseTreeStore;
1351
1451
 
1352
1452
  /** Chat-internal projection of an A2UI component, materialized by the
@@ -1401,6 +1501,19 @@ interface A2uiSurfaceStore {
1401
1501
  readonly surfaceStates: Signal<Map<string, A2uiSurfaceState>>;
1402
1502
  surfaceState(surfaceId: string): Signal<A2uiSurfaceState | undefined>;
1403
1503
  }
1504
+ /**
1505
+ * Create an {@link A2uiSurfaceStore} — the per-conversation store that buffers
1506
+ * streamed A2UI surface updates, tracks each surface's data model + lifecycle
1507
+ * state, and exposes them as signals for rendering. One store backs a chat
1508
+ * thread's A2UI surfaces.
1509
+ *
1510
+ * @returns A fresh, empty {@link A2uiSurfaceStore}.
1511
+ * @example
1512
+ * ```ts
1513
+ * const store = createA2uiSurfaceStore();
1514
+ * const surfaces = store.surfaces; // Signal<Map<string, A2uiSurface>>
1515
+ * ```
1516
+ */
1404
1517
  declare function createA2uiSurfaceStore(): A2uiSurfaceStore;
1405
1518
 
1406
1519
  type ContentType = 'pending' | 'markdown' | 'json-render' | 'a2ui' | 'mixed';
@@ -1416,6 +1529,19 @@ interface ContentClassifier {
1416
1529
  readonly errors: Signal<string[]>;
1417
1530
  dispose(): void;
1418
1531
  }
1532
+ /**
1533
+ * Create a {@link ContentClassifier} — the streaming accumulator that inspects
1534
+ * an assistant message's content as it arrives and classifies it (markdown vs a
1535
+ * generative-UI/A2UI spec), exposing the parsed result and per-element state as
1536
+ * signals so the renderer can switch modes mid-stream.
1537
+ *
1538
+ * @returns A fresh {@link ContentClassifier}; call `dispose()` when done.
1539
+ * @example
1540
+ * ```ts
1541
+ * const cc = createContentClassifier();
1542
+ * effect(() => console.log(cc.type())); // 'pending' | 'markdown' | 'spec'
1543
+ * ```
1544
+ */
1419
1545
  declare function createContentClassifier(): ContentClassifier;
1420
1546
 
1421
1547
  /**
@@ -1542,6 +1668,26 @@ declare class ChatComponent {
1542
1668
  * reasoning pill collapses (per its internal logic).
1543
1669
  */
1544
1670
  protected isReasoningStreaming(message: Message, index: number): boolean;
1671
+ /** The nearest preceding assistant message (skipping hidden tool messages), or undefined. */
1672
+ private prevAssistant;
1673
+ /**
1674
+ * True when message[index] starts a reasoning RUN — a maximal sequence of
1675
+ * consecutive assistant reasoning steps separated only by (hidden) tool
1676
+ * messages. The merged reasoning pill renders once, here.
1677
+ */
1678
+ protected reasoningRunStart(index: number): boolean;
1679
+ /**
1680
+ * Aggregate the reasoning RUN starting at `index`: joins each step's
1681
+ * reasoning, sums durations, counts steps, and computes the streaming flag
1682
+ * and the merged label when N > 1 ("Thought for {total} · {N} steps", or
1683
+ * just "{N} steps" when no step reported timing).
1684
+ */
1685
+ protected reasoningRun(index: number): {
1686
+ content: string;
1687
+ durationMs: number | undefined;
1688
+ streaming: boolean;
1689
+ label: string | undefined;
1690
+ };
1545
1691
  private readonly classifiers;
1546
1692
  private readonly destroyRef;
1547
1693
  private readonly injector;
@@ -2000,6 +2146,36 @@ declare class MarkdownInlineCodeComponent {
2000
2146
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<MarkdownInlineCodeComponent, "chat-md-inline-code", never, { "node": { "alias": "node"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
2001
2147
  }
2002
2148
 
2149
+ type MathNode = MarkdownMathInlineNode | MarkdownMathDisplayNode;
2150
+ /**
2151
+ * Renders a `math-inline` / `math-display` markdown node as KaTeX. KaTeX is
2152
+ * lazy-loaded (see katex-loader); until it resolves, or if the LaTeX is
2153
+ * invalid, the raw `$…$` source is shown — never blank, never a crash.
2154
+ */
2155
+ declare class MarkdownMathComponent {
2156
+ readonly node: _angular_core.InputSignal<MathNode>;
2157
+ private readonly sanitizer;
2158
+ protected readonly display: _angular_core.Signal<boolean>;
2159
+ protected readonly raw: _angular_core.Signal<string>;
2160
+ protected readonly html: _angular_core.Signal<SafeHtml | null>;
2161
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<MarkdownMathComponent, never>;
2162
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<MarkdownMathComponent, "chat-md-math", never, { "node": { "alias": "node"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
2163
+ }
2164
+
2165
+ /**
2166
+ * Renders a `html-block` / `html-inline` markdown node as **escaped text** —
2167
+ * the raw HTML is shown literally (Angular interpolation auto-escapes it),
2168
+ * never injected as live markup. This preserves the pre-0.4 behavior where
2169
+ * raw HTML was plain text, and keeps the chat XSS-safe: model-emitted
2170
+ * `<script>`, `<iframe>`, etc. are displayed as text and never executed.
2171
+ */
2172
+ declare class MarkdownHtmlComponent {
2173
+ readonly node: _angular_core.InputSignal<MarkdownHtmlInlineNode | MarkdownHtmlBlockNode>;
2174
+ protected readonly raw: _angular_core.Signal<string>;
2175
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<MarkdownHtmlComponent, never>;
2176
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<MarkdownHtmlComponent, "chat-md-html", never, { "node": { "alias": "node"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
2177
+ }
2178
+
2003
2179
  declare class MarkdownLinkComponent {
2004
2180
  readonly node: _angular_core.InputSignal<MarkdownLinkNode>;
2005
2181
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<MarkdownLinkComponent, never>;
@@ -2069,8 +2245,6 @@ declare class MarkdownTableCellComponent {
2069
2245
  */
2070
2246
  declare const IS_HEADER_ROW: InjectionToken<Signal<boolean>>;
2071
2247
 
2072
- declare const CHAT_MARKDOWN_STYLES = "\n chat-streaming-md { display: block; color: var(--ngaf-chat-text); line-height: var(--ngaf-chat-line-height); }\n\n /* Headings */\n chat-streaming-md h1, chat-streaming-md h2, chat-streaming-md h3, chat-streaming-md h4, chat-streaming-md h5, chat-streaming-md h6 {\n font-weight: 600;\n line-height: 1.25;\n margin: 1.25rem 0 0.75rem;\n }\n chat-streaming-md h1:first-child, chat-streaming-md h2:first-child, chat-streaming-md h3:first-child,\n chat-streaming-md h4:first-child, chat-streaming-md h5:first-child, chat-streaming-md h6:first-child { margin-top: 0; }\n chat-streaming-md h1 { font-size: 1.5em; font-weight: 700; }\n chat-streaming-md h2 { font-size: 1.25em; }\n chat-streaming-md h3 { font-size: 1.1em; }\n chat-streaming-md h4 { font-size: 1em; }\n chat-streaming-md h5, chat-streaming-md h6 { font-size: 0.95em; color: var(--ngaf-chat-text-muted); }\n\n /* Paragraphs and inline emphasis */\n chat-streaming-md p { margin: 0 0 0.75rem; line-height: 1.6; font-size: var(--ngaf-chat-font-size); }\n chat-streaming-md p:last-child { margin-bottom: 0; }\n chat-streaming-md strong, chat-streaming-md b { font-weight: 700; }\n chat-streaming-md em, chat-streaming-md i { font-style: italic; }\n chat-streaming-md del, chat-streaming-md s { text-decoration: line-through; color: var(--ngaf-chat-text-muted); }\n chat-streaming-md mark { background: var(--ngaf-chat-surface-alt); padding: 0 2px; border-radius: 2px; }\n chat-streaming-md sub { font-size: 0.75em; vertical-align: sub; }\n chat-streaming-md sup { font-size: 0.75em; vertical-align: super; }\n\n /* Links */\n chat-streaming-md a { color: var(--ngaf-chat-primary); text-decoration: underline; text-underline-offset: 2px; }\n chat-streaming-md a:hover { text-decoration-thickness: 2px; }\n\n /* Lists (CommonMark + GFM task lists) */\n chat-streaming-md ul, chat-streaming-md ol { margin: 0 0 0.75rem; padding-left: 1.5rem; }\n chat-streaming-md ul { list-style: disc outside; }\n chat-streaming-md ol { list-style: decimal outside; }\n chat-streaming-md ul ul { list-style: circle outside; }\n chat-streaming-md ul ul ul { list-style: square outside; }\n chat-streaming-md li { margin: 0.2rem 0; }\n chat-streaming-md li::marker { color: var(--ngaf-chat-text-muted); }\n chat-streaming-md li > p { margin: 0 0 0.25rem; }\n chat-streaming-md li > ul, chat-streaming-md li > ol { margin: 0.25rem 0 0; }\n /* GFM task lists: marked emits <li><input type=\"checkbox\" disabled> ... */\n chat-streaming-md li:has(> input[type=\"checkbox\"]) { list-style: none; margin-left: -1.25rem; }\n chat-streaming-md li > input[type=\"checkbox\"] { margin-right: 0.5rem; vertical-align: middle; }\n\n /* Code (inline + fenced) */\n chat-streaming-md code {\n background: var(--ngaf-chat-surface-alt);\n color: var(--ngaf-chat-text);\n padding: 1px 5px;\n border-radius: 4px;\n font-family: var(--ngaf-chat-font-mono);\n font-size: 0.9em;\n }\n chat-streaming-md pre {\n background: var(--ngaf-chat-surface-alt);\n color: var(--ngaf-chat-text);\n padding: 12px 14px;\n border-radius: var(--ngaf-chat-radius-card);\n overflow-x: auto;\n font-family: var(--ngaf-chat-font-mono);\n font-size: var(--ngaf-chat-font-size-sm);\n line-height: 1.5;\n margin: 0 0 0.75rem;\n }\n chat-streaming-md pre code { background: transparent; padding: 0; border-radius: 0; font-size: inherit; }\n\n /* Blockquote */\n chat-streaming-md blockquote {\n border-left: 3px solid var(--ngaf-chat-separator);\n padding: 0.25rem 0 0.25rem 12px;\n margin: 0 0 0.75rem;\n color: var(--ngaf-chat-text-muted);\n }\n chat-streaming-md blockquote > :last-child { margin-bottom: 0; }\n\n /* Horizontal rule */\n chat-streaming-md hr {\n border: none;\n border-top: 1px solid var(--ngaf-chat-separator);\n margin: 1rem 0;\n }\n\n /* Tables (GFM) */\n chat-streaming-md table {\n border-collapse: collapse;\n margin: 0 0 0.75rem;\n width: 100%;\n font-size: 0.95em;\n }\n chat-streaming-md thead { background: var(--ngaf-chat-surface-alt); }\n chat-streaming-md th, chat-streaming-md td {\n border: 1px solid var(--ngaf-chat-separator);\n padding: 6px 10px;\n text-align: left;\n vertical-align: top;\n }\n chat-streaming-md th { font-weight: 600; }\n /* Component-rendered table: chat-md-table becomes a horizontally-scrollable\n wrapper for the inner <table>; row/cell elements stay layout-transparent\n so the browser's table layout takes over. Without this overflow wrapper,\n wide tables push their parent container past the viewport horizontally. */\n chat-streaming-md chat-md-table {\n display: block;\n overflow-x: auto;\n max-width: 100%;\n margin: 0 0 0.75rem;\n }\n chat-streaming-md chat-md-table-row { display: contents; }\n chat-streaming-md chat-md-table-cell { display: contents; }\n chat-streaming-md chat-md-table > table { margin: 0; }\n /* Task-list items: checkbox + first paragraph render inline; subsequent\n blocks (sub-lists, multi-paragraph items) flow normally below. */\n chat-streaming-md li.chat-md-list-item--task {\n list-style: none;\n margin-left: -1.25rem;\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: 0.5rem;\n }\n chat-streaming-md li.chat-md-list-item--task > input[type=\"checkbox\"] {\n margin: 0;\n flex: 0 0 auto;\n transform: translateY(2px);\n }\n /* The chat-md-children wrapper around list-item content takes remaining width */\n chat-streaming-md li.chat-md-list-item--task > chat-md-children {\n flex: 1 1 auto;\n min-width: 0;\n }\n /* Tight task items: only the FIRST paragraph aligns inline with the\n checkbox (margin collapsed). Subsequent paragraphs/blocks keep their\n normal vertical spacing so multi-block items render readably. */\n chat-streaming-md li.chat-md-list-item--task > chat-md-children > chat-md-paragraph:first-child > p {\n margin: 0;\n }\n\n /* Media */\n chat-streaming-md img { max-width: 100%; height: auto; border-radius: 6px; }\n /* Broken-image fallback: muted pill showing alt text + icon. Triggered\n when <img> fires (error). Caught by live browser smoke \u2014 prior impl\n showed only the browser's broken-image icon with no readable alt. */\n chat-streaming-md .chat-md-image--broken {\n display: inline-flex;\n align-items: center;\n gap: 0.4rem;\n padding: 0.25rem 0.5rem;\n background: var(--ngaf-chat-surface-alt);\n border: 1px dashed var(--ngaf-chat-separator);\n border-radius: 6px;\n font-size: 0.9em;\n color: var(--ngaf-chat-text-muted, currentColor);\n opacity: 0.85;\n }\n chat-streaming-md .chat-md-image__icon { font-size: 1em; line-height: 1; }\n chat-streaming-md .chat-md-image__alt { font-style: italic; }\n";
2073
-
2074
2248
  /**
2075
2249
  * Renders markdown content to sanitized HTML.
2076
2250
  * Falls back to plain text with newline->br conversion if `marked` is not installed.
@@ -2090,21 +2264,6 @@ declare function renderMarkdown(content: string, sanitizer: DomSanitizer): SafeH
2090
2264
  */
2091
2265
  declare function formatDuration(ms: number): string;
2092
2266
 
2093
- /** Chevron down (▼ replacement). 12x12, stroke-based. */
2094
- declare const ICON_CHEVRON_DOWN = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M3 4.5L6 7.5L9 4.5\"/></svg>";
2095
- /** Chevron up (▲ replacement). 12x12, stroke-based. */
2096
- declare const ICON_CHEVRON_UP = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M3 7.5L6 4.5L9 7.5\"/></svg>";
2097
- /** Gear icon (⚙ replacement). 14x14. */
2098
- declare const ICON_TOOL = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"3\"/><path d=\"M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42\"/></svg>";
2099
- /** Warning triangle (⚠ replacement). 18x18. */
2100
- declare const ICON_WARNING = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z\"/><line x1=\"12\" y1=\"9\" x2=\"12\" y2=\"13\"/><line x1=\"12\" y1=\"17\" x2=\"12.01\" y2=\"17\"/></svg>";
2101
- /** Robot/agent icon (replacement). 14x14. */
2102
- declare const ICON_AGENT = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"11\" width=\"18\" height=\"10\" rx=\"2\"/><circle cx=\"12\" cy=\"5\" r=\"2\"/><path d=\"M12 7v4\"/><line x1=\"8\" y1=\"16\" x2=\"8\" y2=\"16\"/><line x1=\"16\" y1=\"16\" x2=\"16\" y2=\"16\"/></svg>";
2103
- /** Check mark replacement. 12x12. */
2104
- declare const ICON_CHECK = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M2.5 6L5 8.5L9.5 3.5\"/></svg>";
2105
- /** Send arrow (for chat input). 16x16. */
2106
- declare const ICON_SEND = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M8 12V4M8 4L4 8M8 4L12 8\"/></svg>";
2107
-
2108
2267
  /** Catalog entry for the A2UI surface renderer.
2109
2268
  *
2110
2269
  * `component` is mounted once all of the component's bindings (data
@@ -2222,14 +2381,24 @@ declare class A2uiSurfaceComponent {
2222
2381
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<A2uiSurfaceComponent, "a2ui-surface", never, { "surface": { "alias": "surface"; "required": false; "isSignal": true; }; "state": { "alias": "state"; "required": false; "isSignal": true; }; "catalog": { "alias": "catalog"; "required": true; "isSignal": true; }; "handlers": { "alias": "handlers"; "required": false; "isSignal": true; }; "surfaceFallback": { "alias": "surfaceFallback"; "required": false; "isSignal": true; }; }, { "events": "events"; "action": "action"; }, never, never, true, never>;
2223
2382
  }
2224
2383
 
2225
- declare function surfaceToSpec(surface: A2uiSurface): Spec | null;
2226
-
2227
2384
  /** Builds an A2uiActionMessage from handler params and the current surface.
2228
2385
  * The action.context is serialized as v1 DynamicValue-wrapped entries.
2229
2386
  * Sets action.label when the source component is a Button with a Text
2230
2387
  * child whose literalString is non-empty. */
2231
2388
  declare function buildA2uiActionMessage(params: Record<string, unknown>, surface: A2uiSurface): A2uiActionMessage;
2232
2389
 
2390
+ /**
2391
+ * Build the built-in A2UI component catalog — a {@link ViewRegistry} mapping
2392
+ * the standard A2UI element types (Card, Button, TextField, Image, AudioPlayer,
2393
+ * Video, …) to their Angular renderers. Spread it into `provideViews` (with any
2394
+ * of your own views) so an agent's A2UI surface specs render.
2395
+ *
2396
+ * @returns A {@link ViewRegistry} of the standard A2UI components.
2397
+ * @example
2398
+ * ```ts
2399
+ * providers: [provideViews({ ...a2uiBasicCatalog(), MyWidget: MyWidgetComponent })]
2400
+ * ```
2401
+ */
2233
2402
  declare function a2uiBasicCatalog(): ViewRegistry;
2234
2403
 
2235
2404
  /** Writes a typed value to the render state store if the prop has a binding path. */
@@ -2394,6 +2563,8 @@ declare class A2uiIconComponent {
2394
2563
  readonly childKeys: _angular_core.InputSignal<string[]>;
2395
2564
  readonly spec: _angular_core.InputSignal<Spec | undefined>;
2396
2565
  protected readonly effectiveName: _angular_core.Signal<string>;
2566
+ /** The effective name as a Material Symbols ligature (camelCase → snake_case). */
2567
+ protected readonly glyphName: _angular_core.Signal<string>;
2397
2568
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<A2uiIconComponent, never>;
2398
2569
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<A2uiIconComponent, "a2ui-icon", never, { "name": { "alias": "name"; "required": false; "isSignal": true; }; "icon": { "alias": "icon"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "bindings": { "alias": "bindings"; "required": false; "isSignal": true; }; "emit": { "alias": "emit"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "childKeys": { "alias": "childKeys"; "required": false; "isSignal": true; }; "spec": { "alias": "spec"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
2399
2570
  }
@@ -2763,7 +2934,6 @@ interface ClientToolsCoordinator {
2763
2934
  }
2764
2935
  /** Build the catalog spec list shipped to the model. */
2765
2936
  declare function toClientToolSpecs(registry: ClientToolRegistry): ClientToolSpec[];
2766
- declare function createClientToolsCoordinator(registry: ClientToolRegistry): ClientToolsCoordinator;
2767
2937
 
2768
2938
  interface MockAgent extends Agent {
2769
2939
  messages: WritableSignal<Message[]>;
@@ -2814,10 +2984,25 @@ interface MockAgentOptions {
2814
2984
  history?: AgentCheckpoint[];
2815
2985
  events$?: Observable<AgentEvent>;
2816
2986
  }
2987
+ /**
2988
+ * Build an in-memory {@link Agent} for tests and stories — no transport, no
2989
+ * network. Every field is a writable signal so a test can drive UI states
2990
+ * (loading, error, interrupts, tool calls, subagents) deterministically.
2991
+ *
2992
+ * @param opts Initial values for the mock's signals; all optional.
2993
+ * @returns A {@link MockAgent} satisfying the full `Agent` contract.
2994
+ * @example
2995
+ * ```ts
2996
+ * const agent = mockAgent({
2997
+ * messages: [{ id: '1', role: 'assistant', content: 'Hi' }],
2998
+ * isLoading: true,
2999
+ * });
3000
+ * ```
3001
+ */
2817
3002
  declare function mockAgent(opts?: MockAgentOptions): MockAgent;
2818
3003
 
2819
3004
  /** Inferred argument type for a schema (alias of StandardSchemaInferOutput). */
2820
3005
  type ToolArgs<S extends StandardSchemaV1> = StandardSchemaInferOutput<S>;
2821
3006
 
2822
- export { A2uiAudioPlayerComponent, A2uiButtonComponent, A2uiCardComponent, A2uiCheckBoxComponent, A2uiColumnComponent, A2uiDateTimeInputComponent, A2uiDividerComponent, A2uiIconComponent, A2uiImageComponent, A2uiListComponent, A2uiModalComponent, A2uiMultipleChoiceComponent, A2uiRowComponent, A2uiSliderComponent, A2uiSurfaceComponent, A2uiTabsComponent, A2uiTextComponent, A2uiTextFieldComponent, A2uiVideoComponent, AGENT_ERROR_MESSAGES, AgentError, CHAT_CONFIG, CHAT_LIFECYCLE, CHAT_MARKDOWN_STYLES, ChatApprovalCardComponent, ChatCitationCardTemplateDirective, ChatCitationsCardComponent, ChatCitationsComponent, ChatComponent, ChatConfirmDialogComponent, ChatErrorComponent, ChatGenerativeUiComponent, ChatGenuiSkeletonComponent, ChatHistorySearchPaletteComponent, ChatInputComponent, ChatInterruptComponent, ChatInterruptPanelComponent, ChatLauncherButtonComponent, ChatMessageActionsComponent, ChatMessageComponent, ChatMessageListComponent, ChatOverflowMenuComponent, ChatPopupComponent, ChatProjectListComponent, ChatReasoningComponent, ChatScrollBubbleComponent, ChatSelectComponent, ChatSidebarComponent, ChatSidenavComponent, ChatSidenavScrimComponent, ChatStreamingMdComponent, ChatSubagentCardComponent, ChatSubagentsComponent, ChatSuggestionsComponent, ChatThreadListComponent, ChatTimelineComponent, ChatTimelineSliderComponent, ChatToolCallCardComponent, ChatToolCallTemplateDirective, ChatToolCallsComponent, ChatToolViewsComponent, ChatTraceComponent, ChatTypingIndicatorComponent, ChatWelcomeComponent, ChatWelcomeSuggestionComponent, ChatWindowComponent, CitationsResolverService, ICON_AGENT, ICON_CHECK, ICON_CHEVRON_DOWN, ICON_CHEVRON_UP, ICON_SEND, ICON_TOOL, ICON_WARNING, IS_HEADER_ROW, MARKDOWN_VIEW_REGISTRY, MarkdownAutolinkComponent, MarkdownBlockquoteComponent, MarkdownChildrenComponent, MarkdownCitationReferenceComponent, MarkdownCodeBlockComponent, MarkdownDocumentComponent, MarkdownEmphasisComponent, MarkdownHardBreakComponent, MarkdownHeadingComponent, MarkdownImageComponent, MarkdownInlineCodeComponent, MarkdownLinkComponent, MarkdownListComponent, MarkdownListItemComponent, MarkdownParagraphComponent, MarkdownSoftBreakComponent, MarkdownStrikethroughComponent, MarkdownStrongComponent, MarkdownTableCellComponent, MarkdownTableComponent, MarkdownTableRowComponent, MarkdownTextComponent, MarkdownThematicBreakComponent, MessageTemplateDirective, a2uiBasicCatalog, action, ask, buildA2uiActionMessage, cacheplaneMarkdownViews, createA2uiSurfaceStore, createAgentRef, createClientToolsCoordinator, createContentClassifier, createParseTreeStore, createPartialArgsBridge, deriveJsonSchema, emitBinding, executeFunctionTool, extractErrorMessage, formatDuration, getInterrupt, getMessageType, injectThreadRouting, isAbortError, isAssistantMessage, isSystemMessage, isToolMessage, isTyping, isUserMessage, messageContent, mockAgent, normalizeEnvelopeArgs, normalizeViewEntry, provideChat, renderMarkdown, startClientToolExecutor, statusColor, submitMessage, surfaceToSpec, toAgentError, toClientToolSpecs, tools, validateArgs, view };
3007
+ export { A2uiAudioPlayerComponent, A2uiButtonComponent, A2uiCardComponent, A2uiCheckBoxComponent, A2uiColumnComponent, A2uiDateTimeInputComponent, A2uiDividerComponent, A2uiIconComponent, A2uiImageComponent, A2uiListComponent, A2uiModalComponent, A2uiMultipleChoiceComponent, A2uiRowComponent, A2uiSliderComponent, A2uiSurfaceComponent, A2uiTabsComponent, A2uiTextComponent, A2uiTextFieldComponent, A2uiVideoComponent, AGENT_ERROR_MESSAGES, AgentError, CHAT_CONFIG, CHAT_LIFECYCLE, ChatApprovalCardComponent, ChatCitationCardTemplateDirective, ChatCitationsCardComponent, ChatCitationsComponent, ChatComponent, ChatConfirmDialogComponent, ChatErrorComponent, ChatGenerativeUiComponent, ChatGenuiSkeletonComponent, ChatHistorySearchPaletteComponent, ChatInputComponent, ChatInterruptComponent, ChatInterruptPanelComponent, ChatLauncherButtonComponent, ChatMessageActionsComponent, ChatMessageComponent, ChatMessageListComponent, ChatOverflowMenuComponent, ChatPopupComponent, ChatProjectListComponent, ChatReasoningComponent, ChatScrollBubbleComponent, ChatSelectComponent, ChatSidebarComponent, ChatSidenavComponent, ChatSidenavScrimComponent, ChatStreamingMdComponent, ChatSubagentCardComponent, ChatSubagentsComponent, ChatSuggestionsComponent, ChatThreadListComponent, ChatTimelineComponent, ChatTimelineSliderComponent, ChatToolCallCardComponent, ChatToolCallTemplateDirective, ChatToolCallsComponent, ChatToolViewsComponent, ChatTraceComponent, ChatTypingIndicatorComponent, ChatWelcomeComponent, ChatWelcomeSuggestionComponent, ChatWindowComponent, CitationsResolverService, IS_HEADER_ROW, MARKDOWN_VIEW_REGISTRY, MarkdownAutolinkComponent, MarkdownBlockquoteComponent, MarkdownChildrenComponent, MarkdownCitationReferenceComponent, MarkdownCodeBlockComponent, MarkdownDocumentComponent, MarkdownEmphasisComponent, MarkdownHardBreakComponent, MarkdownHeadingComponent, MarkdownHtmlComponent, MarkdownImageComponent, MarkdownInlineCodeComponent, MarkdownLinkComponent, MarkdownListComponent, MarkdownListItemComponent, MarkdownMathComponent, MarkdownParagraphComponent, MarkdownSoftBreakComponent, MarkdownStrikethroughComponent, MarkdownStrongComponent, MarkdownTableCellComponent, MarkdownTableComponent, MarkdownTableRowComponent, MarkdownTextComponent, MarkdownThematicBreakComponent, MessageTemplateDirective, a2uiBasicCatalog, action, ask, buildA2uiActionMessage, cacheplaneMarkdownViews, createA2uiSurfaceStore, createAgentRef, createContentClassifier, createParseTreeStore, createPartialArgsBridge, deriveJsonSchema, emitBinding, executeFunctionTool, extractErrorMessage, formatDuration, getInterrupt, getMessageType, injectThreadRouting, isAbortError, isAssistantMessage, isSystemMessage, isToolMessage, isTyping, isUserMessage, messageContent, mockAgent, normalizeEnvelopeArgs, normalizeViewEntry, provideChat, renderMarkdown, startClientToolExecutor, statusColor, submitMessage, toAgentError, toClientToolSpecs, tools, validateArgs, view };
2823
3008
  export type { A2uiComponentView, A2uiSurfaceState, A2uiSurfaceStore, A2uiViewEntry, A2uiViews, Agent, AgentCheckpoint, AgentCustomEvent, AgentErrorKind, AgentEvent, AgentInterrupt, AgentRef, AgentRuntimeTelemetryEvent, AgentRuntimeTelemetryPayload, AgentRuntimeTelemetryProperties, AgentRuntimeTelemetrySink, AgentStateUpdateEvent, AgentStatus, AgentSubmitInput, AgentSubmitOptions, AgentWithHistory, AnyFunctionToolDef, AskToolDef, ChatApprovalAction, ChatConfig, ChatLifecycle, ChatMessageRole, ChatRenderEvent, ChatScrollBubbleMode, ChatSelectOption, ChatSidenavMode, ChatToolCallTemplateContext, Citation, ClientToolDef, ClientToolRegistry, ClientToolResult, ClientToolSpec, ClientToolsCapability, ClientToolsCoordinator, ContentBlock, ContentClassifier, ContentType, ElementAccumulationState, FunctionToolDef, InterruptAction, Message, MessageTemplateType, MockAgent, MockAgentOptions, OverflowMenuItem, ParseTreeStore, PartialArgsBridge, Project, ProjectActionAdapter, ResolvedCitation, Role, Subagent, SubagentStatus, Thread, ThreadActionAdapter, ThreadMatch, ThreadRoutingConfig, ToolArgs, ToolCall, ToolCallInfo, ToolCallStatus, TraceState, ViewProps, ViewToolDef };