import * as react0 from "react"; import * as react1 from "react"; import { MouseEvent, ReactNode } from "react"; import { AIGuiPlugin, ASTNode, ActionRuntime, ActionState, CardAction, CardRegistry, CardStore, DebugEventListener, ExportImageOptions, ExportedImage, FeedOptions, FeedSource, NodeRenderer, Patch, PluginSource, RenderOutput, Renderer, RendererOptions } from "@ai-gui/core"; //#region src/use-ai-renderer.d.ts interface UseAIRendererResult { renderer: Renderer; nodes: ASTNode[]; push: (chunk: string) => void; feed: (source: FeedSource, options?: FeedOptions) => Promise; reset: () => void; } declare function useAIRenderer(options?: Omit): UseAIRendererResult; //#endregion //#region src/use-action-state.d.ts declare function useActionState(runtime: ActionRuntime | undefined, key: string): ActionState; //#endregion //#region src/use-plugin-styles.d.ts /** * Put the plugins' stylesheets in the document. * * Plugins declare `css` but have no way to install it themselves, so without this a host has to * know which of its plugins ship styles and import each one by hand. Injection is idempotent, so * several renderers on a page share one copy of each stylesheet. */ declare function usePluginStyles(plugins?: AIGuiPlugin[]): void; //#endregion //#region src/use-plugins.d.ts interface UsePluginsResult { /** The plugins in force now: an array source as given, a loader's plugins once they arrive. */ plugins?: AIGuiPlugin[]; /** Why the loader failed, if it did. The answer keeps rendering as plain markdown. */ error?: unknown; } /** * Resolve a plugin source, loading it if it is a function. * * Diagrams, maths and charts are the heaviest thing a page carrying them loads, and an answer that * draws none should not pay for them. An array is returned as it came — deferring it by a * microtask would draw the first chunk of every answer twice — while a loader's plugins arrive * later and the renderer reparses what it has buffered by then. * * Pass a stable loader: it runs again whenever its identity changes, so define it outside the * component or wrap it in `useCallback`. */ declare function usePlugins(source?: PluginSource): UsePluginsResult; //#endregion //#region src/render-node.d.ts interface CardActionPayload { type: string; params?: unknown; cardType: string; cardId?: string; } interface RenderContext { registry?: CardRegistry; cardStore?: CardStore; plugins?: AIGuiPlugin[]; nodeRenderers?: Record; onCardAction?: (action: CardActionPayload) => void; sanitize?: RendererOptions["sanitize"]; sanitized?: boolean; /** The host's colour scheme, handed to every plugin that renders a node. */ theme?: string; /** The host's locale, handed to every plugin so its own labels match the page. */ locale?: string; } declare function renderNode(node: ASTNode, ctx: RenderContext): ReactNode; interface CardComponentProps { data: unknown; state?: CardAction; onAction: (a: { type: string; params?: unknown; }) => void; } //#endregion //#region src/ai-renderer.d.ts interface AIRendererHandle { readonly debugSource: "renderer"; subscribeDebug: (listener: DebugEventListener) => () => void; push: (chunk: string) => void; feed: (source: FeedSource, options?: FeedOptions) => Promise; /** * Export every drawing currently rendered, as PNG data URLs. * * The element the drawings live in belongs to the renderer, so a host offering "save this chart" * would otherwise have to wrap it in one of its own just to find them. */ exportImages: (options?: ExportImageOptions) => Promise; reset: () => void; } interface AIRendererProps { /** * The whole text to render, as a controlled component. * * Streaming a model's answer means re-rendering with a longer string, and only the added part * is new. Working that out is the renderer's job: pass the full text on every update and it * pushes the delta, or starts over when the new text is not a continuation of what it holds. * Leave it undefined to drive the renderer through the imperative handle instead. */ text?: string; registry?: CardRegistry; cardStore?: CardStore; sanitize?: RendererOptions["sanitize"]; rawHtml?: RendererOptions["rawHtml"]; /** * The plugins, or a function that loads them. * * Diagrams, maths and charts are the heaviest thing a page carrying them loads, and an answer * that draws none should not pay for them: * `plugins={() => import("@ai-gui/plugin-mermaid").then((m) => [m.mermaid()])}`. Until the import * resolves the answer renders as plain markdown; when it lands the renderer reparses the text it * has buffered, so nothing already streamed is lost. Keep the loader stable — define it outside * the component or wrap it in `useCallback` — as it runs again whenever its identity changes. */ plugins?: PluginSource; actionRuntime?: ActionRuntime; onCardAction?: RenderContext["onCardAction"]; /** * Renderers for individual node types, overriding whatever the plugins supply. * * A host that wants its own code block — with its copy button, its theme — otherwise has to * drop the plugin that claims `code` and reimplement everything else it rendered. Keep the * object stable across renders, as with `plugins`. */ nodeRenderers?: Record; /** * Called with the nodes currently on screen, whenever they change. * * What a model produced is only knowable from the parsed nodes: a host that wants to offer * "export this chart" or count the diagrams in an answer would otherwise have to watch the DOM * for the elements a plugin happened to create. */ onRender?: (nodes: ASTNode[]) => void; /** * Called when a click lands inside a rendered block, with the node that block came from. * * What the reader clicked is only meaningful against the model's output: an absolute path in * inline code that should reveal a file, a citation that should open its source, a code block * with a copy button. Without this a host listens on a container of its own and guesses from the * DOM — `closest("code")` and the like — which reads a structure the renderer rebuilds as it * streams and never promised. `event.target` is the exact element clicked inside the block. */ onNodeClick?: (node: ASTNode, event: MouseEvent) => void; /** * The host's colour scheme, "light" or "dark" by convention, handed to every plugin. * * Charts and diagrams choose their own colours and cannot see the page they sit on, so an * answer rendered on a dark page comes back with white plot areas until the host says so. */ theme?: string; /** * The host's locale as a BCP-47 tag, e.g. "zh-CN". * * Handed to every plugin so the chrome it draws — a Copy button, an error line — is in the * page's language. English is the fallback for anything untranslated. */ locale?: string; className?: string; debug?: RendererOptions["debug"]; onDebugEvent?: RendererOptions["onDebugEvent"]; } declare const AIRenderer: react1.ForwardRefExoticComponent>; //#endregion //#region src/render-output.d.ts /** Translate a framework-neutral RenderOutput into React nodes. */ declare function renderOutput(out: RenderOutput, key?: string, sanitize?: RendererOptions["sanitize"], context?: RenderContext): ReactNode; //#endregion //#region src/apply-patches.d.ts declare function applyPatches(nodes: ASTNode[], patches: Patch[]): ASTNode[]; //#endregion export { AIRenderer, AIRendererHandle, AIRendererProps, CardActionPayload, CardComponentProps, RenderContext, UseAIRendererResult, UsePluginsResult, applyPatches, renderNode, renderOutput, useAIRenderer, useActionState, usePluginStyles, usePlugins };