From 45ac95579927f964451da0b089606cc81707abfc Mon Sep 17 00:00:00 2001 From: hugocasa Date: Fri, 22 May 2026 10:31:21 +0200 Subject: [PATCH] feat: add wmill job rerun subcommand (#9275) * feat: add wmill job rerun subcommand * feat: add wmill job restart subcommand for flow restart-at-step --- cli/src/commands/job/job.ts | 73 ++++++++++++++++++- cli/src/guidance/core.ts | 2 + cli/src/guidance/skills.gen.ts | 4 + .../auto-generated/cli/cli-commands.md | 4 + system_prompts/auto-generated/prompts.ts | 4 + .../skills/cli-commands/SKILL.md | 4 + 6 files changed, 90 insertions(+), 1 deletion(-) diff --git a/cli/src/commands/job/job.ts b/cli/src/commands/job/job.ts index 454a600a19..50f0915075 100644 --- a/cli/src/commands/job/job.ts +++ b/cli/src/commands/job/job.ts @@ -376,6 +376,63 @@ async function cancel( log.info(colors.green(`Job ${id} canceled.`)); } +async function rerun( + opts: GlobalOptions, + id: string +) { + log.setSilent(true); + opts = await mergeConfigWithConfigFile(opts); + const workspace = await resolveWorkspace(opts); + await requireLogin(opts); + + const response = await wmill.batchReRunJobs({ + workspace: workspace.workspaceId, + requestBody: { + job_ids: [id], + script_options_by_path: {}, + flow_options_by_path: {}, + }, + }); + + const newIds: string[] = []; + const errorLines: string[] = []; + for (const line of String(response).split("\n")) { + const trimmed = line.trim(); + if (!trimmed) continue; + if (trimmed.startsWith("Error:")) errorLines.push(trimmed); + else newIds.push(trimmed); + } + + for (const err of errorLines) log.error(err); + + if (newIds.length === 0) { + throw new Error(`Failed to re-run job ${id}.`); + } + + console.log(newIds[0]); +} + +async function restart( + opts: GlobalOptions & { step: string; iteration?: number }, + id: string +) { + log.setSilent(true); + opts = await mergeConfigWithConfigFile(opts); + const workspace = await resolveWorkspace(opts); + await requireLogin(opts); + + const newId = await wmill.restartFlowAtStep({ + workspace: workspace.workspaceId, + id, + requestBody: { + step_id: opts.step, + branch_or_iteration_n: opts.iteration, + }, + }); + + console.log(newId); +} + // Shared list options to avoid repetition between default action and list subcommand const listOptions = (cmd: Command) => cmd @@ -410,6 +467,20 @@ const command = listOptions(new Command() .command("cancel", "Cancel a running or queued job") .arguments("") .option("--reason ", "Reason for cancellation") - .action(cancel as any); + .action(cancel as any) + .command( + "rerun", + "Re-run a completed job with the same args. Prints the new job UUID on stdout." + ) + .arguments("") + .action(rerun as any) + .command( + "restart", + "Restart a completed flow at a given top-level step. Prints the new flow job UUID on stdout." + ) + .arguments("") + .option("--step ", "Top-level step id to restart the flow from", { required: true }) + .option("--iteration ", "For a top-level branchall or for-loop step, the iteration to restart at") + .action(restart as any); export default command; diff --git a/cli/src/guidance/core.ts b/cli/src/guidance/core.ts index de65b33343..e87f3c72ca 100644 --- a/cli/src/guidance/core.ts +++ b/cli/src/guidance/core.ts @@ -147,6 +147,8 @@ When the user reports a script or flow failure, is investigating unexpected outp - \`wmill job logs \` — stdout/stderr; for flows, aggregates every step's logs - \`wmill job result \` — JSON result of a completed job - \`wmill job cancel \` — stop a running or queued job +- \`wmill job rerun \` — re-run a completed job with the same args (single-job equivalent of the frontend "rerun" button) +- \`wmill job restart --step [--iteration ]\` — restart a completed flow at a top-level step (for nested-container restart, use the UI) For flow failures, start with \`wmill job get \` to identify the failing step and its sub-job ID, then \`wmill job logs \` to drill in. diff --git a/cli/src/guidance/skills.gen.ts b/cli/src/guidance/skills.gen.ts index de1b8bcdc6..7cf2ae0adc 100644 --- a/cli/src/guidance/skills.gen.ts +++ b/cli/src/guidance/skills.gen.ts @@ -6948,6 +6948,10 @@ Manage jobs (list, inspect, cancel) - \`job logs \` - Get job logs. For flows: aggregates all step logs - \`job cancel \` - Cancel a running or queued job - \`--reason \` - Reason for cancellation +- \`job rerun \` - Re-run a completed job with the same args. Prints the new job UUID on stdout. +- \`job restart \` - Restart a completed flow at a given top-level step. Prints the new flow job UUID on stdout. + - \`--step \` - Top-level step id to restart the flow from + - \`--iteration \` - For a top-level branchall or for-loop step, the iteration to restart at ### jobs diff --git a/system_prompts/auto-generated/cli/cli-commands.md b/system_prompts/auto-generated/cli/cli-commands.md index 342f4cade4..2e431b25b7 100644 --- a/system_prompts/auto-generated/cli/cli-commands.md +++ b/system_prompts/auto-generated/cli/cli-commands.md @@ -334,6 +334,10 @@ Manage jobs (list, inspect, cancel) - `job logs ` - Get job logs. For flows: aggregates all step logs - `job cancel ` - Cancel a running or queued job - `--reason ` - Reason for cancellation +- `job rerun ` - Re-run a completed job with the same args. Prints the new job UUID on stdout. +- `job restart ` - Restart a completed flow at a given top-level step. Prints the new flow job UUID on stdout. + - `--step ` - Top-level step id to restart the flow from + - `--iteration ` - For a top-level branchall or for-loop step, the iteration to restart at ### jobs diff --git a/system_prompts/auto-generated/prompts.ts b/system_prompts/auto-generated/prompts.ts index 3a0ee24ac8..fc8d0b4f28 100644 --- a/system_prompts/auto-generated/prompts.ts +++ b/system_prompts/auto-generated/prompts.ts @@ -2865,6 +2865,10 @@ Manage jobs (list, inspect, cancel) - \`job logs \` - Get job logs. For flows: aggregates all step logs - \`job cancel \` - Cancel a running or queued job - \`--reason \` - Reason for cancellation +- \`job rerun \` - Re-run a completed job with the same args. Prints the new job UUID on stdout. +- \`job restart \` - Restart a completed flow at a given top-level step. Prints the new flow job UUID on stdout. + - \`--step \` - Top-level step id to restart the flow from + - \`--iteration \` - For a top-level branchall or for-loop step, the iteration to restart at ### jobs diff --git a/system_prompts/auto-generated/skills/cli-commands/SKILL.md b/system_prompts/auto-generated/skills/cli-commands/SKILL.md index 0ea6cf848f..4f91714b81 100644 --- a/system_prompts/auto-generated/skills/cli-commands/SKILL.md +++ b/system_prompts/auto-generated/skills/cli-commands/SKILL.md @@ -339,6 +339,10 @@ Manage jobs (list, inspect, cancel) - `job logs ` - Get job logs. For flows: aggregates all step logs - `job cancel ` - Cancel a running or queued job - `--reason ` - Reason for cancellation +- `job rerun ` - Re-run a completed job with the same args. Prints the new job UUID on stdout. +- `job restart ` - Restart a completed flow at a given top-level step. Prints the new flow job UUID on stdout. + - `--step ` - Top-level step id to restart the flow from + - `--iteration ` - For a top-level branchall or for-loop step, the iteration to restart at ### jobs