/** * UI — Agent-to-UI composition namespace (A2UI). * * Declarative UI composition for agents. * Compose with .row() (horizontal) or .column() (vertical). * * Usage: * agent.ui(UI.surface("main", UI.text("Hello!").row(UI.button("Click me")))) * agent.ui(UI.form("Login", { fields: [{ label: "Email", bind: "/email" }] })) */ import { type FluxBadgeArgs, type FluxBannerArgs, type FluxButtonArgs, type FluxCardArgs, type FluxLinkArgs, type FluxMarkdownArgs, type FluxProgressArgs, type FluxSkeletonArgs, type FluxStackArgs, type FluxTextFieldArgs } from "../flux/index.js"; /** Known catalog identifiers. Used by UI.withCatalog and T.a2ui. */ export declare const KNOWN_CATALOGS: readonly ["basic", "flux"]; export type CatalogName = (typeof KNOWN_CATALOGS)[number]; /** Return the currently-active catalog (top of stack). */ export declare function activeCatalog(): CatalogName; /** Data binding specification. */ export interface UIBinding { path: string; direction?: "read" | "write" | "readwrite"; } /** Validation check descriptor. */ export interface UICheck { type: string; config: Record; } /** UI component descriptor — the universal building block. */ export declare class UIComponent { readonly kind: string; readonly props: Record; readonly children: UIComponent[]; readonly id?: string | undefined; constructor(kind: string, props?: Record, children?: UIComponent[], id?: string | undefined); /** Horizontal composition: wrap this and other in a row. */ row(...others: UIComponent[]): UIComponent; /** Vertical composition: wrap this and other in a column. */ column(...others: UIComponent[]): UIComponent; /** Add child components. */ add(...children: UIComponent[]): UIComponent; } /** * Theme marker — produced by ``UI.theme(name)`` and consumed by * ``UI.surface(...)`` to populate ``UISurface.theme``. Theme markers are * stripped from the surface root so they never appear as components. */ export declare class UIThemeMarker { readonly name: string; constructor(name: string); } /** A named UI surface (compilation root). */ export declare class UISurface { readonly name: string; readonly root: UIComponent; readonly meta: Record; readonly data: Record; readonly handlers: Record; /** Theme attached via ``UI.theme(name)``. Empty object when unset. */ readonly theme: { name?: string; }; constructor(name: string, root: UIComponent, meta?: Record, data?: Record, handlers?: Record, /** Theme attached via ``UI.theme(name)``. Empty object when unset. */ theme?: { name?: string; }); /** * Validate this surface for structural integrity. * * Checks (in order, fail-first): * 1. Component IDs are unique across the tree. * 2. Root must be a real component, not a virtual group. * 3. Two-way bind paths reference declared `data` keys (skipped if no data). * 4. Action event names registered must match handler names (skipped if no handlers). * * @throws A2UISurfaceError on the first violation discovered. */ validate(): void; } /** * LLM-guided UI mode marker. * * When passed to `Agent.ui(spec)` (or via `agent.ui(undefined, { llmGuided: true })`), * signals that the LLM should be allowed to design the UI surface itself * via the A2UI toolset and catalog schema injection. */ export declare class UIAutoSpec { catalog: string; readonly fromFlag: boolean; constructor(catalog?: string, opts?: { fromFlag?: boolean; }); } /** * Schema-only prompt injection marker. * * When passed to `Agent.ui(spec)`, signals that only the catalog schema * should be injected into the system prompt — the LLM is not asked to * generate UI itself, but is informed of the available components. */ export declare class UISchemaSpec { catalogUri: string | null; constructor(catalogUri?: string | null); } /** * UI namespace — A2UI component factories. * * All component factories, validation checks, presets, formatting functions, * and surface lifecycle from the Python UI namespace. */ export declare class UI { /** Create data binding to a JSON Pointer path. */ static bind(path: string, opts?: { direction?: "read" | "write" | "readwrite"; }): UIBinding; /** Format string with ${/path} interpolation. */ static fmt(template: string): Record; /** * Create a named UI surface (compilation root). * * The ``root`` argument may be a plain ``UIComponent`` (standard) or an * array mixing components and ``UIThemeMarker``. Theme markers are lifted * off the root list and attached to ``UISurface.theme`` — never rendered. * * When multiple theme markers are present the last one wins; when multiple * components are present without an explicit root a ``UIError`` is thrown. */ static surface(name: string, root: UIComponent | Array, meta?: Record): UISurface; /** * Attach a theme id to the enclosing surface. * * Use inline with ``UI.surface``:: * * UI.surface("demo", [UI.theme("flux-dark"), UI.column([...])]) * * The compiled surface carries ``createSurface.theme = { name: "" }``. */ static theme(name: string): UIThemeMarker; /** * Scoped catalog dispatch. * * Runs ``fn`` with the given catalog active; all ``UI.button`` / ``.badge`` * / ``.card`` / etc. calls inside the callback emit the catalog-specific * components (e.g. ``FluxButton`` when catalog is ``"flux"``). Catalog * state is restored on return (including across thrown errors). * * Nests cleanly. Unknown catalogs throw ``A2UIError``. */ static withCatalog(name: CatalogName | string, fn: () => T): T; /** Catalog-agnostic component factory (escape hatch). */ static component(kind: string, opts?: { id?: string; [key: string]: unknown; }): UIComponent; /** * Lift a flux factory's dict result into a UIComponent so flux nodes * compose with basic-catalog components via .row() / .column() / .add(). */ private static _fluxNodeToComponent; /** LLM-guided mode: inject catalog schema so agent decides UI. */ static auto(opts?: { catalog?: string; fromFlag?: boolean; }): UIAutoSpec; /** Schema-only prompt injection (no auto mode). */ static schema(catalogUri?: string): UISchemaSpec; /** Text content component. */ static text(content: string, opts?: { variant?: "h1" | "h2" | "h3" | "h4" | "h5" | "caption" | "body"; id?: string; }): UIComponent; /** Heading sugar (alias for UI.text with variant='h1'). */ static heading(content: string, opts?: { id?: string; }): UIComponent; /** Image component. */ static image(url: string, opts?: { fit?: "contain" | "cover" | "fill"; variant?: string; id?: string; }): UIComponent; /** Icon component. */ static icon(name: string, opts?: { id?: string; }): UIComponent; /** Video player component. */ static video(url: string, opts?: { id?: string; }): UIComponent; /** Audio player component. */ static audio(url: string, opts?: { description?: string; id?: string; }): UIComponent; /** Horizontal layout. */ static row(children: UIComponent[], opts?: { justify?: string; align?: string; id?: string; }): UIComponent; /** Vertical layout. */ static column(children: UIComponent[], opts?: { justify?: string; align?: string; id?: string; }): UIComponent; /** List layout. */ static list(children: UIComponent[], opts?: { direction?: "horizontal" | "vertical"; align?: string; id?: string; }): UIComponent; /** * Card container. * * Catalog dispatch: * - **basic** (default): wraps a child component in a ``Card``. * - **flux**: emits a ``FluxCard`` with the given flux args (see * ``FluxCardArgs``). When called as ``UI.card(component, {...})`` inside * a flux scope the positional component is ignored and a ``FluxCard`` * is synthesised from the opts. */ static card(): UIComponent; static card(child: UIComponent, opts?: { id?: string; }): UIComponent; static card(args: FluxCardArgs): UIComponent; /** Tabbed interface. */ static tabs(tabs: Array<{ label: string; content: UIComponent; }>, opts?: { id?: string; }): UIComponent; /** Modal dialog. */ static modal(child: UIComponent, opts?: { id?: string; }): UIComponent; /** Divider. */ static divider(opts?: { axis?: "horizontal" | "vertical"; id?: string; }): UIComponent; /** * Button component. * * Catalog dispatch: * - **basic** (default): emits a ``Button`` with a Text child label and * the standard ``variant`` / ``action`` / ``checks`` options. * - **flux**: emits a ``FluxButton``. Accepts either the legacy * ``(label, opts)`` call style (label becomes ``args.label``, ``tone`` * defaulted to ``"primary"``) or a full ``FluxButtonArgs`` object. */ static button(label: string, opts?: { variant?: "default" | "primary" | "borderless"; tone?: "neutral" | "primary" | "danger" | "success"; size?: "sm" | "md" | "lg"; emphasis?: "solid" | "soft" | "outline" | "ghost"; action?: string | Record; checks?: UICheck[]; accessibility?: Record; id?: string; }): UIComponent; static button(args: FluxButtonArgs): UIComponent; /** * Text input field. * * Catalog dispatch: * - **basic** (default): emits a ``TextField`` with ``variant``, * ``bind``, ``checks``, ``value`` — unchanged from prior versions. * - **flux**: emits a ``FluxTextField``. Accepts either the legacy * ``(label, opts)`` call (label is lifted into ``accessibility.label``) * or a full ``FluxTextFieldArgs`` object. */ static textField(label: string, opts?: { value?: string; variant?: "shortText" | "longText" | "number" | "obscured"; type?: "text" | "email" | "password" | "number" | "search" | "tel" | "url"; size?: "sm" | "md" | "lg"; state?: "default" | "error" | "success" | "warning"; placeholder?: string; helper?: string; bind?: UIBinding; checks?: UICheck[]; accessibility?: Record; id?: string; }): UIComponent; static textField(args: FluxTextFieldArgs): UIComponent; /** * Flux badge — compact label for status, counts, tags. Not clickable. * Only meaningful inside ``UI.withCatalog("flux", ...)``. Outside a flux * scope, falls back to a plain ``Text`` component with the label so * basic-catalog surfaces render something sensible. */ static badge(label: string, opts?: Partial): UIComponent; /** * Flux progress indicator. Set ``determinate: true`` with a ``value`` in * 0..100 for known ratios; ``determinate: false`` for indeterminate spin. * Outside a flux scope, falls back to the basic ``Slider`` preview. */ static progress(opts?: Partial): UIComponent; /** * Flux skeleton — loading-state placeholder. ``shape=text`` for paragraph * rows, ``shape=circle`` for avatars, ``shape=rect`` for cards/images. * Outside flux, falls back to a muted Text placeholder. */ static skeleton(opts?: Partial): UIComponent; /** * Flux markdown — prose block rendered from a Markdown source string. * Outside flux, renders as a plain ``Text`` body with the raw source. */ static markdown(source: string, opts?: Partial): UIComponent; /** * Flux link — inline hyperlink. Set ``href`` for navigation *or* * ``action`` for an auth-gated dispatch — never both. * Outside flux, falls back to a plain ``Text`` with the label. */ static link(label: string, opts?: Partial): UIComponent; /** * Flux banner — inline notification row. ``info``/``success`` use * ``role=status``; ``warning``/``danger`` use ``role=alert``. * Outside flux, falls back to a simple two-line ``Column``. */ static banner(opts: { title: string; message: string; } & Partial): UIComponent; /** * Flux stack — layout primitive for arranging children with consistent * spacing. Only meaningful inside a flux scope; outside, falls back to * a ``Column`` with no children (callers add children post-hoc via * ``.add(...)``). */ static stack(opts?: Partial): UIComponent; /** Checkbox component. */ static checkbox(label: string, opts?: { value?: boolean; bind?: UIBinding; checks?: UICheck[]; id?: string; }): UIComponent; /** Choice picker (select / radio). */ static choice(options: Array, opts?: { value?: unknown; label?: string; variant?: "dropdown" | "radio" | "chips"; displayStyle?: string; filterable?: boolean; bind?: UIBinding; checks?: UICheck[]; id?: string; }): UIComponent; /** Slider component. */ static slider(opts?: { max?: number; value?: number; label?: string; min?: number; bind?: UIBinding; checks?: UICheck[]; id?: string; }): UIComponent; /** DateTime input component. */ static dateTime(opts?: { value?: string; enableDate?: boolean; enableTime?: boolean; min?: string; max?: string; label?: string; bind?: UIBinding; checks?: UICheck[]; id?: string; }): UIComponent; /** Required value check. */ static required(msg?: string): UICheck; /** Regex pattern check. */ static regex(pattern: string, msg?: string): UICheck; /** String length check. */ static length(opts: { min?: number; max?: number; msg?: string; }): UICheck; /** Numeric range check. */ static numeric(opts: { min?: number; max?: number; msg?: string; }): UICheck; /** Email format check. */ static email(msg?: string): UICheck; /** String interpolation function. */ static formatString(): Record; /** Number formatting. */ static formatNumber(opts?: { decimals?: number; grouping?: boolean; }): Record; /** Currency formatting. */ static formatCurrency(opts?: { currency?: string; decimals?: number; grouping?: boolean; }): Record; /** Date formatting. */ static formatDate(format?: string): Record; /** Localized pluralization. */ static pluralize(opts: { other: string; zero?: string; one?: string; two?: string; few?: string; many?: string; }): Record; /** Logical AND. */ static and(values: unknown[]): Record; /** Logical OR. */ static or(values: unknown[]): Record; /** Logical NOT. */ static not(): Record; /** Open URL action. */ static openUrl(url: string): Record; /** * Generate a form surface from a field spec or a Zod object schema. * * Two call signatures (auto-detected): * * - **Schema path** — `UI.form(z.object({...}), opts?)`: derives fields, * types, validation checks, and bind paths from the Zod schema. The * dependency on Zod is *optional* (peer dependency). When you pass a * Zod object, this method introspects it via `schema.def.shape` / * `schema.def.checks` (Zod v4 public API). * * - **Legacy path** — `UI.form("title", { fields: [...] })`: explicit * field-spec list. Unchanged from prior versions. * * Throws `A2UIError` when the first argument is neither a Zod object nor a * string. */ static form(schemaOrTitle: unknown, opts?: { title?: string; fields?: Array<{ label: string; bind?: string; type?: string; required?: boolean; }>; submit?: string; submitAction?: string | Record; }): UISurface; /** * Build a typed proxy that returns `UI.bind(path)` instances for every * field declared in a Zod object schema. Nested objects produce nested * proxies — accessing them keeps the JSON-Pointer prefix for free. * * Example: * const Schema = z.object({ email: z.string(), profile: z.object({ age: z.number() }) }); * const paths = UI.paths(Schema); * UI.text_field("Email", { bind: paths.email }); // → { path: "/email", ... } * UI.text_field("Age", { bind: paths.profile.age }); // → { path: "/profile/age", ... } * * Accessing a non-existent field throws A2UIError listing valid keys. */ static paths(schema: unknown): T; /** Detect a Zod object schema via duck-typing the v4 public `def` surface. */ private static _isZodObject; /** Read the `shape` from a Zod object (v4 exposes it on both `.shape` and `.def.shape`). */ private static _zodObjectShape; /** Unwrap optional / nullable wrappers, returning the inner schema. */ private static _unwrapZod; /** Detect optional/nullable wrapper. */ private static _isZodOptional; /** Build a UISurface from a Zod object schema. */ private static _formFromZod; /** Pull `def` off a check (Zod v4 stores it under `_zod.def`). */ private static _checkDef; /** Compute label: prefer schema description, else snake_case → Title Case. */ private static _labelFor; /** Generate a dashboard with metric cards. */ static dashboard(title: string, opts: { cards: Array<{ label: string; bind?: string; value?: string; }>; }): UISurface; /** Generate a confirmation dialog. */ static confirm(message: string, opts?: { yes?: string; no?: string; yesAction?: string | Record; noAction?: string | Record; }): UISurface; /** Generate a data table. */ static table(columns: Array, opts?: { dataBind?: string; id?: string; }): UIComponent; /** Generate a multi-step wizard. */ static wizard(title: string, opts: { steps: Array<{ label: string; content: UIComponent; }>; }): UISurface; } //# sourceMappingURL=ui.d.ts.map