import type { LexiconPlugin } from "../lexicon.js"; /** * The lexicon command-group seam (chant #1078). * * A lexicon may contribute one CLI verb group, mounted under `chant * ` (e.g. `chant kube get`). Core's only job is to find the group and * call the matched verb's handler — it never inspects, validates, or * special-cases what a verb does. That is the whole point: `get -o wide -l * app=x --field-selector` is Kubernetes vocabulary, not something core could * generalize even if it tried (see #1078's motivating case, consumed by * #1079's `chant kube`). * * This is a DIFFERENT shape from `LexiconPlugin.emulator` (#920): the * emulator capability is DATA that core itself aggregates across every * configured lexicon (`chant emulator up --all` loops every plugin with an * `emulator`). A command group is BEHAVIOR owned end-to-end by one lexicon — * core dispatches to it wholesale and never loops or merges across plugins. * The two capabilities are not layers of the same thing; migrating * `emulator` onto this seam would be a worse fit, not a simplification. */ /** Context handed to a mounted command's handler. */ export interface CommandGroupContext { /** The verb invoked, e.g. `"get"` for `chant kube get pods`. */ verb: string; /** * Every CLI token after the group name and verb, unparsed — e.g. `chant * kube get pods -o wide` hands `["pods", "-o", "wide"]`. Core does not * interpret these: it has no vocabulary for a lexicon's own verbs. A * handler that wants #1127's joined-`--flag=value` splitting and * unknown-flag rejection can reuse {@link splitJoinedFlags} / * {@link unknownFlagError} from this module for the same discipline core's * own parser applies, scoped to whatever flags this verb actually accepts. */ rawArgs: string[]; } /** One verb within a lexicon-contributed command group. */ export interface CommandGroupCommand { /** Verb name, e.g. `"get"`, `"logs"`, `"version"`. */ name: string; /** One-line description shown in `chant --help` and in usage errors. */ description: string; /** Runs the verb. Returns the process exit code. */ handler: (ctx: CommandGroupContext) => Promise; } /** * A CLI verb group contributed by a lexicon (chant #1078). Mounted under * `chant `. Returned from {@link LexiconPlugin.commands}. */ export interface CommandGroup { /** Namespace this group mounts under, e.g. `"kube"` for `chant kube `. */ name: string; /** One-line description shown in `chant --help`'s composed listing. */ description: string; /** Verbs in this group. */ commands: CommandGroupCommand[]; } /** * Top-level command words core's own static registry already owns * (`packages/core/src/cli/main.ts`'s `registry`). A lexicon's `commands()` * group name colliding with one of these is always unreachable — core's own * registry is resolved first, unconditionally — so `checkConflicts` * (./conflict-check.ts) treats a collision as a hard, loud failure at * plugin-load time rather than a silently-ignored command group. Hand * maintained alongside the registry; update both together. */ export declare const RESERVED_COMMAND_NAMES: ReadonlySet; /** * chant #1127 — split a joined `--flag=value` token into two array elements * (`--flag`, `value`), the same discipline core's own `parseArgs` applies, * generalized so a lexicon's mounted command can reuse it for its own flag * vocabulary instead of reimplementing the split. Throws the same shape of * error as core's parser when `flag` is declared boolean but was given a * value — a boolean has nothing to assign, and silently reinterpreting the * joined value as the next positional would be exactly the silent misparse * #1127 closed for core's own flags. */ export declare function splitJoinedFlags(args: string[], booleanFlags?: ReadonlySet): string[]; /** * Same "Unknown flag" error shape core's own `parseArgs` throws (#1127), for * a mounted command's own flag vocabulary — core doesn't know that * vocabulary, so it can't produce this error itself; the handler does, using * this helper for a consistent message. */ export declare function unknownFlagError(flag: string, hint?: string): Error; /** Result of looking up a command group + verb among loaded plugins. */ export type CommandGroupLookup = { kind: "no-group"; } | { kind: "no-verb"; group: CommandGroup; } | { kind: "unknown-verb"; group: CommandGroup; } | { kind: "matched"; plugin: LexiconPlugin; group: CommandGroup; command: CommandGroupCommand; }; /** * Find the plugin (if any) whose `commands()` group is named `groupName`, * and the verb within it named `verbName`. Pure — does no I/O, calls * `plugin.commands()` at most once per plugin (registration, not execution: * this never invokes a verb's handler). */ export declare function resolveCommandGroupVerb(plugins: readonly LexiconPlugin[], groupName: string, verbName: string | undefined): CommandGroupLookup; /** Every command group contributed by the given loaded plugins, in plugin order. */ export declare function collectCommandGroups(plugins: readonly LexiconPlugin[]): CommandGroup[]; /** Result of {@link dispatchCommandGroup}. */ export type CommandGroupDispatch = { kind: "no-group"; } | { kind: "usage-error"; message: string; hint: string; } | { kind: "ran"; exitCode: number; }; /** * Resolve `groupName`/`verbName` against the loaded plugins and, if matched, * run the verb's handler with `rawArgs`. Returns `{ kind: "no-group" }` when * nothing claims `groupName` at all — the caller's cue to fall back to its * own "unknown command" handling — and a printable usage error when the * group matched but the verb didn't (or was omitted). */ export declare function dispatchCommandGroup(plugins: readonly LexiconPlugin[], groupName: string, verbName: string | undefined, rawArgs: string[]): Promise; /** * Render the `--help` section listing every lexicon-contributed command * group. Empty string when there are none, so a caller can splice it in * unconditionally without an extra length check. */ export declare function formatCommandGroupsHelp(groups: readonly CommandGroup[]): string; //# sourceMappingURL=command-group.d.ts.map