Files
orca/src/cli/index.ts
T
2026-05-28 13:40:12 -07:00

119 lines
3.7 KiB
JavaScript

#!/usr/bin/env node
import {
findCommandSpec,
isCommandGroup,
normalizeCommandPositionals,
parseArgs,
resolveHelpPath,
validateCommandAndFlags
} from './args'
import { dispatch } from './dispatch'
import { reportCliError } from './format'
import { printHelp } from './help'
import { RuntimeClient } from './runtime-client'
import { COMMAND_SPECS } from './specs'
export { COMMAND_SPECS } from './specs'
export { buildCurrentWorktreeSelector, normalizeWorktreeSelector } from './selectors'
function shouldIgnoreRemoteSelection(commandPath: string[]): boolean {
return (
commandPath[0] === 'environment' ||
commandPath[0] === 'serve' ||
commandPath[0] === 'agent' ||
(commandPath[0] === 'relay' && commandPath[1] === 'serve')
)
}
export async function main(argv = process.argv.slice(2), cwd = process.cwd()): Promise<void> {
const parsed = normalizeCommandPositionals(COMMAND_SPECS, parseArgs(argv))
const helpPath = resolveHelpPath(parsed)
if (helpPath !== null) {
printCliHelp(helpPath)
if (
helpPath.length > 0 &&
!findCommandSpec(COMMAND_SPECS, helpPath) &&
!isCommandGroup(helpPath) &&
!isSpecBackedCommandGroup(helpPath)
) {
process.exitCode = 1
}
return
}
if (parsed.commandPath.length === 0) {
printCliHelp([])
return
}
const json = parsed.flags.has('json')
try {
// Why: CLI syntax and flag errors should be reported before any runtime
// lookup so users do not get misleading "Orca is not running" failures for
// simple command typos or unsupported flags.
validateCommandAndFlags(COMMAND_SPECS, parsed)
const ignoreRemoteSelection = shouldIgnoreRemoteSelection(parsed.commandPath)
const pairingCode = ignoreRemoteSelection ? null : parsed.flags.get('pairing-code')
const environmentSelector = ignoreRemoteSelection ? null : parsed.flags.get('environment')
// Why: pass `null` (not `undefined`) when remote selection is suppressed
// so the RuntimeClient default parameter does not re-activate the
// ORCA_PAIRING_CODE / ORCA_ENVIRONMENT env-var fallback for commands
// that must run locally.
const client = new RuntimeClient(
undefined,
undefined,
typeof pairingCode === 'string' ? pairingCode : ignoreRemoteSelection ? null : undefined,
typeof environmentSelector === 'string'
? environmentSelector
: ignoreRemoteSelection
? null
: undefined
)
await dispatch(parsed.commandPath, {
flags: parsed.flags,
client,
cwd,
json
})
} catch (error) {
reportCliError(error, json)
process.exitCode = 1
}
}
if (require.main === module) {
void main()
}
function printCliHelp(commandPath: string[]): void {
if (isSpecBackedCommandGroup(commandPath)) {
console.log(formatSpecBackedGroupHelp(commandPath[0]))
return
}
printHelp(COMMAND_SPECS, commandPath)
if (commandPath.length === 0) {
console.log(
[
'',
'Relay:',
' relay serve Start a self-hosted Orca runtime relay server'
].join('\n')
)
}
}
function isSpecBackedCommandGroup(commandPath: string[]): boolean {
return (
commandPath.length === 1 &&
COMMAND_SPECS.some((spec) => spec.path.length > 1 && spec.path[0] === commandPath[0])
)
}
function formatSpecBackedGroupHelp(group: string): string {
const lines = [`orca ${group}`, '', `Usage: orca ${group} <command> [options]`, '', 'Commands:']
for (const spec of COMMAND_SPECS.filter((entry) => entry.path[0] === group)) {
lines.push(` ${spec.path.slice(1).join(' ').padEnd(18)} ${spec.summary}`)
}
lines.push('', `Run \`orca ${group} <command> --help\` for command-specific usage.`)
return lines.join('\n')
}