@dudousxd/nestjs-agent-react 0.18.0 → 0.19.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 +1 @@
1
- {"version":3,"sources":["../src/genui/json-render.tsx"],"sourcesContent":["/**\n * Optional json-render adapter for tree frames (`@dudousxd/nestjs-agent-react/genui/json-render`).\n * Needs the optional peer `@json-render/react` (>= 0.21). Use it when your app already renders\n * json-render specs and wants tree frames to go through the same `Renderer` (its state, actions and\n * visibility machinery); otherwise `<GenerativeUI>` renders trees natively.\n *\n * ```tsx\n * const registry = { ...myComponents, [GENUI_TREE_COMPONENT]: jsonRenderTree(myJsonRenderRegistry) };\n * ```\n */\nimport { type ComponentRegistry, JSONUIProvider, Renderer } from '@json-render/react';\nimport { type ReactNode, useMemo } from 'react';\nimport type { GenerativeUIElement, GenuiRegistry, GenuiRenderer } from './types.js';\n\n/** A json-render flat spec: `{ root, elements: { [id]: { type, props, children } } }`. */\nexport interface JsonRenderFlatSpec {\n root: string;\n elements: Record<string, { type: string; props: Record<string, unknown>; children: string[] }>;\n}\n\n/** A tree frame's `root` as a json-render flat spec (ids `el-0`, `el-1`, … depth first). */\nexport function treeToJsonRenderSpec(root: GenerativeUIElement): JsonRenderFlatSpec {\n const elements: JsonRenderFlatSpec['elements'] = {};\n let next = 0;\n const visit = (node: GenerativeUIElement): string => {\n const id = `el-${next++}`;\n const entry = { type: node.type, props: node.props ?? {}, children: [] as string[] };\n elements[id] = entry;\n for (const child of node.children ?? []) entry.children.push(visit(child));\n return id;\n };\n return { root: visit(root), elements };\n}\n\n/**\n * Adapt a genui registry (renderers taking props + `children`) to a json-render registry (renderers\n * taking `{ element, children }`), so one set of components serves both.\n */\nexport function toJsonRenderRegistry(registry: GenuiRegistry): ComponentRegistry {\n return Object.fromEntries(\n Object.entries(registry).map(([name, Renderer]) => [\n name,\n ({ element, children }: { element: { props?: unknown }; children?: ReactNode }) => (\n <Renderer {...((element.props ?? {}) as Record<string, unknown>)}>{children}</Renderer>\n ),\n ]),\n );\n}\n\nexport interface JsonRenderTreeProps {\n root?: GenerativeUIElement;\n registry: ComponentRegistry;\n /** json-render state the spec's `$state` expressions read. */\n initialState?: Record<string, unknown>;\n}\n\n/** Render a tree frame's `root` with json-render. */\nexport function JsonRenderTree({ root, registry, initialState }: JsonRenderTreeProps) {\n const spec = useMemo(() => (root === undefined ? null : treeToJsonRenderSpec(root)), [root]);\n if (spec === null) return null;\n return (\n <JSONUIProvider registry={registry} {...(initialState !== undefined ? { initialState } : {})}>\n <Renderer spec={spec as never} registry={registry} />\n </JSONUIProvider>\n );\n}\n\n/** A registry entry for `genui:tree` that renders through json-render with `registry`. */\nexport function jsonRenderTree(registry: ComponentRegistry): GenuiRenderer<{\n root?: GenerativeUIElement;\n}> {\n return function JsonRenderTreeFrame({ root }: { root?: GenerativeUIElement }) {\n return <JsonRenderTree registry={registry} {...(root !== undefined ? { root } : {})} />;\n };\n}\n"],"mappings":";;;;AAUA,SAAiCA,gBAAgBC,gBAAgB;AACjE,SAAyBC,eAAe;AAUjC,SAASC,qBAAqBC,MAAyB;AAC5D,QAAMC,WAA2C,CAAC;AAClD,MAAIC,OAAO;AACX,QAAMC,QAAQ,wBAACC,SAAAA;AACb,UAAMC,KAAK,MAAMH,MAAAA;AACjB,UAAMI,QAAQ;MAAEC,MAAMH,KAAKG;MAAMC,OAAOJ,KAAKI,SAAS,CAAC;MAAGC,UAAU,CAAA;IAAe;AACnFR,aAASI,EAAAA,IAAMC;AACf,eAAWI,SAASN,KAAKK,YAAY,CAAA,EAAIH,OAAMG,SAASE,KAAKR,MAAMO,KAAAA,CAAAA;AACnE,WAAOL;EACT,GANc;AAOd,SAAO;IAAEL,MAAMG,MAAMH,IAAAA;IAAOC;EAAS;AACvC;AAXgBF;AAiBT,SAASa,qBAAqBC,UAAuB;AAC1D,SAAOC,OAAOC,YACZD,OAAOE,QAAQH,QAAAA,EAAUI,IAAI,CAAC,CAACC,MAAMC,SAAAA,MAAc;IACjDD;IACA,CAAC,EAAEE,SAASX,SAAQ,MAClB,sBAAA,cAACU,WAAeC,QAAQZ,SAAS,CAAC,GAAiCC,QAAAA;GAEtE,CAAA;AAEL;AATgBG;AAmBT,SAASS,eAAe,EAAErB,MAAMa,UAAUS,aAAY,GAAuB;AAClF,QAAMC,OAAOC,QAAQ,MAAOxB,SAASyB,SAAY,OAAO1B,qBAAqBC,IAAAA,GAAQ;IAACA;GAAK;AAC3F,MAAIuB,SAAS,KAAM,QAAO;AAC1B,SACE,sBAAA,cAACG,gBAAAA;IAAeb;IAAqB,GAAIS,iBAAiBG,SAAY;MAAEH;IAAa,IAAI,CAAC;KACxF,sBAAA,cAACH,UAAAA;IAASI;IAAqBV;;AAGrC;AARgBQ;AAWT,SAASM,eAAed,UAA2B;AAGxD,SAAO,gCAASe,oBAAoB,EAAE5B,KAAI,GAAkC;AAC1E,WAAO,sBAAA,cAACqB,gBAAAA;MAAeR;MAAqB,GAAIb,SAASyB,SAAY;QAAEzB;MAAK,IAAI,CAAC;;EACnF,GAFO;AAGT;AANgB2B;","names":["JSONUIProvider","Renderer","useMemo","treeToJsonRenderSpec","root","elements","next","visit","node","id","entry","type","props","children","child","push","toJsonRenderRegistry","registry","Object","fromEntries","entries","map","name","Renderer","element","JsonRenderTree","initialState","spec","useMemo","undefined","JSONUIProvider","jsonRenderTree","JsonRenderTreeFrame"]}
1
+ {"version":3,"sources":["../src/genui/json-render.tsx","../src/genui/generative-ui.tsx","../src/components/ambient-ui.ts","../src/genui/use-generative-ui.ts","../src/genui/types.ts"],"sourcesContent":["/**\n * Optional json-render adapter for tree frames (`@dudousxd/nestjs-agent-react/genui/json-render`).\n * Needs the optional peer `@json-render/react` (>= 0.21). Use it when your app already renders\n * json-render specs and wants tree frames to go through the same `Renderer` (its state, actions and\n * visibility machinery); otherwise `<GenerativeUI>` renders trees natively.\n *\n * ```tsx\n * import { GenuiProvider } from '@dudousxd/nestjs-agent-react/genui/json-render';\n *\n * <GenuiProvider registry={registry} catalog={catalog} jsonRender>…</GenuiProvider>\n * ```\n */\nimport { type ComponentRegistry, JSONUIProvider, Renderer } from '@json-render/react';\nimport { type ReactNode, useMemo } from 'react';\nimport {\n GenuiProvider as BaseGenuiProvider,\n type GenuiProviderProps as BaseGenuiProviderProps,\n} from './generative-ui.js';\nimport type { GenerativeUIElement, GenuiRegistry, GenuiRenderer } from './types.js';\n\n/** A json-render flat spec: `{ root, elements: { [id]: { type, props, children } } }`. */\nexport interface JsonRenderFlatSpec {\n root: string;\n elements: Record<string, { type: string; props: Record<string, unknown>; children: string[] }>;\n}\n\n/** A tree frame's `root` as a json-render flat spec (ids `el-0`, `el-1`, … depth first). */\nexport function treeToJsonRenderSpec(root: GenerativeUIElement): JsonRenderFlatSpec {\n const elements: JsonRenderFlatSpec['elements'] = {};\n let next = 0;\n const visit = (node: GenerativeUIElement): string => {\n const id = `el-${next++}`;\n const entry = { type: node.type, props: node.props ?? {}, children: [] as string[] };\n elements[id] = entry;\n for (const child of node.children ?? []) entry.children.push(visit(child));\n return id;\n };\n return { root: visit(root), elements };\n}\n\n/**\n * Adapt a genui registry (renderers taking props + `children`) to a json-render registry (renderers\n * taking `{ element, children }`), so one set of components serves both.\n */\nexport function toJsonRenderRegistry(registry: GenuiRegistry): ComponentRegistry {\n return Object.fromEntries(\n Object.entries(registry).map(([name, Renderer]) => [\n name,\n ({ element, children }: { element: { props?: unknown }; children?: ReactNode }) => (\n <Renderer {...((element.props ?? {}) as Record<string, unknown>)}>{children}</Renderer>\n ),\n ]),\n );\n}\n\nexport interface JsonRenderTreeProps {\n root?: GenerativeUIElement;\n registry: ComponentRegistry;\n /** json-render state the spec's `$state` expressions read. */\n initialState?: Record<string, unknown>;\n}\n\n/** Render a tree frame's `root` with json-render. */\nexport function JsonRenderTree({ root, registry, initialState }: JsonRenderTreeProps) {\n const spec = useMemo(() => (root === undefined ? null : treeToJsonRenderSpec(root)), [root]);\n if (spec === null) return null;\n return (\n <JSONUIProvider registry={registry} {...(initialState !== undefined ? { initialState } : {})}>\n <Renderer spec={spec as never} registry={registry} />\n </JSONUIProvider>\n );\n}\n\n/** A registry entry for `genui:tree` that renders through json-render with `registry`. */\nexport function jsonRenderTree(registry: ComponentRegistry): GenuiRenderer<{\n root?: GenerativeUIElement;\n}> {\n return function JsonRenderTreeFrame({ root }: { root?: GenerativeUIElement }) {\n return <JsonRenderTree registry={registry} {...(root !== undefined ? { root } : {})} />;\n };\n}\n\nexport interface GenuiProviderProps extends BaseGenuiProviderProps {\n /**\n * Draw composed tree frames through json-render: pass your json-render registry, or `true` to\n * derive one from `registry` ({@link toJsonRenderRegistry}). Omitted → trees render natively.\n * An explicit `treeRenderer` wins over it.\n */\n jsonRender?: ComponentRegistry | true;\n}\n\n/** `GenuiProvider` from `/genui`, plus the {@link GenuiProviderProps.jsonRender} option. */\nexport function GenuiProvider({ jsonRender, treeRenderer, registry, ...rest }: GenuiProviderProps) {\n const derived = useMemo(() => {\n if (jsonRender === undefined) return undefined;\n return jsonRenderTree(jsonRender === true ? toJsonRenderRegistry(registry ?? {}) : jsonRender);\n }, [jsonRender, registry]);\n const tree = treeRenderer ?? derived;\n return (\n <BaseGenuiProvider\n {...rest}\n {...(registry !== undefined ? { registry } : {})}\n {...(tree !== undefined ? { treeRenderer: tree } : {})}\n />\n );\n}\n","import {\n Component,\n type Context,\n type ErrorInfo,\n type ReactNode,\n createContext,\n useCallback,\n useContext,\n useMemo,\n} from 'react';\nimport { AmbientRenderUiContext, sharedContext } from '../components/ambient-ui.js';\nimport type { TranscriptUiBlock } from '../transcript/model.js';\nimport type {\n GenerativeUIElement,\n GenerativeUIItem,\n GenerativeUIOptions,\n GenerativeUIProblem,\n GenerativeUIState,\n GenuiRegistry,\n GenuiRenderer,\n} from './types.js';\nimport {\n useGenerativeUIState,\n useResolvedComponent,\n useValidatedProps,\n} from './use-generative-ui.js';\n\n/** What to draw instead of a component that did not render. Default: nothing. */\nexport type GenerativeUIFallback = ReactNode | ((problem: GenerativeUIProblem) => ReactNode);\n\ninterface TreeScope {\n options: GenerativeUIOptions;\n fallback: GenerativeUIFallback | undefined;\n loading: ReactNode;\n onError: ((error: unknown, item: GenerativeUIItem) => void) | undefined;\n}\n\nconst TreeScopeContext = createContext<TreeScope | null>(null);\n\nfunction renderFallback(fallback: GenerativeUIFallback | undefined, problem: GenerativeUIProblem) {\n if (typeof fallback === 'function') return fallback(problem);\n return fallback ?? null;\n}\n\ninterface BoundaryProps {\n item: GenerativeUIItem;\n fallback: GenerativeUIFallback | undefined;\n onError: ((error: unknown, item: GenerativeUIItem) => void) | undefined;\n children: ReactNode;\n}\n\n/** One failing renderer takes down its own item, never the message around it. */\nclass ItemBoundary extends Component<BoundaryProps, { error: unknown; failed: boolean }> {\n override state = { error: undefined as unknown, failed: false };\n\n static getDerivedStateFromError(error: unknown) {\n return { error, failed: true };\n }\n\n override componentDidCatch(error: unknown, _info: ErrorInfo) {\n this.props.onError?.(error, this.props.item);\n }\n\n override componentDidUpdate(previous: BoundaryProps) {\n // New props for the same item (a streamed update) get a fresh chance to render.\n if (this.state.failed && previous.item !== this.props.item) {\n this.setState({ error: undefined, failed: false });\n }\n }\n\n override render() {\n if (this.state.failed) {\n return renderFallback(this.props.fallback, {\n reason: 'error',\n item: this.props.item,\n error: this.state.error,\n });\n }\n return this.props.children;\n }\n}\n\nfunction nodeItem(node: GenerativeUIElement, id: string): GenerativeUIItem {\n return { id, component: node.type, props: node.props ?? {}, version: null, toolCallId: null };\n}\n\n/** One tree node: resolved and validated like a top-level item, children rendered as its `children`. */\nfunction TreeNode({ node, id }: { node: GenerativeUIElement; id: string }) {\n const scope = useContext(TreeScopeContext);\n const item = useMemo(() => nodeItem(node, id), [node, id]);\n const resolution = useResolvedComponent(\n node.type,\n null,\n scope?.options.registry ?? {},\n scope?.options.resolveComponent,\n );\n const validation = useValidatedProps(scope?.options.catalog, node.type, item.props);\n if (scope === null) return null;\n if (resolution.status === 'loading' || validation.status === 'pending') return scope.loading;\n if (resolution.status === 'unknown') {\n return renderFallback(scope.fallback, { reason: 'unknown', item });\n }\n if (resolution.status === 'error') {\n return renderFallback(scope.fallback, { reason: 'error', item, error: resolution.error });\n }\n if (validation.status === 'invalid') {\n return renderFallback(scope.fallback, { reason: 'invalid', item, issues: validation.issues });\n }\n const Renderer = resolution.Component;\n const children = Array.isArray(node.children) ? node.children : [];\n return (\n <Renderer {...validation.props}>\n {children.length > 0\n ? children.map((child, index) => {\n const childId = `${id}.${index}`;\n return (\n <ItemBoundary\n key={childId}\n item={nodeItem(child, childId)}\n fallback={scope.fallback}\n onError={scope.onError}\n >\n <TreeNode node={child} id={childId} />\n </ItemBoundary>\n );\n })\n : undefined}\n </Renderer>\n );\n}\n\n/**\n * Renders a `genui:tree` frame's `{ root }` node by node through the same registry, catalog and\n * resolver as top-level components. Used automatically for tree frames unless a `treeRenderer`\n * (e.g. the json-render one) or a registry entry for `genui:tree` takes over.\n */\nexport function GenuiTree({ root }: { root?: GenerativeUIElement }) {\n if (root === undefined || root === null || typeof root.type !== 'string') return null;\n return <TreeNode node={root} id=\"root\" />;\n}\n\nexport interface GenerativeUIScopeProps extends GenerativeUIOptions {\n fallback?: GenerativeUIFallback;\n loading?: ReactNode;\n onError?: (error: unknown, item: GenerativeUIItem) => void;\n children?: ReactNode;\n}\n\n/**\n * The registry, catalog and fallbacks tree nodes render with. `<GenerativeUI>` provides it; wrap\n * your own chrome in it when you draw `useGenerativeUI`'s `Component` yourself and it may be a tree.\n */\nexport function GenerativeUIScope({\n registry,\n catalog,\n resolveComponent,\n fallback,\n loading = null,\n onError,\n children,\n}: GenerativeUIScopeProps) {\n const scope = useMemo<TreeScope>(\n () => ({\n options: {\n registry,\n ...(catalog !== undefined ? { catalog } : {}),\n ...(resolveComponent !== undefined ? { resolveComponent } : {}),\n },\n fallback,\n loading,\n onError,\n }),\n [registry, catalog, resolveComponent, fallback, loading, onError],\n );\n return <TreeScopeContext.Provider value={scope}>{children}</TreeScopeContext.Provider>;\n}\n\n/** What `<GenuiProvider>` hands every `<GenerativeUI>` / `useGenerativeUI` below it. */\nexport interface GenuiProviderValue extends Partial<GenerativeUIOptions> {\n fallback?: GenerativeUIFallback;\n loading?: ReactNode;\n onError?: (error: unknown, item: GenerativeUIItem) => void;\n}\n\n// Shared by key: `/genui` and `/genui/json-render` are separate bundles, and a provider from one\n// must reach a `<GenerativeUI>` from the other.\nconst GenuiContext: Context<GenuiProviderValue | null> = sharedContext<GenuiProviderValue>(\n '@dudousxd/nestjs-agent-react:genui-provider',\n);\n\n/** The enclosing `<GenuiProvider>`'s settings, or `null` outside one. */\nexport function useGenuiProvider(): GenuiProviderValue | null {\n return useContext(GenuiContext);\n}\n\nexport interface GenuiProviderProps extends GenuiProviderValue {\n children?: ReactNode;\n}\n\n/**\n * Set generative UI up once, at the app root: the registry of your renderers, the catalog to\n * validate against, a resolver for components the registry lacks, and what to draw when one does\n * not render. Every `<GenerativeUI>` below reads it (its own props still win), and `MessageItem` /\n * `MessageList` draw pushed components with it — no `renderUi` per message.\n *\n * ```tsx\n * <GenuiProvider registry={registry} catalog={catalog} fallback={({ item }) => <Unknown name={item.component} />}>\n * <App />\n * </GenuiProvider>\n * ```\n */\nexport function GenuiProvider({\n registry,\n catalog,\n resolveComponent,\n treeRenderer,\n fallback,\n loading,\n onError,\n children,\n}: GenuiProviderProps) {\n const value = useMemo<GenuiProviderValue>(\n () => ({\n ...(registry !== undefined ? { registry } : {}),\n ...(catalog !== undefined ? { catalog } : {}),\n ...(resolveComponent !== undefined ? { resolveComponent } : {}),\n ...(treeRenderer !== undefined ? { treeRenderer } : {}),\n ...(fallback !== undefined ? { fallback } : {}),\n ...(loading !== undefined ? { loading } : {}),\n ...(onError !== undefined ? { onError } : {}),\n }),\n [registry, catalog, resolveComponent, treeRenderer, fallback, loading, onError],\n );\n const renderUi = useCallback((block: TranscriptUiBlock) => <GenerativeUI part={block} />, []);\n return (\n <GenuiContext.Provider value={value}>\n <AmbientRenderUiContext.Provider value={renderUi}>{children}</AmbientRenderUiContext.Provider>\n </GenuiContext.Provider>\n );\n}\n\nconst NO_REGISTRY: GenuiRegistry = {};\n\n/** Provider settings overlaid with explicit ones (explicit wins), memoized on their parts. */\nfunction useMergedOptions(own: Partial<GenerativeUIOptions>): GenerativeUIOptions {\n const provided = useContext(GenuiContext);\n const registry = own.registry ?? provided?.registry ?? NO_REGISTRY;\n const catalog = own.catalog ?? provided?.catalog;\n const resolveComponent = own.resolveComponent ?? provided?.resolveComponent;\n const treeRenderer = own.treeRenderer ?? provided?.treeRenderer;\n return useMemo(\n () => ({\n registry,\n ...(catalog !== undefined ? { catalog } : {}),\n ...(resolveComponent !== undefined ? { resolveComponent } : {}),\n ...(treeRenderer !== undefined ? { treeRenderer } : {}),\n }),\n [registry, catalog, resolveComponent, treeRenderer],\n );\n}\n\n/**\n * The headless half of {@link GenerativeUI}: what to draw for one pushed component, or `null` when\n * `part` is not one. Options default to the enclosing `<GenuiProvider>`'s.\n */\nexport function useGenerativeUI(\n part: unknown,\n options: Partial<GenerativeUIOptions> = {},\n): GenerativeUIState | null {\n const merged = useMergedOptions(options);\n return useGenerativeUIState(part, merged, merged.treeRenderer ?? (GenuiTree as GenuiRenderer));\n}\n\nexport interface GenerativeUIProps extends Partial<GenerativeUIOptions> {\n /** A transcript `ui` block, a `data-ui` message part, or a stored `{ id, component, props, version? }`. */\n part: TranscriptUiBlock | GenerativeUIItem | unknown;\n /** Drawn for an unknown component, invalid props, or a renderer that threw. Default: the provider's, else nothing. */\n fallback?: GenerativeUIFallback;\n /** Drawn while a resolver or an async validation is pending. Default: the provider's, else nothing. */\n loading?: ReactNode;\n /** A renderer threw (the item shows `fallback`). */\n onError?: (error: unknown, item: GenerativeUIItem) => void;\n}\n\n/**\n * Draws one server-pushed component with the app's own renderer. Headless: it adds no element and\n * no style of its own — only what the registry's component renders (and whatever `fallback` /\n * `loading` you pass). Everything but `part` defaults to the enclosing `<GenuiProvider>`.\n *\n * ```tsx\n * <GenerativeUI part={block} />\n * ```\n */\nexport function GenerativeUI({\n part,\n registry,\n catalog,\n resolveComponent,\n treeRenderer,\n fallback: ownFallback,\n loading: ownLoading,\n onError: ownOnError,\n}: GenerativeUIProps) {\n const provided = useContext(GenuiContext);\n const fallback = ownFallback ?? provided?.fallback;\n const loading = ownLoading ?? provided?.loading ?? null;\n const onError = ownOnError ?? provided?.onError;\n const options = useMergedOptions({\n ...(registry !== undefined ? { registry } : {}),\n ...(catalog !== undefined ? { catalog } : {}),\n ...(resolveComponent !== undefined ? { resolveComponent } : {}),\n ...(treeRenderer !== undefined ? { treeRenderer } : {}),\n });\n const state = useGenerativeUIState(\n part,\n options,\n options.treeRenderer ?? (GenuiTree as GenuiRenderer),\n );\n if (state === null) return null;\n if (state.status === 'loading') return loading;\n if (state.status === 'problem') {\n const { status: _status, ...problem } = state;\n return renderFallback(fallback, problem);\n }\n const Renderer = state.Component;\n return (\n <GenerativeUIScope\n {...options}\n fallback={fallback}\n loading={loading}\n {...(onError !== undefined ? { onError } : {})}\n >\n <ItemBoundary item={state.item} fallback={fallback} onError={onError}>\n <Renderer {...state.props} />\n </ItemBoundary>\n </GenerativeUIScope>\n );\n}\n","import { type Context, type ReactNode, createContext, useContext } from 'react';\nimport type { TranscriptUiBlock } from '../transcript/model.js';\n\n/** Draws a server-pushed component block. */\nexport type AmbientRenderUi = (block: TranscriptUiBlock) => ReactNode;\n\n/**\n * A context stored on `globalThis` under a registered symbol. Each entry point (`.`, `/genui`,\n * `/genui/json-render`) is its own bundle with its own copy of every module, so a context one entry\n * provides and another reads has to be found by key, not by module identity.\n */\nexport function sharedContext<T>(key: string): Context<T | null> {\n const symbol = Symbol.for(key);\n const holder = globalThis as Record<symbol, Context<T | null> | undefined>;\n const existing = holder[symbol];\n if (existing !== undefined) return existing;\n const created = createContext<T | null>(null);\n holder[symbol] = created;\n return created;\n}\n\n/**\n * How pushed components are drawn when no `renderUi` is passed — set by `<GenuiProvider>` (the\n * `/genui` subpath) and read by `MessageItem`.\n */\nexport const AmbientRenderUiContext: Context<AmbientRenderUi | null> =\n sharedContext<AmbientRenderUi>('@dudousxd/nestjs-agent-react:ambient-render-ui');\n\n/**\n * The renderer `<GenuiProvider>` installed for pushed components, or `null` outside one. For a\n * custom transcript built on `useTranscriptItem`: draw a `ui` block with it and you get what\n * `MessageItem` draws.\n */\nexport function useAmbientRenderUi(): AmbientRenderUi | null {\n return useContext(AmbientRenderUiContext);\n}\n","import { useEffect, useMemo, useState } from 'react';\nimport {\n GENUI_TREE_COMPONENT,\n type GenerativeUIItem,\n type GenerativeUIOptions,\n type GenerativeUIState,\n type GenuiCatalogLike,\n type GenuiIssueLike,\n type GenuiRegistry,\n type GenuiRenderer,\n type ResolveComponent,\n} from './types.js';\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Normalize whatever carries a pushed component: a transcript `ui` block, a `data-ui` message part\n * (`{ type: 'data-ui', id, data }`), a stored `{ id, component, props, version? }` entry. `null` for\n * anything else.\n */\nexport function toGenerativeUIItem(part: unknown): GenerativeUIItem | null {\n if (!isRecord(part)) return null;\n const source = part.type === 'data-ui' && isRecord(part.data) ? part.data : part;\n if (typeof source.component !== 'string') return null;\n const id =\n typeof source.id === 'string' ? source.id : typeof part.id === 'string' ? part.id : null;\n if (id === null) return null;\n return {\n id,\n component: source.component,\n props: isRecord(source.props) ? source.props : {},\n version: typeof source.version === 'number' ? source.version : null,\n toolCallId: typeof source.toolCallId === 'string' ? source.toolCallId : null,\n };\n}\n\ntype Resolution =\n | { status: 'ready'; Component: GenuiRenderer }\n | { status: 'loading' }\n | { status: 'unknown' }\n | { status: 'error'; error: unknown };\n\ninterface CacheEntry {\n resolution: Resolution;\n settled: Promise<void> | null;\n}\n\nconst resolverCaches = new WeakMap<ResolveComponent, Map<string, CacheEntry>>();\n\nfunction resolveCached(\n resolve: ResolveComponent,\n name: string,\n version: number | null,\n): CacheEntry {\n let cache = resolverCaches.get(resolve);\n if (cache === undefined) {\n cache = new Map();\n resolverCaches.set(resolve, cache);\n }\n const key = `${name}@${version ?? ''}`;\n const hit = cache.get(key);\n if (hit !== undefined) return hit;\n let entry: CacheEntry;\n try {\n const result = resolve(name, version);\n if (result instanceof Promise) {\n entry = { resolution: { status: 'loading' }, settled: null };\n entry.settled = result.then(\n (Component) => {\n entry.resolution = Component ? { status: 'ready', Component } : { status: 'unknown' };\n },\n (error: unknown) => {\n entry.resolution = { status: 'error', error };\n },\n );\n } else {\n entry = {\n resolution: result ? { status: 'ready', Component: result } : { status: 'unknown' },\n settled: null,\n };\n }\n } catch (error) {\n entry = { resolution: { status: 'error', error }, settled: null };\n }\n cache.set(key, entry);\n return entry;\n}\n\n/**\n * Which renderer draws `name`: the registry first, then `resolveComponent` (cached; async results\n * re-render the caller when they land). `fallbackTree` answers the tree component when the\n * registry does not override it.\n */\nexport function useResolvedComponent(\n name: string,\n version: number | null,\n registry: GenuiRegistry,\n resolve: ResolveComponent | undefined,\n fallbackTree?: GenuiRenderer,\n): Resolution {\n const [, setTick] = useState(0);\n const own = registry[name];\n const entry =\n own !== undefined || resolve === undefined ? null : resolveCached(resolve, name, version);\n const pending = entry?.resolution.status === 'loading' ? entry.settled : null;\n useEffect(() => {\n if (pending === null) return;\n let live = true;\n void pending.then(() => {\n if (live) setTick((tick) => tick + 1);\n });\n return () => {\n live = false;\n };\n }, [pending]);\n if (own !== undefined) return { status: 'ready', Component: own };\n if (entry !== null && entry.resolution.status !== 'unknown') return entry.resolution;\n if (name === GENUI_TREE_COMPONENT && fallbackTree !== undefined) {\n return { status: 'ready', Component: fallbackTree };\n }\n return { status: 'unknown' };\n}\n\ntype Validation =\n | { status: 'ok'; props: Record<string, unknown> }\n | { status: 'pending' }\n | { status: 'invalid'; issues: GenuiIssueLike[] };\n\n/**\n * Props checked against the catalog: synchronously when the catalog can (`validateSync`), else\n * after the async check settles. A component the catalog does not know passes through unchecked.\n */\nexport function useValidatedProps(\n catalog: GenuiCatalogLike | undefined,\n name: string,\n props: Record<string, unknown>,\n): Validation {\n const checked = catalog?.has(name) === true;\n const immediate = useMemo<Validation | null>(() => {\n if (!checked || catalog === undefined) return { status: 'ok', props };\n const result = catalog.validateSync?.(name, props);\n if (result === undefined) return null;\n return result.ok\n ? { status: 'ok', props: result.value }\n : { status: 'invalid', issues: result.issues };\n }, [checked, catalog, name, props]);\n const [late, setLate] = useState<{ props: Record<string, unknown>; result: Validation } | null>(\n null,\n );\n useEffect(() => {\n if (immediate !== null || catalog === undefined) return;\n let live = true;\n catalog.validate(name, props).then(\n (result) => {\n if (!live) return;\n setLate({\n props,\n result: result.ok\n ? { status: 'ok', props: result.value }\n : { status: 'invalid', issues: result.issues },\n });\n },\n (error: unknown) => {\n if (!live) return;\n setLate({\n props,\n result: {\n status: 'invalid',\n issues: [{ path: [], message: error instanceof Error ? error.message : String(error) }],\n },\n });\n },\n );\n return () => {\n live = false;\n };\n }, [immediate, catalog, name, props]);\n if (immediate !== null) return immediate;\n return late !== null && late.props === props ? late.result : { status: 'pending' };\n}\n\n/** {@link import('./generative-ui.js').useGenerativeUI}, with the tree renderer handed in (avoids an import cycle). */\nexport function useGenerativeUIState(\n part: unknown,\n options: GenerativeUIOptions,\n fallbackTree: GenuiRenderer | undefined,\n): GenerativeUIState | null {\n const item = useMemo(() => toGenerativeUIItem(part), [part]);\n const name = item?.component ?? '';\n const resolution = useResolvedComponent(\n name,\n item?.version ?? null,\n options.registry,\n item === null ? undefined : options.resolveComponent,\n fallbackTree,\n );\n const empty = useMemo<Record<string, unknown>>(() => ({}), []);\n // A tree is validated node by node as it renders, not as one component.\n const validation = useValidatedProps(\n item === null || name === GENUI_TREE_COMPONENT ? undefined : options.catalog,\n name,\n item?.props ?? empty,\n );\n if (item === null) return null;\n if (resolution.status === 'loading') return { status: 'loading', item };\n if (resolution.status === 'unknown') return { status: 'problem', reason: 'unknown', item };\n if (resolution.status === 'error') {\n return { status: 'problem', reason: 'error', item, error: resolution.error };\n }\n if (validation.status === 'pending') return { status: 'loading', item };\n if (validation.status === 'invalid') {\n return { status: 'problem', reason: 'invalid', item, issues: validation.issues };\n }\n return { status: 'ready', item, Component: resolution.Component, props: validation.props };\n}\n","import type { ComponentType, ReactNode } from 'react';\n\n/** The `ui` frame component a composed tree is pushed under (`GENUI_TREE_COMPONENT` of `@dudousxd/nestjs-agent-core/genui`). */\nexport const GENUI_TREE_COMPONENT = 'genui:tree';\n\n/** One pushed component, normalized from whatever carried it (a transcript block, a `data-ui` part, a stored entry). */\nexport interface GenerativeUIItem {\n id: string;\n component: string;\n props: Record<string, unknown>;\n version: number | null;\n toolCallId: string | null;\n}\n\n/** A node of a composed tree (`genui:tree` frames): `{ type, props, children? }`. */\nexport interface GenerativeUIElement {\n type: string;\n props: Record<string, unknown>;\n children?: GenerativeUIElement[];\n}\n\n/**\n * An app's renderer for one component: it receives the component's props spread, plus `children`\n * when it is a layout node in a tree. Any React component — the library never styles anything.\n */\nexport type GenuiRenderer<P = any> = ComponentType<P & { children?: ReactNode }>;\n\n/** Component name → the app's renderer. */\nexport type GenuiRegistry = Record<string, GenuiRenderer>;\n\n/**\n * Resolve a component the registry does not have — typically a tenant's own component, fetched for\n * the exact `version` a message was rendered with. Return `null`/`undefined` for \"no such\n * component\". May be async; results are cached per resolver, name and version.\n */\nexport type ResolveComponent = (\n name: string,\n version: number | null,\n) => GenuiRenderer | null | undefined | Promise<GenuiRenderer | null | undefined>;\n\nexport interface GenuiIssueLike {\n path: (string | number)[];\n message: string;\n}\n\ntype ValidationLike =\n | { ok: true; value: Record<string, unknown> }\n | { ok: false; issues: GenuiIssueLike[] };\n\n/**\n * What the renderer needs from a catalog to validate props before drawing them. A `Catalog` from\n * `@dudousxd/nestjs-agent-core/genui` satisfies it; declared structurally so any catalog-shaped\n * object does too.\n */\nexport interface GenuiCatalogLike {\n has(name: string): boolean;\n validate(name: string, props: unknown): Promise<ValidationLike>;\n validateSync?(name: string, props: unknown): ValidationLike | undefined;\n}\n\nexport interface GenerativeUIOptions {\n registry: GenuiRegistry;\n /** Validate props against it before rendering. Components the catalog does not know render unvalidated. */\n catalog?: GenuiCatalogLike;\n resolveComponent?: ResolveComponent;\n /**\n * Draws a composed tree frame (`genui:tree`) whole — e.g. through json-render (see the\n * `/genui/json-render` subpath's `GenuiProvider`). Omitted → trees render node by node through\n * `registry`.\n */\n treeRenderer?: GenuiRenderer<{ root?: GenerativeUIElement }>;\n}\n\n/** Why an item did not render. */\nexport type GenerativeUIProblem =\n | { reason: 'unknown'; item: GenerativeUIItem }\n | { reason: 'invalid'; item: GenerativeUIItem; issues: GenuiIssueLike[] }\n | { reason: 'error'; item: GenerativeUIItem; error: unknown };\n\nexport type GenerativeUIState =\n | {\n status: 'ready';\n item: GenerativeUIItem;\n Component: GenuiRenderer;\n props: Record<string, unknown>;\n }\n | { status: 'loading'; item: GenerativeUIItem }\n | ({ status: 'problem' } & GenerativeUIProblem);\n"],"mappings":"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","names":["JSONUIProvider","Renderer","useMemo","Component","createContext","useCallback","useContext","useMemo","createContext","useContext","sharedContext","key","symbol","Symbol","for","holder","globalThis","existing","undefined","created","createContext","AmbientRenderUiContext","useEffect","useMemo","useState","GENUI_TREE_COMPONENT","isRecord","value","Array","isArray","toGenerativeUIItem","part","source","type","data","component","id","props","version","toolCallId","resolverCaches","WeakMap","resolveCached","resolve","name","cache","get","undefined","Map","set","key","hit","entry","result","Promise","resolution","status","settled","then","Component","error","useResolvedComponent","registry","fallbackTree","setTick","useState","own","pending","useEffect","live","tick","GENUI_TREE_COMPONENT","useValidatedProps","catalog","checked","has","immediate","useMemo","validateSync","ok","issues","late","setLate","validate","path","message","Error","String","useGenerativeUIState","options","item","resolveComponent","empty","validation","reason","TreeScopeContext","createContext","renderFallback","fallback","problem","ItemBoundary","Component","state","error","undefined","failed","getDerivedStateFromError","componentDidCatch","_info","props","onError","item","componentDidUpdate","previous","setState","render","reason","children","nodeItem","node","id","component","type","version","toolCallId","TreeNode","scope","useContext","useMemo","resolution","useResolvedComponent","options","registry","resolveComponent","validation","useValidatedProps","catalog","status","loading","issues","Renderer","Array","isArray","length","map","child","index","childId","key","GenuiTree","root","GenerativeUIScope","Provider","value","GenuiContext","sharedContext","GenuiProvider","registry","catalog","resolveComponent","treeRenderer","fallback","loading","onError","children","value","useMemo","undefined","renderUi","useCallback","block","GenerativeUI","part","GenuiContext","Provider","AmbientRenderUiContext","NO_REGISTRY","useMergedOptions","own","provided","useContext","GenerativeUI","part","registry","catalog","resolveComponent","treeRenderer","fallback","ownFallback","loading","ownLoading","onError","ownOnError","provided","useContext","GenuiContext","options","useMergedOptions","undefined","state","useGenerativeUIState","GenuiTree","status","_status","problem","renderFallback","Renderer","Component","GenerativeUIScope","ItemBoundary","item","props","treeToJsonRenderSpec","root","elements","next","visit","node","id","entry","type","props","children","child","push","toJsonRenderRegistry","registry","Object","fromEntries","entries","map","name","Renderer","element","JsonRenderTree","initialState","spec","useMemo","undefined","JSONUIProvider","jsonRenderTree","JsonRenderTreeFrame","GenuiProvider","jsonRender","treeRenderer","rest","derived","tree","BaseGenuiProvider"]}
package/dist/genui.cjs CHANGED
@@ -24,17 +24,33 @@ __export(genui_exports, {
24
24
  GENUI_TREE_COMPONENT: () => GENUI_TREE_COMPONENT,
25
25
  GenerativeUI: () => GenerativeUI,
26
26
  GenerativeUIScope: () => GenerativeUIScope,
27
+ GenuiProvider: () => GenuiProvider,
27
28
  GenuiTree: () => GenuiTree,
28
29
  toGenerativeUIItem: () => toGenerativeUIItem,
29
- useGenerativeUI: () => useGenerativeUI
30
+ useGenerativeUI: () => useGenerativeUI,
31
+ useGenuiProvider: () => useGenuiProvider
30
32
  });
