/** How prominently a node surfaces in ancestor `-h` listings. Default 'normal'. */ export type ManifestTier = 'normal' | 'common' | 'important'; /** Root-entry prose for a top-level branch — what every agent reads before it * has engaged the command at all. Required on a plugin's top-level branch. */ export interface ManifestRootEntry { concept: string; description: string; whenToUse: string; } /** One declared output field of a leaf's result. */ export interface ManifestField { name: string; type: string; required: boolean; /** Inline semantic constraint — bounds, enum, token caps. */ constraint: string; } /** How a local file named by a `path` param is encoded into the request: 'text' * as UTF-8, 'base64' as the base64 of its raw bytes. The path string itself * never crosses the wire. */ export type ManifestFileEncoding = 'text' | 'base64'; export interface ManifestPositionalParam { kind: 'positional'; name: string; /** Display hint only; always parsed as string. */ type?: 'string' | 'path'; required: boolean; constraint: string; /** Collect every remaining positional token into an array, in argv order. * Only an `in: 'body'` REST mapping can carry an array. */ repeatable?: boolean; /** Valid only on a `path` param. */ encoding?: ManifestFileEncoding; /** See {@link ManifestFlagParam.defaultFromEnv}. */ defaultFromEnv?: string; } export interface ManifestFlagParam { kind: 'flag'; name: string; /** 'bool' flags take no value — presence is true. */ type: 'string' | 'int' | 'bool' | 'path' | 'enum'; /** Required, and only valid, when type is 'enum'. */ choices?: string[]; required: boolean; constraint: string; default?: string | number | boolean; /** Repeat the flag to accumulate an array value. Valid only on string/int/enum, * only with an `in: 'body'` REST mapping, and never alongside `default`. */ repeatable?: boolean; /** Valid only on a `path` flag. */ encoding?: ManifestFileEncoding; /** UPPER_SNAKE_CASE environment variable on the CALLING machine whose value * fills this param when the caller omits it. An env-sourced value counts as * SUPPLIED — it satisfies `required` and ships on the wire — unlike a static * `default`, which does neither. Valid only on string/path params, never * alongside `default` or `repeatable`. */ defaultFromEnv?: string; } /** Raw stdin content blob — piped text, not parsed as JSON. */ export interface ManifestStdinParam { kind: 'stdin'; name: string; required: boolean; constraint: string; } /** `--context-file PATH`: reads and JSON-parses the file at PATH. */ export interface ManifestContextFileParam { kind: 'context-file'; name: string; required: boolean; constraint: string; /** Description of the expected JSON shape. */ shape?: string; } export type ManifestInputParam = ManifestPositionalParam | ManifestFlagParam | ManifestStdinParam | ManifestContextFileParam; export type RestMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'; export type RestParamPlacement = 'path' | 'query' | 'body' | 'header'; export interface RestParamMapping { in: RestParamPlacement; /** Rename for query/body; required for header; forbidden for path. */ as?: string; } export interface RestMapping { method: RestMethod; /** Absolute path template; each `{param}` placeholder names an `in: 'path'` param. */ path: string; /** Default false. true means the response is an NDJSON stream relayed verbatim. */ streaming?: boolean; /** Constant body fields merged into the request body verbatim (e.g. the `op` * discriminator on a single-endpoint invoke surface) — never sourced from a * declared param, and forbidden on GET. */ body?: Record; /** When set, every `in: 'body'` param value nests under this key instead of * sitting top-level (`bodyRoot: 'args'` → `{ args: { name, url } }`); * `body` constants stay top-level regardless. Forbidden on GET. */ bodyRoot?: string; /** Keyed by declared param name; every declared param appears exactly once. */ params: Record; } export interface ManifestTimeouts { connectMs?: number; requestMs?: number; streamIdleMs?: number; } /** Exec transport only: forward every argv token after this branch to an * external binary instead of parsing children. `bin` is either a bare PATH * command or a plugin-root-relative executable path. A passthrough branch is * childless by construction; an HTTP manifest rejects it, because an HTTP * transport must not name a local binary to execute. */ export interface ManifestPassthrough { bin: string; installHint: string; } export interface ManifestLeafBase { kind: 'leaf'; name: string; description: string; whenToUse: string; tier?: ManifestTier; summary: string; params: ManifestInputParam[]; output: ManifestField[]; /** Non-empty; `["None. Read-only."]` for a read-only leaf. Read-only, so a * server assembling a manifest may hand over a frozen or `as const` list. */ effects: readonly string[]; } /** Exec-transport leaf. */ export interface ManifestExecLeaf extends ManifestLeafBase { outputKind: 'object'; } /** HTTP-transport leaf; `outputKind` derives from `rest.streaming`. */ export interface ManifestHttpLeaf extends ManifestLeafBase { rest: RestMapping; } export type ManifestLeaf = ManifestExecLeaf | ManifestHttpLeaf; export interface ManifestBranch { kind: 'branch'; name: string; description: string; whenToUse: string; tier?: ManifestTier; /** Required on a top-level branch, forbidden on a nested one. */ rootEntry?: ManifestRootEntry; /** Allows the nearest repository fragment to contribute children below this * top-level branch. */ extensible?: true; summary: string; model?: string; /** Exec dialect only, and the type says so rather than leaving it to the * runtime validator: an HTTP-transport manifest naming a local binary to run * is the one shape a served manifest must never be able to express. `never` * on the HTTP leaf dialect makes `passthrough: {...}` a compile error in a * `ManifestBranch`, and the conditional distributes over * the default union so a plain `ManifestBranch` still accepts it. */ passthrough?: L extends ManifestExecLeaf ? ManifestPassthrough : never; children: ManifestNode[]; } /** A branch or a leaf. The parameter fixes which leaf dialect the whole subtree * may use, so an HTTP manifest cannot smuggle an exec leaf into a child slot. */ export type ManifestNode = ManifestBranch | L; /** One mount point in the manifest's self-contained forest. */ export interface ManifestMount { /** `[]` mounts `node` as a new top-level command; a non-empty path names a * branch this manifest already contributes or an extensible core branch. * `human` is currently the only extensible core branch. */ parent: string[]; node: ManifestNode; } /** * A whole `commands.json` for an HTTP-transport plugin whose endpoint and auth * live in the bundle's `bundle.json` rather than the manifest. */ export interface HttpPluginCommandManifest { schemaVersion: 1; /** Overrides the registration endpoint as the base for every leaf's REST path. */ baseUrl?: string; timeouts?: ManifestTimeouts; mounts: ManifestMount[]; /** Core command path (space-joined, e.g. "cron add") → product addendum * appended to that command's help, rendered by crtr as an attributed * `` block after the core body. Append-only by * contract: an addendum adds product meaning beneath substrate help, never * replaces it. A key naming no core command path fails validation at guest * install. */ helpAddenda?: Record; } /** * The one field a plugin's HTTP backend adds to an error envelope to say the * client parsed this call from an out-of-date description of its commands. * * crtr acts on it by refetching that plugin's bundle and re-running the * caller's ORIGINAL argv against the refreshed command tree, exactly once. Two * preconditions follow from that, and a server that cannot meet both must not * set the field: * * 1. The manifest the server serves at its bundle endpoint must already * describe the operation it is complaining about. A refetch that hands back * the same description turns the retry into a second identical failure. * 2. The original call must be safe to send again. crtr replays the argv, not * the request, but a leaf that already committed a side effect before the * backend rejected the op would commit it twice. * * Declared here, in the format both sides compile against, so the field name * has one owner: rename it and every reader and writer fails to build. A type * rather than a value — a const would force a CJS consumer to `require()` an * ESM module. */ export interface ManifestStaleEnvelope { manifest_stale?: true; }