@dudousxd/nestjs-agent-react 0.31.5 → 0.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import { ChatQueueState, ThreadSummary, ThreadDetail, MessageAttachment, ToolCatalogEntry, SkillCatalogEntry, QuotaReport, ModelCatalogView, AgentCatalogEntry, AgentClientConfig, MessageFeedbackValue, MessageFeedback } from '@dudousxd/nestjs-agent-core';
1
+ import { ActionProposalMutationResult, ChatQueueState, ThreadSummary, ThreadDetail, ActionProposal, MessageAttachment, ToolCatalogEntry, SkillCatalogEntry, QuotaReport, ModelCatalogView, AgentCatalogEntry, AgentClientConfig, MessageFeedbackValue, MessageFeedback } from '@dudousxd/nestjs-agent-core';
2
2
 
3
3
  /**
4
4
  * What a server said when it refused a request, read once so every error class of this package
@@ -37,10 +37,12 @@ interface ThreadPatch {
37
37
  defaultAgent?: string | null;
38
38
  /** Pin a catalog model on the thread; `null` unpins it. */
39
39
  model?: string | null;
40
+ /** Pin one of the agent's personas on the thread; `null` clears it (the agent's default applies). */
41
+ persona?: string | null;
40
42
  }
41
43
  /** Starting a turn: the body `POST <base>/chat` takes (see docs/stream-protocol.md). */
