@dudousxd/nestjs-agent-core 0.44.1 → 0.45.1

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,8 +1,8 @@
1
- import { a as Catalog, J as JsonSchema, G as GenuiValidation, b as GenuiIssue } from '../catalog-G8usJpx5.cjs';
2
- export { A as AjvLike, c as COMPONENT_NAME, d as CatalogOptions, C as ComponentDefinition, e as JsonSchemaValidator, P as PropsSchema, f as ajvValidator, g as builtinJsonSchemaValidator, h as defineCatalog, i as defineComponent, j as flatComponents, k as formatIssues, l as isStandardSchema, t as toJsonSchema, m as toSnakeCase, n as toolNameFor, v as validateProps, o as validatePropsSync } from '../catalog-G8usJpx5.cjs';
1
+ import { a as Catalog, J as JsonSchema, G as GenuiValidation, b as GenuiStreaming, c as GenuiIssue } from '../catalog-BUmTnAqU.cjs';
2
+ export { A as AjvLike, d as COMPONENT_NAME, e as CatalogOptions, C as ComponentDefinition, f as JsonSchemaValidator, P as PropsSchema, g as ajvValidator, h as builtinJsonSchemaValidator, i as defineCatalog, j as defineComponent, k as flatComponents, l as formatIssues, m as isStandardSchema, t as toJsonSchema, n as toSnakeCase, o as toolNameFor, v as validateProps, p as validatePropsSync } from '../catalog-BUmTnAqU.cjs';
3
+ import { P as PartialToolInput, a as Actor, T as ToolSpec, b as ToolHandler, c as ToolPresentation } from '../stream-events-qB6NOOvn.cjs';
4
+ export { C as ChartProps, d as ComponentFactory, e as ComponentManifest, f as ComponentPresentation, g as ComponentRegistry, h as ComponentRenderer, i as PreparedUiEmission, j as TableCell, k as TableProps, U as UiCapabilities, l as chart, m as createComponent, n as createComponentRegistry, o as negotiateCatalog, p as prepareUiEmission, s as snapshotComponentPresentation, t as table, v as validatePresentationBatch, q as validateUiCapabilities } from '../stream-events-qB6NOOvn.cjs';
3
5
  import { StandardSchemaV1, StandardJSONSchemaV1 } from '@standard-schema/spec';
4
- import { a as Actor, T as ToolSpec, b as ToolHandler, c as ToolPresentation } from '../stream-events-BfxJAckJ.cjs';
5
- export { C as ChartProps, d as ComponentFactory, e as ComponentManifest, f as ComponentPresentation, g as ComponentRegistry, h as ComponentRenderer, P as PreparedUiEmission, i as TableCell, j as TableProps, U as UiCapabilities, k as chart, l as createComponent, m as createComponentRegistry, n as negotiateCatalog, p as prepareUiEmission, s as snapshotComponentPresentation, t as table, v as validatePresentationBatch, o as validateUiCapabilities } from '../stream-events-BfxJAckJ.cjs';
6
6
 
7
7
  /**
8
8
  * One node of a composed UI: a catalog component, its props, and — for components declared with
@@ -40,12 +40,33 @@ interface TreeLimits {
40
40
  */
41
41
  declare function validateTree(catalog: Catalog, tree: unknown, limits?: TreeLimits, phase?: 'input' | 'output'): Promise<GenuiValidation<GenuiElement>>;
42
42
  /**
43
- * The JSON Schema of a tree-mode tool's input: a recursive `{ type, props, children? }` node whose
44
- * `type` is one of the catalog's model-facing component names. Per-component props are described
45
- * to the model in the tool description (see `catalogToModelText`) and checked by
46
- * {@link validateTree}, which keeps this schema small enough for every provider.
43
+ * How exactly a tree-mode tool's input is described to the model ({@link treeJsonSchema}):
44
+ *
45
+ * - `'strict'` (default): every node's `props` is its component's own props schema, and `children`
46
+ * is a discriminated union by `type` over the components — each variant with its exact props, and
47
+ * `children` only on components that take them (recursive, through `$defs` / `$ref`).
48
+ * - `'loose'`: one `{ type, props: object, children }` node shape — for a provider that refuses
49
+ * `$ref` in tool parameters. The props are then only described in the tool's text.
50
+ */
51
+ type TreeSchemaMode = 'strict' | 'loose';
52
+ /**
53
+ * The JSON Schema of a tree-mode tool's input. Whatever it says, {@link validateTree} remains the
54
+ * check every call goes through: a provider is free to ignore the schema.
55
+ *
56
+ * Strict (the default), it is shaped for what the providers accept in tool parameters:
57
+ * - the root is a plain `type: 'object'` — OpenAI and Anthropic both refuse a union at the top
58
+ * level of a tool's parameters — whose `type` lists every component and whose `props` is any of
59
+ * their props schemas;
60
+ * - every `children` item is `{ $ref: '#/$defs/node' }`, an `anyOf` of one variant per component
61
+ * (`type` a one-value `enum`, `props` that component's schema, `children` only where taken,
62
+ * `additionalProperties: false`);
63
+ * - a component whose props schema is not self-contained (it carries its own `$ref`, `$defs` or
64
+ * `definitions`, as a recursive Zod schema does) is described as `{ type: 'object' }`, since its
65
+ * references would not resolve once embedded; `$schema` is dropped.
47
66
  */
