Generative UI (/genui)
The generative-UI API across the packages — the isomorphic catalog in core, AgentGenuiModule in the NestJS package, GenuiProvider in the React package.
Generative UI is not a package of its own: it is a /genui subpath of the three packages an app
already has. For the walkthrough see the Generative UI guide.
| Subpath | Runs in | What it is |
|---|---|---|
@dudousxd/nestjs-agent-core/genui (+ /genui/builtins) | server and browser | The catalog: definitions, validation, model text, fallbacks, tool factories. |
@dudousxd/nestjs-agent/genui | NestJS | AgentGenuiModule, GENUI_CATALOG, GenuiCatalogResolver. Re-exports the core subpath. |
@dudousxd/nestjs-agent-react/genui (+ /genui/json-render) | browser | GenuiProvider, GenerativeUI, useGenerativeUI, createReactComponentRegistry. |
@dudousxd/nestjs-agent-react/genui/server | Node.js | createReactServerRenderer: static HTML and paginated PNG/PDF with your React registry. |
@dudousxd/nestjs-agent-react/genui/server/playwright | Node.js | createPlaywrightCaptureAdapter: optional capture using your installed browser. |
Headless: definitions and renderers' plumbing only, never visuals. Each app draws components its own way, keyed by name.
@dudousxd/nestjs-agent-core/genui
Isomorphic: it bundles nothing server-only, so one catalog file serves the NestJS app and the browser.
| Export | What it is |
|---|---|
createComponent(def) | Validating callable factory returning portable { component, props, version, fallbackText }; exposes .definition. |
createComponentRegistry(options?) | App-owned channel renderers, authoritative prepare/render, .catalog, and .manifest. |
table(props) / chart(props) | Factories for the built-in DataTable and Chart contracts; definitions, not themed visuals. |
defineComponent(def) | Declares one component: { name, title, description, props, children?, fallbackText?, internal?, version? }. |
defineCatalog(defs, { jsonSchemaValidator? }) | A Catalog: get, has, modelComponents(), validate(name, props), validateSync, jsonSchemaFor(name), extend(defs). |
flatComponents(catalog) | The model components a flat tool (ui__show_<snake>, ui__show) offers: every non-internal one without children: true. |
ajvValidator(ajv) / builtinJsonSchemaValidator | JSON Schema checking: bring your Ajv for the full spec, or use the dependency-free subset. |
catalogToModelText(catalog, { mode, namePrefix }) | The catalog as model text (mode: tree, per-component or show). |
componentToText(catalog, component, props) | A pushed component as plain text / Slack mrkdwn (fallbackText, else JSON; a layout component — children: true — whose fallback is empty writes nothing). Handles genui:tree. |
genuiTools(catalog, options) | Lib tools ({ spec, handler }) that validate and push ui frames — what AgentGenuiModule registers. |
validateTree, treeJsonSchema, treeToText, treeToFlatSpec | Tree mode: validation, the tool's input schema, text, json-render flat spec. |
showToolJsonSchema, GENUI_SHOW_TOOL | The generic show tool's input schema and default name (ui__show). |
GENUI_TREE_COMPONENT | 'genui:tree' — the component name a tree frame is pushed under. |
UiCapabilities, validateUiCapabilities(value) | What a client declares it draws, { components: { name, version }[] }, and its strict validator (throws TypeError). |
negotiateCatalog(catalog, capabilities?) | The catalog narrowed to the declared components, matched by name and exact version. undefined returns the catalog unchanged. |
prepareUiEmission(catalog, capabilities, component, props, version?) | Validates one emission against the trusted catalog and returns { kind: 'ui', …, fallbackText } or { kind: 'text', text }. What ctx.emitUi uses. See One answer, every surface. |
validatePresentationBatch, snapshotComponentPresentation | Check what a present hook returned; snapshot a presentation to plain JSON. |
/builtins | BUILTIN_COMPONENTS (DataTable, Chart, KpiCards, SourceCards, Checklist, Timeline, CodeBlock, Diff, Callout) and LAYOUT_COMPONENTS (Stack, Card, Heading, Text, Badge, Link, Image) — definitions only. See Builtin components. |
genuiTools / AgentGenuiModule options
| Option | Default | |
|---|---|---|
mode | 'tree' | One ui__render tool taking { type, props, children? } (a single node is pushed as that component), or 'per-component': one ui__show_<snake> tool per model-facing component except layout ones (children: true). |
treeSchema | 'strict' | ui__render's input schema: a $defs / $ref union by type with each component's props schema (root a plain object), or 'loose': one generic node shape. |
streaming | 'complete' | Tree mode: 'partial' streams the tree as partial ui frames while the model writes it. A component's own streaming overrides it. |
streamingThrottleMs | 100 | Least time between two partial frames of one call. |
terminal | false | The turn ends once a call succeeds. |
showTool | off | Also one generic tool taking { component, props }. true names it ui__show; a string names it. |
showInstructions | Prepended to the show tool's description. | |
namePrefix | 'ui__show_' | Per-component tool names. |
treeToolName | 'ui__render' | |
treeInstructions | Prepended to the tree tool's description. | |
treeLimits | { maxDepth: 12, maxNodes: 200 } | |
roles | ToolSpec.roles for every generated tool. | |
ability | ToolSpec.ability for the generated tools, for an ability-aware policy (AuthzRolesPolicy, or any authorizer that denies a tool with no ability). A string for every tool; a map by tool name ({ ui__render: 'genui.render', ui__sandbox: 'genui.sandbox' }, where a tool left out declares none); or ({ name, component }) => ability | undefined. The policy still decides. | |
presentation(name) | label/running/done from title, result: { kind: 'elsewhere' } | |
resolveCatalog(scope) (core) / resolver (Nest) | The catalog for one request, { actor, threadId?, tenant?, agentName? }. Consulted on every call and every turn's description. |
A genui tool returns { shown, id } to the model: what it pushed, and the frame's id.
@dudousxd/nestjs-agent/genui
| Export | What it is |
|---|---|
AgentGenuiModule.forRoot(options) | Global. Registers the genui tools as agent tools. Options above, plus catalog (default empty) and resolver (a class resolved with DI, or an instance). |
AgentGenuiModule.forRootAsync({ imports, inject, useFactory, resolver }) | Same, options from a factory. |
GENUI_CATALOG, @InjectGenuiCatalog() | The catalog, injectable; overrideProvider(GENUI_CATALOG) in a test rebuilds the tools from yours. |
GenuiCatalogResolver | Abstract class: resolve(scope) → Catalog | Promise<Catalog>. Injectable when configured; overrideProvider(GenuiCatalogResolver) in a test. |
everything from @dudousxd/nestjs-agent-core/genui | Re-exported. |
@dudousxd/nestjs-agent-react/genui
| Export | What it is |
|---|---|
GenuiProvider | { registry, catalog?, resolveComponent?, fallback?, loading?, placeholder?, onError?, treeRenderer? } at the root. Without fallback, a component that cannot be drawn shows its stored fallbackText. MessageItem / MessageList draw pushed components inside it with no renderUi. |
GenerativeUI | <GenerativeUI part /> — one pushed component, with the provider's settings; its own props win. |
useGenerativeUI(part, options?) | The state (ready / loading / problem) for custom chrome. |
useGenuiProvider() | The provider's settings. |
useGenuiNode() | Inside a tree node's renderer: { id, type, incomplete, held } (null outside a tree). See Loading states and skeletons. |
GenerativeUIScope, GenuiTree | Tree rendering for custom chrome. |
/genui/json-render | GenuiProvider with jsonRender (a json-render registry, or true to derive it from registry); JsonRenderTree, jsonRenderTree, toJsonRenderRegistry, treeToJsonRenderSpec. Optional peer @json-render/react >= 0.21. |
Shared React and server rendering
createReactComponentRegistry() registers { react, text?, paginate? } per definition. Its .components and .catalog serve GenuiProvider, and the same registry serves createReactServerRenderer({ registry, stylesheet?, theme?, capture? }). The server renderer exports html(presentation), images(presentation, options?), and pdf(presentation, options?).
The server and Playwright entries are optional Node-only imports. HTML needs matching React/ReactDOM versions; image/PDF capture additionally needs a CaptureAdapter. The Playwright implementation blocks scripts, unapproved asset traffic, and redirects, and keeps supplied browsers caller-owned.
See Component registries and server rendering for code, pagination settings, and transport responsibilities.
@dudousxd/nestjs-agent-react
useAgentChat, the AgentChatTransport and AgentClient, the headless transcript model, styling-agnostic chat components, dictation, and the markdown subpath.
@dudousxd/nestjs-agent-data
createExecuteSqlTool — governed, read-only SQL as a prebuilt tool. AST-validated single SELECTs, a fail-closed table allowlist, tenant scoping, and a row cap.