42
44
  interface ChatStreamRequest {
43
- /** `{ message, threadId?, agent?, model?, attachments?, pageContext?, regenerate?, … }`. */
45
+ /** `{ message, threadId?, agent?, persona?, model?, attachments?, pageContext?, regenerate?, … }`. */
44
46
  body: Record<string, unknown>;
45
47
  /** Per-request headers the AI SDK was handed for this send. */
46
48
  headers?: Record<string, string>;
@@ -65,6 +67,14 @@ interface ResumeStreamRequest {
65
67
  * headers). The body's own `event: meta` frame supplies them otherwise.
66
68
  */
67
69
  interface ChatStreamResponse {
70
+ proposalDecision?: {
71
+ threadId: string;
72
+ proposalDecision: ActionProposalMutationResult | {
73
+ status: 'ambiguous';
74
+ proposalIds: string[];
75
+ };
76
+ text?: string;
77
+ };
68
78
  body: ReadableStream<Uint8Array>;
69
79
  runId?: string;
70
80
  threadId?: string;
@@ -187,6 +197,19 @@ interface AgentBackend {
187
197
  forkFromMessage?(threadId: string, messageId: string): Promise<ThreadSummary>;
188
198
  promoteThread?(id: string): Promise<unknown>;
189
199
  truncateFromMessage?(threadId: string, messageId: string): Promise<unknown>;
200
+ listActionProposals?(input: {
201
+ threadId: string;
202
+ }): Promise<ActionProposal[]>;
203
+ approveActionProposal?(input: {
204
+ threadId: string;
205
+ proposalId: string;
206
+ remember?: boolean;
207
+ }): Promise<ActionProposalMutationResult>;
208
+ rejectActionProposal?(input: {
209
+ threadId: string;
210
+ proposalId: string;
211
+ reason?: string;
212
+ }): Promise<ActionProposalMutationResult>;
190
213
  approveToolCall?(input: {
191
214
  toolCallId: string;
192
215
  remember?: boolean;
@@ -390,6 +413,19 @@ declare class AgentClient implements AgentBackend {
390
413
  * `remember` approves later calls of the same tool in the same thread; `via` names the surface
391
414
  * the decision came through (the server records `'web'` when omitted).
392
415
  */
416
+ listActionProposals({ threadId }: {
417
+ threadId: string;
418
+ }): Promise<ActionProposal[]>;
419
+ approveActionProposal({ threadId, proposalId, remember, }: {
420
+ threadId: string;
421
+ proposalId: string;
422
+ remember?: boolean;
423
+ }): Promise<ActionProposalMutationResult>;
424
+ rejectActionProposal({ threadId, proposalId, reason, }: {
425
+ threadId: string;
426
+ proposalId: string;
427
+ reason?: string;
428
+ }): Promise<ActionProposalMutationResult>;
393
429
  approveToolCall(input: {
394
430
  toolCallId: string;
395
431
  remember?: boolean;
@@ -431,6 +467,7 @@ declare class AgentClient implements AgentBackend {
431
467
  private resolveHeaders;
432
468
  private credentials;
433
469
  private request;
470
+ private requestResponse;
434
471
  /** The error for a refused `response`, already reported to `onHttpError`. */
435
472
  private failure;
436
473
  private handleResponse;
@@ -1,4 +1,4 @@
1
- import { ChatQueueState, ThreadSummary, ThreadDetail, MessageAttachment, ToolCatalogEntry, SkillCatalogEntry, QuotaReport, ModelCatalogView, AgentCatalogEntry, AgentClientConfig, MessageFeedbackValue, MessageFeedback } from '@dudousxd/nestjs-agent-core';
1
+ import { ActionProposalMutationResult, ChatQueueState, ThreadSummary, ThreadDetail, ActionProposal, MessageAttachment, ToolCatalogEntry, SkillCatalogEntry, QuotaReport, ModelCatalogView, AgentCatalogEntry, AgentClientConfig, MessageFeedbackValue, MessageFeedback } from '@dudousxd/nestjs-agent-core';
2
2
 
3
3
  /**
4
4
  * What a server said when it refused a request, read once so every error class of this package
@@ -37,10 +37,12 @@ interface ThreadPatch {
37
37
  defaultAgent?: string | null;
38
38
  /** Pin a catalog model on the thread; `null` unpins it. */
39
39
  model?: string | null;
40
+ /** Pin one of the agent's personas on the thread; `null` clears it (the agent's default applies). */
41
+ persona?: string | null;
40
42
  }
41
43
  /** Starting a turn: the body `POST <base>/chat` takes (see docs/stream-protocol.md). */
42
44
  interface ChatStreamRequest {
43
- /** `{ message, threadId?, agent?, model?, attachments?, pageContext?, regenerate?, … }`. */
45
+ /** `{ message, threadId?, agent?, persona?, model?, attachments?, pageContext?, regenerate?, … }`. */
44
46
  body: Record<string, unknown>;
45
47
  /** Per-request headers the AI SDK was handed for this send. */
46
48
  headers?: Record<string, string>;
@@ -65,6 +67,14 @@ interface ResumeStreamRequest {
65
67
  * headers). The body's own `event: meta` frame supplies them otherwise.
66
68
  */
67
69
  interface ChatStreamResponse {
70
+ proposalDecision?: {
71
+ threadId: string;
72
+ proposalDecision: ActionProposalMutationResult | {
73
+ status: 'ambiguous';
74
+ proposalIds: string[];
75
+ };
76
+ text?: string;
77
+ };
68
78
  body: ReadableStream<Uint8Array>;
69
79
  runId?: string;
70
80
  threadId?: string;
@@ -187,6 +197,19 @@ interface AgentBackend {
187
197
  forkFromMessage?(threadId: string, messageId: string): Promise<ThreadSummary>;
188
198
  promoteThread?(id: string): Promise<unknown>;
189
199
  truncateFromMessage?(threadId: string, messageId: string): Promise<unknown>;
200
+ listActionProposals?(input: {
201
+ threadId: string;
202
+ }): Promise<ActionProposal[]>;
203
+ approveActionProposal?(input: {
204
+ threadId: string;
205
+ proposalId: string;
206
+ remember?: boolean;
207
+ }): Promise<ActionProposalMutationResult>;
208
+ rejectActionProposal?(input: {
209
+ threadId: string;
210
+ proposalId: string;
211
+ reason?: string;
212
+ }): Promise<ActionProposalMutationResult>;
190
213
  approveToolCall?(input: {
191
214
  toolCallId: string;
192
215
  remember?: boolean;
@@ -390,6 +413,19 @@ declare class AgentClient implements AgentBackend {
390
413
  * `remember` approves later calls of the same tool in the same thread; `via` names the surface
391
414
  * the decision came through (the server records `'web'` when omitted).
392
415
  */
416
+ listActionProposals({ threadId }: {
417
+ threadId: string;
418
+ }): Promise<ActionProposal[]>;
419
+ approveActionProposal({ threadId, proposalId, remember, }: {
420
+ threadId: string;
421
+ proposalId: string;
422
+ remember?: boolean;
423
+ }): Promise<ActionProposalMutationResult>;
424
+ rejectActionProposal({ threadId, proposalId, reason, }: {
425
+ threadId: string;
426
+ proposalId: string;
427
+ reason?: string;
428
+ }): Promise<ActionProposalMutationResult>;
393
429
  approveToolCall(input: {
394
430
  toolCallId: string;
395
431
  remember?: boolean;
@@ -431,6 +467,7 @@ declare class AgentClient implements AgentBackend {
431
467
  private resolveHeaders;
432
468
  private credentials;
433
469
  private request;
470
+ private requestResponse;
434
471
  /** The error for a refused `response`, already reported to `onHttpError`. */
435
472
  private failure;
436
473
  private handleResponse;
@@ -1,7 +1,19 @@
1
1
  import * as React from 'react';
2
2
  import { ComponentType, ReactNode } from 'react';
3
- import { ElicitationQuestion, ElicitationInputType, ToolPresentation, ToolCatalogEntry, ToolResultField, ToolResultView, ToolPresentationTone, ElicitationInput } from '@dudousxd/nestjs-agent-core';
4
- import { ToolUIPart, DynamicToolUIPart, UIMessage } from 'ai';
3
+ import { ActionProposal, StoredMessage, ElicitationQuestion, ElicitationInputType, ToolPresentation, ToolCatalogEntry, ToolResultField, ToolResultView, ToolPresentationTone, ToolConfirmation, ElicitationInput } from '@dudousxd/nestjs-agent-core';
4
+ import { UIMessage, ToolUIPart, DynamicToolUIPart } from 'ai';
5
+
6
+ type ApprovalTarget = {
7
+ kind: 'legacy';
8
+ toolCallId: string;
9
+ } | {
10
+ kind: 'proposal';
11
+ proposalId: string;
12
+ threadId?: string;
13
+ };
14
+ declare function proposalNeedsPolling(proposal: ActionProposal): boolean;
15
+ /** Patch proposal metadata and append outcome facts; never replace live text with stored rows. */
16
+ declare function reconcileProposalMessages(current: UIMessage[], proposals: ActionProposal[], facts: StoredMessage[]): UIMessage[];
5
17
 
6
18
  /** What a form control can hand over: a field's value, a checkbox's state, a picked date, a list. */
7
19
  type RawAnswer = string | number | boolean | Date | null | undefined | readonly RawAnswer[];
@@ -96,7 +108,7 @@ declare function resolveResultView(output: unknown, view: ToolResultView | undef
96
108
  * - `done` / `failed` / `denied` — settled. A tool that RETURNS `{ error }` has failed just as much
97
109
  * as one that threw; the two arrive differently and read the same to a person.
98
110
  */
99
- type ToolCallStatus = 'running' | 'awaiting-approval' | 'done' | 'failed' | 'denied';
111
+ type ToolCallStatus = 'running' | 'awaiting-approval' | 'done' | 'failed' | 'denied' | 'queued' | 'executing' | 'succeeded';
100
112
  interface ToolCallState {
101
113
  status: ToolCallStatus;
102
114
  isSettled: boolean;
@@ -136,6 +148,8 @@ interface ToolCallDescription {
136
148
  presentation: ToolPresentation | null;
137
149
  }
138
150
  interface DescribeToolCallOptions {
151
+ /** Resolved strings from the call preflight override the tool catalog templates. */
152
+ confirmation?: ToolConfirmation;
139
153
  /** Words for a tool the catalog does not describe. Default `Working` / `Done`. */
140
154
  fallback?: {
141
155
  running: string;
@@ -263,13 +277,16 @@ interface TranscriptSettleState {
263
277
  run: () => void;
264
278
  }
265
279
  /** How an approval stands. */
266
- type TranscriptApprovalStatus = 'pending' | 'approved' | 'rejected' | 'expired';
280
+ type TranscriptApprovalStatus = 'pending' | 'approved' | 'rejected' | 'expired' | 'superseded';
267
281
  /**
268
282
  * Who has to settle a parked call, until when, and — once it settled — how. From the stream's
269
283
  * `approval-requested` / `approval-settled` frames, or the same parts a reloaded thread carries.
270
284
  * `null` on a call whose runner never said (the call can still be awaiting approval).
271
285
  */
272
286
  interface TranscriptApproval {
287
+ target?: ApprovalTarget;
288
+ executionStatus?: 'queued' | 'executing' | 'succeeded' | 'failed' | null;
289
+ confirmation?: ToolConfirmation;
273
290
  /** Open vocabulary the host defines: `'requester'`, `'admin'`, a role… */
274
291
  approver: string;
275
292
  /** ISO-8601; `null` when the request never lapses. Pair with `useApprovalCountdown`. */
@@ -371,6 +388,8 @@ interface TranscriptUiBlock {
371
388
  props: Record<string, unknown>;
372
389
  /** Schema version of `props`; `null` when the server did not stamp one. */
373
390
  version: number | null;
391
+ fallbackText?: string;
392
+ componentVersions?: Record<string, number>;
374
393
  /** The tool call that pushed it (`ctx.emitUi`); `null` for a component pushed outside a tool. */
375
394
  toolCallId: string | null;
376
395
  }
@@ -516,8 +535,8 @@ interface ElicitationBlockOptions {
516
535
  interface ApprovalBlockOptions {
517
536
  canApprove: boolean;
518
537
  canReject: boolean;
519
- approve: (toolCallId: string, options?: ApproveOptions) => void;
520
- reject: (toolCallId: string) => void;
538
+ approve: (toolCallId: string, options?: ApproveOptions, target?: ApprovalTarget) => void;
539
+ reject: (toolCallId: string, target?: ApprovalTarget) => void;
521
540
  /** Which decision this call is sending, or `null` for none. */
522
541
  submitting: (toolCallId: string) => SettleAction | null;
523
542
  errorOf: (toolCallId: string) => string | null;
@@ -580,6 +599,8 @@ declare function formatRelativeTime(date: Date): string;
580
599
  declare const GENUI_TREE_COMPONENT = "genui:tree";
581
600
  /** One pushed component, normalized from whatever carried it (a transcript block, a `data-ui` part, a stored entry). */
582
601
  interface GenerativeUIItem {
602
+ fallbackText?: string;
603
+ componentVersions?: Record<string, number>;
583
604
  id: string;
584
605
  component: string;
585
606
  props: Record<string, unknown>;
@@ -624,6 +645,9 @@ type ValidationLike = {
624
645
  * object does too.
625
646
  */
626
647
  interface GenuiCatalogLike {
648
+ get?(name: string): {
649
+ version?: number;
650
+ } | undefined;
627
651
  has(name: string): boolean;
628
652
  validate(name: string, props: unknown): Promise<ValidationLike>;
629
653
  validateSync?(name: string, props: unknown): ValidationLike | undefined;
@@ -678,6 +702,8 @@ declare function GenuiTree({ root }: {
678
702
  root?: GenerativeUIElement;
679
703
  }): React.JSX.Element | null;
680
704
  interface GenerativeUIScopeProps extends GenerativeUIOptions {
705
+ fallbackText?: string;
706
+ componentVersions?: Record<string, number>;
681
707
  fallback?: GenerativeUIFallback;
682
708
  loading?: ReactNode;
683
709
  onError?: (error: unknown, item: GenerativeUIItem) => void;
@@ -687,7 +713,7 @@ interface GenerativeUIScopeProps extends GenerativeUIOptions {
687
713
  * The registry, catalog and fallbacks tree nodes render with. `<GenerativeUI>` provides it; wrap
688
714
  * your own chrome in it when you draw `useGenerativeUI`'s `Component` yourself and it may be a tree.
689
715
  */
690
- declare function GenerativeUIScope({ registry, catalog, resolveComponent, fallback, loading, onError, children, }: GenerativeUIScopeProps): React.JSX.Element;
716
+ declare function GenerativeUIScope({ registry, catalog, resolveComponent, fallback, fallbackText, componentVersions, loading, onError, children, }: GenerativeUIScopeProps): React.JSX.Element;
691
717
  /** What `<GenuiProvider>` hands every `<GenerativeUI>` / `useGenerativeUI` below it. */
692
718
  interface GenuiProviderValue extends Partial<GenerativeUIOptions> {
693
719
  fallback?: GenerativeUIFallback;
@@ -720,7 +746,7 @@ declare function useGenerativeUI(part: unknown, options?: Partial<GenerativeUIOp
720
746
  interface GenerativeUIProps extends Partial<GenerativeUIOptions> {
721
747
  /** A transcript `ui` block, a `data-ui` message part, or a stored `{ id, component, props, version? }`. */
722
748
  part: TranscriptUiBlock | GenerativeUIItem | unknown;
723
- /** Drawn for an unknown component, invalid props, or a renderer that threw. Default: the provider's, else nothing. */
749
+ /** Drawn for an unknown component, invalid props, or a renderer that threw. Default: the provider's, then the item's persisted text. */
724
750
  fallback?: GenerativeUIFallback;
725
751
  /** Drawn while a resolver or an async validation is pending. Default: the provider's, else nothing. */
726
752
  loading?: ReactNode;
@@ -738,4 +764,4 @@ interface GenerativeUIProps extends Partial<GenerativeUIOptions> {
738
764
  */
739
765
  declare function GenerativeUI({ part, registry, catalog, resolveComponent, treeRenderer, fallback: ownFallback, loading: ownLoading, onError: ownOnError, }: GenerativeUIProps): string | number | bigint | boolean | Iterable<ReactNode> | Promise<string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | React.JSX.Element | null | undefined;
740
766
 
741
- export { type TranscriptQuestionOption as $, type ApproveOptions as A, type BuildBlocksOptions as B, type ChatStatus as C, type CoercibleQuestion as D, type DescribeToolCallOptions as E, type ElicitationBlockOptions as F, type GenerativeUIItem as G, type GroupToolActivityOptions as H, type RawAnswer as I, type ResolvedReading as J, type ResolvedResultView as K, type RetrievedPassage as L, type MessageUsageInfo as M, type ToolActivityGroup as N, type ToolCallDescription as O, type ToolCallState as P, type ToolCallStatus as Q, type ResolveComponent as R, type SettleAction as S, type TranscriptUiBlock as T, type UsageSummary as U, type TranscriptApproval as V, type TranscriptApprovalStatus as W, type TranscriptElicitationBlock as X, type TranscriptElicitationOutcome as Y, type TranscriptFilesBlock as Z, type TranscriptQuestion as _, GENUI_TREE_COMPONENT as a, type TranscriptReasoningBlock as a0, type TranscriptSettleState as a1, type TranscriptSource as a2, type TranscriptSourcesBlock as a3, type TranscriptTextBlock as a4, type TranscriptToolBlock as a5, type TranscriptToolCall as a6, buildTranscriptBlocks as a7, coerceAnswer as a8, correctedCallIds as a9, describeTimestamp as aa, describeToolCall as ab, describeUsage as ac, extractMessageText as ad, fillTemplate as ae, formatRelativeTime as af, groupToolActivity as ag, inferResultView as ah, isActionCall as ai, phraseFor as aj, readPath as ak, resolveResultView as al, toolCallState as am, toolCatalogFrom as an, GenerativeUI as b, type GenerativeUIElement as c, type GenerativeUIFallback as d, type GenerativeUIOptions as e, type GenerativeUIProblem as f, type GenerativeUIProps as g, GenerativeUIScope as h, type GenerativeUIScopeProps as i, type GenerativeUIState as j, type GenuiCatalogLike as k, type GenuiIssueLike as l, GenuiProvider as m, type GenuiProviderProps as n, type GenuiProviderValue as o, type GenuiRegistry as p, type GenuiRenderer as q, GenuiTree as r, useGenuiProvider as s, type TranscriptBlock as t, useGenerativeUI as u, type TimestampInfo as v, type TranscriptFile as w, type ToolCatalog as x, type AnyToolUIPart as y, type ApprovalBlockOptions as z };
767
+ export { type TranscriptQuestion as $, type ApproveOptions as A, type ApprovalBlockOptions as B, type ChatStatus as C, type BuildBlocksOptions as D, type CoercibleQuestion as E, type DescribeToolCallOptions as F, type GenerativeUIItem as G, type ElicitationBlockOptions as H, type GroupToolActivityOptions as I, type RawAnswer as J, type ResolvedReading as K, type ResolvedResultView as L, type MessageUsageInfo as M, type RetrievedPassage as N, type ToolActivityGroup as O, type ToolCallDescription as P, type ToolCallState as Q, type ResolveComponent as R, type SettleAction as S, type TranscriptUiBlock as T, type UsageSummary as U, type ToolCallStatus as V, type TranscriptApproval as W, type TranscriptApprovalStatus as X, type TranscriptElicitationBlock as Y, type TranscriptElicitationOutcome as Z, type TranscriptFilesBlock as _, GENUI_TREE_COMPONENT as a, type TranscriptQuestionOption as a0, type TranscriptReasoningBlock as a1, type TranscriptSettleState as a2, type TranscriptSource as a3, type TranscriptSourcesBlock as a4, type TranscriptTextBlock as a5, type TranscriptToolBlock as a6, type TranscriptToolCall as a7, buildTranscriptBlocks as a8, coerceAnswer as a9, correctedCallIds as aa, describeTimestamp as ab, describeToolCall as ac, describeUsage as ad, extractMessageText as ae, fillTemplate as af, formatRelativeTime as ag, groupToolActivity as ah, inferResultView as ai, isActionCall as aj, phraseFor as ak, proposalNeedsPolling as al, readPath as am, reconcileProposalMessages as an, resolveResultView as ao, toolCallState as ap, toolCatalogFrom as aq, GenerativeUI as b, type GenerativeUIElement as c, type GenerativeUIFallback as d, type GenerativeUIOptions as e, type GenerativeUIProblem as f, type GenerativeUIProps as g, GenerativeUIScope as h, type GenerativeUIScopeProps as i, type GenerativeUIState as j, type GenuiCatalogLike as k, type GenuiIssueLike as l, GenuiProvider as m, type GenuiProviderProps as n, type GenuiProviderValue as o, type GenuiRegistry as p, type GenuiRenderer as q, GenuiTree as r, useGenuiProvider as s, type ApprovalTarget as t, useGenerativeUI as u, type TranscriptBlock as v, type TimestampInfo as w, type TranscriptFile as x, type ToolCatalog as y, type AnyToolUIPart as z };
@@ -1,7 +1,19 @@
1
1
  import * as React from 'react';
2
2
  import { ComponentType, ReactNode } from 'react';
3
- import { ElicitationQuestion, ElicitationInputType, ToolPresentation, ToolCatalogEntry, ToolResultField, ToolResultView, ToolPresentationTone, ElicitationInput } from '@dudousxd/nestjs-agent-core';
4
- import { ToolUIPart, DynamicToolUIPart, UIMessage } from 'ai';
3
+ import { ActionProposal, StoredMessage, ElicitationQuestion, ElicitationInputType, ToolPresentation, ToolCatalogEntry, ToolResultField, ToolResultView, ToolPresentationTone, ToolConfirmation, ElicitationInput } from '@dudousxd/nestjs-agent-core';
4
+ import { UIMessage, ToolUIPart, DynamicToolUIPart } from 'ai';
5
+
6
+ type ApprovalTarget = {
7
+ kind: 'legacy';
8
+ toolCallId: string;
9
+ } | {
10
+ kind: 'proposal';
11
+ proposalId: string;
12
+ threadId?: string;
13
+ };
14
+ declare function proposalNeedsPolling(proposal: ActionProposal): boolean;
15
+ /** Patch proposal metadata and append outcome facts; never replace live text with stored rows. */
16
+ declare function reconcileProposalMessages(current: UIMessage[], proposals: ActionProposal[], facts: StoredMessage[]): UIMessage[];
5
17
 
6
18
  /** What a form control can hand over: a field's value, a checkbox's state, a picked date, a list. */
7
19
  type RawAnswer = string | number | boolean | Date | null | undefined | readonly RawAnswer[];
@@ -96,7 +108,7 @@ declare function resolveResultView(output: unknown, view: ToolResultView | undef
96
108
  * - `done` / `failed` / `denied` — settled. A tool that RETURNS `{ error }` has failed just as much
97
109
  * as one that threw; the two arrive differently and read the same to a person.
98
110
  */
99
- type ToolCallStatus = 'running' | 'awaiting-approval' | 'done' | 'failed' | 'denied';
111
+ type ToolCallStatus = 'running' | 'awaiting-approval' | 'done' | 'failed' | 'denied' | 'queued' | 'executing' | 'succeeded';
100
112
  interface ToolCallState {
101
113
  status: ToolCallStatus;
102
114
  isSettled: boolean;
@@ -136,6 +148,8 @@ interface ToolCallDescription {
136
148
  presentation: ToolPresentation | null;
137
149
  }
138
150
  interface DescribeToolCallOptions {
151
+ /** Resolved strings from the call preflight override the tool catalog templates. */
152
+ confirmation?: ToolConfirmation;
139
153
  /** Words for a tool the catalog does not describe. Default `Working` / `Done`. */
140
154
  fallback?: {
141
155
  running: string;
@@ -263,13 +277,16 @@ interface TranscriptSettleState {
263
277
  run: () => void;
264
278
  }
265
279
  /** How an approval stands. */
266
- type TranscriptApprovalStatus = 'pending' | 'approved' | 'rejected' | 'expired';
280
+ type TranscriptApprovalStatus = 'pending' | 'approved' | 'rejected' | 'expired' | 'superseded';
267
281
  /**
268
282
  * Who has to settle a parked call, until when, and — once it settled — how. From the stream's
269
283
  * `approval-requested` / `approval-settled` frames, or the same parts a reloaded thread carries.
270
284
  * `null` on a call whose runner never said (the call can still be awaiting approval).
271
285
  */
272
286
  interface TranscriptApproval {
287
+ target?: ApprovalTarget;
288
+ executionStatus?: 'queued' | 'executing' | 'succeeded' | 'failed' | null;
289
+ confirmation?: ToolConfirmation;
273
290
  /** Open vocabulary the host defines: `'requester'`, `'admin'`, a role… */
274
291
  approver: string;
275
292
  /** ISO-8601; `null` when the request never lapses. Pair with `useApprovalCountdown`. */
@@ -371,6 +388,8 @@ interface TranscriptUiBlock {
371
388
  props: Record<string, unknown>;
372
389
  /** Schema version of `props`; `null` when the server did not stamp one. */
373
390
  version: number | null;
391
+ fallbackText?: string;
392
+ componentVersions?: Record<string, number>;
374
393
  /** The tool call that pushed it (`ctx.emitUi`); `null` for a component pushed outside a tool. */
375
394
  toolCallId: string | null;
376
395
  }
@@ -516,8 +535,8 @@ interface ElicitationBlockOptions {
516
535
  interface ApprovalBlockOptions {
517
536
  canApprove: boolean;
518
537
  canReject: boolean;
519
- approve: (toolCallId: string, options?: ApproveOptions) => void;
520
- reject: (toolCallId: string) => void;
538
+ approve: (toolCallId: string, options?: ApproveOptions, target?: ApprovalTarget) => void;
539
+ reject: (toolCallId: string, target?: ApprovalTarget) => void;
521
540
  /** Which decision this call is sending, or `null` for none. */
522
541
  submitting: (toolCallId: string) => SettleAction | null;
523
542
  errorOf: (toolCallId: string) => string | null;
@@ -580,6 +599,8 @@ declare function formatRelativeTime(date: Date): string;
580
599
  declare const GENUI_TREE_COMPONENT = "genui:tree";
581
600
  /** One pushed component, normalized from whatever carried it (a transcript block, a `data-ui` part, a stored entry). */
582
601
  interface GenerativeUIItem {
602
+ fallbackText?: string;
603
+ componentVersions?: Record<string, number>;
583
604
  id: string;
584
605
  component: string;
585
606
  props: Record<string, unknown>;
@@ -624,6 +645,9 @@ type ValidationLike = {
624
645
  * object does too.
625
646
  */
626
647
  interface GenuiCatalogLike {
648
+ get?(name: string): {
649
+ version?: number;
650
+ } | undefined;
627
651
  has(name: string): boolean;
628
652
  validate(name: string, props: unknown): Promise<ValidationLike>;
629
653
  validateSync?(name: string, props: unknown): ValidationLike | undefined;
@@ -678,6 +702,8 @@ declare function GenuiTree({ root }: {
678
702
  root?: GenerativeUIElement;
679
703
  }): React.JSX.Element | null;
680
704
  interface GenerativeUIScopeProps extends GenerativeUIOptions {
705
+ fallbackText?: string;
706
+ componentVersions?: Record<string, number>;
681
707
  fallback?: GenerativeUIFallback;
682
708
  loading?: ReactNode;
683
709
  onError?: (error: unknown, item: GenerativeUIItem) => void;
@@ -687,7 +713,7 @@ interface GenerativeUIScopeProps extends GenerativeUIOptions {
687
713
  * The registry, catalog and fallbacks tree nodes render with. `<GenerativeUI>` provides it; wrap
688
714
  * your own chrome in it when you draw `useGenerativeUI`'s `Component` yourself and it may be a tree.
689
715
  */
690
- declare function GenerativeUIScope({ registry, catalog, resolveComponent, fallback, loading, onError, children, }: GenerativeUIScopeProps): React.JSX.Element;
716
+ declare function GenerativeUIScope({ registry, catalog, resolveComponent, fallback, fallbackText, componentVersions, loading, onError, children, }: GenerativeUIScopeProps): React.JSX.Element;
691
717
  /** What `<GenuiProvider>` hands every `<GenerativeUI>` / `useGenerativeUI` below it. */
692
718
  interface GenuiProviderValue extends Partial<GenerativeUIOptions> {
693
719
  fallback?: GenerativeUIFallback;
@@ -720,7 +746,7 @@ declare function useGenerativeUI(part: unknown, options?: Partial<GenerativeUIOp
720
746
  interface GenerativeUIProps extends Partial<GenerativeUIOptions> {
721
747
  /** A transcript `ui` block, a `data-ui` message part, or a stored `{ id, component, props, version? }`. */
722
748
  part: TranscriptUiBlock | GenerativeUIItem | unknown;
723
- /** Drawn for an unknown component, invalid props, or a renderer that threw. Default: the provider's, else nothing. */
749
+ /** Drawn for an unknown component, invalid props, or a renderer that threw. Default: the provider's, then the item's persisted text. */
724
750
  fallback?: GenerativeUIFallback;
725
751
  /** Drawn while a resolver or an async validation is pending. Default: the provider's, else nothing. */
726
752
  loading?: ReactNode;
@@ -738,4 +764,4 @@ interface GenerativeUIProps extends Partial<GenerativeUIOptions> {
738
764
  */
739
765
  declare function GenerativeUI({ part, registry, catalog, resolveComponent, treeRenderer, fallback: ownFallback, loading: ownLoading, onError: ownOnError, }: GenerativeUIProps): string | number | bigint | boolean | Iterable<ReactNode> | Promise<string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | React.JSX.Element | null | undefined;
740
766
 
741
- export { type TranscriptQuestionOption as $, type ApproveOptions as A, type BuildBlocksOptions as B, type ChatStatus as C, type CoercibleQuestion as D, type DescribeToolCallOptions as E, type ElicitationBlockOptions as F, type GenerativeUIItem as G, type GroupToolActivityOptions as H, type RawAnswer as I, type ResolvedReading as J, type ResolvedResultView as K, type RetrievedPassage as L, type MessageUsageInfo as M, type ToolActivityGroup as N, type ToolCallDescription as O, type ToolCallState as P, type ToolCallStatus as Q, type ResolveComponent as R, type SettleAction as S, type TranscriptUiBlock as T, type UsageSummary as U, type TranscriptApproval as V, type TranscriptApprovalStatus as W, type TranscriptElicitationBlock as X, type TranscriptElicitationOutcome as Y, type TranscriptFilesBlock as Z, type TranscriptQuestion as _, GENUI_TREE_COMPONENT as a, type TranscriptReasoningBlock as a0, type TranscriptSettleState as a1, type TranscriptSource as a2, type TranscriptSourcesBlock as a3, type TranscriptTextBlock as a4, type TranscriptToolBlock as a5, type TranscriptToolCall as a6, buildTranscriptBlocks as a7, coerceAnswer as a8, correctedCallIds as a9, describeTimestamp as aa, describeToolCall as ab, describeUsage as ac, extractMessageText as ad, fillTemplate as ae, formatRelativeTime as af, groupToolActivity as ag, inferResultView as ah, isActionCall as ai, phraseFor as aj, readPath as ak, resolveResultView as al, toolCallState as am, toolCatalogFrom as an, GenerativeUI as b, type GenerativeUIElement as c, type GenerativeUIFallback as d, type GenerativeUIOptions as e, type GenerativeUIProblem as f, type GenerativeUIProps as g, GenerativeUIScope as h, type GenerativeUIScopeProps as i, type GenerativeUIState as j, type GenuiCatalogLike as k, type GenuiIssueLike as l, GenuiProvider as m, type GenuiProviderProps as n, type GenuiProviderValue as o, type GenuiRegistry as p, type GenuiRenderer as q, GenuiTree as r, useGenuiProvider as s, type TranscriptBlock as t, useGenerativeUI as u, type TimestampInfo as v, type TranscriptFile as w, type ToolCatalog as x, type AnyToolUIPart as y, type ApprovalBlockOptions as z };
767
+ export { type TranscriptQuestion as $, type ApproveOptions as A, type ApprovalBlockOptions as B, type ChatStatus as C, type BuildBlocksOptions as D, type CoercibleQuestion as E, type DescribeToolCallOptions as F, type GenerativeUIItem as G, type ElicitationBlockOptions as H, type GroupToolActivityOptions as I, type RawAnswer as J, type ResolvedReading as K, type ResolvedResultView as L, type MessageUsageInfo as M, type RetrievedPassage as N, type ToolActivityGroup as O, type ToolCallDescription as P, type ToolCallState as Q, type ResolveComponent as R, type SettleAction as S, type TranscriptUiBlock as T, type UsageSummary as U, type ToolCallStatus as V, type TranscriptApproval as W, type TranscriptApprovalStatus as X, type TranscriptElicitationBlock as Y, type TranscriptElicitationOutcome as Z, type TranscriptFilesBlock as _, GENUI_TREE_COMPONENT as a, type TranscriptQuestionOption as a0, type TranscriptReasoningBlock as a1, type TranscriptSettleState as a2, type TranscriptSource as a3, type TranscriptSourcesBlock as a4, type TranscriptTextBlock as a5, type TranscriptToolBlock as a6, type TranscriptToolCall as a7, buildTranscriptBlocks as a8, coerceAnswer as a9, correctedCallIds as aa, describeTimestamp as ab, describeToolCall as ac, describeUsage as ad, extractMessageText as ae, fillTemplate as af, formatRelativeTime as ag, groupToolActivity as ah, inferResultView as ai, isActionCall as aj, phraseFor as ak, proposalNeedsPolling as al, readPath as am, reconcileProposalMessages as an, resolveResultView as ao, toolCallState as ap, toolCatalogFrom as aq, GenerativeUI as b, type GenerativeUIElement as c, type GenerativeUIFallback as d, type GenerativeUIOptions as e, type GenerativeUIProblem as f, type GenerativeUIProps as g, GenerativeUIScope as h, type GenerativeUIScopeProps as i, type GenerativeUIState as j, type GenuiCatalogLike as k, type GenuiIssueLike as l, GenuiProvider as m, type GenuiProviderProps as n, type GenuiProviderValue as o, type GenuiRegistry as p, type GenuiRenderer as q, GenuiTree as r, useGenuiProvider as s, type ApprovalTarget as t, useGenerativeUI as u, type TranscriptBlock as v, type TimestampInfo as w, type TranscriptFile as x, type ToolCatalog as y, type AnyToolUIPart as z };
@@ -65,6 +65,10 @@ function toGenerativeUIItem(part) {
65
65
  return {
66
66
  id,
67
67
  component: source.component,
68
+ ...isRecord(source.componentVersions) && Object.values(source.componentVersions).every(
69
+ (version) => typeof version === "number" && Number.isSafeInteger(version) && version > 0
70
+ ) ? { componentVersions: { ...source.componentVersions } } : {},
71
+ ...typeof source.fallbackText === "string" ? { fallbackText: source.fallbackText } : {},
68
72
  props: isRecord(source.props) ? source.props : {},
69
73
  version: typeof source.version === "number" ? source.version : null,
70
74
  toolCallId: typeof source.toolCallId === "string" ? source.toolCallId : null
@@ -170,20 +174,29 @@ function useValidatedProps(catalog, name, props) {
170
174
  function useGenerativeUIState(part, options, fallbackTree) {
171
175
  const item = (0, import_react2.useMemo)(() => toGenerativeUIItem(part), [part]);
172
176
  const name = item?.component ?? "";
177
+ const definition = options.catalog?.get?.(name);
178
+ const incompatible = item?.fallbackText !== void 0 && item.version !== null && definition !== void 0 && item.version !== (definition.version ?? 1);
173
179
  const resolution = useResolvedComponent(
174
180
  name,
175
181
  item?.version ?? null,
176
- options.registry,
182
+ incompatible ? {} : options.registry,
177
183
  item === null ? void 0 : options.resolveComponent,
178
184
  fallbackTree
179
185
  );
180
186
  const empty = (0, import_react2.useMemo)(() => ({}), []);
181
187
  const validation = useValidatedProps(
182
- item === null || name === GENUI_TREE_COMPONENT ? void 0 : options.catalog,
188
+ item === null || name === GENUI_TREE_COMPONENT || incompatible ? void 0 : options.catalog,
183
189
  name,
184
190
  item?.props ?? empty
185
191
  );
186
192
  if (item === null) return null;
193
+ if (name === GENUI_TREE_COMPONENT && item.fallbackText !== void 0 && (!isRecord(item.props.root) || typeof item.props.root.type !== "string"))
194
+ return {
195
+ status: "problem",
196
+ reason: "invalid",
197
+ item,
198
+ issues: [{ path: ["root"], message: "Invalid UI tree root" }]
199
+ };
187
200
  if (resolution.status === "loading") return { status: "loading", item };
188
201
  if (resolution.status === "unknown") return { status: "problem", reason: "unknown", item };
189
202
  if (resolution.status === "error") {
@@ -201,7 +214,8 @@ var import_jsx_runtime = require("react/jsx-runtime");
201
214
  var TreeScopeContext = (0, import_react3.createContext)(null);
202
215
  function renderFallback(fallback, problem) {
203
216
  if (typeof fallback === "function") return fallback(problem);
204
- return fallback ?? null;
217
+ if (fallback !== void 0) return fallback;
218
+ return problem.item.fallbackText !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { whiteSpace: "pre-wrap" }, children: problem.item.fallbackText }) : null;
205
219
  }
206
220
  var ItemBoundary = class extends import_react3.Component {
207
221
  state = { error: void 0, failed: false };
@@ -233,28 +247,42 @@ function nodeItem(node, id) {
233
247
  function TreeNode({ node, id }) {
234
248
  const scope = (0, import_react3.useContext)(TreeScopeContext);
235
249
  const item = (0, import_react3.useMemo)(() => nodeItem(node, id), [node, id]);
250
+ const storedVersion = scope?.componentVersions?.[node.type];
251
+ const definition = scope?.options.catalog?.get?.(node.type);
252
+ const incompatible = storedVersion !== void 0 && definition !== void 0 && storedVersion !== (definition.version ?? 1);
236
253
  const resolution = useResolvedComponent(
237
254
  node.type,
238
- null,
239
- scope?.options.registry ?? {},
255
+ storedVersion ?? null,
256
+ incompatible ? {} : scope?.options.registry ?? {},
240
257
  scope?.options.resolveComponent
241
258
  );
242
- const validation = useValidatedProps(scope?.options.catalog, node.type, item.props);
259
+ const validation = useValidatedProps(
260
+ incompatible ? void 0 : scope?.options.catalog,
261
+ node.type,
262
+ item.props
263
+ );
243
264
  if (scope === null) return null;
244
265
  if (resolution.status === "loading" || validation.status === "pending") return scope.loading;
245
266
  if (resolution.status === "unknown") {
267
+ if (scope.fallback === void 0 && scope.fallbackText !== void 0)
268
+ throw new Error("Unknown tree component");
246
269
  return renderFallback(scope.fallback, { reason: "unknown", item });
247
270
  }
248
271
  if (resolution.status === "error") {
272
+ if (scope.fallback === void 0 && scope.fallbackText !== void 0) throw resolution.error;
249
273
  return renderFallback(scope.fallback, { reason: "error", item, error: resolution.error });
250
274
  }
251
275
  if (validation.status === "invalid") {
276
+ if (scope.fallback === void 0 && scope.fallbackText !== void 0)
277
+ throw new Error("Invalid tree component");
252
278
  return renderFallback(scope.fallback, { reason: "invalid", item, issues: validation.issues });
253
279
  }
254
280
  const Renderer2 = resolution.Component;
255
281
  const children = Array.isArray(node.children) ? node.children : [];
256
282
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Renderer2, { ...validation.props, children: children.length > 0 ? children.map((child, index) => {
257
283
  const childId = `${id}.${index}`;
284
+ if (scope.fallback === void 0 && scope.fallbackText !== void 0)
285
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TreeNode, { node: child, id: childId }, childId);
258
286
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
259
287
  ItemBoundary,
260
288
  {
@@ -276,6 +304,8 @@ function GenerativeUIScope({
276
304
  catalog,
277
305
  resolveComponent,
278
306
  fallback,
307
+ fallbackText,
308
+ componentVersions,
279
309
  loading = null,
280
310
  onError,
281
311
  children
@@ -288,10 +318,21 @@ function GenerativeUIScope({
288
318
  ...resolveComponent !== void 0 ? { resolveComponent } : {}
289
319
  },
290
320
  fallback,
321
+ ...componentVersions !== void 0 ? { componentVersions } : {},
322
+ ...fallbackText !== void 0 ? { fallbackText } : {},
291
323
  loading,
292
324
  onError
293
325
  }),
294
- [registry, catalog, resolveComponent, fallback, loading, onError]
326
+ [
327
+ registry,
328
+ catalog,
329
+ resolveComponent,
330
+ fallback,
331
+ fallbackText,
332
+ componentVersions,
333
+ loading,
334
+ onError
335
+ ]
295
336
  );
296
337
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TreeScopeContext.Provider, { value: scope, children });
297
338
  }
@@ -351,7 +392,7 @@ function GenerativeUI({
351
392
  onError: ownOnError
352
393
  }) {
353
394
  const provided = (0, import_react3.useContext)(GenuiContext);
354
- const fallback = ownFallback ?? provided?.fallback;
395
+ const fallback = ownFallback !== void 0 ? ownFallback : provided?.fallback;
355
396
  const loading = ownLoading ?? provided?.loading ?? null;
356
397
  const onError = ownOnError ?? provided?.onError;
357
398
  const options = useMergedOptions({
@@ -376,6 +417,8 @@ function GenerativeUI({
376
417
  GenerativeUIScope,
377
418
  {
378
419
  ...options,
420
+ ...state.item.componentVersions !== void 0 ? { componentVersions: state.item.componentVersions } : {},
421
+ ...state.item.fallbackText !== void 0 ? { fallbackText: state.item.fallbackText } : {},
379
422
  fallback,
380
423
  loading,
381
424
  ...onError !== void 0 ? { onError } : {},