import { z } from "zod"; import type { DefaultContext } from "./context.js"; import { type InferParams, type ParamsLike } from "./params.js"; /** * A registered query: schema-typed params/return shape, optional access predicate * and summary metadata, and the runtime function the executor calls. The `query` * function is whatever the user wires up — Drizzle, Prisma, raw SQL, in-memory — * as long as it satisfies the `(params) => Promise` signature. * * The `returns` schema is the source of truth for `$bind` resolution during plan * validation — the runtime output of `query` is never inspected by core. */ export interface CarteEntry

{ id: string; description: string; exampleQuestions?: string[]; params: P; returns: R; access?: (ctx: TCtx) => boolean; /** * Optional human-facing title template rendered by the framework when this * entry is shown in a UI panel. Supports typed slot interpolation: each * `{paramName}` placeholder is filled with the corresponding param value * the LLM emitted (after Zod parsing). The LLM never authors the literal * string — it only fills slots, preserving the no-paraphrase contract. * * The renderer reads this template via `useInjectedTitle(panelIndex)` and * passes the rendered string as the `title` prop on every component. * Components MUST NOT receive `title` from the LLM-emitted plan; the * catalog excludes it from each component's prop schema. */ titleTemplate?: string; /** * Optional callback that returns small, prompt-time metadata about this * entry — counts, ranges, default values, enum lists, freshness timestamps. * The return value is rendered verbatim into the LLM's prompt via * `JSON.stringify`, so it lives on the bounded surface. * * **Security contract** (the renamed-from-`summaryStats` shape, v0.2.1): * * 1. The function takes NO arguments. There is no request context. The * same value is computed for every user, every role, every tenant — * role-conditional hints are a denormalization smell and should be * modeled as separate entries with different `access` predicates. * 2. The function MUST be deterministic — calling it twice in the same * process MUST return equal values. The framework cannot statically * prove this in JavaScript, but enabling `CARTE_VERIFY_STATIC_HINTS` * causes `generatePrompt` to call the function twice and assert * equality, catching the "I'll just memoize a query" foot-gun in CI. * 3. The return value is restricted to `StaticHints` — a flat record of * primitives and primitive arrays. Row data, sample rows, arrays of * objects, and anything derived from query results at runtime are * structurally rejected at prompt-generation time. * * Together these mean the value cannot exfiltrate runtime data: it is * authoring-time-shaped, deterministic, and structurally bounded. */ staticHints?: () => StaticHints | Promise; query: (params: InferParams

) => Promise>; } export type Carte = Record>; /** * A single value permitted inside a `staticHints` payload. Deliberately * narrow: primitives and arrays of primitives only. Restricting the shape * structurally rules out the foot-gun of an author returning row-shaped * data (e.g. `{ recentUsers: [{ id, email }, ...] }`) and silently * leaking it through the prompt. */ export type StaticHintValue = string | number | boolean | null | undefined | ReadonlyArray; /** * Shape `staticHints` callbacks must return. A flat record of primitives * and primitive arrays — counts, ranges, defaults, enum lists, freshness * timestamps. The runtime guard in `generatePrompt` rejects payloads that * violate this shape. * * The contract is "authoring-time, deterministic, structurally bounded" — * see the field-level docs on `CarteEntry.staticHints` for the full * security rationale, and `skills/carte/references/static-hints.md` for * authoring guidance. */ export type StaticHints = Readonly>; /** * Indexes carte entries by `id`, verifies uniqueness, and enforces * **Invariant 1** for entries that haven't already been through `defineEntry`. * * `defineEntry` is the recommended path (it anchors TypeScript inference) and * already runs `assertStaticSchema` on its argument; entries it returns are * frozen, so we re-check only entries that arrive raw. The frozen-skip is an * optimization — running the check twice is correct, just wasted work. */ export declare function defineCarte(entries: ReadonlyArray>): Carte; /** * Identity helper that anchors TypeScript's contextual typing so the `query` * callback's params and return are inferred from the entry's `params` and * `returns` schemas in the same object literal. * * Without this, writing the entry literal directly inside `defineCarte([...])` * widens the entry to `CarteEntry` and `params` becomes * `unknown`. Wrapping with `defineEntry({...})` introduces a generic inference * point so destructuring `({ limit })` is typed as `number`. * * Also enforces **Invariant 1** (security): `params` and `returns` must be * Zod schemas declared at authoring time, not derived from runtime values. * The check is best-effort — it catches the obvious foot-guns (non-Zod * objects, `z.lazy(() => fresh-schema-each-call)`) but cannot prove general * staticness. Treat it as a guard, not a security boundary; the contract is * enforced by code review, with the runtime check as a backstop. */ export declare function defineEntry

(entry: CarteEntry): CarteEntry; //# sourceMappingURL=carte.d.ts.map