2025-11-11 12:32:46 +05:30
|
|
|
import { executeWorkflow, resumeWorkflow } from "./application/lib/exec-workflow.js";
|
2025-10-28 13:17:06 +05:30
|
|
|
import { StreamRenderer } from "./application/lib/stream-renderer.js";
|
2025-11-11 12:32:46 +05:30
|
|
|
import { createInterface } from "node:readline/promises";
|
|
|
|
|
import { stdin as input, stdout as output } from "node:process";
|
2025-10-28 13:17:06 +05:30
|
|
|
|
2025-11-11 12:32:46 +05:30
|
|
|
type ParsedArgs = {
|
|
|
|
|
command: "run" | "resume" | "help" | null;
|
|
|
|
|
id: string | null;
|
|
|
|
|
interactive: boolean;
|
|
|
|
|
message: string;
|
|
|
|
|
};
|
2025-10-28 13:17:06 +05:30
|
|
|
|
2025-11-11 12:32:46 +05:30
|
|
|
function parseArgs(argv: string[]): ParsedArgs {
|
|
|
|
|
const args = argv.slice(2);
|
|
|
|
|
if (args.length === 0) {
|
|
|
|
|
return { command: "help", id: null, interactive: true, message: "" };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let command: ParsedArgs["command"] = null;
|
|
|
|
|
let id: string | null = null;
|
|
|
|
|
let interactive = true;
|
|
|
|
|
const messageParts: string[] = [];
|
|
|
|
|
|
|
|
|
|
if (args[0] !== "run" && args[0] !== "resume") {
|
|
|
|
|
command = "help";
|
|
|
|
|
return { command, id: null, interactive, message: "" };
|
|
|
|
|
}
|
|
|
|
|
command = args[0];
|
|
|
|
|
|
|
|
|
|
for (let i = 1; i < args.length; i++) {
|
|
|
|
|
const a = args[i];
|
|
|
|
|
if (a.startsWith("--")) {
|
|
|
|
|
if (a === "--no-interactive") {
|
|
|
|
|
interactive = false;
|
|
|
|
|
} else if (a.startsWith("--interactive")) {
|
|
|
|
|
const [, value] = a.split("=");
|
|
|
|
|
if (value === undefined) {
|
|
|
|
|
interactive = true;
|
|
|
|
|
} else {
|
|
|
|
|
interactive = value !== "false";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (!id) {
|
|
|
|
|
id = a;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
messageParts.push(a);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return { command, id, interactive, message: messageParts.join(" ") };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function printUsage(): void {
|
|
|
|
|
console.log([
|
|
|
|
|
"Usage:",
|
|
|
|
|
" rowboatx run <workflow_id> [message...] [--interactive | --no-interactive]",
|
|
|
|
|
" rowboatx resume <run_id> [message...] [--interactive | --no-interactive]",
|
|
|
|
|
"",
|
|
|
|
|
"Flags:",
|
|
|
|
|
" --interactive Run interactively (default: true)",
|
|
|
|
|
" --no-interactive Disable interactive prompts",
|
|
|
|
|
].join("\n"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function promptForResumeInput(): Promise<string> {
|
|
|
|
|
const rl = createInterface({ input, output });
|
|
|
|
|
try {
|
|
|
|
|
const answer = await rl.question("Enter input to resume the run: ");
|
|
|
|
|
return answer;
|
|
|
|
|
} finally {
|
|
|
|
|
rl.close();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function render(generator: AsyncGenerator<any, void, unknown>): Promise<void> {
|
2025-10-28 13:17:06 +05:30
|
|
|
const renderer = new StreamRenderer();
|
2025-11-11 12:32:46 +05:30
|
|
|
for await (const event of generator) {
|
2025-11-07 11:42:10 +05:30
|
|
|
renderer.render(event);
|
2025-11-11 12:32:46 +05:30
|
|
|
if (event?.type === "error") {
|
|
|
|
|
process.exitCode = 1;
|
|
|
|
|
}
|
2025-10-28 13:17:06 +05:30
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-11 12:32:46 +05:30
|
|
|
async function main() {
|
|
|
|
|
const { command, id, interactive, message } = parseArgs(process.argv);
|
|
|
|
|
|
|
|
|
|
if (command === "help" || !command) {
|
|
|
|
|
printUsage();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (!id) {
|
|
|
|
|
printUsage();
|
|
|
|
|
process.exitCode = 1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (command) {
|
|
|
|
|
case "run": {
|
|
|
|
|
const initialInput = message ?? "";
|
|
|
|
|
await render(executeWorkflow(id, initialInput, interactive));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case "resume": {
|
|
|
|
|
const resumeInput = message !== "" ? message : (interactive ? await promptForResumeInput() : "");
|
|
|
|
|
await render(resumeWorkflow(id, resumeInput, interactive));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-10-28 13:17:06 +05:30
|
|
|
|
2025-11-11 12:32:46 +05:30
|
|
|
main().catch((err) => {
|
|
|
|
|
console.error("Failed:", err instanceof Error ? err.message : String(err));
|
|
|
|
|
process.exitCode = 1;
|
|
|
|
|
});
|