@threadplane/chat 0.0.56 → 0.0.58

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,28 +1,86 @@
1
1
  import * as _threadplane_render from '@threadplane/render';
2
2
  import { StandardSchemaV1, StandardSchemaInferOutput, AngularRegistry, RenderEvent, ViewRegistry, RenderViewEntry, RenderHost } from '@threadplane/render';
3
3
  export { StandardSchemaInferInput, StandardSchemaInferOutput, StandardSchemaV1, ViewRegistry, toRenderRegistry, views, withViews, withoutViews } from '@threadplane/render';
4
- import { A2uiComponentDef, A2uiSurface, A2uiMessage, A2uiActionMessage } from '@threadplane/a2ui';
5
- export { A2uiAction, A2uiActionContextEntry, A2uiActionMessage, A2uiChildren, A2uiClientDataModel, A2uiComponent, A2uiComponentDef, A2uiSurface, A2uiTheme, DynamicBoolean, DynamicNumber, DynamicString, isLiteralBoolean, isLiteralNumber, isLiteralString, isPathRef } from '@threadplane/a2ui';
4
+ import { A2uiComponent, A2uiSurface, A2uiMessage, A2uiActionMessage, A2uiErrorMessage, A2uiClientCapabilities } from '@threadplane/a2ui';
5
+ export { A2UI_BASIC_CATALOG_ID, A2UI_MIME_TYPE, A2UI_WIRE_VERSION, A2uiAction, A2uiActionMessage, A2uiCatalogComponent, A2uiCheck, A2uiChildren, A2uiClientCapabilities, A2uiClientDataModel, A2uiComponent, A2uiComponentBase, A2uiErrorMessage, A2uiEventAction, A2uiFunctionAction, A2uiFunctionCall, A2uiPathRef, A2uiSurface, A2uiTheme, DynamicBoolean, DynamicNumber, DynamicString, DynamicStringList, DynamicValue, isFunctionCall, isPathRef } from '@threadplane/a2ui';
6
6
  import * as _angular_core from '@angular/core';
7
7
  import { Type, InjectionToken, Signal, TemplateRef, ElementRef, WritableSignal, InputSignal, InputSignalWithTransform } from '@angular/core';
8
8
  import * as _json_render_core from '@json-render/core';
9
9
  import { StateStore, Spec } from '@json-render/core';
10
10
  import { Observable } from 'rxjs';
11
11
  import * as _threadplane_chat from '@threadplane/chat';
12
+ import * as _cacheplane_partial_markdown from '@cacheplane/partial-markdown';
13
+ import { MarkdownDocumentNode, CitationDefinition, 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';
12
14
  import { PartialJsonParser } from '@cacheplane/partial-json';
13
15
  import { BaseMessage } from '@langchain/core/messages';
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, MarkdownMathInlineNode, MarkdownMathDisplayNode, MarkdownHtmlInlineNode, MarkdownHtmlBlockNode, MarkdownLinkNode, MarkdownAutolinkNode, MarkdownImageNode, MarkdownSoftBreakNode, MarkdownHardBreakNode, MarkdownCitationReferenceNode, MarkdownTableNode, MarkdownTableRowNode, MarkdownTableCellNode } from '@cacheplane/partial-markdown';
16
16
  import { SafeHtml, DomSanitizer } from '@angular/platform-browser';
17
17
  import { NavigationExtras } from '@angular/router';
18
18
 
19
+ type ToolCallStatus = 'pending' | 'running' | 'complete' | 'error';
20
+ interface ToolCall {
21
+ id: string;
22
+ name: string;
23
+ /** Arguments. May be partial while streaming (`status !== 'complete'`). */
24
+ args: unknown;
25
+ status: ToolCallStatus;
26
+ /** Present when status === 'complete' or 'error'. */
27
+ result?: unknown;
28
+ /** Optional error payload when status === 'error'. */
29
+ error?: unknown;
30
+ }
31
+
32
+ /** Runtime context passed to browser-executed function tool handlers. */
33
+ interface FunctionToolHandlerContext {
34
+ /** Aborts when the client tool execution should stop without resolving. */
35
+ readonly signal: AbortSignal;
36
+ }
37
+ /** Execution policy options for browser-executed function tools. */
38
+ interface ClientToolContinuationOptions {
39
+ /** False when the tool result should be recorded without forcing a continuation. */
40
+ readonly followUp?: boolean;
41
+ }
42
+ /** Execution policy options for browser-executed function tools. */
43
+ interface ClientToolExecutionOptions extends ClientToolContinuationOptions {
44
+ /** True when the handler may safely re-run and should skip durable pre-claims. */
45
+ readonly idempotent?: boolean;
46
+ }
47
+ /** Diagnostic emitted when client-tool continuation would exceed the configured max turn count. */
48
+ interface ClientToolContinuationLimitEvent {
49
+ readonly maxTurns: number;
50
+ readonly attemptedTurn: number;
51
+ readonly toolCallIds: readonly string[];
52
+ readonly toolNames: readonly string[];
53
+ }
54
+ /** Policy for automatic client-tool continuation. */
55
+ interface ClientToolContinuationPolicy {
56
+ /** Maximum consecutive client-tool continuation groups per user turn. Default: 10. Use 0 for unlimited. */
57
+ readonly maxTurns?: number;
58
+ /** Called when the max-turn guard stops a continuation group. */
59
+ readonly onLimit?: (event: ClientToolContinuationLimitEvent) => void;
60
+ }
61
+ type ClientToolLifecyclePhase = 'running' | 'complete' | 'error';
62
+ interface ClientToolLifecycle {
63
+ readonly id: string;
64
+ readonly name: string;
65
+ readonly status: ToolCallStatus;
66
+ readonly phase: ClientToolLifecyclePhase;
67
+ readonly hasResult: boolean;
68
+ readonly result?: unknown;
69
+ readonly error?: unknown;
70
+ }
71
+ type ClientToolViewProps<S extends StandardSchemaV1> = StandardSchemaInferOutput<S> & {
72
+ readonly status?: ToolCallStatus;
73
+ readonly clientTool?: ClientToolLifecycle;
74
+ };
19
75
  /** Precise authored function tool — what `action()` returns. Carries the schema
20
76
  * `S` and the handler's resolved return type `R`. */
21
77
  interface FunctionToolDef<S extends StandardSchemaV1 = StandardSchemaV1, R = unknown> {
22
78
  readonly kind: 'function';
23
79
  readonly description: string;
24
80
  readonly schema: S;
25
- readonly handler: (args: StandardSchemaInferOutput<S>) => R | Promise<R>;
81
+ readonly followUp?: boolean;
82
+ readonly idempotent?: boolean;
83
+ readonly handler: (args: StandardSchemaInferOutput<S>, context: FunctionToolHandlerContext) => R | Promise<R>;
26
84
  }
27
85
  /** Bivariant union member used only for registry storage/iteration. The handler
28
86
  * param is `any` (NOT `never`): `any` is simultaneously a supertype any precise
@@ -33,18 +91,22 @@ interface AnyFunctionToolDef {
33
91
  readonly kind: 'function';
34
92
  readonly description: string;
35
93
  readonly schema: StandardSchemaV1;
36
- readonly handler: (args: any) => unknown | Promise<unknown>;
94
+ readonly followUp?: boolean;
95
+ readonly idempotent?: boolean;
96
+ readonly handler: (args: any, context: FunctionToolHandlerContext) => unknown | Promise<unknown>;
37
97
  }
38
98
  interface ViewToolDef<S extends StandardSchemaV1 = StandardSchemaV1, C = unknown> {
39
99
  readonly kind: 'view';
40
100
  readonly description: string;
41
101
  readonly schema: S;
102
+ readonly followUp?: boolean;
42
103
  readonly component: Type<C>;
43
104
  }
44
105
  interface AskToolDef<S extends StandardSchemaV1 = StandardSchemaV1, C = unknown> {
45
106
  readonly kind: 'ask';
46
107
  readonly description: string;
47
108
  readonly schema: S;
109
+ readonly followUp?: boolean;
48
110
  readonly component: Type<C>;
49
111
  }
50
112
  /** A client tool the model can call; executed in the browser. */
@@ -178,9 +240,50 @@ interface Citation {
178
240
  publishedAt?: string | number | Date;
179
241
  }
180
242
 
243
+ /**
244
+ * Terminal result of one response attempt.
245
+ *
246
+ * `paused` is an intentional stop awaiting resumable input; `interrupted` means
247
+ * the response stream ended unexpectedly. The other outcomes indicate normal
248
+ * completion, failure, or caller cancellation.
249
+ */
250
+ type CompleteOutcome = 'success' | 'error' | 'aborted' | 'interrupted' | 'paused';
251
+ /**
252
+ * Delivery lifecycle for one response attempt. `generation` identifies that
253
+ * attempt and is stable only for its lifetime. `streaming` means chunks may
254
+ * still arrive; `complete` means the attempt has stopped with a terminal outcome.
255
+ */
256
+ type MessageDelivery = {
257
+ readonly generation: string;
258
+ readonly phase: 'streaming';
259
+ } | {
260
+ readonly generation: string;
261
+ readonly phase: 'complete';
262
+ readonly outcome: CompleteOutcome;
263
+ };
264
+ /** Creates the active delivery state for one response-attempt generation. */
265
+ declare function streamingDelivery(generation: string): {
266
+ readonly generation: string;
267
+ readonly phase: "streaming";
268
+ };
269
+ /** Creates a terminal delivery state for an existing response-attempt generation. */
270
+ declare function completeDelivery<const TOutcome extends CompleteOutcome>(generation: string, outcome: TOutcome): {
271
+ readonly generation: string;
272
+ readonly phase: "complete";
273
+ readonly outcome: TOutcome;
274
+ };
275
+ /** Creates a successful terminal delivery state for an already-complete message. */
276
+ declare function staticDelivery(messageId: string): {
277
+ readonly generation: string;
278
+ readonly phase: "complete";
279
+ readonly outcome: "success";
280
+ };
281
+
181
282
  type Role = 'user' | 'assistant' | 'system' | 'tool';