31
33
  module.exports = __toCommonJS(genui_exports);
32
34
 
33
35
  // src/genui/generative-ui.tsx
34
- var import_react2 = require("react");
36
+ var import_react3 = require("react");
35
37
 
36
- // src/genui/use-generative-ui.ts
38
+ // src/components/ambient-ui.ts
37
39
  var import_react = require("react");
40
+ function sharedContext(key) {
41
+ const symbol = Symbol.for(key);
42
+ const holder = globalThis;
43
+ const existing = holder[symbol];
44
+ if (existing !== void 0) return existing;
45
+ const created = (0, import_react.createContext)(null);
46
+ holder[symbol] = created;
47
+ return created;
48
+ }
49
+ __name(sharedContext, "sharedContext");
50
+ var AmbientRenderUiContext = sharedContext("@dudousxd/nestjs-agent-react:ambient-render-ui");
51
+
52
+ // src/genui/use-generative-ui.ts
53
+ var import_react2 = require("react");
38
54
 
39
55
  // src/genui/types.ts
40
56
  var GENUI_TREE_COMPONENT = "genui:tree";
@@ -117,11 +133,11 @@ function resolveCached(resolve, name, version) {
117
133
  }
118
134
  __name(resolveCached, "resolveCached");
119
135
  function useResolvedComponent(name, version, registry, resolve, fallbackTree) {
120
- const [, setTick] = (0, import_react.useState)(0);
136
+ const [, setTick] = (0, import_react2.useState)(0);
121
137
  const own = registry[name];
122
138
  const entry = own !== void 0 || resolve === void 0 ? null : resolveCached(resolve, name, version);
123
139
  const pending = entry?.resolution.status === "loading" ? entry.settled : null;
124
- (0, import_react.useEffect)(() => {
140
+ (0, import_react2.useEffect)(() => {
125
141
  if (pending === null) return;
126
142
  let live = true;
127
143
  void pending.then(() => {
@@ -151,7 +167,7 @@ function useResolvedComponent(name, version, registry, resolve, fallbackTree) {
151
167
  __name(useResolvedComponent, "useResolvedComponent");
152
168
  function useValidatedProps(catalog, name, props) {
153
169
  const checked = catalog?.has(name) === true;
154
- const immediate = (0, import_react.useMemo)(() => {
170
+ const immediate = (0, import_react2.useMemo)(() => {
155
171
  if (!checked || catalog === void 0) return {
156
172
  status: "ok",
157
173
  props
@@ -171,8 +187,8 @@ function useValidatedProps(catalog, name, props) {
171
187
  name,
172
188
  props
173
189
  ]);
174
- const [late, setLate] = (0, import_react.useState)(null);
175
- (0, import_react.useEffect)(() => {
190
+ const [late, setLate] = (0, import_react2.useState)(null);
191
+ (0, import_react2.useEffect)(() => {
176
192
  if (immediate !== null || catalog === void 0) return;
177
193
  let live = true;
178
194
  catalog.validate(name, props).then((result) => {
@@ -218,12 +234,12 @@ function useValidatedProps(catalog, name, props) {
218
234
  }
219
235
  __name(useValidatedProps, "useValidatedProps");
220
236
  function useGenerativeUIState(part, options, fallbackTree) {
221
- const item = (0, import_react.useMemo)(() => toGenerativeUIItem(part), [
237
+ const item = (0, import_react2.useMemo)(() => toGenerativeUIItem(part), [
222
238
  part
223
239
  ]);
224
240
  const name = item?.component ?? "";
225
241
  const resolution = useResolvedComponent(name, item?.version ?? null, options.registry, item === null ? void 0 : options.resolveComponent, fallbackTree);
226
- const empty = (0, import_react.useMemo)(() => ({}), []);
242
+ const empty = (0, import_react2.useMemo)(() => ({}), []);
227
243
  const validation = useValidatedProps(item === null || name === GENUI_TREE_COMPONENT ? void 0 : options.catalog, name, item?.props ?? empty);
228
244
  if (item === null) return null;
229
245
  if (resolution.status === "loading") return {
@@ -265,13 +281,13 @@ function useGenerativeUIState(part, options, fallbackTree) {
265
281
  __name(useGenerativeUIState, "useGenerativeUIState");
266
282
 
267
283
  // src/genui/generative-ui.tsx
268
- var TreeScopeContext = /* @__PURE__ */ (0, import_react2.createContext)(null);
284
+ var TreeScopeContext = /* @__PURE__ */ (0, import_react3.createContext)(null);
269
285
  function renderFallback(fallback, problem) {
270
286
  if (typeof fallback === "function") return fallback(problem);
271
287
  return fallback ?? null;
272
288
  }
273
289
  __name(renderFallback, "renderFallback");
274
- var ItemBoundary = class ItemBoundary2 extends import_react2.Component {
290
+ var ItemBoundary = class ItemBoundary2 extends import_react3.Component {
275
291
  static {
276
292
  __name(this, "ItemBoundary");
277
293
  }
@@ -318,8 +334,8 @@ function nodeItem(node, id) {
318
334
  }
319
335
  __name(nodeItem, "nodeItem");
320
336
  function TreeNode({ node, id }) {
321
- const scope = (0, import_react2.useContext)(TreeScopeContext);
322
- const item = (0, import_react2.useMemo)(() => nodeItem(node, id), [
337
+ const scope = (0, import_react3.useContext)(TreeScopeContext);
338
+ const item = (0, import_react3.useMemo)(() => nodeItem(node, id), [
323
339
  node,
324
340
  id
325
341
  ]);
@@ -372,7 +388,7 @@ function GenuiTree({ root }) {
372
388
  }
373
389
  __name(GenuiTree, "GenuiTree");
374
390
  function GenerativeUIScope({ registry, catalog, resolveComponent, fallback, loading = null, onError, children }) {
375
- const scope = (0, import_react2.useMemo)(() => ({
391
+ const scope = (0, import_react3.useMemo)(() => ({
376
392
  options: {
377
393
  registry,
378
394
  ...catalog !== void 0 ? {
@@ -398,25 +414,104 @@ function GenerativeUIScope({ registry, catalog, resolveComponent, fallback, load
398
414
  }, children);
399
415
  }
400
416
  __name(GenerativeUIScope, "GenerativeUIScope");
401
- function useGenerativeUI(part, options) {
402
- return useGenerativeUIState(part, options, GenuiTree);
417
+ var GenuiContext = sharedContext("@dudousxd/nestjs-agent-react:genui-provider");
418
+ function useGenuiProvider() {
419
+ return (0, import_react3.useContext)(GenuiContext);
403
420
  }
404
- __name(useGenerativeUI, "useGenerativeUI");
405
- function GenerativeUI({ part, registry, catalog, resolveComponent, fallback, loading = null, onError }) {
406
- const options = (0, import_react2.useMemo)(() => ({
421
+ __name(useGenuiProvider, "useGenuiProvider");
422
+ function GenuiProvider({ registry, catalog, resolveComponent, treeRenderer, fallback, loading, onError, children }) {
423
+ const value = (0, import_react3.useMemo)(() => ({
424
+ ...registry !== void 0 ? {
425
+ registry
426
+ } : {},
427
+ ...catalog !== void 0 ? {
428
+ catalog
429
+ } : {},
430
+ ...resolveComponent !== void 0 ? {
431
+ resolveComponent
432
+ } : {},
433
+ ...treeRenderer !== void 0 ? {
434
+ treeRenderer
435
+ } : {},
436
+ ...fallback !== void 0 ? {
437
+ fallback
438
+ } : {},
439
+ ...loading !== void 0 ? {
440
+ loading
441
+ } : {},
442
+ ...onError !== void 0 ? {
443
+ onError
444
+ } : {}
445
+ }), [
446
+ registry,
447
+ catalog,
448
+ resolveComponent,
449
+ treeRenderer,
450
+ fallback,
451
+ loading,
452
+ onError
453
+ ]);
454
+ const renderUi = (0, import_react3.useCallback)((block) => /* @__PURE__ */ React.createElement(GenerativeUI, {
455
+ part: block
456
+ }), []);
457
+ return /* @__PURE__ */ React.createElement(GenuiContext.Provider, {
458
+ value
459
+ }, /* @__PURE__ */ React.createElement(AmbientRenderUiContext.Provider, {
460
+ value: renderUi
461
+ }, children));
462
+ }
463
+ __name(GenuiProvider, "GenuiProvider");
464
+ var NO_REGISTRY = {};
465
+ function useMergedOptions(own) {
466
+ const provided = (0, import_react3.useContext)(GenuiContext);
467
+ const registry = own.registry ?? provided?.registry ?? NO_REGISTRY;
468
+ const catalog = own.catalog ?? provided?.catalog;
469
+ const resolveComponent = own.resolveComponent ?? provided?.resolveComponent;
470
+ const treeRenderer = own.treeRenderer ?? provided?.treeRenderer;
471
+ return (0, import_react3.useMemo)(() => ({
407
472
  registry,
408
473
  ...catalog !== void 0 ? {
409
474
  catalog
410
475
  } : {},
411
476
  ...resolveComponent !== void 0 ? {
412
477
  resolveComponent
478
+ } : {},
479
+ ...treeRenderer !== void 0 ? {
480
+ treeRenderer
413
481
  } : {}
414
482
  }), [
415
483
  registry,
416
484
  catalog,
417
- resolveComponent
485
+ resolveComponent,
486
+ treeRenderer
418
487
  ]);
419
- const state = useGenerativeUI(part, options);
488
+ }
489
+ __name(useMergedOptions, "useMergedOptions");
490
+ function useGenerativeUI(part, options = {}) {
491
+ const merged = useMergedOptions(options);
492
+ return useGenerativeUIState(part, merged, merged.treeRenderer ?? GenuiTree);
493
+ }
494
+ __name(useGenerativeUI, "useGenerativeUI");
495
+ function GenerativeUI({ part, registry, catalog, resolveComponent, treeRenderer, fallback: ownFallback, loading: ownLoading, onError: ownOnError }) {
496
+ const provided = (0, import_react3.useContext)(GenuiContext);
497
+ const fallback = ownFallback ?? provided?.fallback;
498
+ const loading = ownLoading ?? provided?.loading ?? null;
499
+ const onError = ownOnError ?? provided?.onError;
500
+ const options = useMergedOptions({
501
+ ...registry !== void 0 ? {
502
+ registry
503
+ } : {},
504
+ ...catalog !== void 0 ? {
505
+ catalog
506
+ } : {},
507
+ ...resolveComponent !== void 0 ? {
508
+ resolveComponent
509
+ } : {},
510
+ ...treeRenderer !== void 0 ? {
511
+ treeRenderer
512
+ } : {}
513
+ });
514
+ const state = useGenerativeUIState(part, options, options.treeRenderer ?? GenuiTree);
420
515
  if (state === null) return null;
421
516
  if (state.status === "loading") return loading;
422
517
  if (state.status === "problem") {
@@ -443,8 +538,10 @@ __name(GenerativeUI, "GenerativeUI");
443
538
  GENUI_TREE_COMPONENT,
444
539
  GenerativeUI,
445
540
  GenerativeUIScope,
541
+ GenuiProvider,
446
542
  GenuiTree,
447
543
  toGenerativeUIItem,
448
- useGenerativeUI
544
+ useGenerativeUI,
545
+ useGenuiProvider
449
546
  });
450
547
  //# sourceMappingURL=genui.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/genui/index.ts","../src/genui/generative-ui.tsx","../src/genui/use-generative-ui.ts","../src/genui/types.ts"],"sourcesContent":["export {\n GenerativeUI,\n type GenerativeUIFallback,\n type GenerativeUIProps,\n GenerativeUIScope,\n type GenerativeUIScopeProps,\n GenuiTree,\n useGenerativeUI,\n} from './generative-ui.js';\nexport {\n GENUI_TREE_COMPONENT,\n type GenerativeUIElement,\n type GenerativeUIItem,\n type GenerativeUIOptions,\n type GenerativeUIProblem,\n type GenerativeUIState,\n type GenuiCatalogLike,\n type GenuiIssueLike,\n type GenuiRegistry,\n type GenuiRenderer,\n type ResolveComponent,\n} from './types.js';\nexport { toGenerativeUIItem } from './use-generative-ui.js';\n","import {\n Component,\n type ErrorInfo,\n type ReactNode,\n createContext,\n useContext,\n useMemo,\n} from 'react';\nimport type { TranscriptUiBlock } from '../transcript/model.js';\nimport type {\n GenerativeUIElement,\n GenerativeUIItem,\n GenerativeUIOptions,\n GenerativeUIProblem,\n GenerativeUIState,\n GenuiRenderer,\n} from './types.js';\nimport {\n useGenerativeUIState,\n useResolvedComponent,\n useValidatedProps,\n} from './use-generative-ui.js';\n\n/** What to draw instead of a component that did not render. Default: nothing. */\nexport type GenerativeUIFallback = ReactNode | ((problem: GenerativeUIProblem) => ReactNode);\n\ninterface TreeScope {\n options: GenerativeUIOptions;\n fallback: GenerativeUIFallback | undefined;\n loading: ReactNode;\n onError: ((error: unknown, item: GenerativeUIItem) => void) | undefined;\n}\n\nconst TreeScopeContext = createContext<TreeScope | null>(null);\n\nfunction renderFallback(fallback: GenerativeUIFallback | undefined, problem: GenerativeUIProblem) {\n if (typeof fallback === 'function') return fallback(problem);\n return fallback ?? null;\n}\n\ninterface BoundaryProps {\n item: GenerativeUIItem;\n fallback: GenerativeUIFallback | undefined;\n onError: ((error: unknown, item: GenerativeUIItem) => void) | undefined;\n children: ReactNode;\n}\n\n/** One failing renderer takes down its own item, never the message around it. */\nclass ItemBoundary extends Component<BoundaryProps, { error: unknown; failed: boolean }> {\n override state = { error: undefined as unknown, failed: false };\n\n static getDerivedStateFromError(error: unknown) {\n return { error, failed: true };\n }\n\n override componentDidCatch(error: unknown, _info: ErrorInfo) {\n this.props.onError?.(error, this.props.item);\n }\n\n override componentDidUpdate(previous: BoundaryProps) {\n // New props for the same item (a streamed update) get a fresh chance to render.\n if (this.state.failed && previous.item !== this.props.item) {\n this.setState({ error: undefined, failed: false });\n }\n }\n\n override render() {\n if (this.state.failed) {\n return renderFallback(this.props.fallback, {\n reason: 'error',\n item: this.props.item,\n error: this.state.error,\n });\n }\n return this.props.children;\n }\n}\n\nfunction nodeItem(node: GenerativeUIElement, id: string): GenerativeUIItem {\n return { id, component: node.type, props: node.props ?? {}, version: null, toolCallId: null };\n}\n\n/** One tree node: resolved and validated like a top-level item, children rendered as its `children`. */\nfunction TreeNode({ node, id }: { node: GenerativeUIElement; id: string }) {\n const scope = useContext(TreeScopeContext);\n const item = useMemo(() => nodeItem(node, id), [node, id]);\n const resolution = useResolvedComponent(\n node.type,\n null,\n scope?.options.registry ?? {},\n scope?.options.resolveComponent,\n );\n const validation = useValidatedProps(scope?.options.catalog, node.type, item.props);\n if (scope === null) return null;\n if (resolution.status === 'loading' || validation.status === 'pending') return scope.loading;\n if (resolution.status === 'unknown') {\n return renderFallback(scope.fallback, { reason: 'unknown', item });\n }\n if (resolution.status === 'error') {\n return renderFallback(scope.fallback, { reason: 'error', item, error: resolution.error });\n }\n if (validation.status === 'invalid') {\n return renderFallback(scope.fallback, { reason: 'invalid', item, issues: validation.issues });\n }\n const Renderer = resolution.Component;\n const children = Array.isArray(node.children) ? node.children : [];\n return (\n <Renderer {...validation.props}>\n {children.length > 0\n ? children.map((child, index) => {\n const childId = `${id}.${index}`;\n return (\n <ItemBoundary\n key={childId}\n item={nodeItem(child, childId)}\n fallback={scope.fallback}\n onError={scope.onError}\n >\n <TreeNode node={child} id={childId} />\n </ItemBoundary>\n );\n })\n : undefined}\n </Renderer>\n );\n}\n\n/**\n * Renders a `genui:tree` frame's `{ root }` node by node through the same registry, catalog and\n * resolver as top-level components. Used automatically for tree frames unless the registry\n * overrides `genui:tree` (e.g. with the json-render adapter).\n */\nexport function GenuiTree({ root }: { root?: GenerativeUIElement }) {\n if (root === undefined || root === null || typeof root.type !== 'string') return null;\n return <TreeNode node={root} id=\"root\" />;\n}\n\nexport interface GenerativeUIScopeProps extends GenerativeUIOptions {\n fallback?: GenerativeUIFallback;\n loading?: ReactNode;\n onError?: (error: unknown, item: GenerativeUIItem) => void;\n children?: ReactNode;\n}\n\n/**\n * The registry, catalog and fallbacks tree nodes render with. `<GenerativeUI>` provides it; wrap\n * your own chrome in it when you draw `useGenerativeUI`'s `Component` yourself and it may be a tree.\n */\nexport function GenerativeUIScope({\n registry,\n catalog,\n resolveComponent,\n fallback,\n loading = null,\n onError,\n children,\n}: GenerativeUIScopeProps) {\n const scope = useMemo<TreeScope>(\n () => ({\n options: {\n registry,\n ...(catalog !== undefined ? { catalog } : {}),\n ...(resolveComponent !== undefined ? { resolveComponent } : {}),\n },\n fallback,\n loading,\n onError,\n }),\n [registry, catalog, resolveComponent, fallback, loading, onError],\n );\n return <TreeScopeContext.Provider value={scope}>{children}</TreeScopeContext.Provider>;\n}\n\n/** The headless half of {@link GenerativeUI}: what to draw for one pushed component, or `null` when `part` is not one. */\nexport function useGenerativeUI(\n part: unknown,\n options: GenerativeUIOptions,\n): GenerativeUIState | null {\n return useGenerativeUIState(part, options, GenuiTree as GenuiRenderer);\n}\n\nexport interface GenerativeUIProps extends GenerativeUIOptions {\n /** A transcript `ui` block, a `data-ui` message part, or a stored `{ id, component, props, version? }`. */\n part: TranscriptUiBlock | GenerativeUIItem | unknown;\n /** Drawn for an unknown component, invalid props, or a renderer that threw. Default: nothing. */\n fallback?: GenerativeUIFallback;\n /** Drawn while a resolver or an async validation is pending. Default: nothing. */\n loading?: ReactNode;\n /** A renderer threw (the item shows `fallback`). */\n onError?: (error: unknown, item: GenerativeUIItem) => void;\n}\n\n/**\n * Draws one server-pushed component with the app's own renderer. Headless: it adds no element and\n * no style of its own — only what the registry's component renders (and whatever `fallback` /\n * `loading` you pass).\n *\n * ```tsx\n * <MessageItem message={m} renderUi={(block) => (\n * <GenerativeUI part={block} registry={registry} catalog={catalog} fallback={({ item }) => <Unknown name={item.component} />} />\n * )} />\n * ```\n */\nexport function GenerativeUI({\n part,\n registry,\n catalog,\n resolveComponent,\n fallback,\n loading = null,\n onError,\n}: GenerativeUIProps) {\n const options = useMemo<GenerativeUIOptions>(\n () => ({\n registry,\n ...(catalog !== undefined ? { catalog } : {}),\n ...(resolveComponent !== undefined ? { resolveComponent } : {}),\n }),\n [registry, catalog, resolveComponent],\n );\n const state = useGenerativeUI(part, options);\n if (state === null) return null;\n if (state.status === 'loading') return loading;\n if (state.status === 'problem') {\n const { status: _status, ...problem } = state;\n return renderFallback(fallback, problem);\n }\n const Renderer = state.Component;\n return (\n <GenerativeUIScope\n {...options}\n fallback={fallback}\n loading={loading}\n {...(onError !== undefined ? { onError } : {})}\n >\n <ItemBoundary item={state.item} fallback={fallback} onError={onError}>\n <Renderer {...state.props} />\n </ItemBoundary>\n </GenerativeUIScope>\n );\n}\n","import { useEffect, useMemo, useState } from 'react';\nimport {\n GENUI_TREE_COMPONENT,\n type GenerativeUIItem,\n type GenerativeUIOptions,\n type GenerativeUIState,\n type GenuiCatalogLike,\n type GenuiIssueLike,\n type GenuiRegistry,\n type GenuiRenderer,\n type ResolveComponent,\n} from './types.js';\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Normalize whatever carries a pushed component: a transcript `ui` block, a `data-ui` message part\n * (`{ type: 'data-ui', id, data }`), a stored `{ id, component, props, version? }` entry. `null` for\n * anything else.\n */\nexport function toGenerativeUIItem(part: unknown): GenerativeUIItem | null {\n if (!isRecord(part)) return null;\n const source = part.type === 'data-ui' && isRecord(part.data) ? part.data : part;\n if (typeof source.component !== 'string') return null;\n const id =\n typeof source.id === 'string' ? source.id : typeof part.id === 'string' ? part.id : null;\n if (id === null) return null;\n return {\n id,\n component: source.component,\n props: isRecord(source.props) ? source.props : {},\n version: typeof source.version === 'number' ? source.version : null,\n toolCallId: typeof source.toolCallId === 'string' ? source.toolCallId : null,\n };\n}\n\ntype Resolution =\n | { status: 'ready'; Component: GenuiRenderer }\n | { status: 'loading' }\n | { status: 'unknown' }\n | { status: 'error'; error: unknown };\n\ninterface CacheEntry {\n resolution: Resolution;\n settled: Promise<void> | null;\n}\n\nconst resolverCaches = new WeakMap<ResolveComponent, Map<string, CacheEntry>>();\n\nfunction resolveCached(\n resolve: ResolveComponent,\n name: string,\n version: number | null,\n): CacheEntry {\n let cache = resolverCaches.get(resolve);\n if (cache === undefined) {\n cache = new Map();\n resolverCaches.set(resolve, cache);\n }\n const key = `${name}@${version ?? ''}`;\n const hit = cache.get(key);\n if (hit !== undefined) return hit;\n let entry: CacheEntry;\n try {\n const result = resolve(name, version);\n if (result instanceof Promise) {\n entry = { resolution: { status: 'loading' }, settled: null };\n entry.settled = result.then(\n (Component) => {\n entry.resolution = Component ? { status: 'ready', Component } : { status: 'unknown' };\n },\n (error: unknown) => {\n entry.resolution = { status: 'error', error };\n },\n );\n } else {\n entry = {\n resolution: result ? { status: 'ready', Component: result } : { status: 'unknown' },\n settled: null,\n };\n }\n } catch (error) {\n entry = { resolution: { status: 'error', error }, settled: null };\n }\n cache.set(key, entry);\n return entry;\n}\n\n/**\n * Which renderer draws `name`: the registry first, then `resolveComponent` (cached; async results\n * re-render the caller when they land). `fallbackTree` answers the tree component when the\n * registry does not override it.\n */\nexport function useResolvedComponent(\n name: string,\n version: number | null,\n registry: GenuiRegistry,\n resolve: ResolveComponent | undefined,\n fallbackTree?: GenuiRenderer,\n): Resolution {\n const [, setTick] = useState(0);\n const own = registry[name];\n const entry =\n own !== undefined || resolve === undefined ? null : resolveCached(resolve, name, version);\n const pending = entry?.resolution.status === 'loading' ? entry.settled : null;\n useEffect(() => {\n if (pending === null) return;\n let live = true;\n void pending.then(() => {\n if (live) setTick((tick) => tick + 1);\n });\n return () => {\n live = false;\n };\n }, [pending]);\n if (own !== undefined) return { status: 'ready', Component: own };\n if (entry !== null && entry.resolution.status !== 'unknown') return entry.resolution;\n if (name === GENUI_TREE_COMPONENT && fallbackTree !== undefined) {\n return { status: 'ready', Component: fallbackTree };\n }\n return { status: 'unknown' };\n}\n\ntype Validation =\n | { status: 'ok'; props: Record<string, unknown> }\n | { status: 'pending' }\n | { status: 'invalid'; issues: GenuiIssueLike[] };\n\n/**\n * Props checked against the catalog: synchronously when the catalog can (`validateSync`), else\n * after the async check settles. A component the catalog does not know passes through unchecked.\n */\nexport function useValidatedProps(\n catalog: GenuiCatalogLike | undefined,\n name: string,\n props: Record<string, unknown>,\n): Validation {\n const checked = catalog?.has(name) === true;\n const immediate = useMemo<Validation | null>(() => {\n if (!checked || catalog === undefined) return { status: 'ok', props };\n const result = catalog.validateSync?.(name, props);\n if (result === undefined) return null;\n return result.ok\n ? { status: 'ok', props: result.value }\n : { status: 'invalid', issues: result.issues };\n }, [checked, catalog, name, props]);\n const [late, setLate] = useState<{ props: Record<string, unknown>; result: Validation } | null>(\n null,\n );\n useEffect(() => {\n if (immediate !== null || catalog === undefined) return;\n let live = true;\n catalog.validate(name, props).then(\n (result) => {\n if (!live) return;\n setLate({\n props,\n result: result.ok\n ? { status: 'ok', props: result.value }\n : { status: 'invalid', issues: result.issues },\n });\n },\n (error: unknown) => {\n if (!live) return;\n setLate({\n props,\n result: {\n status: 'invalid',\n issues: [{ path: [], message: error instanceof Error ? error.message : String(error) }],\n },\n });\n },\n );\n return () => {\n live = false;\n };\n }, [immediate, catalog, name, props]);\n if (immediate !== null) return immediate;\n return late !== null && late.props === props ? late.result : { status: 'pending' };\n}\n\n/** {@link import('./generative-ui.js').useGenerativeUI}, with the tree renderer handed in (avoids an import cycle). */\nexport function useGenerativeUIState(\n part: unknown,\n options: GenerativeUIOptions,\n fallbackTree: GenuiRenderer | undefined,\n): GenerativeUIState | null {\n const item = useMemo(() => toGenerativeUIItem(part), [part]);\n const name = item?.component ?? '';\n const resolution = useResolvedComponent(\n name,\n item?.version ?? null,\n options.registry,\n item === null ? undefined : options.resolveComponent,\n fallbackTree,\n );\n const empty = useMemo<Record<string, unknown>>(() => ({}), []);\n // A tree is validated node by node as it renders, not as one component.\n const validation = useValidatedProps(\n item === null || name === GENUI_TREE_COMPONENT ? undefined : options.catalog,\n name,\n item?.props ?? empty,\n );\n if (item === null) return null;\n if (resolution.status === 'loading') return { status: 'loading', item };\n if (resolution.status === 'unknown') return { status: 'problem', reason: 'unknown', item };\n if (resolution.status === 'error') {\n return { status: 'problem', reason: 'error', item, error: resolution.error };\n }\n if (validation.status === 'pending') return { status: 'loading', item };\n if (validation.status === 'invalid') {\n return { status: 'problem', reason: 'invalid', item, issues: validation.issues };\n }\n return { status: 'ready', item, Component: resolution.Component, props: validation.props };\n}\n","import type { ComponentType, ReactNode } from 'react';\n\n/** The `ui` frame component a composed tree is pushed under (`@dudousxd/nestjs-agent-genui`'s `GENUI_TREE_COMPONENT`). */\nexport const GENUI_TREE_COMPONENT = 'genui:tree';\n\n/** One pushed component, normalized from whatever carried it (a transcript block, a `data-ui` part, a stored entry). */\nexport interface GenerativeUIItem {\n id: string;\n component: string;\n props: Record<string, unknown>;\n version: number | null;\n toolCallId: string | null;\n}\n\n/** A node of a composed tree (`genui:tree` frames): `{ type, props, children? }`. */\nexport interface GenerativeUIElement {\n type: string;\n props: Record<string, unknown>;\n children?: GenerativeUIElement[];\n}\n\n/**\n * An app's renderer for one component: it receives the component's props spread, plus `children`\n * when it is a layout node in a tree. Any React component — the library never styles anything.\n */\nexport type GenuiRenderer<P = any> = ComponentType<P & { children?: ReactNode }>;\n\n/** Component name → the app's renderer. */\nexport type GenuiRegistry = Record<string, GenuiRenderer>;\n\n/**\n * Resolve a component the registry does not have — typically a tenant's own component, fetched for\n * the exact `version` a message was rendered with. Return `null`/`undefined` for \"no such\n * component\". May be async; results are cached per resolver, name and version.\n */\nexport type ResolveComponent = (\n name: string,\n version: number | null,\n) => GenuiRenderer | null | undefined | Promise<GenuiRenderer | null | undefined>;\n\nexport interface GenuiIssueLike {\n path: (string | number)[];\n message: string;\n}\n\ntype ValidationLike =\n | { ok: true; value: Record<string, unknown> }\n | { ok: false; issues: GenuiIssueLike[] };\n\n/**\n * What the renderer needs from a catalog to validate props before drawing them. A\n * `@dudousxd/nestjs-agent-genui` `Catalog` satisfies it; declared structurally so this subpath does\n * not depend on that package.\n */\nexport interface GenuiCatalogLike {\n has(name: string): boolean;\n validate(name: string, props: unknown): Promise<ValidationLike>;\n validateSync?(name: string, props: unknown): ValidationLike | undefined;\n}\n\nexport interface GenerativeUIOptions {\n registry: GenuiRegistry;\n /** Validate props against it before rendering. Components the catalog does not know render unvalidated. */\n catalog?: GenuiCatalogLike;\n resolveComponent?: ResolveComponent;\n}\n\n/** Why an item did not render. */\nexport type GenerativeUIProblem =\n | { reason: 'unknown'; item: GenerativeUIItem }\n | { reason: 'invalid'; item: GenerativeUIItem; issues: GenuiIssueLike[] }\n | { reason: 'error'; item: GenerativeUIItem; error: unknown };\n\nexport type GenerativeUIState =\n | {\n status: 'ready';\n item: GenerativeUIItem;\n Component: GenuiRenderer;\n props: Record<string, unknown>;\n }\n | { status: 'loading'; item: GenerativeUIItem }\n | ({ status: 'problem' } & GenerativeUIProblem);\n"],"mappings":"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","names":["import_react","GENUI_TREE_COMPONENT","isRecord","value","Array","isArray","toGenerativeUIItem","part","source","type","data","component","id","props","version","toolCallId","resolverCaches","WeakMap","resolveCached","resolve","name","cache","get","undefined","Map","set","key","hit","entry","result","Promise","resolution","status","settled","then","Component","error","useResolvedComponent","registry","fallbackTree","setTick","useState","own","pending","useEffect","live","tick","GENUI_TREE_COMPONENT","useValidatedProps","catalog","checked","has","immediate","useMemo","validateSync","ok","issues","late","setLate","validate","path","message","Error","String","useGenerativeUIState","options","item","resolveComponent","empty","validation","reason","TreeScopeContext","createContext","renderFallback","fallback","problem","ItemBoundary","Component","state","error","undefined","failed","getDerivedStateFromError","componentDidCatch","_info","props","onError","item","componentDidUpdate","previous","setState","render","reason","children","nodeItem","node","id","component","type","version","toolCallId","TreeNode","scope","useContext","useMemo","resolution","useResolvedComponent","options","registry","resolveComponent","validation","useValidatedProps","catalog","status","loading","issues","Renderer","Array","isArray","length","map","child","index","childId","key","GenuiTree","root","GenerativeUIScope","Provider","value","useGenerativeUI","part","useGenerativeUIState","GenerativeUI","_status"]}
1
+ {"version":3,"sources":["../src/genui/index.ts","../src/genui/generative-ui.tsx","../src/components/ambient-ui.ts","../src/genui/use-generative-ui.ts","../src/genui/types.ts"],"sourcesContent":["export {\n GenerativeUI,\n type GenerativeUIFallback,\n type GenerativeUIProps,\n GenerativeUIScope,\n type GenerativeUIScopeProps,\n GenuiProvider,\n type GenuiProviderProps,\n type GenuiProviderValue,\n GenuiTree,\n useGenerativeUI,\n useGenuiProvider,\n} from './generative-ui.js';\nexport {\n GENUI_TREE_COMPONENT,\n type GenerativeUIElement,\n type GenerativeUIItem,\n type GenerativeUIOptions,\n type GenerativeUIProblem,\n type GenerativeUIState,\n type GenuiCatalogLike,\n type GenuiIssueLike,\n type GenuiRegistry,\n type GenuiRenderer,\n type ResolveComponent,\n} from './types.js';\nexport { toGenerativeUIItem } from './use-generative-ui.js';\n","import {\n Component,\n type Context,\n type ErrorInfo,\n type ReactNode,\n createContext,\n useCallback,\n useContext,\n useMemo,\n} from 'react';\nimport { AmbientRenderUiContext, sharedContext } from '../components/ambient-ui.js';\nimport type { TranscriptUiBlock } from '../transcript/model.js';\nimport type {\n GenerativeUIElement,\n GenerativeUIItem,\n GenerativeUIOptions,\n GenerativeUIProblem,\n GenerativeUIState,\n GenuiRegistry,\n GenuiRenderer,\n} from './types.js';\nimport {\n useGenerativeUIState,\n useResolvedComponent,\n useValidatedProps,\n} from './use-generative-ui.js';\n\n/** What to draw instead of a component that did not render. Default: nothing. */\nexport type GenerativeUIFallback = ReactNode | ((problem: GenerativeUIProblem) => ReactNode);\n\ninterface TreeScope {\n options: GenerativeUIOptions;\n fallback: GenerativeUIFallback | undefined;\n loading: ReactNode;\n onError: ((error: unknown, item: GenerativeUIItem) => void) | undefined;\n}\n\nconst TreeScopeContext = createContext<TreeScope | null>(null);\n\nfunction renderFallback(fallback: GenerativeUIFallback | undefined, problem: GenerativeUIProblem) {\n if (typeof fallback === 'function') return fallback(problem);\n return fallback ?? null;\n}\n\ninterface BoundaryProps {\n item: GenerativeUIItem;\n fallback: GenerativeUIFallback | undefined;\n onError: ((error: unknown, item: GenerativeUIItem) => void) | undefined;\n children: ReactNode;\n}\n\n/** One failing renderer takes down its own item, never the message around it. */\nclass ItemBoundary extends Component<BoundaryProps, { error: unknown; failed: boolean }> {\n override state = { error: undefined as unknown, failed: false };\n\n static getDerivedStateFromError(error: unknown) {\n return { error, failed: true };\n }\n\n override componentDidCatch(error: unknown, _info: ErrorInfo) {\n this.props.onError?.(error, this.props.item);\n }\n\n override componentDidUpdate(previous: BoundaryProps) {\n // New props for the same item (a streamed update) get a fresh chance to render.\n if (this.state.failed && previous.item !== this.props.item) {\n this.setState({ error: undefined, failed: false });\n }\n }\n\n override render() {\n if (this.state.failed) {\n return renderFallback(this.props.fallback, {\n reason: 'error',\n item: this.props.item,\n error: this.state.error,\n });\n }\n return this.props.children;\n }\n}\n\nfunction nodeItem(node: GenerativeUIElement, id: string): GenerativeUIItem {\n return { id, component: node.type, props: node.props ?? {}, version: null, toolCallId: null };\n}\n\n/** One tree node: resolved and validated like a top-level item, children rendered as its `children`. */\nfunction TreeNode({ node, id }: { node: GenerativeUIElement; id: string }) {\n const scope = useContext(TreeScopeContext);\n const item = useMemo(() => nodeItem(node, id), [node, id]);\n const resolution = useResolvedComponent(\n node.type,\n null,\n scope?.options.registry ?? {},\n scope?.options.resolveComponent,\n );\n const validation = useValidatedProps(scope?.options.catalog, node.type, item.props);\n if (scope === null) return null;\n if (resolution.status === 'loading' || validation.status === 'pending') return scope.loading;\n if (resolution.status === 'unknown') {\n return renderFallback(scope.fallback, { reason: 'unknown', item });\n }\n if (resolution.status === 'error') {\n return renderFallback(scope.fallback, { reason: 'error', item, error: resolution.error });\n }\n if (validation.status === 'invalid') {\n return renderFallback(scope.fallback, { reason: 'invalid', item, issues: validation.issues });\n }\n const Renderer = resolution.Component;\n const children = Array.isArray(node.children) ? node.children : [];\n return (\n <Renderer {...validation.props}>\n {children.length > 0\n ? children.map((child, index) => {\n const childId = `${id}.${index}`;\n return (\n <ItemBoundary\n key={childId}\n item={nodeItem(child, childId)}\n fallback={scope.fallback}\n onError={scope.onError}\n >\n <TreeNode node={child} id={childId} />\n </ItemBoundary>\n );\n })\n : undefined}\n </Renderer>\n );\n}\n\n/**\n * Renders a `genui:tree` frame's `{ root }` node by node through the same registry, catalog and\n * resolver as top-level components. Used automatically for tree frames unless a `treeRenderer`\n * (e.g. the json-render one) or a registry entry for `genui:tree` takes over.\n */\nexport function GenuiTree({ root }: { root?: GenerativeUIElement }) {\n if (root === undefined || root === null || typeof root.type !== 'string') return null;\n return <TreeNode node={root} id=\"root\" />;\n}\n\nexport interface GenerativeUIScopeProps extends GenerativeUIOptions {\n fallback?: GenerativeUIFallback;\n loading?: ReactNode;\n onError?: (error: unknown, item: GenerativeUIItem) => void;\n children?: ReactNode;\n}\n\n/**\n * The registry, catalog and fallbacks tree nodes render with. `<GenerativeUI>` provides it; wrap\n * your own chrome in it when you draw `useGenerativeUI`'s `Component` yourself and it may be a tree.\n */\nexport function GenerativeUIScope({\n registry,\n catalog,\n resolveComponent,\n fallback,\n loading = null,\n onError,\n children,\n}: GenerativeUIScopeProps) {\n const scope = useMemo<TreeScope>(\n () => ({\n options: {\n registry,\n ...(catalog !== undefined ? { catalog } : {}),\n ...(resolveComponent !== undefined ? { resolveComponent } : {}),\n },\n fallback,\n loading,\n onError,\n }),\n [registry, catalog, resolveComponent, fallback, loading, onError],\n );\n return <TreeScopeContext.Provider value={scope}>{children}</TreeScopeContext.Provider>;\n}\n\n/** What `<GenuiProvider>` hands every `<GenerativeUI>` / `useGenerativeUI` below it. */\nexport interface GenuiProviderValue extends Partial<GenerativeUIOptions> {\n fallback?: GenerativeUIFallback;\n loading?: ReactNode;\n onError?: (error: unknown, item: GenerativeUIItem) => void;\n}\n\n// Shared by key: `/genui` and `/genui/json-render` are separate bundles, and a provider from one\n// must reach a `<GenerativeUI>` from the other.\nconst GenuiContext: Context<GenuiProviderValue | null> = sharedContext<GenuiProviderValue>(\n '@dudousxd/nestjs-agent-react:genui-provider',\n);\n\n/** The enclosing `<GenuiProvider>`'s settings, or `null` outside one. */\nexport function useGenuiProvider(): GenuiProviderValue | null {\n return useContext(GenuiContext);\n}\n\nexport interface GenuiProviderProps extends GenuiProviderValue {\n children?: ReactNode;\n}\n\n/**\n * Set generative UI up once, at the app root: the registry of your renderers, the catalog to\n * validate against, a resolver for components the registry lacks, and what to draw when one does\n * not render. Every `<GenerativeUI>` below reads it (its own props still win), and `MessageItem` /\n * `MessageList` draw pushed components with it — no `renderUi` per message.\n *\n * ```tsx\n * <GenuiProvider registry={registry} catalog={catalog} fallback={({ item }) => <Unknown name={item.component} />}>\n * <App />\n * </GenuiProvider>\n * ```\n */\nexport function GenuiProvider({\n registry,\n catalog,\n resolveComponent,\n treeRenderer,\n fallback,\n loading,\n onError,\n children,\n}: GenuiProviderProps) {\n const value = useMemo<GenuiProviderValue>(\n () => ({\n ...(registry !== undefined ? { registry } : {}),\n ...(catalog !== undefined ? { catalog } : {}),\n ...(resolveComponent !== undefined ? { resolveComponent } : {}),\n ...(treeRenderer !== undefined ? { treeRenderer } : {}),\n ...(fallback !== undefined ? { fallback } : {}),\n ...(loading !== undefined ? { loading } : {}),\n ...(onError !== undefined ? { onError } : {}),\n }),\n [registry, catalog, resolveComponent, treeRenderer, fallback, loading, onError],\n );\n const renderUi = useCallback((block: TranscriptUiBlock) => <GenerativeUI part={block} />, []);\n return (\n <GenuiContext.Provider value={value}>\n <AmbientRenderUiContext.Provider value={renderUi}>{children}</AmbientRenderUiContext.Provider>\n </GenuiContext.Provider>\n );\n}\n\nconst NO_REGISTRY: GenuiRegistry = {};\n\n/** Provider settings overlaid with explicit ones (explicit wins), memoized on their parts. */\nfunction useMergedOptions(own: Partial<GenerativeUIOptions>): GenerativeUIOptions {\n const provided = useContext(GenuiContext);\n const registry = own.registry ?? provided?.registry ?? NO_REGISTRY;\n const catalog = own.catalog ?? provided?.catalog;\n const resolveComponent = own.resolveComponent ?? provided?.resolveComponent;\n const treeRenderer = own.treeRenderer ?? provided?.treeRenderer;\n return useMemo(\n () => ({\n registry,\n ...(catalog !== undefined ? { catalog } : {}),\n ...(resolveComponent !== undefined ? { resolveComponent } : {}),\n ...(treeRenderer !== undefined ? { treeRenderer } : {}),\n }),\n [registry, catalog, resolveComponent, treeRenderer],\n );\n}\n\n/**\n * The headless half of {@link GenerativeUI}: what to draw for one pushed component, or `null` when\n * `part` is not one. Options default to the enclosing `<GenuiProvider>`'s.\n */\nexport function useGenerativeUI(\n part: unknown,\n options: Partial<GenerativeUIOptions> = {},\n): GenerativeUIState | null {\n const merged = useMergedOptions(options);\n return useGenerativeUIState(part, merged, merged.treeRenderer ?? (GenuiTree as GenuiRenderer));\n}\n\nexport interface GenerativeUIProps extends Partial<GenerativeUIOptions> {\n /** A transcript `ui` block, a `data-ui` message part, or a stored `{ id, component, props, version? }`. */\n part: TranscriptUiBlock | GenerativeUIItem | unknown;\n /** Drawn for an unknown component, invalid props, or a renderer that threw. Default: the provider's, else nothing. */\n fallback?: GenerativeUIFallback;\n /** Drawn while a resolver or an async validation is pending. Default: the provider's, else nothing. */\n loading?: ReactNode;\n /** A renderer threw (the item shows `fallback`). */\n onError?: (error: unknown, item: GenerativeUIItem) => void;\n}\n\n/**\n * Draws one server-pushed component with the app's own renderer. Headless: it adds no element and\n * no style of its own — only what the registry's component renders (and whatever `fallback` /\n * `loading` you pass). Everything but `part` defaults to the enclosing `<GenuiProvider>`.\n *\n * ```tsx\n * <GenerativeUI part={block} />\n * ```\n */\nexport function GenerativeUI({\n part,\n registry,\n catalog,\n resolveComponent,\n treeRenderer,\n fallback: ownFallback,\n loading: ownLoading,\n onError: ownOnError,\n}: GenerativeUIProps) {\n const provided = useContext(GenuiContext);\n const fallback = ownFallback ?? provided?.fallback;\n const loading = ownLoading ?? provided?.loading ?? null;\n const onError = ownOnError ?? provided?.onError;\n const options = useMergedOptions({\n ...(registry !== undefined ? { registry } : {}),\n ...(catalog !== undefined ? { catalog } : {}),\n ...(resolveComponent !== undefined ? { resolveComponent } : {}),\n ...(treeRenderer !== undefined ? { treeRenderer } : {}),\n });\n const state = useGenerativeUIState(\n part,\n options,\n options.treeRenderer ?? (GenuiTree as GenuiRenderer),\n );\n if (state === null) return null;\n if (state.status === 'loading') return loading;\n if (state.status === 'problem') {\n const { status: _status, ...problem } = state;\n return renderFallback(fallback, problem);\n }\n const Renderer = state.Component;\n return (\n <GenerativeUIScope\n {...options}\n fallback={fallback}\n loading={loading}\n {...(onError !== undefined ? { onError } : {})}\n >\n <ItemBoundary item={state.item} fallback={fallback} onError={onError}>\n <Renderer {...state.props} />\n </ItemBoundary>\n </GenerativeUIScope>\n );\n}\n","import { type Context, type ReactNode, createContext, useContext } from 'react';\nimport type { TranscriptUiBlock } from '../transcript/model.js';\n\n/** Draws a server-pushed component block. */\nexport type AmbientRenderUi = (block: TranscriptUiBlock) => ReactNode;\n\n/**\n * A context stored on `globalThis` under a registered symbol. Each entry point (`.`, `/genui`,\n * `/genui/json-render`) is its own bundle with its own copy of every module, so a context one entry\n * provides and another reads has to be found by key, not by module identity.\n */\nexport function sharedContext<T>(key: string): Context<T | null> {\n const symbol = Symbol.for(key);\n const holder = globalThis as Record<symbol, Context<T | null> | undefined>;\n const existing = holder[symbol];\n if (existing !== undefined) return existing;\n const created = createContext<T | null>(null);\n holder[symbol] = created;\n return created;\n}\n\n/**\n * How pushed components are drawn when no `renderUi` is passed — set by `<GenuiProvider>` (the\n * `/genui` subpath) and read by `MessageItem`.\n */\nexport const AmbientRenderUiContext: Context<AmbientRenderUi | null> =\n sharedContext<AmbientRenderUi>('@dudousxd/nestjs-agent-react:ambient-render-ui');\n\n/**\n * The renderer `<GenuiProvider>` installed for pushed components, or `null` outside one. For a\n * custom transcript built on `useTranscriptItem`: draw a `ui` block with it and you get what\n * `MessageItem` draws.\n */\nexport function useAmbientRenderUi(): AmbientRenderUi | null {\n return useContext(AmbientRenderUiContext);\n}\n","import { useEffect, useMemo, useState } from 'react';\nimport {\n GENUI_TREE_COMPONENT,\n type GenerativeUIItem,\n type GenerativeUIOptions,\n type GenerativeUIState,\n type GenuiCatalogLike,\n type GenuiIssueLike,\n type GenuiRegistry,\n type GenuiRenderer,\n type ResolveComponent,\n} from './types.js';\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Normalize whatever carries a pushed component: a transcript `ui` block, a `data-ui` message part\n * (`{ type: 'data-ui', id, data }`), a stored `{ id, component, props, version? }` entry. `null` for\n * anything else.\n */\nexport function toGenerativeUIItem(part: unknown): GenerativeUIItem | null {\n if (!isRecord(part)) return null;\n const source = part.type === 'data-ui' && isRecord(part.data) ? part.data : part;\n if (typeof source.component !== 'string') return null;\n const id =\n typeof source.id === 'string' ? source.id : typeof part.id === 'string' ? part.id : null;\n if (id === null) return null;\n return {\n id,\n component: source.component,\n props: isRecord(source.props) ? source.props : {},\n version: typeof source.version === 'number' ? source.version : null,\n toolCallId: typeof source.toolCallId === 'string' ? source.toolCallId : null,\n };\n}\n\ntype Resolution =\n | { status: 'ready'; Component: GenuiRenderer }\n | { status: 'loading' }\n | { status: 'unknown' }\n | { status: 'error'; error: unknown };\n\ninterface CacheEntry {\n resolution: Resolution;\n settled: Promise<void> | null;\n}\n\nconst resolverCaches = new WeakMap<ResolveComponent, Map<string, CacheEntry>>();\n\nfunction resolveCached(\n resolve: ResolveComponent,\n name: string,\n version: number | null,\n): CacheEntry {\n let cache = resolverCaches.get(resolve);\n if (cache === undefined) {\n cache = new Map();\n resolverCaches.set(resolve, cache);\n }\n const key = `${name}@${version ?? ''}`;\n const hit = cache.get(key);\n if (hit !== undefined) return hit;\n let entry: CacheEntry;\n try {\n const result = resolve(name, version);\n if (result instanceof Promise) {\n entry = { resolution: { status: 'loading' }, settled: null };\n entry.settled = result.then(\n (Component) => {\n entry.resolution = Component ? { status: 'ready', Component } : { status: 'unknown' };\n },\n (error: unknown) => {\n entry.resolution = { status: 'error', error };\n },\n );\n } else {\n entry = {\n resolution: result ? { status: 'ready', Component: result } : { status: 'unknown' },\n settled: null,\n };\n }\n } catch (error) {\n entry = { resolution: { status: 'error', error }, settled: null };\n }\n cache.set(key, entry);\n return entry;\n}\n\n/**\n * Which renderer draws `name`: the registry first, then `resolveComponent` (cached; async results\n * re-render the caller when they land). `fallbackTree` answers the tree component when the\n * registry does not override it.\n */\nexport function useResolvedComponent(\n name: string,\n version: number | null,\n registry: GenuiRegistry,\n resolve: ResolveComponent | undefined,\n fallbackTree?: GenuiRenderer,\n): Resolution {\n const [, setTick] = useState(0);\n const own = registry[name];\n const entry =\n own !== undefined || resolve === undefined ? null : resolveCached(resolve, name, version);\n const pending = entry?.resolution.status === 'loading' ? entry.settled : null;\n useEffect(() => {\n if (pending === null) return;\n let live = true;\n void pending.then(() => {\n if (live) setTick((tick) => tick + 1);\n });\n return () => {\n live = false;\n };\n }, [pending]);\n if (own !== undefined) return { status: 'ready', Component: own };\n if (entry !== null && entry.resolution.status !== 'unknown') return entry.resolution;\n if (name === GENUI_TREE_COMPONENT && fallbackTree !== undefined) {\n return { status: 'ready', Component: fallbackTree };\n }\n return { status: 'unknown' };\n}\n\ntype Validation =\n | { status: 'ok'; props: Record<string, unknown> }\n | { status: 'pending' }\n | { status: 'invalid'; issues: GenuiIssueLike[] };\n\n/**\n * Props checked against the catalog: synchronously when the catalog can (`validateSync`), else\n * after the async check settles. A component the catalog does not know passes through unchecked.\n */\nexport function useValidatedProps(\n catalog: GenuiCatalogLike | undefined,\n name: string,\n props: Record<string, unknown>,\n): Validation {\n const checked = catalog?.has(name) === true;\n const immediate = useMemo<Validation | null>(() => {\n if (!checked || catalog === undefined) return { status: 'ok', props };\n const result = catalog.validateSync?.(name, props);\n if (result === undefined) return null;\n return result.ok\n ? { status: 'ok', props: result.value }\n : { status: 'invalid', issues: result.issues };\n }, [checked, catalog, name, props]);\n const [late, setLate] = useState<{ props: Record<string, unknown>; result: Validation } | null>(\n null,\n );\n useEffect(() => {\n if (immediate !== null || catalog === undefined) return;\n let live = true;\n catalog.validate(name, props).then(\n (result) => {\n if (!live) return;\n setLate({\n props,\n result: result.ok\n ? { status: 'ok', props: result.value }\n : { status: 'invalid', issues: result.issues },\n });\n },\n (error: unknown) => {\n if (!live) return;\n setLate({\n props,\n result: {\n status: 'invalid',\n issues: [{ path: [], message: error instanceof Error ? error.message : String(error) }],\n },\n });\n },\n );\n return () => {\n live = false;\n };\n }, [immediate, catalog, name, props]);\n if (immediate !== null) return immediate;\n return late !== null && late.props === props ? late.result : { status: 'pending' };\n}\n\n/** {@link import('./generative-ui.js').useGenerativeUI}, with the tree renderer handed in (avoids an import cycle). */\nexport function useGenerativeUIState(\n part: unknown,\n options: GenerativeUIOptions,\n fallbackTree: GenuiRenderer | undefined,\n): GenerativeUIState | null {\n const item = useMemo(() => toGenerativeUIItem(part), [part]);\n const name = item?.component ?? '';\n const resolution = useResolvedComponent(\n name,\n item?.version ?? null,\n options.registry,\n item === null ? undefined : options.resolveComponent,\n fallbackTree,\n );\n const empty = useMemo<Record<string, unknown>>(() => ({}), []);\n // A tree is validated node by node as it renders, not as one component.\n const validation = useValidatedProps(\n item === null || name === GENUI_TREE_COMPONENT ? undefined : options.catalog,\n name,\n item?.props ?? empty,\n );\n if (item === null) return null;\n if (resolution.status === 'loading') return { status: 'loading', item };\n if (resolution.status === 'unknown') return { status: 'problem', reason: 'unknown', item };\n if (resolution.status === 'error') {\n return { status: 'problem', reason: 'error', item, error: resolution.error };\n }\n if (validation.status === 'pending') return { status: 'loading', item };\n if (validation.status === 'invalid') {\n return { status: 'problem', reason: 'invalid', item, issues: validation.issues };\n }\n return { status: 'ready', item, Component: resolution.Component, props: validation.props };\n}\n","import type { ComponentType, ReactNode } from 'react';\n\n/** The `ui` frame component a composed tree is pushed under (`GENUI_TREE_COMPONENT` of `@dudousxd/nestjs-agent-core/genui`). */\nexport const GENUI_TREE_COMPONENT = 'genui:tree';\n\n/** One pushed component, normalized from whatever carried it (a transcript block, a `data-ui` part, a stored entry). */\nexport interface GenerativeUIItem {\n id: string;\n component: string;\n props: Record<string, unknown>;\n version: number | null;\n toolCallId: string | null;\n}\n\n/** A node of a composed tree (`genui:tree` frames): `{ type, props, children? }`. */\nexport interface GenerativeUIElement {\n type: string;\n props: Record<string, unknown>;\n children?: GenerativeUIElement[];\n}\n\n/**\n * An app's renderer for one component: it receives the component's props spread, plus `children`\n * when it is a layout node in a tree. Any React component — the library never styles anything.\n */\nexport type GenuiRenderer<P = any> = ComponentType<P & { children?: ReactNode }>;\n\n/** Component name → the app's renderer. */\nexport type GenuiRegistry = Record<string, GenuiRenderer>;\n\n/**\n * Resolve a component the registry does not have — typically a tenant's own component, fetched for\n * the exact `version` a message was rendered with. Return `null`/`undefined` for \"no such\n * component\". May be async; results are cached per resolver, name and version.\n */\nexport type ResolveComponent = (\n name: string,\n version: number | null,\n) => GenuiRenderer | null | undefined | Promise<GenuiRenderer | null | undefined>;\n\nexport interface GenuiIssueLike {\n path: (string | number)[];\n message: string;\n}\n\ntype ValidationLike =\n | { ok: true; value: Record<string, unknown> }\n | { ok: false; issues: GenuiIssueLike[] };\n\n/**\n * What the renderer needs from a catalog to validate props before drawing them. A `Catalog` from\n * `@dudousxd/nestjs-agent-core/genui` satisfies it; declared structurally so any catalog-shaped\n * object does too.\n */\nexport interface GenuiCatalogLike {\n has(name: string): boolean;\n validate(name: string, props: unknown): Promise<ValidationLike>;\n validateSync?(name: string, props: unknown): ValidationLike | undefined;\n}\n\nexport interface GenerativeUIOptions {\n registry: GenuiRegistry;\n /** Validate props against it before rendering. Components the catalog does not know render unvalidated. */\n catalog?: GenuiCatalogLike;\n resolveComponent?: ResolveComponent;\n /**\n * Draws a composed tree frame (`genui:tree`) whole — e.g. through json-render (see the\n * `/genui/json-render` subpath's `GenuiProvider`). Omitted → trees render node by node through\n * `registry`.\n */\n treeRenderer?: GenuiRenderer<{ root?: GenerativeUIElement }>;\n}\n\n/** Why an item did not render. */\nexport type GenerativeUIProblem =\n | { reason: 'unknown'; item: GenerativeUIItem }\n | { reason: 'invalid'; item: GenerativeUIItem; issues: GenuiIssueLike[] }\n | { reason: 'error'; item: GenerativeUIItem; error: unknown };\n\nexport type GenerativeUIState =\n | {\n status: 'ready';\n item: GenerativeUIItem;\n Component: GenuiRenderer;\n props: Record<string, unknown>;\n }\n | { status: 'loading'; item: GenerativeUIItem }\n | ({ status: 'problem' } & GenerativeUIProblem);\n"],"mappings":"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","names":["import_react","sharedContext","key","symbol","Symbol","for","holder","globalThis","existing","undefined","created","createContext","AmbientRenderUiContext","import_react","GENUI_TREE_COMPONENT","isRecord","value","Array","isArray","toGenerativeUIItem","part","source","type","data","component","id","props","version","toolCallId","resolverCaches","WeakMap","resolveCached","resolve","name","cache","get","undefined","Map","set","key","hit","entry","result","Promise","resolution","status","settled","then","Component","error","useResolvedComponent","registry","fallbackTree","setTick","useState","own","pending","useEffect","live","tick","GENUI_TREE_COMPONENT","useValidatedProps","catalog","checked","has","immediate","useMemo","validateSync","ok","issues","late","setLate","validate","path","message","Error","String","useGenerativeUIState","options","item","resolveComponent","empty","validation","reason","TreeScopeContext","createContext","renderFallback","fallback","problem","ItemBoundary","Component","state","error","undefined","failed","getDerivedStateFromError","componentDidCatch","_info","props","onError","item","componentDidUpdate","previous","setState","render","reason","children","nodeItem","node","id","component","type","version","toolCallId","TreeNode","scope","useContext","useMemo","resolution","useResolvedComponent","options","registry","resolveComponent","validation","useValidatedProps","catalog","status","loading","issues","Renderer","Array","isArray","length","map","child","index","childId","key","GenuiTree","root","GenerativeUIScope","Provider","value","GenuiContext","sharedContext","useGenuiProvider","GenuiProvider","treeRenderer","renderUi","useCallback","block","GenerativeUI","part","AmbientRenderUiContext","NO_REGISTRY","useMergedOptions","own","provided","useGenerativeUI","merged","useGenerativeUIState","ownFallback","ownLoading","ownOnError","_status"]}
package/dist/genui.d.cts CHANGED
@@ -1,57 +1,10 @@
1
- import * as React from 'react';
2
- import { ReactNode } from 'react';
3
- import { T as TranscriptUiBlock } from './model-gHqjNjLJ.cjs';
4
- import { G as GenerativeUIOptions, a as GenerativeUIItem, b as GenerativeUIProblem, c as GenerativeUIElement, d as GenerativeUIState } from './types-DFD-soWU.cjs';
5
- export { e as GENUI_TREE_COMPONENT, f as GenuiCatalogLike, g as GenuiIssueLike, h as GenuiRegistry, i as GenuiRenderer, R as ResolveComponent } from './types-DFD-soWU.cjs';
1
+ import { G as GenerativeUIItem } from './generative-ui-C53b3FoA.cjs';
2
+ export { a as GENUI_TREE_COMPONENT, b as GenerativeUI, c as GenerativeUIElement, d as GenerativeUIFallback, e as GenerativeUIOptions, f as GenerativeUIProblem, g as GenerativeUIProps, h as GenerativeUIScope, i as GenerativeUIScopeProps, j as GenerativeUIState, k as GenuiCatalogLike, l as GenuiIssueLike, m as GenuiProvider, n as GenuiProviderProps, o as GenuiProviderValue, p as GenuiRegistry, q as GenuiRenderer, r as GenuiTree, R as ResolveComponent, u as useGenerativeUI, s as useGenuiProvider } from './generative-ui-C53b3FoA.cjs';
3
+ import 'react';
4
+ import './model-gHqjNjLJ.cjs';
6
5
  import '@dudousxd/nestjs-agent-core';
7
6
  import 'ai';
8
7
 
9
- /** What to draw instead of a component that did not render. Default: nothing. */
10
- type GenerativeUIFallback = ReactNode | ((problem: GenerativeUIProblem) => ReactNode);
11
- /**
12
- * Renders a `genui:tree` frame's `{ root }` node by node through the same registry, catalog and
13
- * resolver as top-level components. Used automatically for tree frames unless the registry
14
- * overrides `genui:tree` (e.g. with the json-render adapter).
15
- */
16
- declare function GenuiTree({ root }: {
17
- root?: GenerativeUIElement;
18
- }): React.JSX.Element | null;
19
- interface GenerativeUIScopeProps extends GenerativeUIOptions {
20
- fallback?: GenerativeUIFallback;
21
- loading?: ReactNode;
22
- onError?: (error: unknown, item: GenerativeUIItem) => void;
23
- children?: ReactNode;
24
- }
25
- /**
26
- * The registry, catalog and fallbacks tree nodes render with. `<GenerativeUI>` provides it; wrap
27
- * your own chrome in it when you draw `useGenerativeUI`'s `Component` yourself and it may be a tree.
28
- */
29
- declare function GenerativeUIScope({ registry, catalog, resolveComponent, fallback, loading, onError, children, }: GenerativeUIScopeProps): React.JSX.Element;
30
- /** The headless half of {@link GenerativeUI}: what to draw for one pushed component, or `null` when `part` is not one. */
31
- declare function useGenerativeUI(part: unknown, options: GenerativeUIOptions): GenerativeUIState | null;
32
- interface GenerativeUIProps extends GenerativeUIOptions {
33
- /** A transcript `ui` block, a `data-ui` message part, or a stored `{ id, component, props, version? }`. */
34
- part: TranscriptUiBlock | GenerativeUIItem | unknown;
35
- /** Drawn for an unknown component, invalid props, or a renderer that threw. Default: nothing. */
36
- fallback?: GenerativeUIFallback;
37
- /** Drawn while a resolver or an async validation is pending. Default: nothing. */
38
- loading?: ReactNode;
39
- /** A renderer threw (the item shows `fallback`). */
40
- onError?: (error: unknown, item: GenerativeUIItem) => void;
41
- }
42
- /**
43
- * Draws one server-pushed component with the app's own renderer. Headless: it adds no element and
44
- * no style of its own — only what the registry's component renders (and whatever `fallback` /
45
- * `loading` you pass).
46
- *
47
- * ```tsx
48
- * <MessageItem message={m} renderUi={(block) => (
49
- * <GenerativeUI part={block} registry={registry} catalog={catalog} fallback={({ item }) => <Unknown name={item.component} />} />
50
- * )} />
51
- * ```
52
- */
53
- declare function GenerativeUI({ part, registry, catalog, resolveComponent, fallback, loading, onError, }: 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;
54
-
55
8
  /**
56
9
  * Normalize whatever carries a pushed component: a transcript `ui` block, a `data-ui` message part
57
10
  * (`{ type: 'data-ui', id, data }`), a stored `{ id, component, props, version? }` entry. `null` for
@@ -59,4 +12,4 @@ declare function GenerativeUI({ part, registry, catalog, resolveComponent, fallb
59
12
  */
60
13
  declare function toGenerativeUIItem(part: unknown): GenerativeUIItem | null;
61
14
 
62
- export { GenerativeUI, GenerativeUIElement, type GenerativeUIFallback, GenerativeUIItem, GenerativeUIOptions, GenerativeUIProblem, type GenerativeUIProps, GenerativeUIScope, type GenerativeUIScopeProps, GenerativeUIState, GenuiTree, toGenerativeUIItem, useGenerativeUI };
15
+ export { GenerativeUIItem, toGenerativeUIItem };