/** * Zod schema for {@link DataContract} — the canonical wire shape for * agent-authored contract declarations. * * ## Why this file exists * * Output-side seams that type-narrow contract on the wire — * `renderOutputSchema.contract` and the various `decision` echoes — use * `z.custom()` because they trust the shape (it * originates from internal server state). * * The input seam is different: agents author contract on * `story.contract` and the handler MUST plumb them to the generator. * `z.custom()` does NOT work on input schemas — the * MCP SDK serializes input schemas as JSON Schema for `tools/list`, * and `z.custom()` has no JSON-Schema representation (it's a * TypeScript-only escape hatch). The narrow alternative * (`z.record(z.string(), z.unknown())`) erases the type and forces * `as DataContract` casts downstream, which violates the project's * Zero Workarounds Policy + Strict Typing First principle. * * The fundamental fix is this file: a real zod schema mirroring the * `DataContract` interface field-for-field. Both the protocol's * `handshakeInputSchema` and the OSS handler's `inputSchema` build * their `contract?` field from `dataContractSchema`, the type derives * via `z.infer`, and JSON-Schema serialization for MCP `tools/list` * advertises the contract surface to agents. * * ## Shape source of truth * * The TS interface in `../types/data-contract.ts` remains the * declared source of truth (consumers import the type). This file's * schemas are a structural mirror — `dataContractSchema` is typed * `z.ZodType` so any drift between schema and * interface fails compile. A future cleanup can flip the relationship * (TS via `z.infer`), but that's a broader refactor. * * ## JsonSchema posture * * Every nested `schema: JsonSchema` field on contract entries * (PropEntry, ActionEntry, StreamChannelEntry, ContextEntry, ...) * accepts `jsonSchemaSchema` — a permissive `z.object` over the * known JSON Schema draft-07 subset {@link JsonSchema} declares, * with `passthrough()` for fields the shape doesn't enumerate. We * deliberately do NOT enforce JSON Schema's full grammar at this * layer — that work belongs in * `@ggui-ai/protocol/validation/schema-subset` and runs at * render-time + blueprint-registration-time as the F4 schema * compatibility checker. Agents authoring malformed schemas surface * at that pass with a named violation reason; this layer's job is * just to accept the contract and pass it to the generator. */ import { z } from 'zod'; import type { DataContract, JsonValue, JsonSchema, JsonObject } from '../types/data-contract.js'; /** * Recursive {@link JsonValue} — string | number | boolean | null | * array | object. All fields on contract entries that carry default * values, examples, or arbitrary JSON payloads use this. */ export declare const jsonValueSchema: z.ZodType; /** A JSON object — the protocol's `JsonObject`, never a bare `Record`. */ export declare const jsonObjectSchema: z.ZodType; export declare const jsonSchemaSchema: z.ZodType; /** * {@link PropEntry} — per-prop metadata in a {@link PropsSpec}. * * Shape: `{schema: {type:'string', ...}, required?, default?, ...}`. * The JSON Schema NEVER sits flat at the entry level — every entry's * schema lives in `.schema`. Authors writing `{type:'string'}` instead * of `{schema: {type:'string'}}` will hit a shape error at render time. */ export declare const propEntrySchema: z.ZodObject<{ description: z.ZodOptional; schema: z.ZodType>; required: z.ZodOptional; default: z.ZodOptional>>; example: z.ZodOptional>>; sourceTool: z.ZodOptional; }, z.core.$strict>; /** {@link PropsSpec} — wrapper `{description?, properties}` over the per-prop map. */ export declare const propsSpecSchema: z.ZodObject<{ description: z.ZodOptional; properties: z.ZodRecord; schema: z.ZodType>; required: z.ZodOptional; default: z.ZodOptional>>; example: z.ZodOptional>>; sourceTool: z.ZodOptional; }, z.core.$strict>>; }, z.core.$strict>; /** * {@link ActionEntry} — per-action metadata in an {@link ActionSpec}. * * Actions are agent-routed gestures; no dispatch discriminator. Optional * `nextStep` hints at the agent's intended next tool call (must resolve * to an `agentCapabilities.tools[*]` key on the same contract — * cross-ref enforced by the `CTR_REF_NEXT_STEP` linter). * * Anti-pattern: do NOT write `dispatch: {kind: 'tool', tool: '...'}` — * that vocabulary is retired. Use a flat optional `nextStep: ''`. */ export declare const actionEntrySchema: z.ZodObject<{ description: z.ZodOptional; label: z.ZodString; schema: z.ZodOptional>>; example: z.ZodOptional>>; icon: z.ZodOptional; confirm: z.ZodOptional; oneShot: z.ZodOptional; nextStep: z.ZodOptional; }, z.core.$strict>; /** {@link ActionSpec} — flat `Record`. */ export declare const actionSpecSchema: z.ZodRecord; label: z.ZodString; schema: z.ZodOptional>>; example: z.ZodOptional>>; icon: z.ZodOptional; confirm: z.ZodOptional; oneShot: z.ZodOptional; nextStep: z.ZodOptional; }, z.core.$strict>>; /** {@link StreamChannelEntry} — per-channel metadata in a {@link StreamSpec}. */ export declare const streamChannelEntrySchema: z.ZodObject<{ description: z.ZodOptional; schema: z.ZodType>; example: z.ZodOptional>>; mode: z.ZodOptional>; replay: z.ZodOptional>; complete: z.ZodOptional; source: z.ZodOptional>>>; }, z.core.$strict>>; }, z.core.$strict>; /** {@link StreamSpec} — flat `Record`. */ export declare const streamSpecSchema: z.ZodRecord; schema: z.ZodType>; example: z.ZodOptional>>; mode: z.ZodOptional>; replay: z.ZodOptional>; complete: z.ZodOptional; source: z.ZodOptional>>>; }, z.core.$strict>>; }, z.core.$strict>>; /** {@link ContextEntry} — per-slot metadata in a {@link ContextSpec}. */ export declare const contextEntrySchema: z.ZodObject<{ description: z.ZodOptional; schema: z.ZodType>; default: z.ZodOptional>>; debounceMs: z.ZodOptional; example: z.ZodOptional>>; }, z.core.$strict>; /** {@link ContextSpec} — flat `Record`. */ export declare const contextSpecSchema: z.ZodRecord; schema: z.ZodType>; default: z.ZodOptional>>; debounceMs: z.ZodOptional; example: z.ZodOptional>>; }, z.core.$strict>>; /** {@link AgentToolEntry} — per-tool metadata in an {@link AgentCapabilitiesSpec}. */ export declare const agentToolEntrySchema: z.ZodObject<{ serverInfo: z.ZodOptional; }, z.core.$strict>>; toolInfo: z.ZodObject<{ inputSchema: z.ZodType>; description: z.ZodOptional; outputSchema: z.ZodOptional>>; }, z.core.$strict>; usage: z.ZodOptional; example: z.ZodOptional>; output: z.ZodType>; }, z.core.$strict>>; }, z.core.$strict>; /** {@link AgentCapabilitiesSpec} — wrapper over the per-tool map. */ export declare const agentCapabilitiesSpecSchema: z.ZodObject<{ tools: z.ZodRecord; }, z.core.$strict>>; toolInfo: z.ZodObject<{ inputSchema: z.ZodType>; description: z.ZodOptional; outputSchema: z.ZodOptional>>; }, z.core.$strict>; usage: z.ZodOptional; example: z.ZodOptional>; output: z.ZodType>; }, z.core.$strict>>; }, z.core.$strict>>; }, z.core.$loose>; /** * Single source of truth for the `requires[]` field shape on gadget * descriptors. The wire-permissive `gadgetDescriptorSchema`, the * strict `strictGadgetDescriptorSchema`, AND the author-facing * `@ggui-ai/artifact-manifest#gadgetManifestSchema` all need an * identical `z.array(z.string().regex(PUBLIC_ENV_APP_KEY_RE))`. * Exported here so any future tightening (e.g., cap count, dedupe * refinement) lives in one place. * * Entries are App.publicEnv key names — `GGUI_PUBLIC_APP_*`. Wrappers * that declare a `requires` key must have a corresponding App-side * publicEnv value at render time (gate: `assertPublicEnvSatisfied`). */ export declare const gadgetRequiresSchema: z.ZodArray; /** * SRI hash format for gadget bundles. Registry install writes * `bundleSri` in this shape; iframe-runtime emits it verbatim into * the `