182
283
  interface Message {
183
284
  id: string;
285
+ /** Adapter-owned authoritative delivery lifecycle state for this message. */
286
+ delivery: MessageDelivery;
184
287
  role: Role;
185
288
  /** Plain text, or a list of structured content blocks. */
186
289
  content: string | ContentBlock[];
@@ -271,19 +374,6 @@ declare function isSystemMessage(m: Message): m is Message & {
271
374
  role: 'system';
272
375
  };
273
376
 
274
- type ToolCallStatus = 'pending' | 'running' | 'complete' | 'error';
275
- interface ToolCall {
276
- id: string;
277
- name: string;
278
- /** Arguments. May be partial while streaming (`status !== 'complete'`). */
279
- args: unknown;
280
- status: ToolCallStatus;
281
- /** Present when status === 'complete' or 'error'. */
282
- result?: unknown;
283
- /** Optional error payload when status === 'error'. */
284
- error?: unknown;
285
- }
286
-
287
377
  type AgentStatus = 'idle' | 'running' | 'error';
288
378
 
289
379
  interface AgentInterrupt {
@@ -385,6 +475,15 @@ interface ClientToolsCapability {
385
475
  setCatalog(specs: readonly ClientToolSpec[]): void;
386
476
  /** Tool calls the model made for client tools that await a client result. */
387
477
  readonly pending: Signal<readonly ToolCall[]>;
478
+ /** Record a client tool's result without continuing the run. */
479
+ settle?(toolCallId: string, result: ClientToolResult): void;
480
+ /**
481
+ * Make every result recorded via {@link settle} durable on the server
482
+ * WITHOUT continuing the run. No-op for adapters whose settle() is already
483
+ * durable. Adapters that buffer locally MUST clear their buffer only on a
484
+ * successful write, so a failure degrades to a later flush or submit.
485
+ */
486
+ flush?(): void | Promise<void>;
388
487
  /** Return a client tool's result (or error) and continue the run. */
389
488
  resolve(toolCallId: string, result: ClientToolResult): void;
390
489
  }
@@ -456,7 +555,7 @@ declare const AGENT_ERROR_MESSAGES: Record<AgentErrorKind, string>;
456
555
  * Invariant: state lives on signals; `events$` carries only things that are
457
556
  * not derivable from signals.
458
557
  */
459
- interface Agent<TState = Record<string, unknown>> {
558
+ interface Agent<TState = unknown> {
460
559
  messages: Signal<Message[]>;
461
560
  status: Signal<AgentStatus>;
462
561
  isLoading: Signal<boolean>;
@@ -539,7 +638,7 @@ interface AgentCheckpoint {
539
638
  * implement this. Pure request/response runtimes that don't have checkpoints
540
639
  * should implement plain Agent.
541
640
  */
542
- interface AgentWithHistory<TState = Record<string, unknown>> extends Agent<TState> {
641
+ interface AgentWithHistory<TState = unknown> extends Agent<TState> {
543
642
  history: Signal<AgentCheckpoint[]>;
544
643
  /**
545
644
  * Optional reactive map of `messageId → checkpointId`, computed by
@@ -601,7 +700,7 @@ declare class MessageTemplateDirective {
601
700
  */
602
701
  declare function getMessageType(message: Message): MessageTemplateType;
603
702
  declare class ChatMessageListComponent {
604
- readonly agent: _angular_core.InputSignal<Agent<Record<string, unknown>>>;
703
+ readonly agent: _angular_core.InputSignal<Agent<unknown>>;
605
704
  readonly messageTemplates: _angular_core.Signal<readonly MessageTemplateDirective[]>;
606
705
  readonly messages: _angular_core.Signal<Message[]>;
607
706
  readonly getMessageType: typeof getMessageType;
@@ -689,17 +788,19 @@ declare class ChatTraceComponent {
689
788
  * step labels often appear in reasoning output).
690
789
  *
691
790
  * Internal state: a tristate "expanded" — null means follow auto state-
692
- * driven logic (force-expand on isStreaming, otherwise honor
791
+ * driven logic (force-expand while delivery is streaming, otherwise honor
693
792
  * defaultExpanded), boolean is a manual user choice that wins for the
694
793
  * lifetime of the instance.
695
794
  */
696
795
  declare class ChatReasoningComponent {
697
796
  readonly content: _angular_core.InputSignal<string>;
698
- readonly isStreaming: _angular_core.InputSignal<boolean>;
797
+ readonly delivery: _angular_core.InputSignal<MessageDelivery>;
699
798
  readonly durationMs: _angular_core.InputSignal<number | undefined>;
700
799
  readonly label: _angular_core.InputSignal<string | undefined>;
701
800
  readonly defaultExpanded: _angular_core.InputSignal<boolean>;
702
801
  readonly hasContent: _angular_core.Signal<boolean>;
802
+ readonly isStreaming: _angular_core.Signal<boolean>;
803
+ readonly document: _angular_core.Signal<_threadplane_chat.StreamingMarkdownDocument>;
703
804
  /** null = follow auto logic (streaming → expanded, else defaultExpanded). */
704
805
  private readonly _expandedOverride;
705
806
  readonly expanded: _angular_core.Signal<boolean>;
@@ -708,7 +809,7 @@ declare class ChatReasoningComponent {
708
809
  constructor();
709
810
  toggle(): void;
710
811
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<ChatReasoningComponent, never>;
711
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<ChatReasoningComponent, "chat-reasoning", never, { "content": { "alias": "content"; "required": false; "isSignal": true; }; "isStreaming": { "alias": "isStreaming"; "required": false; "isSignal": true; }; "durationMs": { "alias": "durationMs"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "defaultExpanded": { "alias": "defaultExpanded"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
812
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ChatReasoningComponent, "chat-reasoning", never, { "content": { "alias": "content"; "required": false; "isSignal": true; }; "delivery": { "alias": "delivery"; "required": true; "isSignal": true; }; "durationMs": { "alias": "durationMs"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "defaultExpanded": { "alias": "defaultExpanded"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
712
813
  }
713
814
 
714
815
  declare class ChatLauncherButtonComponent {
@@ -736,7 +837,7 @@ declare class ChatSuggestionsComponent {
736
837
  */
737
838
  declare function submitMessage(agent: Agent, text: string): string | null;
738
839
  declare class ChatInputComponent {
739
- readonly agent: _angular_core.InputSignal<Agent<Record<string, unknown>>>;
840
+ readonly agent: _angular_core.InputSignal<Agent<unknown>>;
740
841
  readonly submitOnEnter: _angular_core.InputSignal<boolean>;
741
842
  readonly placeholder: _angular_core.InputSignal<string>;
742
843
  /** When true (default), shows a stop button while the agent is streaming. */
@@ -788,7 +889,7 @@ declare class ChatInputComponent {
788
889
  */
789
890
  declare function isTyping(agent: Agent): boolean;
790
891
  declare class ChatTypingIndicatorComponent {
791
- readonly agent: _angular_core.InputSignal<Agent<Record<string, unknown>>>;
892
+ readonly agent: _angular_core.InputSignal<Agent<unknown>>;
792
893
  readonly visible: _angular_core.Signal<boolean>;
793
894
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<ChatTypingIndicatorComponent, never>;
794
895
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<ChatTypingIndicatorComponent, "chat-typing-indicator", never, { "agent": { "alias": "agent"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
@@ -897,7 +998,7 @@ declare class ChatScrollBubbleComponent {
897
998
  */
898
999
  declare function extractErrorMessage(error: unknown): string | null;
899
1000
  declare class ChatErrorComponent {
900
- readonly agent: _angular_core.InputSignal<Agent<Record<string, unknown>>>;
1001
+ readonly agent: _angular_core.InputSignal<Agent<unknown>>;
901
1002
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<ChatErrorComponent, never>;
902
1003
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<ChatErrorComponent, "chat-error", never, { "agent": { "alias": "agent"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
903
1004
  }
@@ -916,7 +1017,7 @@ declare class ChatErrorComponent {
916
1017
  */
917
1018
  declare function getInterrupt(agent: Agent): AgentInterrupt | undefined;
918
1019
  declare class ChatInterruptComponent {
919
- readonly agent: _angular_core.InputSignal<Agent<Record<string, unknown>>>;
1020
+ readonly agent: _angular_core.InputSignal<Agent<unknown>>;
920
1021
  readonly templateRef: _angular_core.Signal<TemplateRef<any> | undefined>;
921
1022
  readonly interrupt: _angular_core.Signal<AgentInterrupt | undefined>;
922
1023
  defaultText(i: AgentInterrupt): string;
@@ -987,7 +1088,7 @@ interface Group {
987
1088
  subagent?: Subagent;
988
1089
  }
989
1090
  declare class ChatToolCallsComponent {
990
- readonly agent: _angular_core.InputSignal<Agent<Record<string, unknown>>>;
1091
+ readonly agent: _angular_core.InputSignal<Agent<unknown>>;
991
1092
  readonly message: _angular_core.InputSignal<Message | undefined>;
992
1093
  readonly grouping: _angular_core.InputSignal<"auto" | "none">;
993
1094
  readonly groupSummary: _angular_core.InputSignal<((name: string, count: number) => string) | undefined>;
@@ -1026,7 +1127,7 @@ declare class ChatToolCallsComponent {
1026
1127
  * (and a `status` a component chooses not to declare) are harmless.
1027
1128
  */
1028
1129
  declare class ChatToolViewsComponent {
1029
- readonly agent: _angular_core.InputSignal<Agent<Record<string, unknown>>>;
1130
+ readonly agent: _angular_core.InputSignal<Agent<unknown>>;
1030
1131
  readonly events: _angular_core.OutputEmitterRef<RenderEvent>;
1031
1132
  readonly message: _angular_core.InputSignal<Message | undefined>;
1032
1133
  readonly views: _angular_core.InputSignal<Readonly<Record<string, _angular_core.Type<unknown> | _threadplane_render.RenderViewEntry>> | undefined>;
@@ -1043,7 +1144,7 @@ declare class ChatToolViewsComponent {
1043
1144
  }
1044
1145
 
1045
1146
  declare class ChatSubagentsComponent {
1046
- readonly agent: _angular_core.InputSignal<Agent<Record<string, unknown>>>;
1147
+ readonly agent: _angular_core.InputSignal<Agent<unknown>>;
1047
1148
  readonly templateRef: _angular_core.Signal<TemplateRef<any> | undefined>;
1048
1149
  readonly activeSubagents: _angular_core.Signal<Subagent[]>;
1049
1150
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<ChatSubagentsComponent, never>;
@@ -1249,7 +1350,7 @@ declare class ChatGenuiSkeletonComponent {
1249
1350
  }
1250
1351
 
1251
1352
  declare class ChatTimelineComponent {
1252
- readonly agent: _angular_core.InputSignal<AgentWithHistory<Record<string, unknown>>>;
1353
+ readonly agent: _angular_core.InputSignal<AgentWithHistory<unknown>>;
1253
1354
  readonly checkpointSelected: _angular_core.OutputEmitterRef<AgentCheckpoint>;
1254
1355
  readonly templateRef: _angular_core.Signal<TemplateRef<any> | undefined>;
1255
1356
  readonly history: _angular_core.Signal<AgentCheckpoint[]>;
@@ -1418,6 +1519,53 @@ declare class ChatConnectedOverlayDirective {
1418
1519
  static ɵdir: _angular_core.ɵɵDirectiveDeclaration<ChatConnectedOverlayDirective, "[chatConnectedOverlay]", never, { "origin": { "alias": "chatOverlayOrigin"; "required": true; "isSignal": true; }; "open": { "alias": "chatOverlayOpen"; "required": false; "isSignal": true; }; "positions": { "alias": "chatOverlayPositions"; "required": false; "isSignal": true; }; "panelClass": { "alias": "chatOverlayPanelClass"; "required": false; "isSignal": true; }; }, { "attached": "chatOverlayAttached"; "outsideClick": "chatOverlayOutsideClick"; "detached": "chatOverlayDetach"; }, never, never, true, never>;
1419
1520
  }
1420
1521
 
1522
+ type CitationTypeIcon = 'web' | 'file' | 'app' | 'memory' | 'generic';
1523
+ interface CitationTypeMeta {
1524
+ type: string;
1525
+ label: string | null;
1526
+ icon: CitationTypeIcon;
1527
+ tone: CitationTypeIcon;
1528
+ isKnown: boolean;
1529
+ }
1530
+ interface CitationImageVisual {
1531
+ kind: 'image';
1532
+ iconUrl: string;
1533
+ }
1534
+ interface CitationTypeIconVisual {
1535
+ kind: 'type-icon';
1536
+ icon: CitationTypeIcon;
1537
+ tone: CitationTypeIcon;
1538
+ label: string | null;
1539
+ }
1540
+ interface CitationMonogramVisual {
1541
+ kind: 'monogram';
1542
+ monogram: string;
1543
+ color: string;
1544
+ }
1545
+ type CitationSourceVisual = CitationImageVisual | CitationTypeIconVisual | CitationMonogramVisual;
1546
+ /** Hostname of `url` with a leading `www.` removed; null if absent/malformed. */
1547
+ declare function deriveDomain(url?: string): string | null;
1548
+ /** Explicit `sourceType`, else 'web' inferred from a url, else 'unknown'. */
1549
+ declare function deriveSourceType(c: Citation): string;
1550
+ /** Uppercased first letter of the domain (or title) for the monogram chip. */
1551
+ declare function deriveMonogram(c: Citation): string;
1552
+ /** Deterministic hue in [0,360) from a seed string (stable monogram color). */
1553
+ declare function monogramHue(seed: string): number;
1554
+ /** Short freshness label (e.g. "Apr 2024"); null when absent or unparseable. */
1555
+ declare function formatPublished(value?: string | number | Date): string | null;
1556
+ /** Deterministic monogram-chip background color (stable per source). */
1557
+ declare function monogramColor(c: Citation): string;
1558
+ /**
1559
+ * Derive normalized source-type metadata for badges, icons, and tone tokens.
1560
+ */
1561
+ declare function citationTypeMeta(c: Citation): CitationTypeMeta;
1562
+ /**
1563
+ * Choose the visual source marker for a citation: provider image, type icon, or monogram.
1564
+ */
1565
+ declare function citationSourceVisual(c: Citation): CitationSourceVisual;
1566
+ /** Human label for the source-type badge; null when type is 'unknown'. */
1567
+ declare function citationTypeLabel(c: Citation): string | null;
1568
+
1421
1569
  /**
1422
1570
  * ContentChild template directive for custom citation card rendering.
1423
1571
  * Usage: <ng-template chatCitationCard let-citation>...</ng-template>
@@ -1431,9 +1579,12 @@ declare class ChatCitationCardTemplateDirective {
1431
1579
  }
1432
1580
  interface FavEntry {
1433
1581
  id: string;
1582
+ kind: 'image' | 'type-icon' | 'monogram';
1434
1583
  iconUrl?: string;
1435
- mono: string;
1436
- color: string;
1584
+ icon?: CitationTypeIcon;
1585
+ tone?: CitationTypeIcon;
1586
+ monogram?: string;
1587
+ color?: string;
1437
1588
  }
1438
1589
  declare class ChatCitationsComponent {
1439
1590
  readonly message: _angular_core.InputSignal<Message>;
@@ -1462,11 +1613,17 @@ declare class ChatCitationsComponent {
1462
1613
  */
1463
1614
  declare class ChatCitationsCardComponent {
1464
1615
  readonly citation: _angular_core.InputSignal<Citation>;
1616
+ private readonly sourceVisual;
1617
+ private readonly typeMeta;
1465
1618
  protected readonly domain: _angular_core.Signal<string | null>;
1466
1619
  protected readonly title: _angular_core.Signal<string | null>;
1467
- protected readonly monogram: _angular_core.Signal<string>;
1468
- protected readonly monoColor: _angular_core.Signal<string>;
1620
+ protected readonly sourceIconUrl: _angular_core.Signal<string | null>;
1621
+ protected readonly sourceIcon: _angular_core.Signal<CitationTypeIcon | null>;
1622
+ protected readonly sourceMonogram: _angular_core.Signal<string | null>;
1623
+ protected readonly sourceMonoColor: _angular_core.Signal<string | null>;
1469
1624
  protected readonly typeLabel: _angular_core.Signal<string | null>;
1625
+ protected readonly typeTone: _angular_core.Signal<CitationTypeIcon>;
1626
+ protected isTypeTone(tone: CitationTypeIcon): boolean;
1470
1627
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<ChatCitationsCardComponent, never>;
1471
1628
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<ChatCitationsCardComponent, "chat-citations-card", never, { "citation": { "alias": "citation"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
1472
1629
  }
@@ -1478,30 +1635,21 @@ declare class ChatCitationsCardComponent {
1478
1635
  */
1479
1636
  declare class ChatCitationPreviewComponent {
1480
1637
  readonly citation: _angular_core.InputSignal<Citation>;
1638
+ private readonly sourceVisual;
1639
+ private readonly typeMeta;
1481
1640
  protected readonly domain: _angular_core.Signal<string | null>;
1482
- protected readonly monogram: _angular_core.Signal<string>;
1483
- protected readonly monoColor: _angular_core.Signal<string>;
1641
+ protected readonly sourceIconUrl: _angular_core.Signal<string | null>;
1642
+ protected readonly sourceIcon: _angular_core.Signal<CitationTypeIcon | null>;
1643
+ protected readonly sourceMonogram: _angular_core.Signal<string | null>;
1644
+ protected readonly sourceMonoColor: _angular_core.Signal<string | null>;
1484
1645
  protected readonly typeLabel: _angular_core.Signal<string | null>;
1646
+ protected readonly typeTone: _angular_core.Signal<CitationTypeIcon>;
1485
1647
  protected readonly published: _angular_core.Signal<string | null>;
1648
+ protected isTypeTone(tone: CitationTypeIcon): boolean;
1486
1649
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<ChatCitationPreviewComponent, never>;
1487
1650
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<ChatCitationPreviewComponent, "chat-citation-preview", never, { "citation": { "alias": "citation"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
1488
1651
  }
1489
1652
 
1490
- /** Hostname of `url` with a leading `www.` removed; null if absent/malformed. */
1491
- declare function deriveDomain(url?: string): string | null;
1492
- /** Explicit `sourceType`, else 'web' inferred from a url, else 'unknown'. */
1493
- declare function deriveSourceType(c: Citation): string;
1494
- /** Uppercased first letter of the domain (or title) for the monogram chip. */
1495
- declare function deriveMonogram(c: Citation): string;
1496
- /** Deterministic hue in [0,360) from a seed string (stable monogram color). */
1497
- declare function monogramHue(seed: string): number;
1498
- /** Short freshness label (e.g. "Apr 2024"); null when absent or unparseable. */
1499
- declare function formatPublished(value?: string | number | Date): string | null;
1500
- /** Deterministic monogram-chip background color (stable per source). */
1501
- declare function monogramColor(c: Citation): string;
1502
- /** Human label for the source-type badge; null when type is 'unknown'. */
1503
- declare function citationTypeLabel(c: Citation): string | null;
1504
-
1505
1653
  interface ThreadRoutingConfig {
1506
1654
  /** The app-owned source-of-truth signal for the active thread id. */
1507
1655
  threadId: WritableSignal<string | null>;
@@ -1543,6 +1691,76 @@ interface ChatLifecycle {
1543
1691
  }
1544
1692
  declare const CHAT_LIFECYCLE: InjectionToken<ChatLifecycle>;
1545
1693
 
1694
+ /** Durable identity for one client-tool execution on one thread. */
1695
+ interface ClientToolExecutionKey {
1696
+ readonly threadId: string;
1697
+ readonly toolCallId: string;
1698
+ }
1699
+ /** Prior durable execution state returned by a client-tool execution store. */
1700
+ type ClientToolExecutionRecord = {
1701
+ readonly status: 'executing';
1702
+ } | {
1703
+ readonly status: 'done';
1704
+ readonly result: ClientToolResult;
1705
+ } | {
1706
+ readonly status: 'failed';
1707
+ readonly result?: ClientToolResult;
1708
+ };
1709
+ /** Structural store contract for guarded browser client-tool execution. */
1710
+ interface ClientToolExecutionStore {
1711
+ /** Atomically claim a tool-call execution. Returns prior state when present. */
1712
+ claim(key: ClientToolExecutionKey): Promise<'claimed' | ClientToolExecutionRecord>;
1713
+ /** Record the final client-tool result for a claimed execution. */
1714
+ record(key: ClientToolExecutionKey, result: ClientToolResult): Promise<void>;
1715
+ /** Lookup prior execution states for pending tool calls on a thread. */
1716
+ lookup(threadId: string, toolCallIds: readonly string[]): Promise<Record<string, ClientToolExecutionRecord>>;
1717
+ }
1718
+ /** Opt-in guard configuration for claim-before-execute client tools. */
1719
+ interface ClientToolExecutionGuard {
1720
+ readonly threadId: string;
1721
+ readonly store: ClientToolExecutionStore;
1722
+ }
1723
+ /** Return whether this function tool should claim before browser execution. */
1724
+ declare function shouldClaimBeforeExecute(def: AnyFunctionToolDef): boolean;
1725
+ /** Default fail-closed result for a stale in-progress client-tool execution. */
1726
+ declare function defaultInterruptedClientToolResult(toolCallId: string): ClientToolResult;
1727
+ /** Result recorded when the user stops a run while a client tool is running. */
1728
+ declare function cancelledClientToolResult(toolCallId: string): ClientToolResult;
1729
+ /** Default fail-closed result when the execution guard itself cannot be reached. */
1730
+ declare function clientToolGuardFailureResult(toolCallId: string, error: unknown): ClientToolResult;
1731
+
1732
+ interface StreamingMarkdownDocument {
1733
+ readonly generation: string;
1734
+ readonly phase: 'streaming' | 'complete';
1735
+ readonly content: string;
1736
+ }
1737
+ /** Creates the atomic document consumed by the streaming Markdown renderer. */
1738
+ declare function markdownDocument(content: string, delivery: MessageDelivery, suffix?: string): StreamingMarkdownDocument;
1739
+ type StreamingMarkdownContractViolationPolicy = 'throw' | 'rebuild';
1740
+ declare const STREAMING_MARKDOWN_CONTRACT_VIOLATION_POLICY: InjectionToken<StreamingMarkdownContractViolationPolicy>;
1741
+ /**
1742
+ * Renders one explicitly-versioned markdown document through the shared view
1743
+ * registry. A generation owns one parser session; append-only updates preserve
1744
+ * parser and subtree identity, while generation changes replace the session.
1745
+ */
1746
+ declare class ChatStreamingMdComponent {
1747
+ readonly document: _angular_core.InputSignal<StreamingMarkdownDocument>;
1748
+ readonly viewRegistry: _angular_core.InputSignal<Readonly<Record<string, _angular_core.Type<unknown> | _threadplane_render.RenderViewEntry>> | undefined>;
1749
+ readonly resolvedRegistry: _angular_core.Signal<Readonly<Record<string, _angular_core.Type<unknown> | _threadplane_render.RenderViewEntry>>>;
1750
+ private readonly resolver;
1751
+ private readonly violationPolicy;
1752
+ private readonly createParser;
1753
+ private parser;
1754
+ private prior;
1755
+ private materializedRoot;
1756
+ readonly root: _angular_core.Signal<MarkdownDocumentNode | null>;
1757
+ constructor();
1758
+ private process;
1759
+ private replaceFrom;
1760
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ChatStreamingMdComponent, never>;
1761
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ChatStreamingMdComponent, "chat-streaming-md", never, { "document": { "alias": "document"; "required": true; "isSignal": true; }; "viewRegistry": { "alias": "viewRegistry"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1762
+ }
1763
+
1546
1764
  interface ElementAccumulationState {
1547
1765
  hasType: boolean;
1548
1766
  hasProps: boolean;
@@ -1573,29 +1791,29 @@ declare function createParseTreeStore(parser: PartialJsonParser): ParseTreeStore
1573
1791
 
1574
1792
  /** Chat-internal projection of an A2UI component, materialized by the
1575
1793
  * surface store. Distinct from the wire-format `A2uiComponent` in
1576
- * `@threadplane/a2ui` (which carries the raw `component: A2uiComponentDef`
1577
- * payload) — this type adds the per-component readiness fields the
1578
- * progressive renderer consumes. */
1794
+ * `@threadplane/a2ui` this type adds the per-component readiness fields
1795
+ * the progressive renderer consumes. */
1579
1796
  interface A2uiComponentView {
1580
1797
  /** The component's id (same as the wire-format `A2uiComponent.id`). */
1581
1798
  readonly id: string;
1582
- /** The component type key — e.g. `'Button'`, `'TextField'` — matched
1583
- * against catalog `views` entries. */
1799
+ /** The component type — e.g. `'Button'`, `'TextField'` — matched
1800
+ * against catalog `views` entries. Mirrors the wire `component` string. */
1584
1801
  readonly type: string;
1585
1802
  /** Data model paths this component references via its `{$.path}` prop
1586
- * expressions. Extracted once on `surfaceUpdate` apply; immutable. */
1803
+ * expressions. Extracted once on `updateComponents` apply; immutable. */
1587
1804
  readonly bindings: readonly string[];
1588
1805
  /** Monotonic: `false` until every binding has resolved at least once
1589
1806
  * in the accumulated data model, then `true` forever. Once `true`,
1590
- * subsequent `dataModelUpdate` envelopes push new prop values but do
1807
+ * subsequent `updateDataModel` envelopes push new prop values but do
1591
1808
  * NOT flip this back to `false`. */
1592
1809
  readonly ready: boolean;
1593
- /** Resolved property bag. Meaningful only when `ready === true`. */
1810
+ /** Resolved property bag (reserved protocol keys stripped). Meaningful
1811
+ * only when `ready === true`. */
1594
1812
  readonly props: Readonly<Record<string, unknown>>;
1595
- /** The raw wire-format component def, retained so the slot directive
1813
+ /** The raw wire-format component, retained so the slot directive
1596
1814
  * can look up the catalog entry by type and resolve nested children
1597
1815
  * on re-renders. */
1598
- readonly def: A2uiComponentDef;
1816
+ readonly def: A2uiComponent;
1599
1817
  }
1600
1818
 
1601
1819
  /** Chat-side state for a surface — wraps the wire-format `A2uiSurface`
@@ -1625,10 +1843,15 @@ interface A2uiSurfaceStore {
1625
1843
  }
1626
1844
  /**
1627
1845
  * Create an {@link A2uiSurfaceStore} — the per-conversation store that buffers
1628
- * streamed A2UI surface updates, tracks each surface's data model + lifecycle
1846
+ * streamed A2UI v0.9 envelopes, tracks each surface's data model + lifecycle
1629
1847
  * state, and exposes them as signals for rendering. One store backs a chat
1630
1848
  * thread's A2UI surfaces.
1631
1849
  *
1850
+ * A surface becomes visible once its `createSurface` envelope has arrived AND
1851
+ * a component with id `root` has been defined (the v0.9 progressive-rendering
1852
+ * rule). Everything received earlier is buffered; afterwards, components merge
1853
+ * incrementally by id and data-model updates apply immediately.
1854
+ *
1632
1855
  * @returns A fresh, empty {@link A2uiSurfaceStore}.
1633
1856
  * @example
1634
1857
  * ```ts
@@ -1685,7 +1908,7 @@ interface ChatRenderEvent {
1685
1908
  }
1686
1909
 
1687
1910
  declare class ChatComponent {
1688
- readonly agent: _angular_core.InputSignal<Agent<Record<string, unknown>>>;
1911
+ readonly agent: _angular_core.InputSignal<Agent<unknown>>;
1689
1912
  readonly views: _angular_core.InputSignal<Readonly<Record<string, _angular_core.Type<unknown> | _threadplane_render.RenderViewEntry>> | undefined>;
1690
1913
  /**
1691
1914
  * Client-declared tools (`view`/`ask`/`function`) the model may call. When
@@ -1726,9 +1949,12 @@ declare class ChatComponent {
1726
1949
  * Default covers the canonical A2UI + json-render schema tools.
1727
1950
  */
1728
1951
  readonly genuiToolNames: _angular_core.InputSignal<readonly string[]>;
1952
+ readonly clientToolExecutionGuard: _angular_core.InputSignal<ClientToolExecutionGuard | undefined>;
1953
+ readonly clientToolContinuationPolicy: _angular_core.InputSignal<ClientToolContinuationPolicy | undefined>;
1729
1954
  readonly showWelcome: _angular_core.Signal<boolean>;
1730
1955
  readonly threadSelected: _angular_core.OutputEmitterRef<string>;
1731
1956
  readonly renderEvent: _angular_core.OutputEmitterRef<ChatRenderEvent>;
1957
+ readonly clientToolContinuationLimit: _angular_core.OutputEmitterRef<ClientToolContinuationLimitEvent>;
1732
1958
  /** Emitted when the user clicks the regenerate button on an assistant message. */
1733
1959
  readonly regenerate: _angular_core.OutputEmitterRef<void>;
1734
1960
  /** Emitted when the user rates an assistant message. */
@@ -1783,13 +2009,6 @@ declare class ChatComponent {
1783
2009
  * back to the original text.
1784
2010
  */
1785
2011
  protected humanContent(message: unknown): string;
1786
- /**
1787
- * True while a message's reasoning is mid-stream — i.e. it's the latest
1788
- * message, the agent is loading, the message has reasoning content, and
1789
- * no response text has arrived yet. Once the response text begins, the
1790
- * reasoning pill collapses (per its internal logic).
1791
- */
1792
- protected isReasoningStreaming(message: Message, index: number): boolean;
1793
2012
  /** The nearest preceding assistant message (skipping hidden tool messages), or undefined. */
1794
2013
  private prevAssistant;
1795
2014
  /**
@@ -1800,17 +2019,19 @@ declare class ChatComponent {
1800
2019
  protected reasoningRunStart(index: number): boolean;
1801
2020
  /**
1802
2021
  * Aggregate the reasoning RUN starting at `index`: joins each step's
1803
- * reasoning, sums durations, counts steps, and computes the streaming flag
1804
- * and the merged label when N > 1 ("Thought for {total} · {N} steps", or
1805
- * just "{N} steps" when no step reported timing).
2022
+ * reasoning, sums durations, counts steps, and returns the last step's
2023
+ * delivery because that step owns the current aggregate snapshot. Also
2024
+ * computes the merged label when N > 1 ("Thought for {total} · {N} steps",
2025
+ * or just "{N} steps" when no step reported timing).
1806
2026
  */
1807
2027
  protected reasoningRun(index: number): {
1808
2028
  content: string;
1809
2029
  durationMs: number | undefined;
1810
- streaming: boolean;
2030
+ delivery: MessageDelivery;
1811
2031
  label: string | undefined;
1812
2032
  };
1813
2033
  private readonly classifiers;
2034
+ private readonly markdownDocuments;
1814
2035
  private readonly destroyRef;
1815
2036
  private readonly injector;
1816
2037
  private readonly lifecycle;
@@ -1831,15 +2052,13 @@ declare class ChatComponent {
1831
2052
  private programmaticScrollCount;
1832
2053
  private static readonly PIN_TOLERANCE_PX;
1833
2054
  /**
1834
- * True iff there's a current (last-index) assistant message that's
1835
- * still streaming. The bubble's own caret already signals loading;
2055
+ * True iff the current (last-index) assistant message owns an active
2056
+ * delivery generation. The bubble's own caret already signals loading;
1836
2057
  * we suppress the floor typing-indicator in that case so the user
1837
2058
  * doesn't see two loading affordances at once.
1838
2059
  *
1839
2060
  * Matches the same `streaming + current` condition the bubble uses
1840
- * to enable `.chat-message__caret`:
1841
- * `this.agent().isLoading() && i === this.agent().messages().length - 1`
1842
- * `i === this.agent().messages().length - 1`
2061
+ * to enable `.chat-message__caret`.
1843
2062
  *
1844
2063
  * Restricted to assistant role because the caret only renders on
1845
2064
  * assistant bubbles (`:host([data-role="assistant"][data-current=...
@@ -1889,9 +2108,8 @@ declare class ChatComponent {
1889
2108
  * unlike a single prev-message check.
1890
2109
  */
1891
2110
  protected isGenuiTurn(message: unknown, _prevMsg: unknown, index?: number): boolean;
1892
- classifyMessage(content: string, message: {
1893
- id?: string;
1894
- }): ContentClassifier;
2111
+ classifyMessage(content: string, message: Pick<Message, 'id' | 'delivery'>): ContentClassifier;
2112
+ protected markdownDocumentFor(content: string, message: Pick<Message, 'id' | 'delivery'>): StreamingMarkdownDocument;
1895
2113
  clearClassifiers(): void;
1896
2114
  onSpecEvent(event: RenderEvent, messageIndex: number): void;
1897
2115
  /**
@@ -1908,11 +2126,11 @@ declare class ChatComponent {
1908
2126
  onRate(message: unknown, value: 'up' | 'down'): void;
1909
2127
  onCopy(message: unknown, content: string): void;
1910
2128
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<ChatComponent, never>;
1911
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<ChatComponent, "chat", never, { "agent": { "alias": "agent"; "required": true; "isSignal": true; }; "views": { "alias": "views"; "required": false; "isSignal": true; }; "clientTools": { "alias": "clientTools"; "required": false; "isSignal": true; }; "store": { "alias": "store"; "required": false; "isSignal": true; }; "handlers": { "alias": "handlers"; "required": false; "isSignal": true; }; "threads": { "alias": "threads"; "required": false; "isSignal": true; }; "activeThreadId": { "alias": "activeThreadId"; "required": false; "isSignal": true; }; "welcomeDisabled": { "alias": "welcomeDisabled"; "required": false; "isSignal": true; }; "modelOptions": { "alias": "modelOptions"; "required": false; "isSignal": true; }; "showModelPicker": { "alias": "showModelPicker"; "required": false; "isSignal": true; }; "selectedModel": { "alias": "selectedModel"; "required": false; "isSignal": true; }; "modelPickerPlaceholder": { "alias": "modelPickerPlaceholder"; "required": false; "isSignal": true; }; "genuiToolNames": { "alias": "genuiToolNames"; "required": false; "isSignal": true; }; }, { "selectedModel": "selectedModelChange"; "threadSelected": "threadSelected"; "renderEvent": "renderEvent"; "regenerate": "regenerate"; "rate": "rate"; "messageCopy": "messageCopy"; }, never, ["[chatWelcomeSuggestions]", "[chatHeader]", "[chatToolCallTemplate]", "[chatInputModelSelect]"], true, never>;
2129
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ChatComponent, "chat", never, { "agent": { "alias": "agent"; "required": true; "isSignal": true; }; "views": { "alias": "views"; "required": false; "isSignal": true; }; "clientTools": { "alias": "clientTools"; "required": false; "isSignal": true; }; "store": { "alias": "store"; "required": false; "isSignal": true; }; "handlers": { "alias": "handlers"; "required": false; "isSignal": true; }; "threads": { "alias": "threads"; "required": false; "isSignal": true; }; "activeThreadId": { "alias": "activeThreadId"; "required": false; "isSignal": true; }; "welcomeDisabled": { "alias": "welcomeDisabled"; "required": false; "isSignal": true; }; "modelOptions": { "alias": "modelOptions"; "required": false; "isSignal": true; }; "showModelPicker": { "alias": "showModelPicker"; "required": false; "isSignal": true; }; "selectedModel": { "alias": "selectedModel"; "required": false; "isSignal": true; }; "modelPickerPlaceholder": { "alias": "modelPickerPlaceholder"; "required": false; "isSignal": true; }; "genuiToolNames": { "alias": "genuiToolNames"; "required": false; "isSignal": true; }; "clientToolExecutionGuard": { "alias": "clientToolExecutionGuard"; "required": false; "isSignal": true; }; "clientToolContinuationPolicy": { "alias": "clientToolContinuationPolicy"; "required": false; "isSignal": true; }; }, { "selectedModel": "selectedModelChange"; "threadSelected": "threadSelected"; "renderEvent": "renderEvent"; "clientToolContinuationLimit": "clientToolContinuationLimit"; "regenerate": "regenerate"; "rate": "rate"; "messageCopy": "messageCopy"; }, never, ["[chatWelcomeSuggestions]", "[chatHeader]", "[chatToolCallTemplate]", "[chatInputModelSelect]"], true, never>;
1912
2130
  }
1913
2131
 
1914
2132
  declare class ChatPopupComponent {
1915
- readonly agent: _angular_core.InputSignal<Agent<Record<string, unknown>>>;
2133
+ readonly agent: _angular_core.InputSignal<Agent<unknown>>;
1916
2134
  /** A2UI component catalog forwarded to the inner <chat>. Without it,
1917
2135
  * messages classified as A2UI parse correctly but never mount a
1918
2136
  * surface. Pass `a2uiBasicCatalog()` from `@threadplane/chat`. */
@@ -1952,7 +2170,7 @@ declare class ChatPopupComponent {
1952
2170
  }
1953
2171
 
1954
2172
  declare class ChatSidebarComponent {
1955
- readonly agent: _angular_core.InputSignal<Agent<Record<string, unknown>>>;
2173
+ readonly agent: _angular_core.InputSignal<Agent<unknown>>;
1956
2174
  /** A2UI component catalog forwarded to the inner <chat>. Without it,
1957
2175
  * messages classified as A2UI parse correctly but never mount a
1958
2176
  * surface. Pass `a2uiBasicCatalog()` from `@threadplane/chat`. */
@@ -1986,7 +2204,7 @@ declare class ChatSidebarComponent {
1986
2204
  }
1987
2205
 
1988
2206
  declare class ChatTimelineSliderComponent {
1989
- readonly agent: _angular_core.InputSignal<AgentWithHistory<Record<string, unknown>>>;
2207
+ readonly agent: _angular_core.InputSignal<AgentWithHistory<unknown>>;
1990
2208
  readonly selectedIndex: _angular_core.WritableSignal<number>;
1991
2209
  readonly history: _angular_core.Signal<AgentCheckpoint[]>;
1992
2210
  readonly replayRequested: _angular_core.OutputEmitterRef<string>;
@@ -1998,6 +2216,37 @@ declare class ChatTimelineSliderComponent {
1998
2216
  }
1999
2217
 
2000
2218
  type ChatSidenavMode = 'expanded' | 'collapsed' | 'drawer';
2219
+ /**
2220
+ * The conversation sidebar: thread list, projects, search, and the new-chat
2221
+ * action. Pair it with a runtime's thread store (e.g. `LangGraphThreadsAdapter`)
2222
+ * and a {@link ThreadActionAdapter} for the per-row rename/delete/archive menu.
2223
+ *
2224
+ * **This component renders the sidebar only — it is not a layout wrapper.** Its
2225
+ * `<ng-content>` slots are all named (`sidenavHeader`, `sidenavPrimary`,
2226
+ * `sidenavSections`, `sidenavFooterLeft`, `sidenavFooterRight`,
2227
+ * `sidenavAccount`) and target regions *inside* the sidebar. There is no default
2228
+ * slot, so a `<chat>` placed between the tags is silently dropped. Render the
2229
+ * chat as a sibling and lay the two out yourself:
2230
+ *
2231
+ * @example
2232
+ * ```html
2233
+ * <chat-sidenav
2234
+ * [threads]="threads.threads()"
2235
+ * [activeThreadId]="activeThread()"
2236
+ * [actions]="threadActions"
2237
+ * [agent]="agent"
2238
+ * (newChat)="activeThread.set(null)"
2239
+ * (threadSelected)="activeThread.set($event)"
2240
+ * />
2241
+ * <main class="chat-pane">
2242
+ * <chat [agent]="agent" />
2243
+ * </main>
2244
+ * ```
2245
+ * ```css
2246
+ * :host { display: flex; height: 100dvh; }
2247
+ * .chat-pane { flex: 1; min-width: 0; }
2248
+ * ```
2249
+ */
2001
2250
  declare class ChatSidenavComponent {
2002
2251
  readonly mode: _angular_core.InputSignal<ChatSidenavMode>;
2003
2252
  readonly open: _angular_core.InputSignal<boolean>;
@@ -2008,7 +2257,7 @@ declare class ChatSidenavComponent {
2008
2257
  readonly projects: _angular_core.InputSignal<Project[] | null>;
2009
2258
  readonly selectedProjectId: _angular_core.InputSignal<string | null>;
2010
2259
  readonly projectActions: _angular_core.InputSignal<ProjectActionAdapter | null>;
2011
- readonly agent: _angular_core.InputSignal<Agent<Record<string, unknown>> | AgentWithHistory<Record<string, unknown>> | null>;
2260
+ readonly agent: _angular_core.InputSignal<Agent<unknown> | AgentWithHistory<unknown> | null>;
2012
2261
  readonly debug: _angular_core.InputSignal<boolean>;
2013
2262
  readonly newChat: _angular_core.OutputEmitterRef<void>;
2014
2263
  readonly threadSelected: _angular_core.OutputEmitterRef<string>;
@@ -2059,7 +2308,7 @@ declare class ChatSidenavScrimComponent {
2059
2308
 
2060
2309
  type InterruptAction = 'accept' | 'edit' | 'respond' | 'ignore';
2061
2310
  declare class ChatInterruptPanelComponent {
2062
- readonly agent: _angular_core.InputSignal<Agent<Record<string, unknown>>>;
2311
+ readonly agent: _angular_core.InputSignal<Agent<unknown>>;
2063
2312
  readonly action: _angular_core.OutputEmitterRef<InterruptAction>;
2064
2313
  readonly interrupt: _angular_core.Signal<AgentInterrupt | undefined>;
2065
2314
  readonly interruptReason: _angular_core.Signal<string>;
@@ -2069,7 +2318,7 @@ declare class ChatInterruptPanelComponent {
2069
2318
 
2070
2319
  type ChatApprovalAction = 'approve' | 'edit' | 'cancel';
2071
2320
  declare class ChatApprovalCardComponent {
2072
- readonly agent: _angular_core.InputSignal<Agent<Record<string, unknown>>>;
2321
+ readonly agent: _angular_core.InputSignal<Agent<unknown>>;
2073
2322
  readonly matchKind: _angular_core.InputSignal<string | undefined>;
2074
2323
  readonly title: _angular_core.InputSignal<string>;
2075
2324
  readonly showEdit: _angular_core.InputSignal<boolean>;
@@ -2099,6 +2348,9 @@ declare function statusColor(status: SubagentStatus): string;
2099
2348
  declare class ChatSubagentCardComponent {
2100
2349
  readonly subagent: _angular_core.InputSignal<Subagent>;
2101
2350
  readonly state: _angular_core.Signal<TraceState>;
2351
+ private readonly markdownDocuments;
2352
+ constructor();
2353
+ protected markdownDocumentFor(content: string, message: Message): StreamingMarkdownDocument;
2102
2354
  protected textOf(m: Message): string;
2103
2355
  protected toolCallsFor(m: Message): ToolCall[];
2104
2356
  protected toToolCallInfo(tc: ToolCall): ToolCallInfo;
@@ -2118,39 +2370,6 @@ declare class CitationsResolverService {
2118
2370
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<CitationsResolverService>;
2119
2371
  }
2120
2372
 
2121
- /**
2122
- * Renders streaming markdown by walking a @cacheplane/partial-markdown AST
2123
- * through @threadplane/render's view registry.
2124
- *
2125
- * Reactivity model: the live `parser.root` keeps a stable JS reference
2126
- * across pushes (partial-markdown's identity guarantee). To make Angular
2127
- * signals propagate downstream when the underlying tree changes, we surface
2128
- * a materialized snapshot via `materialize()`. The snapshot shares
2129
- * structurally — unchanged subtrees keep the SAME reference, and any
2130
- * descendant change yields a NEW root reference. This lets Angular's
2131
- * `Object.is` equality check both detect changes (root reference differs)
2132
- * and short-circuit unchanged subtrees (per-node references stable).
2133
- *
2134
- * Override per-node-type renderers via the `[viewRegistry]` input or by
2135
- * supplying a different `MARKDOWN_VIEW_REGISTRY` provider in the injector
2136
- * tree.
2137
- */
2138
- declare class ChatStreamingMdComponent {
2139
- readonly content: _angular_core.InputSignal<string>;
2140
- readonly streaming: _angular_core.InputSignal<boolean>;
2141
- readonly viewRegistry: _angular_core.InputSignal<Readonly<Record<string, _angular_core.Type<unknown> | _threadplane_render.RenderViewEntry>> | undefined>;
2142
- readonly resolvedRegistry: _angular_core.Signal<Readonly<Record<string, _angular_core.Type<unknown> | _threadplane_render.RenderViewEntry>>>;
2143
- private readonly resolver;
2144
- constructor();
2145
- private parser;
2146
- private prior;
2147
- private finished;
2148
- private readonly finalizeTick;
2149
- readonly root: _angular_core.Signal<MarkdownDocumentNode | null>;
2150
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<ChatStreamingMdComponent, never>;
2151
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<ChatStreamingMdComponent, "chat-streaming-md", never, { "content": { "alias": "content"; "required": false; "isSignal": true; }; "streaming": { "alias": "streaming"; "required": false; "isSignal": true; }; "viewRegistry": { "alias": "viewRegistry"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
2152
- }
2153
-
2154
2373
  /**
2155
2374
  * DI token for the markdown view registry consumed by <chat-streaming-md>
2156
2375
  * and <md-children>. Maps MarkdownNode.type strings (e.g. "paragraph",
@@ -2456,17 +2675,15 @@ interface PartialArgsBridge {
2456
2675
  * tool_call.arguments JSON. Uses @cacheplane/partial-json to extract
2457
2676
  * structurally-complete envelope objects from the growing args string.
2458
2677
  *
2459
- * Synthesis safety net: if the first complete surfaceUpdate arrives and
2460
- * no beginRendering has been extracted yet, the bridge synthesises one
2461
- * targeted at the surfaceUpdate's first component (preferring id='root'
2462
- * if present). This makes the surface mount IMMEDIATELY after the first
2463
- * surfaceUpdate parses without waiting for the LLM to emit beginRendering
2464
- * at the end of its envelope list so the render-element fallback gate
2465
- * (PR #252) actually fires while dataModelUpdates flow in.
2678
+ * Synthesis safety net: v0.9 requires a `createSurface` envelope before
2679
+ * any `updateComponents`. If a complete `updateComponents` arrives for a
2680
+ * surface with no `createSurface` seen yet this turn, the bridge
2681
+ * synthesises one (basic catalog) so the surface can mount as soon as its
2682
+ * `root` component is defined the store gates rendering on
2683
+ * createSurface + root, and fills the tree in progressively after that.
2466
2684
  *
2467
- * The store's apply() already treats repeated beginRendering for the same
2468
- * surfaceId as idempotent (just re-applies styles), so the LLM's eventual
2469
- * beginRendering (if any) is a no-op rather than a conflict.
2685
+ * The store treats a later "real" createSurface for the same surface as an
2686
+ * idempotent refresh, so LLMs that emit one out of order are harmless.
2470
2687
  */
2471
2688
  declare function createPartialArgsBridge(store: A2uiSurfaceStore): PartialArgsBridge;
2472
2689
 
@@ -2495,27 +2712,40 @@ declare class A2uiSurfaceComponent {
2495
2712
  readonly surfaceFallback: _angular_core.InputSignal<Type<unknown> | undefined>;
2496
2713
  readonly events: _angular_core.OutputEmitterRef<RenderEvent>;
2497
2714
  readonly action: _angular_core.OutputEmitterRef<A2uiActionMessage>;
2498
- /** Agent-set primary color from `beginRendering.styles.primaryColor`.
2715
+ /** Emitted when a submit is blocked by failing validation checks —
2716
+ * the spec client → agent error message (code VALIDATION_FAILED). */
2717
+ readonly validationError: _angular_core.OutputEmitterRef<A2uiErrorMessage>;
2718
+ /** Surface-owned live state store: `$bindState` props read it and input
2719
+ * components write user edits into it, so event-time logic (checks,
2720
+ * action context) sees CURRENT values instead of the agent-seeded
2721
+ * snapshot. Seeded from spec.state with user edits preserved. Public so
2722
+ * hosts (and tests) can read the live values of a rendered surface. */
2723
+ readonly liveStore: _json_render_core.StateStore;
2724
+ /** Last value this component seeded per state path (see chat-generative-ui:
2725
+ * distinguishes "still our seed — safe to overwrite" from "user edited"). */
2726
+ private readonly seeded;
2727
+ constructor();
2728
+ /** Agent-set primary color from `createSurface.theme.primaryColor`.
2499
2729
  * Returns null when unset so the host binding doesn't override the
2500
2730
  * consumer's `:root`-level `--a2ui-primary` default. */
2501
2731
  readonly primaryColor: _angular_core.Signal<string | null>;
2502
- /** Agent-set font family from `beginRendering.styles.font`. Returns
2503
- * null when unset so the host doesn't override consumer fonts. */
2504
- readonly fontFamily: _angular_core.Signal<string | null>;
2505
- /** Roots from the surface state — components whose ids appear as
2506
- * children of no other component. The wire spec includes
2507
- * `beginRendering.root` as the single root; that path stays usable
2508
- * but we keep the renderer permissive in case future surfaces emit
2509
- * multiple top-level components.
2732
+ /** Agent identity chrome from `createSurface.theme`. When neither
2733
+ * `agentDisplayName` nor `iconUrl` is set, no header renders at all
2734
+ * (zero layout impact for themeless surfaces — the common case). */
2735
+ protected readonly agentDisplayName: _angular_core.Signal<string | null>;
2736
+ protected readonly iconUrl: _angular_core.Signal<string | null>;
2737
+ /** Roots from the surface state. The v0.9 wire contract reserves the
2738
+ * component id `root` as the single tree root; we keep the renderer
2739
+ * permissive in case future surfaces emit multiple top-level
2740
+ * components.
2510
2741
  *
2511
2742
  * Conservative: returns only the first key from componentViews
2512
- * insertion order. The wire format's beginRendering.root carries the
2513
- * true root id; plumbing it through A2uiSurfaceState is a follow-up. */
2743
+ * insertion order. */
2514
2744
  readonly rootIds: _angular_core.Signal<string[]>;
2515
2745
  /** Convert the A2UI surface to a json-render Spec for rendering.
2516
2746
  * Prefers `state().surface` (the progressively-built wire surface)
2517
2747
  * over the legacy `surface` input. surfaceToSpec handles
2518
- * children.explicitList → spec.children translation + reserved-key
2748
+ * children-id-list → spec.children translation + reserved-key
2519
2749
  * filtering + path-ref → $bindState rewriting; the rendered tree
2520
2750
  * then uses render-element's standard input-mapping
2521
2751
  * (`childKeys: el.children`) so catalog components receive the
@@ -2533,14 +2763,19 @@ declare class A2uiSurfaceComponent {
2533
2763
  'a2ui:localAction': (params: Record<string, unknown>) => unknown;
2534
2764
  }>;
2535
2765
  onRenderEvent(event: RenderEvent): void;
2766
+ /** Agent-seeded data model overlaid with the store's current state
2767
+ * (user edits + check messages). Shallow per-key merge is sufficient:
2768
+ * store snapshots hold whole top-level values written via pointers. */
2769
+ private mergedLiveModel;
2536
2770
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<A2uiSurfaceComponent, never>;
2537
- 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>;
2771
+ 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"; "validationError": "validationError"; }, never, never, true, never>;
2538
2772
  }
2539
2773
 
2540
- /** Builds an A2uiActionMessage from handler params and the current surface.
2541
- * The action.context is serialized as v1 DynamicValue-wrapped entries.
2542
- * Sets action.label when the source component is a Button with a Text
2543
- * child whose literalString is non-empty. */
2774
+ /** Builds a v0.9 A2uiActionMessage from handler params and the current
2775
+ * surface. The action.context is the resolved plain object the renderer
2776
+ * produced from the component's `action.event.context`. Sets action.label
2777
+ * when the source component is a Button with a Text child whose text is a
2778
+ * non-empty bare literal. */
2544
2779
  declare function buildA2uiActionMessage(params: Record<string, unknown>, surface: A2uiSurface): A2uiActionMessage;
2545
2780
 
2546
2781
  /**
@@ -2560,20 +2795,36 @@ declare function a2uiBasicCatalog(): ViewRegistry;
2560
2795
  /** Writes a typed value to the render state store if the prop has a binding path. */
2561
2796
  declare function emitBinding(host: RenderHost, bindings: Record<string, string> | undefined, prop: string, value: unknown): void;
2562
2797
 
2563
- /** v1 textFieldType values from A2uiTextField. */
2564
- type TextFieldType = 'date' | 'longText' | 'number' | 'shortText' | 'obscured';
2798
+ /**
2799
+ * The A2UI client capabilities this renderer supports the typed
2800
+ * `a2uiClientCapabilities` metadata a host attaches to agent requests so
2801
+ * the agent knows which component catalogs it may target
2802
+ * (catalog negotiation, A2UI v0.9 transport metadata).
2803
+ *
2804
+ * @example
2805
+ * ```ts
2806
+ * const metadata = { a2uiClientCapabilities: a2uiClientCapabilities() };
2807
+ * ```
2808
+ */
2809
+ declare function a2uiClientCapabilities(): A2uiClientCapabilities;
2810
+
2811
+ /** v0.9 TextField variant values ('date' was removed — DateTimeInput owns dates). */
2812
+ type TextFieldVariant = 'longText' | 'number' | 'shortText' | 'obscured';
2565
2813
  declare class A2uiTextFieldComponent {
2566
2814
  private static _idCounter;
2567
2815
  protected readonly _inputId: string;
2568
2816
  private readonly host;
2569
2817
  readonly label: _angular_core.InputSignal<string>;
2570
- /** v1 prop: text (resolved string value). */
2571
- readonly text: _angular_core.InputSignal<string>;
2572
- /** Back-compat alias: value. surface-to-spec resolves DynamicString → plain string. */
2573
- readonly value: _angular_core.Signal<string>;
2818
+ /** v0.9 prop: resolved string value. */
2819
+ readonly value: _angular_core.InputSignal<string>;
2574
2820
  readonly placeholder: _angular_core.InputSignal<string>;
2575
- readonly textFieldType: _angular_core.InputSignal<TextFieldType>;
2821
+ /** v0.9 prop: input variant (default 'shortText'). */
2822
+ readonly variant: _angular_core.InputSignal<TextFieldVariant>;
2823
+ /** Enforced by the surface's check gate as an implicit regex rule (plus the native pattern attribute). */
2576
2824
  readonly validationRegexp: _angular_core.InputSignal<string>;
2825
+ /** Live validation message written by the surface's check gate
2826
+ * (bound to /_a2uiChecks/<id>); empty when valid. */
2827
+ readonly errorText: _angular_core.InputSignal<string>;
2577
2828
  readonly _bindings: _angular_core.InputSignal<Record<string, string>>;
2578
2829
  readonly bindings: _angular_core.InputSignal<Record<string, string>>;
2579
2830
  readonly loading: _angular_core.InputSignal<boolean>;
@@ -2582,39 +2833,42 @@ declare class A2uiTextFieldComponent {
2582
2833
  protected readonly htmlInputType: _angular_core.Signal<string>;
2583
2834
  onInput(event: Event): void;
2584
2835
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<A2uiTextFieldComponent, never>;
2585
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<A2uiTextFieldComponent, "a2ui-text-field", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "text": { "alias": "text"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "textFieldType": { "alias": "textFieldType"; "required": false; "isSignal": true; }; "validationRegexp": { "alias": "validationRegexp"; "required": false; "isSignal": true; }; "_bindings": { "alias": "_bindings"; "required": false; "isSignal": true; }; "bindings": { "alias": "bindings"; "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>;
2836
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<A2uiTextFieldComponent, "a2ui-text-field", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "validationRegexp": { "alias": "validationRegexp"; "required": false; "isSignal": true; }; "errorText": { "alias": "errorText"; "required": false; "isSignal": true; }; "_bindings": { "alias": "_bindings"; "required": false; "isSignal": true; }; "bindings": { "alias": "bindings"; "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>;
2586
2837
  }
2587
2838
 
2588
2839
  declare class A2uiCheckBoxComponent {
2589
2840
  private readonly host;
2590
2841
  readonly label: _angular_core.InputSignal<string>;
2591
- /** v1 canonical prop: boolean checked state. */
2592
- readonly value: _angular_core.InputSignal<boolean | undefined>;
2593
- /** Pre-v1 alias retained for back-compat. */
2594
- readonly checked: _angular_core.InputSignal<boolean>;
2842
+ /** v0.9 prop: boolean checked state. */
2843
+ readonly value: _angular_core.InputSignal<boolean>;
2844
+ /** Live validation message written by the surface's check gate
2845
+ * (bound to /_a2uiChecks/<id>); empty when valid. */
2846
+ readonly errorText: _angular_core.InputSignal<string>;
2595
2847
  readonly _bindings: _angular_core.InputSignal<Record<string, string>>;
2596
2848
  readonly bindings: _angular_core.InputSignal<Record<string, string>>;
2597
2849
  readonly loading: _angular_core.InputSignal<boolean>;
2598
2850
  readonly childKeys: _angular_core.InputSignal<string[]>;
2599
2851
  readonly spec: _angular_core.InputSignal<Spec | undefined>;
2600
- protected readonly effectiveValue: _angular_core.Signal<boolean>;
2601
2852
  onChange(event: Event): void;
2602
2853
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<A2uiCheckBoxComponent, never>;
2603
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<A2uiCheckBoxComponent, "a2ui-check-box", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "checked": { "alias": "checked"; "required": false; "isSignal": true; }; "_bindings": { "alias": "_bindings"; "required": false; "isSignal": true; }; "bindings": { "alias": "bindings"; "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>;
2854
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<A2uiCheckBoxComponent, "a2ui-check-box", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "errorText": { "alias": "errorText"; "required": false; "isSignal": true; }; "_bindings": { "alias": "_bindings"; "required": false; "isSignal": true; }; "bindings": { "alias": "bindings"; "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>;
2604
2855
  }
2605
2856
 
2857
+ type ButtonVariant = 'default' | 'primary' | 'borderless';
2606
2858
  declare class A2uiButtonComponent {
2607
- /** v1: child Text component is rendered inside the button via childKeys. */
2859
+ /** v0.9: child Text component is rendered inside the button via childKeys. */
2608
2860
  readonly childKeys: _angular_core.InputSignal<string[]>;
2609
2861
  readonly spec: _angular_core.InputSignal<Spec>;
2610
- readonly primary: _angular_core.InputSignal<boolean>;
2862
+ /** v0.9 prop: visual style (default 'default'). */
2863
+ readonly variant: _angular_core.InputSignal<ButtonVariant>;
2611
2864
  readonly disabled: _angular_core.InputSignal<boolean>;
2612
2865
  readonly emit: _angular_core.InputSignal<(event: string) => void>;
2613
2866
  readonly bindings: _angular_core.InputSignal<Record<string, string>>;
2614
2867
  readonly loading: _angular_core.InputSignal<boolean>;
2868
+ protected cssClass(): string;
2615
2869
  handleClick(): void;
2616
2870
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<A2uiButtonComponent, never>;
2617
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<A2uiButtonComponent, "a2ui-button", never, { "childKeys": { "alias": "childKeys"; "required": false; "isSignal": true; }; "spec": { "alias": "spec"; "required": true; "isSignal": true; }; "primary": { "alias": "primary"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "emit": { "alias": "emit"; "required": false; "isSignal": true; }; "bindings": { "alias": "bindings"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
2871
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<A2uiButtonComponent, "a2ui-button", never, { "childKeys": { "alias": "childKeys"; "required": false; "isSignal": true; }; "spec": { "alias": "spec"; "required": true; "isSignal": true; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "emit": { "alias": "emit"; "required": false; "isSignal": true; }; "bindings": { "alias": "bindings"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
2618
2872
  }
2619
2873
 
2620
2874
  /** Resolved option shape — label and value are plain strings after surface-to-spec resolves them. */
@@ -2622,30 +2876,44 @@ interface ResolvedOption {
2622
2876
  label: string;
2623
2877
  value: string;
2624
2878
  }
2625
- declare class A2uiMultipleChoiceComponent {
2879
+ declare class A2uiChoicePickerComponent {
2880
+ private static _idCounter;
2881
+ /** Groups the radio inputs of this instance (mutuallyExclusive mode). */
2882
+ protected readonly _groupName: string;
2626
2883
  private readonly host;
2627
2884
  readonly label: _angular_core.InputSignal<string>;
2628
- /** Resolved current selections from surface-to-spec. Normalized in
2629
- * `selectionsArray` because LLMs sometimes seed the data model with a
2630
- * scalar (e.g. `"5"`) instead of an array (`["5"]`); we coerce so
2631
- * .includes() works either way. */
2632
- readonly selections: _angular_core.InputSignal<string | string[] | undefined>;
2633
- protected readonly selectionsArray: _angular_core.Signal<string[]>;
2885
+ /** v0.9 prop: current selection (string[]). Normalized in `valueArray`
2886
+ * because LLMs sometimes seed the data model with a scalar (e.g. `"5"`)
2887
+ * instead of an array (`["5"]`); we coerce so .includes() works either way. */
2888
+ readonly value: _angular_core.InputSignal<string | string[] | undefined>;
2634
2889
  /** Resolved options with plain string labels (surface-to-spec resolves DynamicString). */
2635
2890
  readonly options: _angular_core.InputSignal<ResolvedOption[]>;
2636
- /** When 1 — render as single-select <select>; otherwise multi-select checkboxes. */
2637
- readonly maxAllowedSelections: _angular_core.InputSignal<number>;
2891
+ /** v0.9 prop: 'mutuallyExclusive' (single-select, default) or 'multipleSelection'. */
2892
+ readonly variant: _angular_core.InputSignal<"mutuallyExclusive" | "multipleSelection">;
2893
+ /** v0.9 prop: render as 'checkbox' rows (default) or 'chips'. */
2894
+ readonly displayStyle: _angular_core.InputSignal<"checkbox" | "chips">;
2895
+ /** v0.9 prop: when true, show a client-side option filter input. */
2896
+ readonly filterable: _angular_core.InputSignal<boolean>;
2897
+ /** Live validation message written by the surface's check gate
2898
+ * (bound to /_a2uiChecks/<id>); empty when valid. */
2899
+ readonly errorText: _angular_core.InputSignal<string>;
2638
2900
  readonly _bindings: _angular_core.InputSignal<Record<string, string>>;
2639
2901
  readonly bindings: _angular_core.InputSignal<Record<string, string>>;
2640
2902
  readonly loading: _angular_core.InputSignal<boolean>;
2641
2903
  readonly childKeys: _angular_core.InputSignal<string[]>;
2642
2904
  readonly spec: _angular_core.InputSignal<Spec | undefined>;
2905
+ protected readonly valueArray: _angular_core.Signal<string[]>;
2643
2906
  protected readonly isSingleSelect: _angular_core.Signal<boolean>;
2907
+ /** Local, client-side option filter (only rendered when filterable). */
2908
+ protected readonly filterText: _angular_core.WritableSignal<string>;
2909
+ protected readonly visibleOptions: _angular_core.Signal<ResolvedOption[]>;
2644
2910
  protected isSelected(value: string): boolean;
2645
- onSelectChange(event: Event): void;
2911
+ onFilterInput(event: Event): void;
2646
2912
  onCheckChange(value: string, event: Event): void;
2647
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<A2uiMultipleChoiceComponent, never>;
2648
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<A2uiMultipleChoiceComponent, "a2ui-multiple-choice", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "selections": { "alias": "selections"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; "maxAllowedSelections": { "alias": "maxAllowedSelections"; "required": false; "isSignal": true; }; "_bindings": { "alias": "_bindings"; "required": false; "isSignal": true; }; "bindings": { "alias": "bindings"; "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>;
2913
+ onChipToggle(value: string): void;
2914
+ private toggled;
2915
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<A2uiChoicePickerComponent, never>;
2916
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<A2uiChoicePickerComponent, "a2ui-choice-picker", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "displayStyle": { "alias": "displayStyle"; "required": false; "isSignal": true; }; "filterable": { "alias": "filterable"; "required": false; "isSignal": true; }; "errorText": { "alias": "errorText"; "required": false; "isSignal": true; }; "_bindings": { "alias": "_bindings"; "required": false; "isSignal": true; }; "bindings": { "alias": "bindings"; "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>;
2649
2917
  }
2650
2918
 
2651
2919
  declare class A2uiSliderComponent {
@@ -2653,13 +2921,15 @@ declare class A2uiSliderComponent {
2653
2921
  protected readonly _inputId: string;
2654
2922
  private readonly host;
2655
2923
  readonly label: _angular_core.InputSignal<string>;
2656
- /** v1 prop: value (resolved DynamicNumber). */
2924
+ /** v0.9 prop: value (resolved DynamicNumber). */
2657
2925
  readonly value: _angular_core.InputSignal<number>;
2658
- /** v1 prop: minValue. */
2659
- readonly minValue: _angular_core.InputSignal<number>;
2660
- /** v1 prop: maxValue. */
2661
- readonly maxValue: _angular_core.InputSignal<number>;
2662
- readonly step: _angular_core.InputSignal<number>;
2926
+ /** v0.9 prop: lower bound (default 0). */
2927
+ readonly min: _angular_core.InputSignal<number>;
2928
+ /** v0.9 prop: upper bound. */
2929
+ readonly max: _angular_core.InputSignal<number>;
2930
+ /** Live validation message written by the surface's check gate
2931
+ * (bound to /_a2uiChecks/<id>); empty when valid. */
2932
+ readonly errorText: _angular_core.InputSignal<string>;
2663
2933
  readonly _bindings: _angular_core.InputSignal<Record<string, string>>;
2664
2934
  readonly bindings: _angular_core.InputSignal<Record<string, string>>;
2665
2935
  readonly loading: _angular_core.InputSignal<boolean>;
@@ -2667,7 +2937,7 @@ declare class A2uiSliderComponent {
2667
2937
  readonly spec: _angular_core.InputSignal<Spec | undefined>;
2668
2938
  onInput(event: Event): void;
2669
2939
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<A2uiSliderComponent, never>;
2670
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<A2uiSliderComponent, "a2ui-slider", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "minValue": { "alias": "minValue"; "required": false; "isSignal": true; }; "maxValue": { "alias": "maxValue"; "required": false; "isSignal": true; }; "step": { "alias": "step"; "required": false; "isSignal": true; }; "_bindings": { "alias": "_bindings"; "required": false; "isSignal": true; }; "bindings": { "alias": "bindings"; "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>;
2940
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<A2uiSliderComponent, "a2ui-slider", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "min": { "alias": "min"; "required": false; "isSignal": true; }; "max": { "alias": "max"; "required": false; "isSignal": true; }; "errorText": { "alias": "errorText"; "required": false; "isSignal": true; }; "_bindings": { "alias": "_bindings"; "required": false; "isSignal": true; }; "bindings": { "alias": "bindings"; "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>;
2671
2941
  }
2672
2942
 
2673
2943
  declare class A2uiDateTimeInputComponent {
@@ -2675,12 +2945,19 @@ declare class A2uiDateTimeInputComponent {
2675
2945
  protected readonly _inputId: string;
2676
2946
  private readonly host;
2677
2947
  readonly label: _angular_core.InputSignal<string>;
2678
- /** v1 prop: value (resolved DynamicString). */
2948
+ /** v0.9 prop: ISO 8601 value (resolved DynamicString). Still renders when absent. */
2679
2949
  readonly value: _angular_core.InputSignal<string>;
2680
- /** v1 prop: enableDate — include date portion. */
2950
+ /** v0.9 prop: enableDate — include date portion. */
2681
2951
  readonly enableDate: _angular_core.InputSignal<boolean>;
2682
- /** v1 prop: enableTime — include time portion. */
2952
+ /** v0.9 prop: enableTime — include time portion. */
2683
2953
  readonly enableTime: _angular_core.InputSignal<boolean>;
2954
+ /** v0.9 prop: ISO lower bound mapped to the native input's min. */
2955
+ readonly min: _angular_core.InputSignal<string | undefined>;
2956
+ /** v0.9 prop: ISO upper bound mapped to the native input's max. */
2957
+ readonly max: _angular_core.InputSignal<string | undefined>;
2958
+ /** Live validation message written by the surface's check gate
2959
+ * (bound to /_a2uiChecks/<id>); empty when valid. */
2960
+ readonly errorText: _angular_core.InputSignal<string>;
2684
2961
  readonly _bindings: _angular_core.InputSignal<Record<string, string>>;
2685
2962
  readonly bindings: _angular_core.InputSignal<Record<string, string>>;
2686
2963
  readonly loading: _angular_core.InputSignal<boolean>;
@@ -2690,13 +2967,14 @@ declare class A2uiDateTimeInputComponent {
2690
2967
  protected readonly htmlInputType: _angular_core.Signal<string>;
2691
2968
  onChange(event: Event): void;
2692
2969
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<A2uiDateTimeInputComponent, never>;
2693
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<A2uiDateTimeInputComponent, "a2ui-date-time-input", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "enableDate": { "alias": "enableDate"; "required": false; "isSignal": true; }; "enableTime": { "alias": "enableTime"; "required": false; "isSignal": true; }; "_bindings": { "alias": "_bindings"; "required": false; "isSignal": true; }; "bindings": { "alias": "bindings"; "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>;
2970
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<A2uiDateTimeInputComponent, "a2ui-date-time-input", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "enableDate": { "alias": "enableDate"; "required": false; "isSignal": true; }; "enableTime": { "alias": "enableTime"; "required": false; "isSignal": true; }; "min": { "alias": "min"; "required": false; "isSignal": true; }; "max": { "alias": "max"; "required": false; "isSignal": true; }; "errorText": { "alias": "errorText"; "required": false; "isSignal": true; }; "_bindings": { "alias": "_bindings"; "required": false; "isSignal": true; }; "bindings": { "alias": "bindings"; "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>;
2694
2971
  }
2695
2972
 
2696
- type UsageHint = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'caption' | 'body';
2973
+ type TextVariant = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'caption' | 'body';
2697
2974
  declare class A2uiTextComponent {
2698
2975
  readonly text: _angular_core.InputSignal<string>;
2699
- readonly usageHint: _angular_core.InputSignal<UsageHint>;
2976
+ /** v0.9 prop: typography variant. */
2977
+ readonly variant: _angular_core.InputSignal<TextVariant>;
2700
2978
  readonly bindings: _angular_core.InputSignal<Record<string, string>>;
2701
2979
  readonly emit: _angular_core.InputSignal<(event: string) => void>;
2702
2980
  readonly loading: _angular_core.InputSignal<boolean>;
@@ -2704,92 +2982,98 @@ declare class A2uiTextComponent {
2704
2982
  readonly spec: _angular_core.InputSignal<Spec | undefined>;
2705
2983
  protected cssClass(): string;
2706
2984
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<A2uiTextComponent, never>;
2707
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<A2uiTextComponent, "a2ui-text", never, { "text": { "alias": "text"; "required": false; "isSignal": true; }; "usageHint": { "alias": "usageHint"; "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>;
2985
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<A2uiTextComponent, "a2ui-text", never, { "text": { "alias": "text"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "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>;
2708
2986
  }
2709
2987
 
2710
2988
  declare class A2uiIconComponent {
2711
- /** v1 canonical prop. */
2712
- readonly name: _angular_core.InputSignal<string | undefined>;
2713
- /** Pre-v1 alias retained for back-compat. */
2714
- readonly icon: _angular_core.InputSignal<string>;
2715
- readonly size: _angular_core.InputSignal<number | null>;
2989
+ /** v0.9 prop: a Material Symbols name (string) or an inline `{ svgPath }`. */
2990
+ readonly name: _angular_core.InputSignal<string | {
2991
+ svgPath: string;
2992
+ } | undefined>;
2716
2993
  readonly bindings: _angular_core.InputSignal<Record<string, string>>;
2717
2994
  readonly emit: _angular_core.InputSignal<(event: string) => void>;
2718
2995
  readonly loading: _angular_core.InputSignal<boolean>;
2719
2996
  readonly childKeys: _angular_core.InputSignal<string[]>;
2720
2997
  readonly spec: _angular_core.InputSignal<Spec | undefined>;
2721
- protected readonly effectiveName: _angular_core.Signal<string>;
2998
+ /** Inline SVG path when `name` is the `{ svgPath }` object form. */
2999
+ protected readonly svgPath: _angular_core.Signal<string | null>;
3000
+ /** The string ligature name when `name` is a string. */
3001
+ protected readonly ligatureName: _angular_core.Signal<string>;
2722
3002
  /** The effective name as a Material Symbols ligature (camelCase → snake_case). */
2723
3003
  protected readonly glyphName: _angular_core.Signal<string>;
2724
3004
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<A2uiIconComponent, never>;
2725
- 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>;
3005
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<A2uiIconComponent, "a2ui-icon", never, { "name": { "alias": "name"; "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>;
2726
3006
  }
2727
3007
 
2728
- /** v1 fit values mapped 1:1 to CSS object-fit. */
2729
- type ImageFit = 'contain' | 'cover' | 'fill' | 'none' | 'scale-down';
2730
- /** v1 usageHint maps to a sizing preset. The component renders fluid by
2731
- * default; usageHint sets a max-width / aspect-ratio to match common
2732
- * intents. */
2733
- type ImageUsageHint = 'icon' | 'avatar' | 'smallFeature' | 'mediumFeature' | 'largeFeature' | 'header';
3008
+ /** v0.9 fit values; 'scaleDown' maps to CSS object-fit: scale-down. */
3009
+ type ImageFit = 'contain' | 'cover' | 'fill' | 'none' | 'scaleDown';
3010
+ /** v0.9 variant maps to a sizing preset class. */
3011
+ type ImageVariant = 'icon' | 'avatar' | 'smallFeature' | 'mediumFeature' | 'largeFeature' | 'header';
2734
3012
  declare class A2uiImageComponent {
2735
3013
  readonly url: _angular_core.InputSignal<string>;
2736
- readonly alt: _angular_core.InputSignal<string>;
2737
- readonly width: _angular_core.InputSignal<number | null>;
2738
- readonly height: _angular_core.InputSignal<number | null>;
2739
- /** v1 prop: CSS object-fit equivalent. */
2740
- readonly fit: _angular_core.InputSignal<ImageFit | undefined>;
2741
- /** v1 prop: sizing preset. */
2742
- readonly usageHint: _angular_core.InputSignal<ImageUsageHint | undefined>;
3014
+ /** v0.9 prop: alt text / accessible description. */
3015
+ readonly description: _angular_core.InputSignal<string>;
3016
+ /** v0.9 prop: CSS object-fit equivalent ('scaleDown' → 'scale-down'). */
3017
+ readonly fit: _angular_core.InputSignal<ImageFit>;
3018
+ /** v0.9 prop: sizing preset. */
3019
+ readonly variant: _angular_core.InputSignal<ImageVariant>;
2743
3020
  readonly bindings: _angular_core.InputSignal<Record<string, string>>;
2744
3021
  readonly emit: _angular_core.InputSignal<(event: string) => void>;
2745
3022
  readonly loading: _angular_core.InputSignal<boolean>;
2746
3023
  readonly childKeys: _angular_core.InputSignal<string[]>;
2747
3024
  readonly spec: _angular_core.InputSignal<Spec | undefined>;
2748
- protected explicitWidth(): string | null;
2749
- protected explicitHeight(): string | null;
2750
- protected hintStyle(): {
2751
- maxWidth: string;
2752
- aspectRatio?: string;
2753
- borderRadius?: string;
2754
- } | null;
3025
+ protected readonly objectFit: _angular_core.Signal<string>;
3026
+ protected readonly cssClass: _angular_core.Signal<string>;
2755
3027
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<A2uiImageComponent, never>;
2756
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<A2uiImageComponent, "a2ui-image", never, { "url": { "alias": "url"; "required": false; "isSignal": true; }; "alt": { "alias": "alt"; "required": false; "isSignal": true; }; "width": { "alias": "width"; "required": false; "isSignal": true; }; "height": { "alias": "height"; "required": false; "isSignal": true; }; "fit": { "alias": "fit"; "required": false; "isSignal": true; }; "usageHint": { "alias": "usageHint"; "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>;
3028
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<A2uiImageComponent, "a2ui-image", never, { "url": { "alias": "url"; "required": false; "isSignal": true; }; "description": { "alias": "description"; "required": false; "isSignal": true; }; "fit": { "alias": "fit"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "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>;
2757
3029
  }
2758
3030
 
2759
- type ColumnAlignment = 'start' | 'center' | 'end' | 'stretch';
3031
+ type ColumnAlign = 'start' | 'center' | 'end' | 'stretch';
3032
+ type ColumnJustify = 'start' | 'center' | 'end' | 'spaceAround' | 'spaceBetween' | 'spaceEvenly' | 'stretch';
2760
3033
  declare class A2uiColumnComponent {
2761
3034
  readonly childKeys: _angular_core.InputSignal<string[]>;
2762
3035
  readonly spec: _angular_core.InputSignal<Spec>;
2763
- readonly gap: _angular_core.InputSignal<number>;
2764
- readonly alignment: _angular_core.InputSignal<ColumnAlignment>;
2765
- readonly distribution: _angular_core.InputSignal<"center" | "start" | "end" | "spaceBetween" | "spaceAround" | "spaceEvenly">;
3036
+ /** v0.9 prop: cross-axis alignment (default 'stretch'). */
3037
+ readonly align: _angular_core.InputSignal<ColumnAlign>;
3038
+ /** v0.9 prop: main-axis distribution (default 'start'). */
3039
+ readonly justify: _angular_core.InputSignal<ColumnJustify>;
3040
+ /** Not part of the v0.9 catalog — kept for json-render generative-ui
3041
+ * specs, which may set a numeric spacing unit (multiples of 4px) or a
3042
+ * named size. Unset falls back to the CSS default gap. */
3043
+ readonly gap: _angular_core.InputSignal<number | "small" | "medium" | "large" | undefined>;
2766
3044
  readonly bindings: _angular_core.InputSignal<Record<string, string>>;
2767
3045
  readonly emit: _angular_core.InputSignal<(event: string) => void>;
2768
3046
  readonly loading: _angular_core.InputSignal<boolean>;
2769
3047
  protected readonly alignItems: _angular_core.Signal<string>;
2770
- /** Convert the Tailwind gap unit (multiples of 4px) to pixels. */
2771
- protected readonly gapPx: _angular_core.Signal<number>;
3048
+ protected readonly justifyContent: _angular_core.Signal<string>;
3049
+ protected readonly cssClass: _angular_core.Signal<"a2ui-col a2ui-col--justify-stretch" | "a2ui-col">;
3050
+ protected readonly gapPx: _angular_core.Signal<number | null>;
2772
3051
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<A2uiColumnComponent, never>;
2773
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<A2uiColumnComponent, "a2ui-column", never, { "childKeys": { "alias": "childKeys"; "required": false; "isSignal": true; }; "spec": { "alias": "spec"; "required": true; "isSignal": true; }; "gap": { "alias": "gap"; "required": false; "isSignal": true; }; "alignment": { "alias": "alignment"; "required": false; "isSignal": true; }; "distribution": { "alias": "distribution"; "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; }; }, {}, never, never, true, never>;
3052
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<A2uiColumnComponent, "a2ui-column", never, { "childKeys": { "alias": "childKeys"; "required": false; "isSignal": true; }; "spec": { "alias": "spec"; "required": true; "isSignal": true; }; "align": { "alias": "align"; "required": false; "isSignal": true; }; "justify": { "alias": "justify"; "required": false; "isSignal": true; }; "gap": { "alias": "gap"; "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; }; }, {}, never, never, true, never>;
2774
3053
  }
2775
3054
 
2776
- type RowAlignment = 'start' | 'center' | 'end' | 'stretch';
2777
- type RowDistribution = 'start' | 'center' | 'end' | 'space-between' | 'space-around';
3055
+ type RowAlign = 'start' | 'center' | 'end' | 'stretch';
3056
+ type RowJustify = 'start' | 'center' | 'end' | 'spaceAround' | 'spaceBetween' | 'spaceEvenly' | 'stretch';
2778
3057
  declare class A2uiRowComponent {
2779
3058
  readonly childKeys: _angular_core.InputSignal<string[]>;
2780
3059
  readonly spec: _angular_core.InputSignal<Spec>;
2781
- readonly gap: _angular_core.InputSignal<number>;
2782
- readonly alignment: _angular_core.InputSignal<RowAlignment>;
2783
- readonly distribution: _angular_core.InputSignal<RowDistribution>;
3060
+ /** v0.9 prop: cross-axis alignment (default 'stretch'). */
3061
+ readonly align: _angular_core.InputSignal<RowAlign>;
3062
+ /** v0.9 prop: main-axis distribution (default 'start'). */
3063
+ readonly justify: _angular_core.InputSignal<RowJustify>;
3064
+ /** Not part of the v0.9 catalog — kept for json-render generative-ui
3065
+ * specs, which may set a numeric spacing unit (multiples of 4px) or a
3066
+ * named size. Unset falls back to the CSS default gap. */
3067
+ readonly gap: _angular_core.InputSignal<number | "small" | "medium" | "large" | undefined>;
2784
3068
  readonly bindings: _angular_core.InputSignal<Record<string, string>>;
2785
3069
  readonly emit: _angular_core.InputSignal<(event: string) => void>;
2786
3070
  readonly loading: _angular_core.InputSignal<boolean>;
2787
3071
  protected readonly alignItems: _angular_core.Signal<string>;
2788
3072
  protected readonly justifyContent: _angular_core.Signal<string>;
2789
- /** Convert the gap unit (multiples of 4px) to pixels. */
2790
- protected readonly gapPx: _angular_core.Signal<number>;
3073
+ protected readonly cssClass: _angular_core.Signal<"a2ui-row" | "a2ui-row a2ui-row--justify-stretch">;
3074
+ protected readonly gapPx: _angular_core.Signal<number | null>;
2791
3075
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<A2uiRowComponent, never>;
2792
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<A2uiRowComponent, "a2ui-row", never, { "childKeys": { "alias": "childKeys"; "required": false; "isSignal": true; }; "spec": { "alias": "spec"; "required": true; "isSignal": true; }; "gap": { "alias": "gap"; "required": false; "isSignal": true; }; "alignment": { "alias": "alignment"; "required": false; "isSignal": true; }; "distribution": { "alias": "distribution"; "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; }; }, {}, never, never, true, never>;
3076
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<A2uiRowComponent, "a2ui-row", never, { "childKeys": { "alias": "childKeys"; "required": false; "isSignal": true; }; "spec": { "alias": "spec"; "required": true; "isSignal": true; }; "align": { "alias": "align"; "required": false; "isSignal": true; }; "justify": { "alias": "justify"; "required": false; "isSignal": true; }; "gap": { "alias": "gap"; "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; }; }, {}, never, never, true, never>;
2793
3077
  }
2794
3078
 
2795
3079
  declare class A2uiCardComponent {
@@ -2804,11 +3088,8 @@ declare class A2uiCardComponent {
2804
3088
  }
2805
3089
 
2806
3090
  declare class A2uiDividerComponent {
2807
- /** Canonical v1 spec name. The LLM emits this. */
2808
- readonly axis: _angular_core.InputSignal<"horizontal" | "vertical" | undefined>;
2809
- /** Older alias retained for json-render usage and back-compat. */
2810
- readonly direction: _angular_core.InputSignal<"horizontal" | "vertical">;
2811
- /** Effective axis — `axis` wins if provided, otherwise fall back to `direction`. */
3091
+ /** v0.9 prop: divider axis (default 'horizontal'). */
3092
+ readonly axis: _angular_core.InputSignal<"horizontal" | "vertical">;
2812
3093
  protected readonly orientation: _angular_core.Signal<"horizontal" | "vertical">;
2813
3094
  readonly bindings: _angular_core.InputSignal<Record<string, string>>;
2814
3095
  readonly emit: _angular_core.InputSignal<(event: string) => void>;
@@ -2816,33 +3097,31 @@ declare class A2uiDividerComponent {
2816
3097
  readonly childKeys: _angular_core.InputSignal<string[]>;
2817
3098
  readonly spec: _angular_core.InputSignal<Spec | undefined>;
2818
3099
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<A2uiDividerComponent, never>;
2819
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<A2uiDividerComponent, "a2ui-divider", never, { "axis": { "alias": "axis"; "required": false; "isSignal": true; }; "direction": { "alias": "direction"; "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>;
3100
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<A2uiDividerComponent, "a2ui-divider", never, { "axis": { "alias": "axis"; "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>;
2820
3101
  }
2821
3102
 
2822
3103
  declare class A2uiListComponent {
2823
3104
  readonly childKeys: _angular_core.InputSignal<string[]>;
2824
3105
  readonly spec: _angular_core.InputSignal<Spec>;
2825
3106
  readonly direction: _angular_core.InputSignal<"horizontal" | "vertical">;
2826
- /** v1 canonical prop: cross-axis alignment. */
2827
- readonly alignment: _angular_core.InputSignal<"center" | "start" | "end" | "stretch" | undefined>;
3107
+ /** v0.9 prop: cross-axis alignment (default 'stretch'). */
3108
+ readonly align: _angular_core.InputSignal<"center" | "start" | "end" | "stretch">;
2828
3109
  readonly bindings: _angular_core.InputSignal<Record<string, string>>;
2829
3110
  readonly emit: _angular_core.InputSignal<(event: string) => void>;
2830
3111
  readonly loading: _angular_core.InputSignal<boolean>;
2831
3112
  protected readonly listClass: _angular_core.Signal<"a2ui-list--horizontal" | "a2ui-list--vertical">;
2832
- protected readonly alignmentCss: _angular_core.Signal<string | null>;
3113
+ protected readonly alignmentCss: _angular_core.Signal<string>;
2833
3114
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<A2uiListComponent, never>;
2834
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<A2uiListComponent, "a2ui-list", never, { "childKeys": { "alias": "childKeys"; "required": false; "isSignal": true; }; "spec": { "alias": "spec"; "required": true; "isSignal": true; }; "direction": { "alias": "direction"; "required": false; "isSignal": true; }; "alignment": { "alias": "alignment"; "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; }; }, {}, never, never, true, never>;
3115
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<A2uiListComponent, "a2ui-list", never, { "childKeys": { "alias": "childKeys"; "required": false; "isSignal": true; }; "spec": { "alias": "spec"; "required": true; "isSignal": true; }; "direction": { "alias": "direction"; "required": false; "isSignal": true; }; "align": { "alias": "align"; "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; }; }, {}, never, never, true, never>;
2835
3116
  }
2836
3117
 
2837
3118
  declare class A2uiModalComponent {
2838
3119
  /**
2839
- * v1: childKeys[0] = entryPointChild (inline trigger),
2840
- * childKeys[1] = contentChild (modal body).
3120
+ * v0.9: childKeys[0] = trigger (inline entry point),
3121
+ * childKeys[1] = content (modal body).
2841
3122
  */
2842
3123
  readonly childKeys: _angular_core.InputSignal<string[]>;
2843
3124
  readonly spec: _angular_core.InputSignal<Spec>;
2844
- /** Resolved title string (from optional title DynamicString). */
2845
- readonly title: _angular_core.InputSignal<string>;
2846
3125
  readonly bindings: _angular_core.InputSignal<Record<string, string>>;
2847
3126
  readonly emit: _angular_core.InputSignal<(event: string) => void>;
2848
3127
  readonly loading: _angular_core.InputSignal<boolean>;
@@ -2850,13 +3129,13 @@ declare class A2uiModalComponent {
2850
3129
  protected readonly entryPointKey: _angular_core.Signal<string>;
2851
3130
  protected readonly contentKey: _angular_core.Signal<string>;
2852
3131
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<A2uiModalComponent, never>;
2853
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<A2uiModalComponent, "a2ui-modal", never, { "childKeys": { "alias": "childKeys"; "required": false; "isSignal": true; }; "spec": { "alias": "spec"; "required": true; "isSignal": true; }; "title": { "alias": "title"; "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; }; }, {}, never, never, true, never>;
3132
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<A2uiModalComponent, "a2ui-modal", never, { "childKeys": { "alias": "childKeys"; "required": false; "isSignal": true; }; "spec": { "alias": "spec"; "required": true; "isSignal": true; }; "bindings": { "alias": "bindings"; "required": false; "isSignal": true; }; "emit": { "alias": "emit"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
2854
3133
  }
2855
3134
 
2856
3135
  declare class A2uiTabsComponent {
2857
- /** Resolved tab titles from tabItems[*].title — produced by surface-to-spec. */
3136
+ /** Resolved tab titles from tabs[*].title — produced by surface-to-spec. */
2858
3137
  readonly tabTitles: _angular_core.InputSignal<string[]>;
2859
- /** v1: each child key corresponds to a tab's contentChild (childKeys[i] ↔ tabTitles[i]). */
3138
+ /** v0.9: each child key corresponds to a tab's child (childKeys[i] ↔ tabTitles[i]). */
2860
3139
  readonly childKeys: _angular_core.InputSignal<string[]>;
2861
3140
  readonly spec: _angular_core.InputSignal<Spec>;
2862
3141
  readonly bindings: _angular_core.InputSignal<Record<string, string>>;
@@ -2872,32 +3151,26 @@ declare class A2uiTabsComponent {
2872
3151
 
2873
3152
  declare class A2uiAudioPlayerComponent {
2874
3153
  readonly url: _angular_core.InputSignal<string>;
2875
- /** v1 canonical prop: short description / title rendered above the player. */
3154
+ /** v0.9 prop: short description / title rendered above the player. */
2876
3155
  readonly description: _angular_core.InputSignal<string>;
2877
- /** v1 prop name: autoPlay (camelCase). */
2878
- readonly autoPlay: _angular_core.InputSignal<boolean>;
2879
- readonly controls: _angular_core.InputSignal<boolean>;
2880
3156
  readonly bindings: _angular_core.InputSignal<Record<string, string>>;
2881
3157
  readonly emit: _angular_core.InputSignal<(event: string) => void>;
2882
3158
  readonly loading: _angular_core.InputSignal<boolean>;
2883
3159
  readonly childKeys: _angular_core.InputSignal<string[]>;
2884
3160
  readonly spec: _angular_core.InputSignal<Spec | undefined>;
2885
3161
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<A2uiAudioPlayerComponent, never>;
2886
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<A2uiAudioPlayerComponent, "a2ui-audio-player", never, { "url": { "alias": "url"; "required": false; "isSignal": true; }; "description": { "alias": "description"; "required": false; "isSignal": true; }; "autoPlay": { "alias": "autoPlay"; "required": false; "isSignal": true; }; "controls": { "alias": "controls"; "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>;
3162
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<A2uiAudioPlayerComponent, "a2ui-audio-player", never, { "url": { "alias": "url"; "required": false; "isSignal": true; }; "description": { "alias": "description"; "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>;
2887
3163
  }
2888
3164
 
2889
3165
  declare class A2uiVideoComponent {
2890
3166
  readonly url: _angular_core.InputSignal<string>;
2891
- /** v1 prop name: autoPlay (camelCase). */
2892
- readonly autoPlay: _angular_core.InputSignal<boolean>;
2893
- readonly controls: _angular_core.InputSignal<boolean>;
2894
3167
  readonly bindings: _angular_core.InputSignal<Record<string, string>>;
2895
3168
  readonly emit: _angular_core.InputSignal<(event: string) => void>;
2896
3169
  readonly loading: _angular_core.InputSignal<boolean>;
2897
3170
  readonly childKeys: _angular_core.InputSignal<string[]>;
2898
3171
  readonly spec: _angular_core.InputSignal<Spec | undefined>;
2899
3172
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<A2uiVideoComponent, never>;
2900
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<A2uiVideoComponent, "a2ui-video", never, { "url": { "alias": "url"; "required": false; "isSignal": true; }; "autoPlay": { "alias": "autoPlay"; "required": false; "isSignal": true; }; "controls": { "alias": "controls"; "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>;
3173
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<A2uiVideoComponent, "a2ui-video", never, { "url": { "alias": "url"; "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>;
2901
3174
  }
2902
3175
 
2903
3176
  /**
@@ -2961,8 +3234,11 @@ type ViewProps<S extends StandardSchemaV1> = Prettify<StandardSchemaInferOutput<
2961
3234
  * @param description Natural-language description the model sees.
2962
3235
  * @param schema Standard Schema (e.g. a Zod object) for the arguments; the
2963
3236
  * handler's argument type is inferred from it.
2964
- * @param handler Runs in the browser when the model calls the tool; its return
2965
- * type `R` is carried on the resulting {@link FunctionToolDef}.
3237
+ * @param handler Runs in the browser when the model calls the tool. The second
3238
+ * argument carries an `AbortSignal`; its return type `R` is carried on the
3239
+ * resulting {@link FunctionToolDef}.
3240
+ * @param options Execution policy options, including `idempotent: true` to skip
3241
+ * durable pre-execution claims when a guard is configured.
2966
3242
  * @returns A {@link FunctionToolDef} for inclusion in {@link tools}.
2967
3243
  * @example
2968
3244
  * ```ts
@@ -2970,7 +3246,7 @@ type ViewProps<S extends StandardSchemaV1> = Prettify<StandardSchemaInferOutput<
2970
3246
  * const registry = tools({ move_stop: move });
2971
3247
  * ```
2972
3248
  */
2973
- declare function action<S extends StandardSchemaV1, R>(description: string, schema: S, handler: (args: StandardSchemaInferOutput<S>) => R | Promise<R>): FunctionToolDef<S, R>;
3249
+ declare function action<S extends StandardSchemaV1, R>(description: string, schema: S, handler: (args: StandardSchemaInferOutput<S>, context: FunctionToolHandlerContext) => R | Promise<R>, options?: ClientToolExecutionOptions): FunctionToolDef<S, R>;
2974
3250
  /**
2975
3251
  * Render-only component tool — the model fills the component's props from the
2976
3252
  * schema's output; the tool call is auto-acknowledged once the component mounts.
@@ -3001,7 +3277,7 @@ declare function action<S extends StandardSchemaV1, R>(description: string, sche
3001
3277
  * const registry = tools({ day_card: dayCard });
3002
3278
  * ```
3003
3279
  */
3004
- declare function view<S extends StandardSchemaV1, C>(description: string, schema: S, component: AcceptComponent<S, C>): ViewToolDef<S, C>;
3280
+ declare function view<S extends StandardSchemaV1, C>(description: string, schema: S, component: AcceptComponent<S, C>, options?: ClientToolContinuationOptions): ViewToolDef<S, C>;
3005
3281
  /**
3006
3282
  * Interactive (human-in-the-loop) component tool — the model fills the
3007
3283
  * component's props from the schema's output; the value the component emits
@@ -3034,7 +3310,7 @@ declare function view<S extends StandardSchemaV1, C>(description: string, schema
3034
3310
  * const registry = tools({ pick_option: choice });
3035
3311
  * ```
3036
3312
  */
3037
- declare function ask<S extends StandardSchemaV1, C>(description: string, schema: S, component: AcceptComponent<S, C>): AskToolDef<S, C>;
3313
+ declare function ask<S extends StandardSchemaV1, C>(description: string, schema: S, component: AcceptComponent<S, C>, options?: ClientToolContinuationOptions): AskToolDef<S, C>;
3038
3314
  /**
3039
3315
  * Collect named client tools into a frozen, name-keyed registry.
3040
3316
  *
@@ -3059,6 +3335,20 @@ declare function ask<S extends StandardSchemaV1, C>(description: string, schema:
3059
3335
  */
3060
3336
  declare function tools<const M extends Record<string, ClientToolDef>>(map: M): Readonly<M>;
3061
3337
 
3338
+ /** Inputs for {@link selectPendingClientToolCalls}. */
3339
+ interface SelectPendingClientToolCallsInput {
3340
+ /** Whether the agent is currently streaming a run. Pending client tools are hidden while loading. */
3341
+ isLoading: boolean;
3342
+ /** Tool calls observed from the current agent state. */
3343
+ toolCalls: readonly ToolCall[];
3344
+ /** Client-declared tool names that should be handled in the browser. */
3345
+ catalogNames: ReadonlySet<string>;
3346
+ /** Tool-call ids already resolved by the local client instance. */
3347
+ resolvedIds: ReadonlySet<string>;
3348
+ }
3349
+ /** Select client tool calls that are ready for browser-side resolution. */
3350
+ declare function selectPendingClientToolCalls(input: SelectPendingClientToolCallsInput): readonly ToolCall[];
3351
+
3062
3352
  /** Validate raw model args against a Standard Schema. */
3063
3353
  declare function validateArgs(schema: StandardSchemaV1, args: unknown): Promise<{
3064
3354
  ok: true;
@@ -3068,15 +3358,23 @@ declare function validateArgs(schema: StandardSchemaV1, args: unknown): Promise<
3068
3358
  error: string;
3069
3359
  }>;
3070
3360
  /** Validate args, run the handler, and normalize the outcome to a ClientToolResult. */
3071
- declare function executeFunctionTool(def: AnyFunctionToolDef, rawArgs: unknown): Promise<ClientToolResult>;
3361
+ declare function executeFunctionTool(def: AnyFunctionToolDef, rawArgs: unknown, context?: FunctionToolHandlerContext): Promise<ClientToolResult>;
3072
3362
 
3363
+ /** Options for wiring automatic browser function-tool execution. */
3364
+ interface ClientToolExecutorOptions {
3365
+ readonly executionGuard?: ClientToolExecutionGuard;
3366
+ readonly settleToolCall?: (toolCall: ToolCall, result: ClientToolResult) => void;
3367
+ /** Settlement for calls that must NOT continue the run (user abort, teardown). */
3368
+ readonly settleWithoutContinuing?: (toolCall: ToolCall, result: ClientToolResult) => void;
3369
+ readonly shouldExecuteToolCall?: (toolCall: ToolCall) => boolean;
3370
+ }
3073
3371
  /**
3074
3372
  * Watches the agent's pending client tool calls and auto-runs FUNCTION tools,
3075
3373
  * resolving each with its result. View/ask (component) tools are handled by the
3076
3374
  * rendering layer, not here. No-op if the agent lacks the clientTools
3077
3375
  * capability. MUST be called in an injection context (sets up an effect).
3078
3376
  */
3079
- declare function startClientToolExecutor(agent: Agent, registry: ClientToolRegistry): void;
3377
+ declare function startClientToolExecutor(agent: Agent, registry: ClientToolRegistry, options?: ClientToolExecutorOptions): void;
3080
3378
 
3081
3379
  interface ClientToolsCoordinator {
3082
3380
  /** Components for `view`/`ask` tools, keyed by tool name — merge into the chat `views`. */
@@ -3149,8 +3447,10 @@ interface MockAgentOptions {
3149
3447
  * @returns A {@link MockAgent} satisfying the full `Agent` contract.
3150
3448
  * @example
3151
3449
  * ```ts
3450
+ * import { staticDelivery } from '@threadplane/chat';
3451
+ *
3152
3452
  * const agent = mockAgent({
3153
- * messages: [{ id: '1', role: 'assistant', content: 'Hi' }],
3453
+ * messages: [{ id: '1', role: 'assistant', content: 'Hi', delivery: staticDelivery('1') }],
3154
3454
  * isLoading: true,
3155
3455
  * });
3156
3456
  * ```
@@ -3160,5 +3460,5 @@ declare function mockAgent(opts?: MockAgentOptions): MockAgent;
3160
3460
  /** Inferred argument type for a schema (alias of StandardSchemaInferOutput). */
3161
3461
  type ToolArgs<S extends StandardSchemaV1> = StandardSchemaInferOutput<S>;
3162
3462
 
3163
- 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, ChatCitationPreviewComponent, ChatCitationsCardComponent, ChatCitationsComponent, ChatComponent, ChatConfirmDialogComponent, ChatConnectedOverlayDirective, ChatErrorComponent, ChatGenerativeUiComponent, ChatGenuiSkeletonComponent, ChatHistorySearchPaletteComponent, ChatInputComponent, ChatInterruptComponent, ChatInterruptPanelComponent, ChatLauncherButtonComponent, ChatMessageActionsComponent, ChatMessageComponent, ChatMessageListComponent, ChatOverflowMenuComponent, ChatOverlayOriginDirective, 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, citationTypeLabel, createA2uiSurfaceStore, createAgentRef, createContentClassifier, createParseTreeStore, createPartialArgsBridge, deriveDomain, deriveJsonSchema, deriveMonogram, deriveSourceType, emitBinding, executeFunctionTool, extractErrorMessage, formatDuration, formatPublished, getInterrupt, getMessageType, injectThreadRouting, isAbortError, isAssistantMessage, isSystemMessage, isToolMessage, isTyping, isUserMessage, messageContent, mockAgent, monogramColor, monogramHue, normalizeEnvelopeArgs, normalizeViewEntry, provideChat, renderMarkdown, startClientToolExecutor, statusColor, submitMessage, toAgentError, toClientToolSpecs, tools, validateArgs, view };
3164
- 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, ConnectedPosition, ContentBlock, ContentClassifier, ContentType, ElementAccumulationState, FunctionToolDef, InterruptAction, Message, MessageTemplateType, MockAgent, MockAgentOptions, OverflowMenuItem, OverlayPositionResult, ParseTreeStore, PartialArgsBridge, Project, ProjectActionAdapter, ResolvedCitation, Role, Subagent, SubagentStatus, Thread, ThreadActionAdapter, ThreadMatch, ThreadRoutingConfig, ToolArgs, ToolCall, ToolCallInfo, ToolCallStatus, TraceState, ViewProps, ViewToolDef };
3463
+ export { A2uiAudioPlayerComponent, A2uiButtonComponent, A2uiCardComponent, A2uiCheckBoxComponent, A2uiChoicePickerComponent, A2uiColumnComponent, A2uiDateTimeInputComponent, A2uiDividerComponent, A2uiIconComponent, A2uiImageComponent, A2uiListComponent, A2uiModalComponent, A2uiRowComponent, A2uiSliderComponent, A2uiSurfaceComponent, A2uiTabsComponent, A2uiTextComponent, A2uiTextFieldComponent, A2uiVideoComponent, AGENT_ERROR_MESSAGES, AgentError, CHAT_CONFIG, CHAT_LIFECYCLE, ChatApprovalCardComponent, ChatCitationCardTemplateDirective, ChatCitationPreviewComponent, ChatCitationsCardComponent, ChatCitationsComponent, ChatComponent, ChatConfirmDialogComponent, ChatConnectedOverlayDirective, ChatErrorComponent, ChatGenerativeUiComponent, ChatGenuiSkeletonComponent, ChatHistorySearchPaletteComponent, ChatInputComponent, ChatInterruptComponent, ChatInterruptPanelComponent, ChatLauncherButtonComponent, ChatMessageActionsComponent, ChatMessageComponent, ChatMessageListComponent, ChatOverflowMenuComponent, ChatOverlayOriginDirective, 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, STREAMING_MARKDOWN_CONTRACT_VIOLATION_POLICY, a2uiBasicCatalog, a2uiClientCapabilities, action, ask, buildA2uiActionMessage, cacheplaneMarkdownViews, cancelledClientToolResult, citationSourceVisual, citationTypeLabel, citationTypeMeta, clientToolGuardFailureResult, completeDelivery, createA2uiSurfaceStore, createAgentRef, createContentClassifier, createParseTreeStore, createPartialArgsBridge, defaultInterruptedClientToolResult, deriveDomain, deriveJsonSchema, deriveMonogram, deriveSourceType, emitBinding, executeFunctionTool, extractErrorMessage, formatDuration, formatPublished, getInterrupt, getMessageType, injectThreadRouting, isAbortError, isAssistantMessage, isSystemMessage, isToolMessage, isTyping, isUserMessage, markdownDocument, messageContent, mockAgent, monogramColor, monogramHue, normalizeEnvelopeArgs, normalizeViewEntry, provideChat, renderMarkdown, selectPendingClientToolCalls, shouldClaimBeforeExecute, startClientToolExecutor, staticDelivery, statusColor, streamingDelivery, submitMessage, toAgentError, toClientToolSpecs, tools, validateArgs, view };
3464
+ 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, CitationImageVisual, CitationMonogramVisual, CitationSourceVisual, CitationTypeIcon, CitationTypeIconVisual, CitationTypeMeta, ClientToolContinuationLimitEvent, ClientToolContinuationOptions, ClientToolContinuationPolicy, ClientToolDef, ClientToolExecutionGuard, ClientToolExecutionKey, ClientToolExecutionOptions, ClientToolExecutionRecord, ClientToolExecutionStore, ClientToolExecutorOptions, ClientToolLifecycle, ClientToolLifecyclePhase, ClientToolRegistry, ClientToolResult, ClientToolSpec, ClientToolViewProps, ClientToolsCapability, ClientToolsCoordinator, CompleteOutcome, ConnectedPosition, ContentBlock, ContentClassifier, ContentType, ElementAccumulationState, FunctionToolDef, FunctionToolHandlerContext, InterruptAction, Message, MessageDelivery, MessageTemplateType, MockAgent, MockAgentOptions, OverflowMenuItem, OverlayPositionResult, ParseTreeStore, PartialArgsBridge, Project, ProjectActionAdapter, ResolvedCitation, Role, SelectPendingClientToolCallsInput, StreamingMarkdownContractViolationPolicy, StreamingMarkdownDocument, Subagent, SubagentStatus, Thread, ThreadActionAdapter, ThreadMatch, ThreadRoutingConfig, ToolArgs, ToolCall, ToolCallInfo, ToolCallStatus, TraceState, ViewProps, ViewToolDef };