@adonis-agora/agent
Version:
Governed, durable-backed AI agent (chat + tool-calling + governance) for AdonisJS — part of the Agora ecosystem.
133 lines • 7.7 kB
TypeScript
import type { ComponentChannels } from './channels.js';
import { type GenuiValidation, type JsonSchema, type JsonSchemaValidator, type PropsSchema } from './schema.js';
/**
* One component a server may push into a conversation. Data only — how it LOOKS is each app's own
* renderer, looked up by {@link name}. The same definition serves the model (description + props
* schema), the server (validation), text-only channels ({@link fallbackText}) and the client
* (validation before rendering).
*/
export interface ComponentDefinition<P = Record<string, unknown>> {
/** Registry key, e.g. `DataTable`. What a `ui` frame's `component` names. */
name: string;
/** Human label: "Data table". */
title: string;
/** Shown to the model: what the component is for and when to use it. */
description: string;
/** The props schema: a Standard Schema (Zod, Valibot, ArkType) or a JSON Schema object. */
props: PropsSchema;
/** Portable normalized props schema. Required when input transformations are not idempotent. */
outputProps?: PropsSchema;
/**
* The component takes nested elements (a layout: `Stack`, `Card`). Only meaningful in tree mode,
* where a node's `children` are validated against the catalog too. Outside tree mode such a
* component has nothing to hold, so it gets no `ui__show_*` tool and the generic show tool does
* not offer it.
*/
children?: boolean;
/**
* Plain text / Slack mrkdwn rendering of these props, for a channel that cannot draw the
* component. Absent → {@link componentToText} prints the props as JSON. An empty string renders
* nothing (a layout with nothing of its own to say); in a tree its children still render.
*/
fallbackText?(props: P): string;
/**
* Pushed by the server (e.g. an approval card), never offered to the model. Excluded from
* {@link catalogToModelText} and from the tool factories.
*/
internal?: boolean;
/**
* Schema version of {@link props}. Stamped on every `ui` frame the component is pushed with, so a
* client can keep rendering messages persisted under an older shape.
*/
version?: number;
/**
* How this component appears in a tree the model is still writing (tree mode with streaming
* previews — see `GenuiToolsOptions.streaming`). Absent → the tree's default.
*
* - `'partial'`: drawn as soon as its type is known, its props filling in as they arrive (the
* node is flagged `incomplete` until its object closes).
* - `'complete'`: held back until its whole subtree has arrived — the node is sent as a
* placeholder (`held`, no props, no children) and drawn once it closes. For a component that
* cannot draw half its data: a chart, a map.
*/
streaming?: GenuiStreaming;
/**
* What a preview may show of props the model is still writing (a `streaming: 'partial'` node, or
* a per-component call being previewed): drop what must not be drawn or run half written. Called
* with the raw partial props and the parser's view of them. Absent → the props as they are.
*/
partialProps?(props: Record<string, unknown>, input: {
isOpen(container: object): boolean;
pendingMember(container: object): unknown;
}): Record<string, unknown>;
/**
* What the component is on a channel the server draws for, by channel name: `whatsapp: (props) =>
* ({ text, buttons })`, `telegram: …`, `email: (props) => ({ html })` (see `ChannelNativeMessage`).
* Without one the channel sends {@link fallbackText}. `false` → never offered on that channel.
*/
channels?: ComponentChannels<P>;
/**
* Checks beyond the props schema, run on the server once the props are valid — the sandbox parses
* its code here. An `error` refuses the call (the model gets its message and retries); a
* `warning` lets it through and is handed back with the result.
*/
check?(props: P): GenuiCheck[] | Promise<GenuiCheck[]>;
}
/** One finding of a {@link ComponentDefinition.check}. */
export interface GenuiCheck {
severity: 'error' | 'warning';
/** What kind of mistake it is (what telemetry counts): `syntax`, `bridge`, `unknown-component`, … */
category: string;
/** Short, with where and the fix: "jsx line 12:5: `flippy.send` — the bridge is `agent.send(payload)`". */
message: string;
}
/** The second argument of {@link defineComponent}: what a component is on each channel. */
export interface DefineComponentExtras<P> {
channels?: ComponentChannels<P>;
}
/** How a tree node appears while the model writes it ({@link ComponentDefinition.streaming}). */
export type GenuiStreaming = 'partial' | 'complete';
/** Component names: an identifier a registry key, a tool name and a snake_case slug can all be derived from. */
export declare const COMPONENT_NAME: RegExp;
/** Declare a component. Validates the name and returns the definition unchanged (typed). */
export declare function defineComponent<P = Record<string, unknown>>(definition: ComponentDefinition<P>, extras?: DefineComponentExtras<P>): ComponentDefinition<P>;
export interface CatalogOptions {
/** How JSON Schema props are checked. Default: {@link builtinJsonSchemaValidator}; pass `ajvValidator(new Ajv())` for full JSON Schema. */
jsonSchemaValidator?: JsonSchemaValidator;
}
/** An immutable set of component definitions, looked up by name. */
export interface Catalog {
readonly components: readonly ComponentDefinition<unknown>[];
readonly validator: JsonSchemaValidator;
get(name: string): ComponentDefinition<unknown> | undefined;
has(name: string): boolean;
/** The components a model may be offered (every non-`internal` one). */
modelComponents(): ComponentDefinition<unknown>[];
/** Validate `props` for `component`. An unknown component is a validation failure, not a throw. */
validate(component: string, props: unknown): Promise<GenuiValidation<Record<string, unknown>>>;
/**
* {@link validate} without waiting — `undefined` only when the component's Standard Schema
* validates asynchronously. An unknown component is a failure, as in `validate`.
*/
validateSync(component: string, props: unknown): GenuiValidation<Record<string, unknown>> | undefined;
/** The component's props as JSON Schema, when it can be derived (see {@link toJsonSchema}). */
jsonSchemaFor(component: string): JsonSchema | undefined;
/** A new catalog with these components added (a later definition replaces an earlier one of the same name). */
extend(components: readonly ComponentDefinition<unknown>[]): Catalog;
}
/**
* Collect component definitions into a {@link Catalog}. Names must be unique; to override a
* definition (e.g. a builtin), use {@link Catalog.extend}.
*/
export declare function defineCatalog(components: readonly ComponentDefinition<unknown>[], options?: CatalogOptions): Catalog;
/**
* The model components that stand on their own: every one but a layout (`children: true`). Outside
* tree mode nothing can be nested, so a layout could only be pushed empty — it gets no
* `ui__show_*` tool and is not offered by the generic show tool.
*/
export declare function standaloneComponents(catalog: Catalog): ComponentDefinition<unknown>[];
/** `DataTable` → `data_table`, `KPICards` → `kpi_cards`. */
export declare function toSnakeCase(name: string): string;
/** The per-component tool name: `ui__show_data_table` with the default prefix. */
export declare function toolNameFor(component: string, prefix?: string): string;
//# sourceMappingURL=catalog.d.ts.map