Files
agent-workflow/src/cli.ts
T

134 lines
3.3 KiB
JavaScript

#!/usr/bin/env node
/**
* agent-workflow CLI entry point.
*
* Supports direct subcommands: start, review, retry-review, retry-execute, decide, status, abort.
*/
import {
parseWorkflowArgs,
workflowUsage,
type WorkflowArgs,
} from "./workflow-args.js";
import {
startWorkflow,
reviewWorkflow,
decideWorkflow,
statusWorkflow,
abortWorkflow,
logsWorkflow,
retryReviewWorkflow,
retryExecuteWorkflow,
extendWorkflow,
WorkflowEngineError,
} from "./workflow-engine.js";
import { WorkflowConfigError } from "./workflow-config.js";
import { WorkflowLockError } from "./workflow-state.js";
import { startWorkflowWebServer } from "./workflow-web.js";
async function main() {
let args: WorkflowArgs;
try {
args = parseWorkflowArgs(process.argv.slice(2));
} catch (err) {
if (err instanceof Error && err.name === "WorkflowArgsError") {
process.stderr.write(`Error: ${err.message}\n\n`);
workflowUsage(1);
}
throw err;
}
try {
switch (args.sub) {
case "start":
await startWorkflow({
planInput: args.planInput,
executor: args.executor,
vcs: args.vcs,
maxCycles: args.maxCycles,
newTask: args.newTask,
});
break;
case "review":
await reviewWorkflow({ runId: args.runId });
break;
case "retry-review":
retryReviewWorkflow({ runId: args.runId });
break;
case "retry-execute":
await retryExecuteWorkflow({ runId: args.runId, sessionId: args.sessionId });
break;
case "decide":
await decideWorkflow({
runId: args.runId,
decisionInput: args.decisionInput,
});
break;
case "status":
statusWorkflow({ runId: args.runId, json: args.json });
break;
case "abort":
abortWorkflow({ runId: args.runId, reason: args.reason });
break;
case "logs":
await logsWorkflow({
runId: args.runId,
follow: args.follow,
tail: args.tail,
});
break;
case "extend":
await extendWorkflow({
runId: args.runId,
additionalCycles: args.additionalCycles,
});
break;
case "web":
await startWorkflowWebServer(args.port);
// Keep the process alive
await new Promise(() => {});
break;
default: {
const _exhaustive: never = args;
throw new Error(`Unknown subcommand: ${(_exhaustive as any).sub}`);
}
}
} catch (err: any) {
if (err && err.code === "EADDRINUSE") {
process.stderr.write(`Error: Port is already in use.\n`);
process.exit(1);
}
if (err instanceof WorkflowEngineError) {
process.stderr.write(`Error: ${err.message}\n`);
process.exit(err.exitCode);
}
if (err instanceof WorkflowConfigError) {
process.stderr.write(`Configuration error: ${err.message}\n`);
process.exit(4);
}
if (err instanceof WorkflowLockError) {
process.stderr.write(`Lock error: ${err.message}\n`);
process.exit(4);
}
throw err;
}
}
main().catch((err) => {
process.stderr.write(`Unexpected error: ${err.message}\n`);
if (err.stack) {
process.stderr.write(err.stack + "\n");
}
process.exit(1);
});