48
- declare function treeJsonSchema(catalog: Catalog): JsonSchema;
67
+ declare function treeJsonSchema(catalog: Catalog, options?: {
68
+ schema?: TreeSchemaMode;
69
+ }): JsonSchema;
49
70
  /** A json-render flat spec: `{ root, elements: { [id]: { type, props, children: id[] } } }`. */
50
71
  interface FlatSpec {
51
72
  root: string;
@@ -58,6 +79,47 @@ interface FlatSpec {
58
79
  /** Convert a tree to a json-render flat spec (ids are `el-0`, `el-1`, … in depth-first order). */
59
80
  declare function treeToFlatSpec(root: GenuiElement): FlatSpec;
60
81
 
82
+ /**
83
+ * One node of a tree the model is still writing — what a partial `genui:tree` frame carries.
84
+ *
85
+ * `id` is the node's position: `root`, then `<parent id>.<index>` (`root.1.0`). It never changes as
86
+ * the tree grows (a model only ever appends), and the final tree's nodes are addressed by the same
87
+ * rule, so a renderer keyed on it keeps every node mounted from the first preview to the final frame.
88
+ */
89
+ interface GenuiPartialElement {
90
+ id: string;
91
+ type: string;
92
+ props: Record<string, unknown>;
93
+ children?: GenuiPartialElement[];
94
+ /** The model has not finished writing this node: its props (or children) may still grow. */
95
+ incomplete?: true;
96
+ /**
97
+ * The node's component streams `complete`: its props and children are held back until its whole
98
+ * subtree has arrived (`props` is `{}`). Draw a placeholder, never the component.
99
+ */
100
+ held?: true;
101
+ }
102
+ /** The id of the child at `index` of the node `parentId` (the root is `root`). */
103
+ declare function treeNodeId(parentId: string, index: number): string;
104
+ interface PartialTreeOptions {
105
+ /** How a component without its own `streaming` appears. Default `'complete'`. */
106
+ streaming?: GenuiStreaming;
107
+ limits?: TreeLimits;
108
+ }
109
+ /**
110
+ * The part of a streaming `ui__render` input worth drawing: every node whose `type` has fully
111
+ * arrived and names a component of `catalog` (the negotiated one: what this client draws), with its
112
+ * props so far — unvalidated, and flagged `incomplete` while still open. A node whose component
113
+ * streams `complete` is a `held` placeholder until it closes.
114
+ *
115
+ * `{ root: null }` while nothing is drawable yet. `null` when the input can no longer become a tree
116
+ * this client draws (an unknown or undrawable component, children where none are taken, past the
117
+ * size limits): the preview stops there, and the final push decides what is shown.
118
+ */
119
+ declare function partialTree(catalog: Catalog, input: PartialToolInput, options?: PartialTreeOptions): {
120
+ root: GenuiPartialElement | null;
121
+ } | null;
122
+
61
123
  /**
62
124
  * Plain text (Slack mrkdwn compatible) for a pushed component: its definition's `fallbackText`, or
63
125
  * the props as a JSON block when the catalog has no text for it. A tree frame
@@ -117,12 +179,20 @@ interface GenuiCatalogScope {
117
179
  type ResolveGenuiCatalog = (scope: GenuiCatalogScope) => Catalog | Promise<Catalog>;
118
180
  interface GenuiToolsOptions {
119
181
  /**
120
- * `per-component` (default): one tool per model-facing component, `ui__show_<snake>`, whose input
121
- * IS the component's props — except layout components (`children: true`), which a flat input
122
- * cannot fill. `tree`: a single tool whose input is a nested
123
- * `{ type, props, children }` tree composed from the catalog (json-render's nested shape).
182
+ * `tree` (default): a single `ui__render` tool whose input is a nested `{ type, props, children }`
183
+ * tree composed from the catalog (json-render's nested shape). A tree of one component with no
184
+ * children is pushed as that component, exactly as its `ui__show_*` tool would push it.
185
+ * `per-component`: one tool per model-facing component, `ui__show_<snake>`, whose input IS the
186
+ * component's props — for small models, or when each tool should carry its exact schema. Layouts
187
+ * (`children: true`) get none: a flat input cannot fill them.
124
188
  */
125
189
  mode?: 'per-component' | 'tree';
190
+ /**
191
+ * How the tree tool's input schema describes the nodes (see {@link treeJsonSchema}): `'strict'`
192
+ * (default) — a recursive union by `type` with each component's exact props; `'loose'` — one
193
+ * generic node shape, for a provider that refuses `$ref` in tool parameters.
194
+ */
195
+ treeSchema?: TreeSchemaMode;
126
196
  /**
127
197
  * The model's turn ends once a genui call succeeds — no further model call to narrate what the UI
128
198
  * already shows. Stamped as `spec.terminal`.
@@ -136,6 +206,21 @@ interface GenuiToolsOptions {
136
206
  treeInstructions?: string;
137
207
  /** Size limits for `tree`. */
138
208
  treeLimits?: TreeLimits;
209
+ /**
210
+ * Tree mode: whether the layout is drawn WHILE the model writes it.
211
+ *
212
+ * - `'complete'` (default): nothing is drawn until the call has run; then the validated tree
213
+ * appears whole.
214
+ * - `'partial'`: the server parses the streaming `ui__render` arguments and pushes the tree so far
215
+ * as `partial` `ui` frames under the id the final push replaces — throttled, unvalidated, never
216
+ * persisted, never sent to a text channel. Nodes still being written are flagged `incomplete`; a
217
+ * component declared `streaming: 'complete'` is a `held` placeholder until its subtree closes.
218
+ *
219
+ * A component's own {@link ComponentDefinition.streaming} overrides this per component.
220
+ */
221
+ streaming?: GenuiStreaming;
222
+ /** Least time between two partial tree frames of one call, in ms. Default 100. */
223
+ streamingThrottleMs?: number;
139
224
  /**
140
225
  * Also offer ONE generic tool taking `{ component, props }`, validated against the (resolved)
141
226
  * catalog — how a model reaches components that only exist per request (a tenant's own), which a
@@ -175,4 +260,4 @@ type JsonStandardSchema = StandardSchemaV1 & StandardJSONSchemaV1;
175
260
  */
176
261
  declare function jsonStandardSchema(schema: JsonSchema, validate: (value: unknown) => GenuiIssue[]): JsonStandardSchema;
177
262
 
178
- export { Catalog, type CatalogTextOptions, type FlatSpec, GENUI_SHOW_TOOL, GENUI_TREE_COMPONENT, type GenuiCatalogScope, type GenuiElement, GenuiIssue, type GenuiTool, type GenuiToolOutput, type GenuiToolsOptions, type GenuiTreeProps, GenuiValidation, JsonSchema, type ResolveGenuiCatalog, type TreeLimits, catalogToModelText, componentToText, fillTemplate, genuiTools, getPath, jsonStandardSchema, showToolJsonSchema, summarizeSchema, treeJsonSchema, treeToFlatSpec, treeToText, validateTree };
263
+ export { Catalog, type CatalogTextOptions, type FlatSpec, GENUI_SHOW_TOOL, GENUI_TREE_COMPONENT, type GenuiCatalogScope, type GenuiElement, GenuiIssue, type GenuiPartialElement, GenuiStreaming, type GenuiTool, type GenuiToolOutput, type GenuiToolsOptions, type GenuiTreeProps, GenuiValidation, JsonSchema, type PartialTreeOptions, type ResolveGenuiCatalog, type TreeLimits, type TreeSchemaMode, catalogToModelText, componentToText, fillTemplate, genuiTools, getPath, jsonStandardSchema, partialTree, showToolJsonSchema, summarizeSchema, treeJsonSchema, treeNodeId, treeToFlatSpec, treeToText, validateTree };
@@ -1,8 +1,8 @@
1
- import { a as Catalog, J as JsonSchema, G as GenuiValidation, b as GenuiIssue } from '../catalog-G8usJpx5.js';
2
- export { A as AjvLike, c as COMPONENT_NAME, d as CatalogOptions, C as ComponentDefinition, e as JsonSchemaValidator, P as PropsSchema, f as ajvValidator, g as builtinJsonSchemaValidator, h as defineCatalog, i as defineComponent, j as flatComponents, k as formatIssues, l as isStandardSchema, t as toJsonSchema, m as toSnakeCase, n as toolNameFor, v as validateProps, o as validatePropsSync } from '../catalog-G8usJpx5.js';
1
+ import { a as Catalog, J as JsonSchema, G as GenuiValidation, b as GenuiStreaming, c as GenuiIssue } from '../catalog-BUmTnAqU.js';
2
+ export { A as AjvLike, d as COMPONENT_NAME, e as CatalogOptions, C as ComponentDefinition, f as JsonSchemaValidator, P as PropsSchema, g as ajvValidator, h as builtinJsonSchemaValidator, i as defineCatalog, j as defineComponent, k as flatComponents, l as formatIssues, m as isStandardSchema, t as toJsonSchema, n as toSnakeCase, o as toolNameFor, v as validateProps, p as validatePropsSync } from '../catalog-BUmTnAqU.js';
3
+ import { P as PartialToolInput, a as Actor, T as ToolSpec, b as ToolHandler, c as ToolPresentation } from '../stream-events-CqCqYjJw.js';
4
+ export { C as ChartProps, d as ComponentFactory, e as ComponentManifest, f as ComponentPresentation, g as ComponentRegistry, h as ComponentRenderer, i as PreparedUiEmission, j as TableCell, k as TableProps, U as UiCapabilities, l as chart, m as createComponent, n as createComponentRegistry, o as negotiateCatalog, p as prepareUiEmission, s as snapshotComponentPresentation, t as table, v as validatePresentationBatch, q as validateUiCapabilities } from '../stream-events-CqCqYjJw.js';
3
5
  import { StandardSchemaV1, StandardJSONSchemaV1 } from '@standard-schema/spec';
4
- import { a as Actor, T as ToolSpec, b as ToolHandler, c as ToolPresentation } from '../stream-events-DFa2Do42.js';
5
- export { C as ChartProps, d as ComponentFactory, e as ComponentManifest, f as ComponentPresentation, g as ComponentRegistry, h as ComponentRenderer, P as PreparedUiEmission, i as TableCell, j as TableProps, U as UiCapabilities, k as chart, l as createComponent, m as createComponentRegistry, n as negotiateCatalog, p as prepareUiEmission, s as snapshotComponentPresentation, t as table, v as validatePresentationBatch, o as validateUiCapabilities } from '../stream-events-DFa2Do42.js';
6
6
 
7
7
  /**
8
8
  * One node of a composed UI: a catalog component, its props, and — for components declared with
@@ -40,12 +40,33 @@ interface TreeLimits {
40
40
  */
41
41
  declare function validateTree(catalog: Catalog, tree: unknown, limits?: TreeLimits, phase?: 'input' | 'output'): Promise<GenuiValidation<GenuiElement>>;
42
42
  /**
43
- * The JSON Schema of a tree-mode tool's input: a recursive `{ type, props, children? }` node whose
44
- * `type` is one of the catalog's model-facing component names. Per-component props are described
45
- * to the model in the tool description (see `catalogToModelText`) and checked by
46
- * {@link validateTree}, which keeps this schema small enough for every provider.
43
+ * How exactly a tree-mode tool's input is described to the model ({@link treeJsonSchema}):
44
+ *
45
+ * - `'strict'` (default): every node's `props` is its component's own props schema, and `children`
46
+ * is a discriminated union by `type` over the components — each variant with its exact props, and
47
+ * `children` only on components that take them (recursive, through `$defs` / `$ref`).
48
+ * - `'loose'`: one `{ type, props: object, children }` node shape — for a provider that refuses
49
+ * `$ref` in tool parameters. The props are then only described in the tool's text.
50
+ */
51
+ type TreeSchemaMode = 'strict' | 'loose';
52
+ /**
53
+ * The JSON Schema of a tree-mode tool's input. Whatever it says, {@link validateTree} remains the
54
+ * check every call goes through: a provider is free to ignore the schema.
55
+ *
56
+ * Strict (the default), it is shaped for what the providers accept in tool parameters:
57
+ * - the root is a plain `type: 'object'` — OpenAI and Anthropic both refuse a union at the top
58
+ * level of a tool's parameters — whose `type` lists every component and whose `props` is any of
59
+ * their props schemas;
60
+ * - every `children` item is `{ $ref: '#/$defs/node' }`, an `anyOf` of one variant per component
61
+ * (`type` a one-value `enum`, `props` that component's schema, `children` only where taken,
62
+ * `additionalProperties: false`);
63
+ * - a component whose props schema is not self-contained (it carries its own `$ref`, `$defs` or
64
+ * `definitions`, as a recursive Zod schema does) is described as `{ type: 'object' }`, since its
65
+ * references would not resolve once embedded; `$schema` is dropped.
47
66
  */
48
- declare function treeJsonSchema(catalog: Catalog): JsonSchema;
67
+ declare function treeJsonSchema(catalog: Catalog, options?: {
68
+ schema?: TreeSchemaMode;
69
+ }): JsonSchema;
49
70
  /** A json-render flat spec: `{ root, elements: { [id]: { type, props, children: id[] } } }`. */
50
71
  interface FlatSpec {
51
72
  root: string;
@@ -58,6 +79,47 @@ interface FlatSpec {
58
79
  /** Convert a tree to a json-render flat spec (ids are `el-0`, `el-1`, … in depth-first order). */
59
80
  declare function treeToFlatSpec(root: GenuiElement): FlatSpec;
60
81
 
82
+ /**
83
+ * One node of a tree the model is still writing — what a partial `genui:tree` frame carries.
84
+ *
85
+ * `id` is the node's position: `root`, then `<parent id>.<index>` (`root.1.0`). It never changes as
86
+ * the tree grows (a model only ever appends), and the final tree's nodes are addressed by the same
87
+ * rule, so a renderer keyed on it keeps every node mounted from the first preview to the final frame.
88
+ */
89
+ interface GenuiPartialElement {
90
+ id: string;
91
+ type: string;
92
+ props: Record<string, unknown>;
93
+ children?: GenuiPartialElement[];
94
+ /** The model has not finished writing this node: its props (or children) may still grow. */
95
+ incomplete?: true;
96
+ /**
97
+ * The node's component streams `complete`: its props and children are held back until its whole
98
+ * subtree has arrived (`props` is `{}`). Draw a placeholder, never the component.
99
+ */
100
+ held?: true;
101
+ }
102
+ /** The id of the child at `index` of the node `parentId` (the root is `root`). */
103
+ declare function treeNodeId(parentId: string, index: number): string;
104
+ interface PartialTreeOptions {
105
+ /** How a component without its own `streaming` appears. Default `'complete'`. */
106
+ streaming?: GenuiStreaming;
107
+ limits?: TreeLimits;
108
+ }
109
+ /**
110
+ * The part of a streaming `ui__render` input worth drawing: every node whose `type` has fully
111
+ * arrived and names a component of `catalog` (the negotiated one: what this client draws), with its
112
+ * props so far — unvalidated, and flagged `incomplete` while still open. A node whose component
113
+ * streams `complete` is a `held` placeholder until it closes.
114
+ *
115
+ * `{ root: null }` while nothing is drawable yet. `null` when the input can no longer become a tree
116
+ * this client draws (an unknown or undrawable component, children where none are taken, past the
117
+ * size limits): the preview stops there, and the final push decides what is shown.
118
+ */
119
+ declare function partialTree(catalog: Catalog, input: PartialToolInput, options?: PartialTreeOptions): {
120
+ root: GenuiPartialElement | null;
121
+ } | null;
122
+
61
123
  /**
62
124
  * Plain text (Slack mrkdwn compatible) for a pushed component: its definition's `fallbackText`, or
63
125
  * the props as a JSON block when the catalog has no text for it. A tree frame
@@ -117,12 +179,20 @@ interface GenuiCatalogScope {
117
179
  type ResolveGenuiCatalog = (scope: GenuiCatalogScope) => Catalog | Promise<Catalog>;
118
180
  interface GenuiToolsOptions {
119
181
  /**
120
- * `per-component` (default): one tool per model-facing component, `ui__show_<snake>`, whose input
121
- * IS the component's props — except layout components (`children: true`), which a flat input
122
- * cannot fill. `tree`: a single tool whose input is a nested
123
- * `{ type, props, children }` tree composed from the catalog (json-render's nested shape).
182
+ * `tree` (default): a single `ui__render` tool whose input is a nested `{ type, props, children }`
183
+ * tree composed from the catalog (json-render's nested shape). A tree of one component with no
184
+ * children is pushed as that component, exactly as its `ui__show_*` tool would push it.
185
+ * `per-component`: one tool per model-facing component, `ui__show_<snake>`, whose input IS the
186
+ * component's props — for small models, or when each tool should carry its exact schema. Layouts
187
+ * (`children: true`) get none: a flat input cannot fill them.
124
188
  */
125
189
  mode?: 'per-component' | 'tree';
190
+ /**
191
+ * How the tree tool's input schema describes the nodes (see {@link treeJsonSchema}): `'strict'`
192
+ * (default) — a recursive union by `type` with each component's exact props; `'loose'` — one
193
+ * generic node shape, for a provider that refuses `$ref` in tool parameters.
194
+ */
195
+ treeSchema?: TreeSchemaMode;
126
196
  /**
127
197
  * The model's turn ends once a genui call succeeds — no further model call to narrate what the UI
128
198
  * already shows. Stamped as `spec.terminal`.
@@ -136,6 +206,21 @@ interface GenuiToolsOptions {
136
206
  treeInstructions?: string;
137
207
  /** Size limits for `tree`. */
138
208
  treeLimits?: TreeLimits;
209
+ /**
210
+ * Tree mode: whether the layout is drawn WHILE the model writes it.
211
+ *
212
+ * - `'complete'` (default): nothing is drawn until the call has run; then the validated tree
213
+ * appears whole.
214
+ * - `'partial'`: the server parses the streaming `ui__render` arguments and pushes the tree so far
215
+ * as `partial` `ui` frames under the id the final push replaces — throttled, unvalidated, never
216
+ * persisted, never sent to a text channel. Nodes still being written are flagged `incomplete`; a
217
+ * component declared `streaming: 'complete'` is a `held` placeholder until its subtree closes.
218
+ *
219
+ * A component's own {@link ComponentDefinition.streaming} overrides this per component.
220
+ */
221
+ streaming?: GenuiStreaming;
222
+ /** Least time between two partial tree frames of one call, in ms. Default 100. */
223
+ streamingThrottleMs?: number;
139
224
  /**
140
225
  * Also offer ONE generic tool taking `{ component, props }`, validated against the (resolved)
141
226
  * catalog — how a model reaches components that only exist per request (a tenant's own), which a
@@ -175,4 +260,4 @@ type JsonStandardSchema = StandardSchemaV1 & StandardJSONSchemaV1;
175
260
  */
176
261
  declare function jsonStandardSchema(schema: JsonSchema, validate: (value: unknown) => GenuiIssue[]): JsonStandardSchema;
177
262
 
178
- export { Catalog, type CatalogTextOptions, type FlatSpec, GENUI_SHOW_TOOL, GENUI_TREE_COMPONENT, type GenuiCatalogScope, type GenuiElement, GenuiIssue, type GenuiTool, type GenuiToolOutput, type GenuiToolsOptions, type GenuiTreeProps, GenuiValidation, JsonSchema, type ResolveGenuiCatalog, type TreeLimits, catalogToModelText, componentToText, fillTemplate, genuiTools, getPath, jsonStandardSchema, showToolJsonSchema, summarizeSchema, treeJsonSchema, treeToFlatSpec, treeToText, validateTree };
263
+ export { Catalog, type CatalogTextOptions, type FlatSpec, GENUI_SHOW_TOOL, GENUI_TREE_COMPONENT, type GenuiCatalogScope, type GenuiElement, GenuiIssue, type GenuiPartialElement, GenuiStreaming, type GenuiTool, type GenuiToolOutput, type GenuiToolsOptions, type GenuiTreeProps, GenuiValidation, JsonSchema, type PartialTreeOptions, type ResolveGenuiCatalog, type TreeLimits, type TreeSchemaMode, catalogToModelText, componentToText, fillTemplate, genuiTools, getPath, jsonStandardSchema, partialTree, showToolJsonSchema, summarizeSchema, treeJsonSchema, treeNodeId, treeToFlatSpec, treeToText, validateTree };
@@ -355,6 +355,7 @@ function defineComponent(definition) {
355
355
  }
356
356
  if (definition.version !== void 0 && (!Number.isSafeInteger(definition.version) || definition.version <= 0)) throw new RangeError("genui: component version must be a positive safe integer");
357
357
  if (definition.fallbackText !== void 0 && typeof definition.fallbackText !== "function") throw new TypeError("genui: fallbackText must be a function");
358
+ if (definition.streaming !== void 0 && definition.streaming !== "partial" && definition.streaming !== "complete") throw new TypeError("genui: streaming must be 'partial' or 'complete'");
358
359
  return definition;
359
360
  }
360
361
  __name(defineComponent, "defineComponent");
@@ -439,6 +440,97 @@ function toolNameFor(component, prefix = "ui__show_") {
439
440
  }
440
441
  __name(toolNameFor, "toolNameFor");
441
442
 
443
+ // src/genui/progressive.ts
444
+ function treeNodeId(parentId, index) {
445
+ return `${parentId}.${index}`;
446
+ }
447
+ __name(treeNodeId, "treeNodeId");
448
+ function isRecord(value) {
449
+ return typeof value === "object" && value !== null && !Array.isArray(value);
450
+ }
451
+ __name(isRecord, "isRecord");
452
+ function partialTree(catalog, input, options = {}) {
453
+ const maxDepth = options.limits?.maxDepth ?? 12;
454
+ const maxNodes = options.limits?.maxNodes ?? 200;
455
+ const fallback = options.streaming ?? "complete";
456
+ let nodes = 0;
457
+ let broken = false;
458
+ const visit = /* @__PURE__ */ __name((value, id, depth) => {
459
+ if (broken) return void 0;
460
+ if (!isRecord(value)) {
461
+ if (value !== void 0) broken = true;
462
+ return void 0;
463
+ }
464
+ const open = input.isOpen(value);
465
+ const type = value.type;
466
+ if (typeof type !== "string" || open && input.pendingMember(value) === "type") {
467
+ if (!open) broken = true;
468
+ return void 0;
469
+ }
470
+ const definition = catalog.get(type);
471
+ nodes += 1;
472
+ if (definition === void 0 || definition.internal === true || nodes > maxNodes || depth > maxDepth) {
473
+ broken = true;
474
+ return void 0;
475
+ }
476
+ const mode = definition.streaming ?? fallback;
477
+ if (mode === "complete") {
478
+ const checked = open ? void 0 : validatePropsSync(definition.props, value.props ?? {}, catalog.validator);
479
+ if (checked === void 0 || !checked.ok) {
480
+ return {
481
+ id,
482
+ type,
483
+ props: {},
484
+ incomplete: true,
485
+ held: true
486
+ };
487
+ }
488
+ const children2 = childrenOf(value, id, depth, definition.children === true);
489
+ return {
490
+ id,
491
+ type,
492
+ props: checked.value,
493
+ ...children2 !== void 0 && children2.length > 0 ? {
494
+ children: children2
495
+ } : {}
496
+ };
497
+ }
498
+ const props = isRecord(value.props) ? value.props : {};
499
+ const children = childrenOf(value, id, depth, definition.children === true);
500
+ return {
501
+ id,
502
+ type,
503
+ props,
504
+ ...children !== void 0 && children.length > 0 ? {
505
+ children
506
+ } : {},
507
+ ...open ? {
508
+ incomplete: true
509
+ } : {}
510
+ };
511
+ }, "visit");
512
+ const childrenOf = /* @__PURE__ */ __name((value, id, depth, takesChildren) => {
513
+ const raw = value.children;
514
+ if (!Array.isArray(raw)) return void 0;
515
+ if (raw.length > 0 && !takesChildren) {
516
+ broken = true;
517
+ return void 0;
518
+ }
519
+ const children = [];
520
+ for (const [index, child] of raw.entries()) {
521
+ const next = visit(child, treeNodeId(id, index), depth + 1);
522
+ if (next !== void 0) children.push(next);
523
+ }
524
+ return children;
525
+ }, "childrenOf");
526
+ const root = visit(input.value, "root", 1);
527
+ if (broken) return null;
528
+ return {
529
+ root: root ?? null
530
+ };
531
+ }
532
+ __name(partialTree, "partialTree");
533
+
442
534
  // src/genui/tree.ts
443
535
  var GENUI_TREE_COMPONENT = "genui:tree";
444
536
  async function validateTree(catalog, tree, limits = {}, phase = "output") {
@@ -571,34 +663,120 @@ async function validateTree(catalog, tree, limits = {}, phase = "output") {
571
663
  };
572
664
  }
573
665
  __name(validateTree, "validateTree");
574
- function treeJsonSchema(catalog) {
666
+ function treeJsonSchema(catalog, options = {}) {
667
+ const components = catalog.modelComponents();
668
+ const names = components.map((component) => component.name);
669
+ if (options.schema === "loose") {
670
+ return {
671
+ type: "object",
672
+ properties: {
673
+ type: {
674
+ type: "string",
675
+ enum: names,
676
+ description: "Component name from the catalog"
677
+ },
678
+ props: {
679
+ type: "object",
680
+ description: "The component's props, as the catalog describes them"
681
+ },
682
+ children: {
683
+ type: "array",
684
+ items: {
685
+ $ref: "#"
686
+ },
687
+ description: "Nested elements, only for components that take children. A literal JSON array, never a JSON-stringified one."
688
+ }
689
+ },
690
+ required: [
691
+ "type",
692
+ "props"
693
+ ]
694
+ };
695
+ }
696
+ const defs = {};
697
+ const childrenSchema = {
698
+ type: "array",
699
+ items: {
700
+ $ref: "#/$defs/node"
701
+ },
702
+ description: "Nested elements. A literal JSON array, never a JSON-stringified one."
703
+ };
704
+ for (const component of components) {
705
+ defs[`props_${component.name}`] = embeddableProps(toJsonSchema(component.props));
706
+ defs[`node_${component.name}`] = {
707
+ type: "object",
708
+ properties: {
709
+ type: {
710
+ type: "string",
711
+ enum: [
712
+ component.name
713
+ ]
714
+ },
715
+ props: {
716
+ $ref: `#/$defs/props_${component.name}`
717
+ },
718
+ ...component.children === true ? {
719
+ children: childrenSchema
720
+ } : {}
721
+ },
722
+ required: [
723
+ "type",
724
+ "props"
725
+ ],
726
+ additionalProperties: false
727
+ };
728
+ }
729
+ defs.node = {
730
+ anyOf: components.map((component) => ({
731
+ $ref: `#/$defs/node_${component.name}`
732
+ }))
733
+ };
575
734
  return {
576
735
  type: "object",
577
736
  properties: {
578
737
  type: {
579
738
  type: "string",
580
- enum: catalog.modelComponents().map((component) => component.name),
581
- description: "Component name from the catalog"
739
+ enum: names,
740
+ description: "Component name from the catalog. A single component (no children) is a valid tree."
582
741
  },
583
742
  props: {
584
- type: "object",
585
- description: "The component's props, as the catalog describes them"
743
+ description: "The component's props: the schema of the component named by `type`",
744
+ anyOf: components.map((component) => ({
745
+ $ref: `#/$defs/props_${component.name}`
746
+ }))
586
747
  },
587
748
  children: {
588
- type: "array",
589
- items: {
590
- $ref: "#"
591
- },
749
+ ...childrenSchema,
592
750
  description: "Nested elements, only for components that take children. A literal JSON array, never a JSON-stringified one."
593
751
  }
594
752
  },
595
753
  required: [
596
754
  "type",
597
755
  "props"
598
- ]
756
+ ],
757
+ additionalProperties: false,
758
+ $defs: defs
599
759
  };
600
760
  }
601
761
  __name(treeJsonSchema, "treeJsonSchema");
762
+ function embeddableProps(schema) {
763
+ if (schema === void 0 || typeof schema !== "object" || schema === null) {
764
+ return {
765
+ type: "object"
766
+ };
767
+ }
768
+ const references = /* @__PURE__ */ __name((value) => {
769
+ if (Array.isArray(value)) return value.some(references);
770
+ if (typeof value !== "object" || value === null) return false;
771
+ return Object.entries(value).some(([key, nested]) => key === "$ref" || key === "$defs" || key === "definitions" || references(nested));
772
+ }, "references");
773
+ if (references(schema)) return {
774
+ type: "object"
775
+ };
776
+ const { $schema: _schema, ...rest } = schema;
777
+ return rest;
778
+ }
779
+ __name(embeddableProps, "embeddableProps");
602
780
  function treeToFlatSpec(root) {
603
781
  const elements = {};
604
782
  let next = 0;
@@ -869,9 +1047,9 @@ __name(prepareUiEmission, "prepareUiEmission");
869
1047
  // src/genui/tools.ts
870
1048
  var GENUI_SHOW_TOOL = "ui__show";
871
1049
  function genuiTools(catalog, options = {}) {
872
- const tools = options.mode === "tree" ? [
1050
+ const tools = options.mode === "per-component" ? flatComponents(catalog).map((component) => componentTool(catalog, component, options)) : [
873
1051
  treeTool(catalog, options)
874
- ] : flatComponents(catalog).map((component) => componentTool(catalog, component, options));
1052
+ ];
875
1053
  if (options.showTool !== void 0 && options.showTool !== false) {
876
1054
  tools.push(showTool(catalog, options));
877
1055
  }
@@ -982,6 +1160,9 @@ function treeTool(catalog, options) {
982
1160
  })
983
1161
  ].join("\n"), "describeFor");
984
1162
  const dynamic = options.resolveCatalog !== void 0;
1163
+ const treeSchemaOptions = options.treeSchema !== void 0 ? {
1164
+ schema: options.treeSchema
1165
+ } : {};
985
1166
  const handler = {
986
1167
  async execute(input, ctx) {
987
1168
  const resolved = await catalogFor(catalog, options, scopeOf(ctx));
@@ -990,6 +1171,10 @@ function treeTool(catalog, options) {
990
1171
  throw new Error(`invalid UI tree: ${formatIssues(result.issues)}`);
991
1172
  }
992
1173
  const root = result.value;
1174
+ const single = flatComponent(resolved, root.type);
1175
+ if (root.children === void 0 && single !== void 0) {
1176
+ return push(ctx, root.type, root.props, single.version);
1177
+ }
993
1178
  return push(ctx, GENUI_TREE_COMPONENT, {
994
1179
  root
995
1180
  });
@@ -1000,7 +1185,36 @@ function treeTool(catalog, options) {
1000
1185
  return {
1001
1186
  available: resolved.modelComponents().length > 0,
1002
1187
  description: describeFor(resolved),
1003
- inputSchema: permissiveSchema(treeJsonSchema(resolved))
1188
+ inputSchema: permissiveSchema(treeJsonSchema(resolved, treeSchemaOptions))
1189
+ };
1190
+ };
1191
+ handler.previewInput = async (scope) => {
1192
+ const resolved = negotiateCatalog(await catalogFor(catalog, options, scopeOf(scope)), scope.uiCapabilities);
1193
+ const streaming = options.streaming ?? "complete";
1194
+ if (!resolved.modelComponents().some((each) => (each.streaming ?? streaming) === "partial")) {
1195
+ return void 0;
1196
+ }
1197
+ return {
1198
+ ...options.streamingThrottleMs !== void 0 ? {
1199
+ throttleMs: options.streamingThrottleMs
1200
+ } : {},
1201
+ render(input) {
1202
+ const tree = partialTree(resolved, input, {
1203
+ streaming,
1204
+ ...options.treeLimits !== void 0 ? {
1205
+ limits: options.treeLimits
1206
+ } : {}
1207
+ });
1208
+ if (tree === null) return null;
1209
+ if (tree.root === null) return void 0;
1210
+ return {
1211
+ component: GENUI_TREE_COMPONENT,
1212
+ props: {
1213
+ root: tree.root
1214
+ },
1215
+ version: 1
1216
+ };
1217
+ }
1004
1218
  };
1005
1219
  };
1006
1220
  return {
@@ -1008,7 +1222,7 @@ function treeTool(catalog, options) {
1008
1222
  name,
1009
1223
  kind: "read",
1010
1224
  description: describeFor(catalog),
1011
- inputSchema: dynamic ? permissiveSchema(treeJsonSchema(catalog)) : asyncJsonStandardSchema(treeJsonSchema(catalog), async (value) => {
1225
+ inputSchema: dynamic ? permissiveSchema(treeJsonSchema(catalog, treeSchemaOptions)) : asyncJsonStandardSchema(treeJsonSchema(catalog, treeSchemaOptions), async (value) => {
1012
1226
  const result = await validateTree(catalog, value, options.treeLimits, "input");
1013
1227
  return result.ok ? {
1014
1228
  value: result.value
@@ -1856,6 +2070,7 @@ export {
1856
2070
  isStandardSchema,
1857
2071
  jsonStandardSchema,
1858
2072
  negotiateCatalog,
2073
+ partialTree,
1859
2074
  prepareUiEmission,
1860
2075
  showToolJsonSchema,
1861
2076
  snapshotComponentPresentation,
@@ -1865,6 +2080,7 @@ export {
1865
2080
  toSnakeCase,
1866
2081
  toolNameFor,
1867
2082
  treeJsonSchema,
2083
+ treeNodeId,
1868
2084
  treeToFlatSpec,
1869
2085
  treeToText,
1870
2086
  validatePresentationBatch,