mirror of
https://github.com/stablyai/orca.git
synced 2026-09-22 08:02:28 +00:00
* feat(cli): make the CLI self-correcting and self-describing for agents Agents build a generalized model of how CLIs work and apply it to every tool. When orca diverged — `rm` where git uses `remove` — a reasonable first guess (`orca worktree remove`) dead-ended on a bare "Unknown command" with no path forward. This makes the CLI degrade gracefully when the orca-cli skill isn't loaded in context. - First-class CommandSpec.aliases, resolved to the canonical path before dispatch (no new handler registrations). `worktree remove`/`delete` now resolve to `rm`; the ad-hoc `terminal focus` duplicate spec/handler is migrated onto the mechanism. - Did-you-mean suggestions on unknown commands and unknown flags, ranked by edit distance over the live registry, surfaced in both stderr and --json error.data (reusing the existing nextSteps channel). - `orca agent-context [--json]`: a versioned, machine-readable dump of the command schema. Pure local read (no RPC), so it works over SSH and when the app isn't running. - CI guards: specs<->handlers parity, and a vocabulary policy that fails on new off-policy deletion/read verbs (existing ones grandfathered). * Address PR review feedback (#6303) - agent-context now emits each command's effective flag set (globals + conditional --page), not just allowedFlags, so the schema no longer under-reports --json/--help. Shared as effectiveAllowedFlags() between validation and the schema. - Collision check now covers alias paths too, so a duplicate alias that would silently shadow a real command fails the build. * fix(cli): harden agent recovery and introspection Co-authored-by: Orca <help@stably.ai> --------- Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com> Co-authored-by: Orca <help@stably.ai>
61 lines
1.9 KiB
TypeScript
61 lines
1.9 KiB
TypeScript
import type { CommandSpec } from './args'
|
|
import { effectiveAllowedFlags } from './args'
|
|
|
|
// Why: serialize the live spec table so agent discovery cannot drift from the
|
|
// command surface it describes.
|
|
|
|
const SCHEMA_VERSION = 1
|
|
|
|
export type AgentContextCommand = {
|
|
command: string
|
|
path: string[]
|
|
aliases: string[][]
|
|
argumentMode: 'parsed' | 'passthrough'
|
|
summary: string
|
|
usage: string
|
|
flags: string[]
|
|
positionalArgs: string[]
|
|
examples: string[]
|
|
notes: string[]
|
|
}
|
|
|
|
export type AgentContextSchema = {
|
|
schemaVersion: number
|
|
commandCount: number
|
|
commands: AgentContextCommand[]
|
|
}
|
|
|
|
export function buildAgentContext(specs: CommandSpec[]): AgentContextSchema {
|
|
const commands = specs
|
|
.map((spec) => ({
|
|
command: spec.path.join(' '),
|
|
path: spec.path,
|
|
aliases: spec.aliases ?? [],
|
|
argumentMode: spec.argumentMode ?? 'parsed',
|
|
summary: spec.summary,
|
|
usage: spec.usage,
|
|
// Why: the effective accepted set (globals + conditional --page), not just
|
|
// allowedFlags — otherwise agents treat --json/--help as unsupported.
|
|
flags: effectiveAllowedFlags(spec),
|
|
positionalArgs: spec.positionalArgs ?? [],
|
|
examples: spec.examples ?? [],
|
|
notes: spec.notes ?? []
|
|
}))
|
|
// Why: deterministic ordering so the JSON diffs cleanly across runs.
|
|
.sort((a, b) => a.command.localeCompare(b.command))
|
|
return {
|
|
schemaVersion: SCHEMA_VERSION,
|
|
commandCount: commands.length,
|
|
commands
|
|
}
|
|
}
|
|
|
|
export function formatAgentContextSummary(schema: AgentContextSchema): string {
|
|
// Why: keep the default (human) output bounded — the full surface is large, so
|
|
// point the reader at --json rather than dumping every command.
|
|
return [
|
|
`${schema.commandCount} commands (schema v${schema.schemaVersion}).`,
|
|
'Run `orca agent-context --json` for the full machine-readable command schema.'
|
|
].join('\n')
|
|
}
|