@threadplane/chat 0.0.56 → 0.0.57

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.
@@ -9,20 +9,78 @@ 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;
@@ -1685,7 +1903,7 @@ interface ChatRenderEvent {
1685
1903
  }
1686
1904
 
1687
1905
  declare class ChatComponent {
1688
- readonly agent: _angular_core.InputSignal<Agent<Record<string, unknown>>>;
1906
+ readonly agent: _angular_core.InputSignal<Agent<unknown>>;
1689
1907
  readonly views: _angular_core.InputSignal<Readonly<Record<string, _angular_core.Type<unknown> | _threadplane_render.RenderViewEntry>> | undefined>;
1690
1908
  /**
1691
1909
  * Client-declared tools (`view`/`ask`/`function`) the model may call. When
@@ -1726,9 +1944,12 @@ declare class ChatComponent {
1726
1944
  * Default covers the canonical A2UI + json-render schema tools.
1727
1945
  */
1728
1946
  readonly genuiToolNames: _angular_core.InputSignal<readonly string[]>;
1947
+ readonly clientToolExecutionGuard: _angular_core.InputSignal<ClientToolExecutionGuard | undefined>;
1948
+ readonly clientToolContinuationPolicy: _angular_core.InputSignal<ClientToolContinuationPolicy | undefined>;
1729
1949
  readonly showWelcome: _angular_core.Signal<boolean>;
1730
1950
  readonly threadSelected: _angular_core.OutputEmitterRef<string>;
1731
1951
  readonly renderEvent: _angular_core.OutputEmitterRef<ChatRenderEvent>;
1952
+ readonly clientToolContinuationLimit: _angular_core.OutputEmitterRef<ClientToolContinuationLimitEvent>;
1732
1953
  /** Emitted when the user clicks the regenerate button on an assistant message. */
1733
1954
  readonly regenerate: _angular_core.OutputEmitterRef<void>;
1734
1955
  /** Emitted when the user rates an assistant message. */
@@ -1783,13 +2004,6 @@ declare class ChatComponent {
1783
2004
  * back to the original text.
1784
2005
  */
1785
2006
  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
2007
  /** The nearest preceding assistant message (skipping hidden tool messages), or undefined. */
1794
2008
  private prevAssistant;
1795
2009
  /**
@@ -1800,17 +2014,19 @@ declare class ChatComponent {
1800
2014
  protected reasoningRunStart(index: number): boolean;
1801
2015
  /**
1802
2016
  * 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).
2017
+ * reasoning, sums durations, counts steps, and returns the last step's
2018
+ * delivery because that step owns the current aggregate snapshot. Also
2019
+ * computes the merged label when N > 1 ("Thought for {total} · {N} steps",
2020
+ * or just "{N} steps" when no step reported timing).
1806
2021
  */
1807
2022
  protected reasoningRun(index: number): {
1808
2023
  content: string;
1809
2024
  durationMs: number | undefined;
1810
- streaming: boolean;
2025
+ delivery: MessageDelivery;
1811
2026
  label: string | undefined;
1812
2027
  };
1813
2028
  private readonly classifiers;
2029
+ private readonly markdownDocuments;
1814
2030
  private readonly destroyRef;
1815
2031
  private readonly injector;
1816
2032
  private readonly lifecycle;
@@ -1831,15 +2047,13 @@ declare class ChatComponent {
1831
2047
  private programmaticScrollCount;
1832
2048
  private static readonly PIN_TOLERANCE_PX;
1833
2049
  /**
1834
- * True iff there's a current (last-index) assistant message that's
1835
- * still streaming. The bubble's own caret already signals loading;
2050
+ * True iff the current (last-index) assistant message owns an active
2051
+ * delivery generation. The bubble's own caret already signals loading;
1836
2052
  * we suppress the floor typing-indicator in that case so the user
1837
2053
  * doesn't see two loading affordances at once.
1838
2054
  *
1839
2055
  * 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`
2056
+ * to enable `.chat-message__caret`.
1843
2057
  *
1844
2058
  * Restricted to assistant role because the caret only renders on
1845
2059
  * assistant bubbles (`:host([data-role="assistant"][data-current=...
@@ -1889,9 +2103,8 @@ declare class ChatComponent {
1889
2103
  * unlike a single prev-message check.
1890
2104
  */
1891
2105
  protected isGenuiTurn(message: unknown, _prevMsg: unknown, index?: number): boolean;
1892
- classifyMessage(content: string, message: {
1893
- id?: string;
1894
- }): ContentClassifier;
2106
+ classifyMessage(content: string, message: Pick<Message, 'id' | 'delivery'>): ContentClassifier;
2107
+ protected markdownDocumentFor(content: string, message: Pick<Message, 'id' | 'delivery'>): StreamingMarkdownDocument;
1895
2108
  clearClassifiers(): void;
1896
2109
  onSpecEvent(event: RenderEvent, messageIndex: number): void;
1897
2110
  /**
@@ -1908,11 +2121,11 @@ declare class ChatComponent {
1908
2121
  onRate(message: unknown, value: 'up' | 'down'): void;
1909
2122
  onCopy(message: unknown, content: string): void;
1910
2123
  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>;
2124
+ 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
2125
  }
1913
2126
 
1914
2127
  declare class ChatPopupComponent {
1915
- readonly agent: _angular_core.InputSignal<Agent<Record<string, unknown>>>;
2128
+ readonly agent: _angular_core.InputSignal<Agent<unknown>>;
1916
2129
  /** A2UI component catalog forwarded to the inner <chat>. Without it,
1917
2130
  * messages classified as A2UI parse correctly but never mount a
1918
2131
  * surface. Pass `a2uiBasicCatalog()` from `@threadplane/chat`. */
@@ -1952,7 +2165,7 @@ declare class ChatPopupComponent {
1952
2165
  }
1953
2166
 
1954
2167
  declare class ChatSidebarComponent {
1955
- readonly agent: _angular_core.InputSignal<Agent<Record<string, unknown>>>;
2168
+ readonly agent: _angular_core.InputSignal<Agent<unknown>>;
1956
2169
  /** A2UI component catalog forwarded to the inner <chat>. Without it,
1957
2170
  * messages classified as A2UI parse correctly but never mount a
1958
2171
  * surface. Pass `a2uiBasicCatalog()` from `@threadplane/chat`. */
@@ -1986,7 +2199,7 @@ declare class ChatSidebarComponent {
1986
2199
  }
1987
2200
 
1988
2201
  declare class ChatTimelineSliderComponent {
1989
- readonly agent: _angular_core.InputSignal<AgentWithHistory<Record<string, unknown>>>;
2202
+ readonly agent: _angular_core.InputSignal<AgentWithHistory<unknown>>;
1990
2203
  readonly selectedIndex: _angular_core.WritableSignal<number>;
1991
2204
  readonly history: _angular_core.Signal<AgentCheckpoint[]>;
1992
2205
  readonly replayRequested: _angular_core.OutputEmitterRef<string>;
@@ -2008,7 +2221,7 @@ declare class ChatSidenavComponent {
2008
2221
  readonly projects: _angular_core.InputSignal<Project[] | null>;
2009
2222
  readonly selectedProjectId: _angular_core.InputSignal<string | null>;
2010
2223
  readonly projectActions: _angular_core.InputSignal<ProjectActionAdapter | null>;
2011
- readonly agent: _angular_core.InputSignal<Agent<Record<string, unknown>> | AgentWithHistory<Record<string, unknown>> | null>;
2224
+ readonly agent: _angular_core.InputSignal<Agent<unknown> | AgentWithHistory<unknown> | null>;
2012
2225
  readonly debug: _angular_core.InputSignal<boolean>;
2013
2226
  readonly newChat: _angular_core.OutputEmitterRef<void>;
2014
2227
  readonly threadSelected: _angular_core.OutputEmitterRef<string>;
@@ -2059,7 +2272,7 @@ declare class ChatSidenavScrimComponent {
2059
2272
 
2060
2273
  type InterruptAction = 'accept' | 'edit' | 'respond' | 'ignore';
2061
2274
  declare class ChatInterruptPanelComponent {
2062
- readonly agent: _angular_core.InputSignal<Agent<Record<string, unknown>>>;
2275
+ readonly agent: _angular_core.InputSignal<Agent<unknown>>;
2063
2276
  readonly action: _angular_core.OutputEmitterRef<InterruptAction>;
2064
2277
  readonly interrupt: _angular_core.Signal<AgentInterrupt | undefined>;
2065
2278
  readonly interruptReason: _angular_core.Signal<string>;
@@ -2069,7 +2282,7 @@ declare class ChatInterruptPanelComponent {
2069
2282
 
2070
2283
  type ChatApprovalAction = 'approve' | 'edit' | 'cancel';
2071
2284
  declare class ChatApprovalCardComponent {
2072
- readonly agent: _angular_core.InputSignal<Agent<Record<string, unknown>>>;
2285
+ readonly agent: _angular_core.InputSignal<Agent<unknown>>;
2073
2286
  readonly matchKind: _angular_core.InputSignal<string | undefined>;
2074
2287
  readonly title: _angular_core.InputSignal<string>;
2075
2288
  readonly showEdit: _angular_core.InputSignal<boolean>;
@@ -2099,6 +2312,9 @@ declare function statusColor(status: SubagentStatus): string;
2099
2312
  declare class ChatSubagentCardComponent {
2100
2313
  readonly subagent: _angular_core.InputSignal<Subagent>;
2101
2314
  readonly state: _angular_core.Signal<TraceState>;
2315
+ private readonly markdownDocuments;
2316
+ constructor();
2317
+ protected markdownDocumentFor(content: string, message: Message): StreamingMarkdownDocument;
2102
2318
  protected textOf(m: Message): string;
2103
2319
  protected toolCallsFor(m: Message): ToolCall[];
2104
2320
  protected toToolCallInfo(tc: ToolCall): ToolCallInfo;
@@ -2118,39 +2334,6 @@ declare class CitationsResolverService {
2118
2334
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<CitationsResolverService>;
2119
2335
  }
2120
2336
 
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
2337
  /**
2155
2338
  * DI token for the markdown view registry consumed by <chat-streaming-md>
2156
2339
  * and <md-children>. Maps MarkdownNode.type strings (e.g. "paragraph",
@@ -2961,8 +3144,11 @@ type ViewProps<S extends StandardSchemaV1> = Prettify<StandardSchemaInferOutput<
2961
3144
  * @param description Natural-language description the model sees.
2962
3145
  * @param schema Standard Schema (e.g. a Zod object) for the arguments; the
2963
3146
  * 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}.
3147
+ * @param handler Runs in the browser when the model calls the tool. The second
3148
+ * argument carries an `AbortSignal`; its return type `R` is carried on the
3149
+ * resulting {@link FunctionToolDef}.
3150
+ * @param options Execution policy options, including `idempotent: true` to skip
3151
+ * durable pre-execution claims when a guard is configured.
2966
3152
  * @returns A {@link FunctionToolDef} for inclusion in {@link tools}.
2967
3153
  * @example
2968
3154
  * ```ts
@@ -2970,7 +3156,7 @@ type ViewProps<S extends StandardSchemaV1> = Prettify<StandardSchemaInferOutput<
2970
3156
  * const registry = tools({ move_stop: move });
2971
3157
  * ```
2972
3158
  */
2973
- declare function action<S extends StandardSchemaV1, R>(description: string, schema: S, handler: (args: StandardSchemaInferOutput<S>) => R | Promise<R>): FunctionToolDef<S, R>;
3159
+ 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
3160
  /**
2975
3161
  * Render-only component tool — the model fills the component's props from the
2976
3162
  * schema's output; the tool call is auto-acknowledged once the component mounts.
@@ -3001,7 +3187,7 @@ declare function action<S extends StandardSchemaV1, R>(description: string, sche
3001
3187
  * const registry = tools({ day_card: dayCard });
3002
3188
  * ```
3003
3189
  */
3004
- declare function view<S extends StandardSchemaV1, C>(description: string, schema: S, component: AcceptComponent<S, C>): ViewToolDef<S, C>;
3190
+ declare function view<S extends StandardSchemaV1, C>(description: string, schema: S, component: AcceptComponent<S, C>, options?: ClientToolContinuationOptions): ViewToolDef<S, C>;
3005
3191
  /**
3006
3192
  * Interactive (human-in-the-loop) component tool — the model fills the
3007
3193
  * component's props from the schema's output; the value the component emits
@@ -3034,7 +3220,7 @@ declare function view<S extends StandardSchemaV1, C>(description: string, schema
3034
3220
  * const registry = tools({ pick_option: choice });
3035
3221
  * ```
3036
3222
  */
3037
- declare function ask<S extends StandardSchemaV1, C>(description: string, schema: S, component: AcceptComponent<S, C>): AskToolDef<S, C>;
3223
+ declare function ask<S extends StandardSchemaV1, C>(description: string, schema: S, component: AcceptComponent<S, C>, options?: ClientToolContinuationOptions): AskToolDef<S, C>;
3038
3224
  /**
3039
3225
  * Collect named client tools into a frozen, name-keyed registry.
3040
3226
  *
@@ -3059,6 +3245,20 @@ declare function ask<S extends StandardSchemaV1, C>(description: string, schema:
3059
3245
  */
3060
3246
  declare function tools<const M extends Record<string, ClientToolDef>>(map: M): Readonly<M>;
3061
3247
 
3248
+ /** Inputs for {@link selectPendingClientToolCalls}. */
3249
+ interface SelectPendingClientToolCallsInput {
3250
+ /** Whether the agent is currently streaming a run. Pending client tools are hidden while loading. */
3251
+ isLoading: boolean;
3252
+ /** Tool calls observed from the current agent state. */
3253
+ toolCalls: readonly ToolCall[];
3254
+ /** Client-declared tool names that should be handled in the browser. */
3255
+ catalogNames: ReadonlySet<string>;
3256
+ /** Tool-call ids already resolved by the local client instance. */
3257
+ resolvedIds: ReadonlySet<string>;
3258
+ }
3259
+ /** Select client tool calls that are ready for browser-side resolution. */
3260
+ declare function selectPendingClientToolCalls(input: SelectPendingClientToolCallsInput): readonly ToolCall[];
3261
+
3062
3262
  /** Validate raw model args against a Standard Schema. */
3063
3263
  declare function validateArgs(schema: StandardSchemaV1, args: unknown): Promise<{
3064
3264
  ok: true;
@@ -3068,15 +3268,23 @@ declare function validateArgs(schema: StandardSchemaV1, args: unknown): Promise<
3068
3268
  error: string;
3069
3269
  }>;
3070
3270
  /** Validate args, run the handler, and normalize the outcome to a ClientToolResult. */
3071
- declare function executeFunctionTool(def: AnyFunctionToolDef, rawArgs: unknown): Promise<ClientToolResult>;
3271
+ declare function executeFunctionTool(def: AnyFunctionToolDef, rawArgs: unknown, context?: FunctionToolHandlerContext): Promise<ClientToolResult>;
3072
3272
 
3273
+ /** Options for wiring automatic browser function-tool execution. */
3274
+ interface ClientToolExecutorOptions {
3275
+ readonly executionGuard?: ClientToolExecutionGuard;
3276
+ readonly settleToolCall?: (toolCall: ToolCall, result: ClientToolResult) => void;
3277
+ /** Settlement for calls that must NOT continue the run (user abort, teardown). */
3278
+ readonly settleWithoutContinuing?: (toolCall: ToolCall, result: ClientToolResult) => void;
3279
+ readonly shouldExecuteToolCall?: (toolCall: ToolCall) => boolean;
3280
+ }
3073
3281
  /**
3074
3282
  * Watches the agent's pending client tool calls and auto-runs FUNCTION tools,
3075
3283
  * resolving each with its result. View/ask (component) tools are handled by the
3076
3284
  * rendering layer, not here. No-op if the agent lacks the clientTools
3077
3285
  * capability. MUST be called in an injection context (sets up an effect).
3078
3286
  */
3079
- declare function startClientToolExecutor(agent: Agent, registry: ClientToolRegistry): void;
3287
+ declare function startClientToolExecutor(agent: Agent, registry: ClientToolRegistry, options?: ClientToolExecutorOptions): void;
3080
3288
 
3081
3289
  interface ClientToolsCoordinator {
3082
3290
  /** Components for `view`/`ask` tools, keyed by tool name — merge into the chat `views`. */
@@ -3149,8 +3357,10 @@ interface MockAgentOptions {
3149
3357
  * @returns A {@link MockAgent} satisfying the full `Agent` contract.
3150
3358
  * @example
3151
3359
  * ```ts
3360
+ * import { staticDelivery } from '@threadplane/chat';
3361
+ *
3152
3362
  * const agent = mockAgent({
3153
- * messages: [{ id: '1', role: 'assistant', content: 'Hi' }],
3363
+ * messages: [{ id: '1', role: 'assistant', content: 'Hi', delivery: staticDelivery('1') }],
3154
3364
  * isLoading: true,
3155
3365
  * });
3156
3366
  * ```
@@ -3160,5 +3370,5 @@ declare function mockAgent(opts?: MockAgentOptions): MockAgent;
3160
3370
  /** Inferred argument type for a schema (alias of StandardSchemaInferOutput). */
3161
3371
  type ToolArgs<S extends StandardSchemaV1> = StandardSchemaInferOutput<S>;
3162
3372
 
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 };
3373
+ 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, STREAMING_MARKDOWN_CONTRACT_VIOLATION_POLICY, a2uiBasicCatalog, 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 };
3374
+ 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 };