/** * @license * Copyright 2026 Steven Roussey * SPDX-License-Identifier: Apache-2.0 */ import type { WebCommandNode } from "./commandTree"; /** * What a downstream package says ABOUT a command or a field it already has. * * The other seams contribute new surface — a panel, a widget, a schema. This * one annotates surface that already exists, which is what a commander-based * CLI needs: `sec query facts ` declares a positional string, and nothing * in commander can say that the string is a CIK, that a picker exists for it, * or that `db reset` drops tables. Every field of an annotation is optional and * additive, so a command nobody annotates renders exactly as it does today. */ /** Tones a badge or a status line can carry. Rendered, never interpreted. */ export type WebTone = "ok" | "warn" | "fail" | "info" | "idle"; /** * What running this command costs, in the terms an operator weighs before * pressing a button they cannot take back. * * `ai` spends model quota, `network` goes out to a rate-limited third party, * `slow` runs longer than someone will sit and watch, `writes` changes stored * data, and `destructive` destroys some of it. They compose: a backfill is * every one of them at once. */ export declare const COMMAND_BADGES: readonly ["ai", "network", "slow", "writes", "destructive"]; export type WebCommandBadge = (typeof COMMAND_BADGES)[number]; /** * One sibling an `all`-style command runs, in the position it runs it. * * `name` is the sibling's own command name, as the tree shows it — not a path: * an `all` runs what sits beside it, and nothing else can be named here. */ export interface WebRunsMember { readonly name: string; /** * The condition, in one phrase, when this member does not run every time — * `"only with --download-docs"`, `"unless --skip-ingest"`. Undefined means it * always runs. */ readonly when?: string; } export interface WebCommandAnnotation { /** * Command path to match. A `"*"` segment matches exactly one segment and a * trailing `"**"` matches the rest, so `["version", "**"]` covers a group * without restating its leaves. */ readonly path: readonly string[]; /** Package name, so an annotation says who owns it. */ readonly source: string; readonly badges?: readonly WebCommandBadge[]; /** One line shown above the form: what this run will actually do. */ readonly note?: string; /** * Text of a confirmation the page requires before it will start a run. * * Reserved for a command whose damage survives the run — dropping a version * slot, resetting a database. A run that merely costs money says so with the * `ai` badge instead; a dialog on every extraction is a dialog nobody reads. */ readonly confirm?: string; /** * The siblings this command runs, in the order it runs them. * * Declared on the `all` itself and stamped onto both sides by * {@link annotateCommandTree}, which is what keeps the two readings of one * fact from drifting: the members are told which step of which `all` they * are, and the `all` is told which siblings it leaves out. * * That last half is the reason this exists. `all` reads as "everything * listed here" and routinely is not — `sync all` skips the ad-hoc sweeper * beside it — and commander carries nothing that says so, so the console * offered a button whose scope could only be learned by reading the source. */ readonly runs?: readonly WebRunsMember[]; } export interface WebFieldAnnotation { /** * The widget hook. Names a `WebFieldWidget` format, which is how a positional * argument gets the picker a schema field gets from its own `format`. */ readonly format?: string; readonly label?: string; readonly description?: string; readonly choices?: readonly string[]; readonly placeholder?: string; /** Moves a field behind the fold, or pulls one out from behind it. */ readonly advanced?: boolean; /** * The field takes a comma-separated list, so picking from the widget appends * rather than replaces. `--models` names several models; `--cik` names one. */ readonly multiple?: boolean; } export interface CommandFieldAnnotations { /** Same matching rules as {@link WebCommandAnnotation.path}. */ readonly path: readonly string[]; readonly source: string; /** Keyed by field key: an argument's name, or an option's long flag. */ readonly fields: Readonly>; } /** * Whether a pattern matches a path, and how specifically. * * Returns the number of literal segments matched, or -1 for no match, so the * caller can apply the general annotation before the particular one and let * the particular one win. */ export declare function matchPathSpecificity(pattern: readonly string[], path: readonly string[]): number; export declare function registerCommandAnnotation(annotation: WebCommandAnnotation): void; export declare function registerCommandFieldAnnotations(annotations: CommandFieldAnnotations): void; /** The badges, note, confirmation and run order that apply to one command path. */ export declare function resolveCommandAnnotation(path: readonly string[]): { readonly badges: readonly WebCommandBadge[]; readonly note: string | undefined; readonly confirm: string | undefined; readonly runs: readonly WebRunsMember[] | undefined; }; /** The annotations for one command's fields, keyed by field key. */ export declare function resolveFieldAnnotations(path: readonly string[]): ReadonlyMap; /** * Decorates a command tree with its annotations, in place of the caller * walking it. Applied where the tree is served rather than where it is built, * so `buildCommandTree` stays a pure reading of the commander program. */ export declare function annotateCommandTree(nodes: readonly WebCommandNode[]): readonly WebCommandNode[]; export declare function resetWebAnnotationsForTesting(): void;