import type { UiCardDefinition } from "./uiCards"; /** * Built-in UI card catalog: chart, table, stat tiles, form, choice, confirm, * diff, plan, and credential-request cards. Declarative specs the model * authors and the host renders — see svg.ts for the dependency-free default * chart renderer. Caps are hard product guards (a model can't render a * 400-row table into a chat bubble). * * Card identity: every spec carries an optional `cardId`. When a host * receives a card whose cardId it has already rendered in the conversation, * it MUST replace that earlier render in place instead of appending a new * card. This is a pure host rendering contract — no loop-side state — and it * is how planCard progresses: the model re-emits the same cardId with * updated step statuses. The field lives here, in the shared spec layer, so * every host implements the same semantics. */ export declare const CHART_TYPES: readonly ["bar", "line", "donut"]; export type ChartType = (typeof CHART_TYPES)[number]; export type ChartSeries = { name: string; values: number[]; }; export type ChartSpec = { type: ChartType; title: string; /** Category labels: x-axis (bar/line) or slice names (donut). */ labels: string[]; /** ≤ 8 series (fixed hue order). Donut charts use exactly one series. */ series: ChartSeries[]; /** Value formatting, e.g. "$" / "%". */ unitPrefix?: string; unitSuffix?: string; /** Optional action buttons rendered under the card (≤ 3). */ actions?: UiAction[]; /** Stable card identity — see the card-identity contract in module docs. */ cardId?: string; }; export type TableSpec = { title?: string; columns: string[]; rows: string[][]; /** Optional action buttons rendered under the card (≤ 3). */ actions?: UiAction[]; /** Stable card identity — see the card-identity contract in module docs. */ cardId?: string; }; export type StatTile = { label: string; value: string; /** Optional change annotation, e.g. "+12% vs last month". */ delta?: string; deltaDirection?: "up" | "down" | "flat"; }; export type StatTilesSpec = { tiles: StatTile[]; actions?: UiAction[]; /** Stable card identity — see the card-identity contract in module docs. */ cardId?: string; }; /** * An action binding on a UI card: a button the host renders under the card * that, on click, invokes one of the HOST'S OWN tools with a model-authored * input. The host decides which tools are click-invokable (approval-gated * tools should queue their normal approval flow, and anything like "approve a * pending action" should be refused outright) and validates the input against * the tool exactly as if the model had called it. */ export type UiAction = { /** Button label, e.g. "Create follow-up task". */ label: string; /** The host tool to invoke, e.g. "create_task". */ tool: string; /** The tool input, fully resolved by the model (real ids, not placeholders). */ input: Record; }; export declare const FORM_FIELD_TYPES: readonly ["text", "textarea", "number", "select", "date", "checkbox", "password"]; export type FormFieldType = (typeof FORM_FIELD_TYPES)[number]; export type FormField = { /** Key the value is submitted under — a valid tool-input property name. */ name: string; label: string; /** * "password" marks a sensitive field: hosts MUST render it masked (an * ``-equivalent) and SHOULD route the submitted * value outside the model loop entirely (e.g. straight to the host's own * secret store) so it never enters the transcript. Password fields never * carry a prefill `value` — parseFormSpec drops it. */ type: FormFieldType; placeholder?: string; required?: boolean; /** Choices — select fields only. */ options?: string[]; /** Prefill (checkbox: "true"/"false"; never present on password fields). */ value?: string; }; /** * An inline form the model renders when it needs several structured inputs * from the member before running a tool. On submit the host merges the field * values into `submit.input` under their field names and invokes `submit.tool` * exactly like a clicked UiAction. */ export type FormSpec = { title: string; description?: string; fields: FormField[]; submit: UiAction; /** Stable card identity — see the card-identity contract in module docs. */ cardId?: string; }; export type ChoiceOption = { /** Stable option id — merged into submit.input on selection. */ id: string; label: string; description?: string; /** Tiny annotation rendered beside the label, e.g. "recommended". */ badge?: string; }; /** * A structured decision card: the member picks one option (or several when * `multi`) and the host merges `{ choice: id }` — or `{ choices: id[] }` — * into `submit.input`, then invokes `submit.tool` exactly like a clicked * UiAction. Same through-loop flow as FormSpec: a choice between * model-authored options is non-secret by definition, so loop-visible * submission is correct here. */ export type ChoiceSpec = { title: string; description?: string; /** ≤ 8 options. */ options: ChoiceOption[]; /** Allow selecting several options (`{ choices: id[] }` on submit). */ multi?: boolean; submit: UiAction; /** Stable card identity — see the card-identity contract in module docs. */ cardId?: string; }; /** * An explicit-consent card for destructive or irreversible actions. * * TRUST CONTRACT: the host must invoke `confirm` ONLY on a real user click * of the confirm button — never programmatically, and never because the * model claims consent was given. Hosts SHOULD mint an unforgeable * server-side confirmation token at click time and require it on the * downstream action, so a model can never fabricate a confirmation: the * token exists only if the click happened. */ export type ConfirmSpec = { title: string; /** What will happen, in plain language (≤ 500 chars). */ consequence: string; confirmLabel: string; cancelLabel?: string; confirm: UiAction; /** Render destructive styling (e.g. a red confirm button). */ danger?: boolean; /** Stable card identity — see the card-identity contract in module docs. */ cardId?: string; }; export type DiffFile = { path: string; /** Unified diff text — DISPLAY data only (the host renders the +/- * coloring); nothing is ever executed or applied from the text itself. */ diff: string; /** The shown diff was cut to fit the display caps. */ truncated?: boolean; }; /** * Proposed file changes for review. Diffs are display data; the actual * change happens through `apply` — a normal UiAction against a host tool * with fully-resolved input. Applying files is destructive, so hosts SHOULD * route `apply` through a click-minted server-side token exactly like * ConfirmSpec. Oversized diffs are truncated by the parser, never rejected: * files beyond 6 drop, and diff bodies are cut to a 400-line total budget * with `truncated: true` set on every file that was cut. */ export type DiffSpec = { title: string; /** ≤ 6 files, ≤ 400 diff lines total across them. */ files: DiffFile[]; apply: UiAction; reject?: UiAction; note?: string; /** Stable card identity — see the card-identity contract in module docs. */ cardId?: string; }; export declare const PLAN_STEP_STATUSES: readonly ["pending", "active", "done", "error"]; export type PlanStepStatus = (typeof PLAN_STEP_STATUSES)[number]; export type PlanStep = { /** Stable step id — keep it identical across re-emits of the same plan. */ id: string; label: string; status: PlanStepStatus; /** One-line progress or error note under the label. */ detail?: string; }; /** * A live multi-step plan. Display-only — no submit action. Progress works * through the card-identity contract: the model re-emits the SAME cardId * with updated step statuses and the host replaces the earlier render in * place, so the member sees one live plan instead of a stack of copies. */ export type PlanSpec = { title: string; /** ≤ 12 steps. */ steps: PlanStep[]; note?: string; /** Stable card identity — see the card-identity contract in module docs. */ cardId?: string; }; export type CredentialKey = { /** Environment variable name, e.g. "STRIPE_SECRET_KEY". */ key: string; /** Human label, e.g. "Stripe secret key". */ label?: string; /** Where to obtain the credential (provider dashboard URL). */ docsUrl?: string; /** Mask and never echo. Defaults to TRUE — parseCredentialSpec normalizes * it to an explicit boolean so hosts never have to guess. */ secret?: boolean; /** Already configured on the host — render as set, offer replace. */ isSet?: boolean; }; /** * A credential-request card. Deliberately has NO submit UiAction — the type * makes through-loop submission impossible. The host UI collects the values * and stores them OUTSIDE the model loop (its own .env or secret store), * then sends a names-only continuation message ("STRIPE_SECRET_KEY was * set") so the model can proceed. Values never enter the transcript in * either direction: parseCredentialSpec drops any value-like field a model * attaches (the password-prefill-drop precedent), and hosts never echo * stored values back. */ export type CredentialSpec = { title: string; /** ≤ 8 keys. */ keys: CredentialKey[]; /** Stable card identity — see the card-identity contract in module docs. */ cardId?: string; }; export declare const CHART_MAX_SERIES = 8; export declare const CHART_MAX_POINTS = 24; export declare const TABLE_MAX_COLUMNS = 8; export declare const TABLE_MAX_ROWS = 30; export declare const STAT_TILES_MAX = 6; export declare const UI_ACTIONS_MAX = 3; export declare const FORM_MAX_FIELDS = 8; export declare const FORM_SELECT_MAX_OPTIONS = 12; export declare const CHOICE_MAX_OPTIONS = 8; export declare const CONFIRM_CONSEQUENCE_MAX_CHARS = 500; export declare const DIFF_MAX_FILES = 6; export declare const DIFF_MAX_LINES = 400; export declare const PLAN_MAX_STEPS = 12; export declare const CREDENTIAL_MAX_KEYS = 8; export declare const CARD_ID_MAX_CHARS = 64; /** Validate a spec's optional action bindings; undefined when none/invalid. * Malformed entries drop individually — a bad button never sinks the card. */ export declare const parseUiActions: (value: unknown) => UiAction[] | undefined; export declare const parseChartSpec: (input: unknown) => ChartSpec | null; export declare const parseTableSpec: (input: unknown) => TableSpec | null; export declare const parseStatTilesSpec: (input: unknown) => StatTilesSpec | null; export declare const parseFormSpec: (input: unknown) => FormSpec | null; export declare const parseChoiceSpec: (input: unknown) => ChoiceSpec | null; export declare const parseConfirmSpec: (input: unknown) => ConfirmSpec | null; export declare const parseDiffSpec: (input: unknown) => DiffSpec | null; export declare const parsePlanSpec: (input: unknown) => PlanSpec | null; export declare const parseCredentialSpec: (input: unknown) => CredentialSpec | null; /** render_chart — bar / line / donut from data you already have. */ export declare const chartCard: UiCardDefinition; /** render_table — a compact data table. */ export declare const tableCard: UiCardDefinition; /** render_stat_tiles — a row of headline numbers. */ export declare const statTilesCard: UiCardDefinition; /** render_form — collect structured inputs, then run a bound tool on submit. */ export declare const formCard: UiCardDefinition; /** render_choice — a structured decision instead of "reply 1 or 2". */ export declare const choiceCard: UiCardDefinition; /** render_confirm — explicit consent for destructive/irreversible actions. */ export declare const confirmCard: UiCardDefinition; /** render_diff — proposed file changes for review before applying. */ export declare const diffCard: UiCardDefinition; /** render_plan — a live multi-step plan, updated in place via cardId. */ export declare const planCard: UiCardDefinition; /** request_credentials — ask for env values WITHOUT a through-loop submit. */ export declare const credentialCard: UiCardDefinition; /** The built-in catalog, ready for createUiCards. */ export declare const BUILTIN_UI_CARDS: readonly [UiCardDefinition, UiCardDefinition, UiCardDefinition, UiCardDefinition, UiCardDefinition, UiCardDefinition, UiCardDefinition, UiCardDefinition, UiCardDefinition];