mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-07 08:02:40 +00:00
refactor(cli): fold flow test-step into flow preview --step
This commit is contained in:
+128
-143
@@ -542,6 +542,7 @@ async function preview(
|
||||
data?: string;
|
||||
silent: boolean;
|
||||
remote?: boolean;
|
||||
step?: string;
|
||||
} & SyncOptions,
|
||||
flowPath: string
|
||||
) {
|
||||
@@ -639,18 +640,35 @@ async function preview(
|
||||
|
||||
const input = opts.data ? await resolve(opts.data) : {};
|
||||
|
||||
log.debug(`Flow value: ${JSON.stringify(localFlow.value, null, 2)}`);
|
||||
|
||||
// Single-step mode: run only the named module's runnable.
|
||||
// The full-flow prep above (inline-script replacement, local PathScript
|
||||
// substitution, tempScriptRefs build) is exactly what the single step needs
|
||||
// too — PathScript modules have already been rewritten to inline rawscript
|
||||
// when `useLocalPathScripts` is set, and tempScriptRefs covers relative
|
||||
// imports in inline scripts.
|
||||
// Compute the flow's windmill path (e.g. "f/cli_smoke/myrelflow"). Used as
|
||||
// the anchor for relative-import resolution: inline scripts in this flow are
|
||||
// treated as living at "<flow_wm_path>/<step_id>", so "./util" resolves to
|
||||
// "<flow_wm_path_parent>/util" — matching the keys in temp_script_refs.
|
||||
const flowWmPath = flowPath.substring(0, flowPath.indexOf(".flow")).replaceAll(SEP, "/");
|
||||
|
||||
if (opts.step) {
|
||||
await previewStep(opts.step, localFlow, flowWmPath, workspace, input, tempScriptRefs, opts.silent);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!opts.silent) {
|
||||
log.info(colors.yellow(`Running flow preview for ${flowPath}...`));
|
||||
}
|
||||
|
||||
log.debug(`Flow value: ${JSON.stringify(localFlow.value, null, 2)}`);
|
||||
|
||||
// Run the flow preview — start the job, then poll for completion
|
||||
const jobId = await wmill.runFlowPreview({
|
||||
workspace: workspace.workspaceId,
|
||||
requestBody: {
|
||||
value: localFlow.value,
|
||||
path: flowPath.substring(0, flowPath.indexOf(".flow")).replaceAll(SEP, "/"),
|
||||
path: flowWmPath,
|
||||
args: input,
|
||||
temp_script_refs: tempScriptRefs,
|
||||
},
|
||||
@@ -677,6 +695,108 @@ async function preview(
|
||||
}
|
||||
}
|
||||
|
||||
async function previewStep(
|
||||
stepId: string,
|
||||
localFlow: FlowFile,
|
||||
flowWmPath: string,
|
||||
workspace: { workspaceId: string },
|
||||
baseArgs: Record<string, unknown>,
|
||||
tempScriptRefs: Record<string, string> | undefined,
|
||||
silent: boolean,
|
||||
) {
|
||||
const module = findStepInFlowValue(localFlow.value, stepId);
|
||||
if (!module) {
|
||||
const available = collectStepIds(localFlow.value).join(", ") || "(none)";
|
||||
throw new Error(`Step '${stepId}' not found in flow. Available steps: ${available}`);
|
||||
}
|
||||
|
||||
// The preprocessor module receives args via _ENTRYPOINT_OVERRIDE so the
|
||||
// runner picks the preprocessor entrypoint (matches frontend behavior in
|
||||
// copilot/chat/flow/core.ts).
|
||||
const args =
|
||||
stepId === "preprocessor"
|
||||
? { _ENTRYPOINT_OVERRIDE: "preprocessor", ...baseArgs }
|
||||
: baseArgs;
|
||||
|
||||
const moduleValue = module.value;
|
||||
let jobId: string;
|
||||
if (moduleValue?.type === "rawscript") {
|
||||
log.info(colors.yellow(`Previewing step '${stepId}' (rawscript, ${moduleValue.language})...`));
|
||||
jobId = await wmill.runScriptPreview({
|
||||
workspace: workspace.workspaceId,
|
||||
requestBody: {
|
||||
content: moduleValue.content ?? "",
|
||||
language: moduleValue.language,
|
||||
// Anchor relative imports to "<flow_wm_path>/<step_id>" so
|
||||
// temp_script_refs (keyed by Windmill paths) resolve correctly.
|
||||
// Without `path`, the worker defaults to "tmp/main" and "../foo"
|
||||
// resolves to "tmp/foo", missing every entry in temp_script_refs.
|
||||
path: `${flowWmPath}/${stepId}`,
|
||||
flow_path: flowWmPath,
|
||||
args,
|
||||
temp_script_refs: tempScriptRefs,
|
||||
},
|
||||
});
|
||||
} else if (moduleValue?.type === "script") {
|
||||
// Falls through here only when the deployed PathScript is what we want —
|
||||
// either --remote was passed, or no local file exists for this path.
|
||||
log.info(colors.yellow(`Previewing step '${stepId}' (script ${moduleValue.path})...`));
|
||||
const script = moduleValue.hash
|
||||
? await wmill.getScriptByHash({
|
||||
workspace: workspace.workspaceId,
|
||||
hash: moduleValue.hash,
|
||||
})
|
||||
: await wmill.getScriptByPath({
|
||||
workspace: workspace.workspaceId,
|
||||
path: moduleValue.path,
|
||||
});
|
||||
jobId = await wmill.runScriptPreview({
|
||||
workspace: workspace.workspaceId,
|
||||
requestBody: {
|
||||
content: script.content,
|
||||
language: script.language as any,
|
||||
// Anchor to the script's own deployed path so its relative imports
|
||||
// resolve against the workspace tree (or temp_script_refs).
|
||||
path: moduleValue.path,
|
||||
flow_path: flowWmPath,
|
||||
args,
|
||||
temp_script_refs: tempScriptRefs,
|
||||
},
|
||||
});
|
||||
} else if (moduleValue?.type === "flow") {
|
||||
log.info(colors.yellow(`Previewing step '${stepId}' (flow ${moduleValue.path})...`));
|
||||
jobId = await wmill.runFlowByPath({
|
||||
workspace: workspace.workspaceId,
|
||||
path: moduleValue.path,
|
||||
requestBody: args,
|
||||
});
|
||||
} else {
|
||||
throw new Error(
|
||||
`Cannot preview step of type '${moduleValue?.type ?? "unknown"}'. Supported types: rawscript, script, flow.`
|
||||
);
|
||||
}
|
||||
|
||||
const { result, success } = await pollForJobResult(workspace.workspaceId, jobId);
|
||||
|
||||
if (!success) {
|
||||
if (silent) {
|
||||
console.log(JSON.stringify(result));
|
||||
} else {
|
||||
log.info(colors.red.bold(`Step '${stepId}' failed:`));
|
||||
log.info(JSON.stringify(result, null, 2));
|
||||
}
|
||||
process.exitCode = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (silent) {
|
||||
console.log(JSON.stringify(result));
|
||||
} else {
|
||||
log.info(colors.bold.underline.green(`Step '${stepId}' completed`));
|
||||
log.info(JSON.stringify(result, null, 2));
|
||||
}
|
||||
}
|
||||
|
||||
function findStepInFlowValue(flowValue: any, stepId: string): any | undefined {
|
||||
if (!flowValue) return undefined;
|
||||
if (flowValue.failure_module?.id === stepId) return flowValue.failure_module;
|
||||
@@ -732,130 +852,6 @@ function collectStepIds(flowValue: any): string[] {
|
||||
return ids;
|
||||
}
|
||||
|
||||
async function testStep(
|
||||
opts: GlobalOptions & {
|
||||
data?: string;
|
||||
silent: boolean;
|
||||
json?: boolean;
|
||||
} & SyncOptions,
|
||||
flowPath: string,
|
||||
stepId: string
|
||||
) {
|
||||
if (opts.silent || opts.json) log.setSilent(true);
|
||||
opts = await mergeConfigWithConfigFile(opts);
|
||||
const workspace = await resolveWorkspace(opts);
|
||||
await requireLogin(opts);
|
||||
|
||||
// Normalize flow path (same logic as `preview`).
|
||||
const isFlowDir = flowPath.endsWith(".flow") || flowPath.endsWith(".flow" + SEP)
|
||||
|| flowPath.endsWith("__flow") || flowPath.endsWith("__flow" + SEP);
|
||||
if (!isFlowDir) {
|
||||
if (flowPath.endsWith("flow.yaml") || flowPath.endsWith("flow.json")) {
|
||||
// Use dirname so a bare "flow.yaml" (no parent dir) becomes "."
|
||||
// instead of "" — the latter, after appending SEP below, becomes "/"
|
||||
// and silently reads from filesystem root.
|
||||
flowPath = dirname(flowPath);
|
||||
} else {
|
||||
throw new Error(
|
||||
"Flow path must be a .flow/__flow directory or a flow.yaml file"
|
||||
);
|
||||
}
|
||||
}
|
||||
if (!flowPath.endsWith(SEP)) flowPath += SEP;
|
||||
|
||||
const localFlow = (await yamlParseFile(flowPath + "flow.yaml")) as FlowFile;
|
||||
const fileReader = async (path: string) => await readTextFile(flowPath + path);
|
||||
await replaceInlineScripts(localFlow.value.modules, fileReader, log, flowPath, SEP);
|
||||
if (localFlow.value.failure_module) {
|
||||
await replaceInlineScripts([localFlow.value.failure_module], fileReader, log, flowPath, SEP);
|
||||
}
|
||||
if (localFlow.value.preprocessor_module) {
|
||||
await replaceInlineScripts([localFlow.value.preprocessor_module], fileReader, log, flowPath, SEP);
|
||||
}
|
||||
|
||||
const module = findStepInFlowValue(localFlow.value, stepId);
|
||||
if (!module) {
|
||||
const available = collectStepIds(localFlow.value).join(", ") || "(none)";
|
||||
throw new Error(`Step '${stepId}' not found in flow. Available steps: ${available}`);
|
||||
}
|
||||
|
||||
const baseArgs = opts.data ? await resolve(opts.data) : {};
|
||||
const args =
|
||||
stepId === "preprocessor"
|
||||
? { _ENTRYPOINT_OVERRIDE: "preprocessor", ...baseArgs }
|
||||
: baseArgs;
|
||||
|
||||
const moduleValue = module.value;
|
||||
let jobId: string;
|
||||
if (moduleValue?.type === "rawscript") {
|
||||
if (!opts.silent && !opts.json) {
|
||||
log.info(colors.yellow(`Testing rawscript step '${stepId}' (${moduleValue.language})...`));
|
||||
}
|
||||
jobId = await wmill.runScriptPreview({
|
||||
workspace: workspace.workspaceId,
|
||||
requestBody: {
|
||||
content: moduleValue.content ?? "",
|
||||
language: moduleValue.language,
|
||||
args,
|
||||
},
|
||||
});
|
||||
} else if (moduleValue?.type === "script") {
|
||||
if (!opts.silent && !opts.json) {
|
||||
log.info(colors.yellow(`Testing script step '${stepId}' (${moduleValue.path})...`));
|
||||
}
|
||||
const script = moduleValue.hash
|
||||
? await wmill.getScriptByHash({
|
||||
workspace: workspace.workspaceId,
|
||||
hash: moduleValue.hash,
|
||||
})
|
||||
: await wmill.getScriptByPath({
|
||||
workspace: workspace.workspaceId,
|
||||
path: moduleValue.path,
|
||||
});
|
||||
jobId = await wmill.runScriptPreview({
|
||||
workspace: workspace.workspaceId,
|
||||
requestBody: {
|
||||
content: script.content,
|
||||
language: script.language as any,
|
||||
args,
|
||||
},
|
||||
});
|
||||
} else if (moduleValue?.type === "flow") {
|
||||
if (!opts.silent && !opts.json) {
|
||||
log.info(colors.yellow(`Testing flow step '${stepId}' (${moduleValue.path})...`));
|
||||
}
|
||||
jobId = await wmill.runFlowByPath({
|
||||
workspace: workspace.workspaceId,
|
||||
path: moduleValue.path,
|
||||
requestBody: args,
|
||||
});
|
||||
} else {
|
||||
throw new Error(
|
||||
`Cannot test step of type '${moduleValue?.type ?? "unknown"}'. Supported types: rawscript, script, flow.`
|
||||
);
|
||||
}
|
||||
|
||||
const { result, success } = await pollForJobResult(workspace.workspaceId, jobId);
|
||||
|
||||
if (!success) {
|
||||
if (opts.silent || opts.json) {
|
||||
console.log(JSON.stringify(result));
|
||||
} else {
|
||||
log.info(colors.yellow.bold(`Step '${stepId}' failed:`));
|
||||
log.info(JSON.stringify(result, null, 2));
|
||||
}
|
||||
process.exitCode = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (opts.silent || opts.json) {
|
||||
console.log(JSON.stringify(result));
|
||||
} else {
|
||||
log.info(colors.bold.underline.green(`Step '${stepId}' completed`));
|
||||
log.info(JSON.stringify(result, null, 2));
|
||||
}
|
||||
}
|
||||
|
||||
export async function generateLocks(
|
||||
opts: GlobalOptions & {
|
||||
yes?: boolean;
|
||||
@@ -1072,7 +1068,7 @@ const command = new Command()
|
||||
.action(run as any)
|
||||
.command(
|
||||
"preview",
|
||||
"preview a local flow without deploying it. Runs the flow definition from local files and uses local PathScripts by default."
|
||||
"preview a local flow without deploying it. Runs the flow definition from local files and uses local PathScripts by default. Pass --step <id> to run only one module in isolation (resolves nested steps inside branchone/branchall/forloopflow/whileloopflow plus the special preprocessor/failure modules; supported step types: rawscript, script, flow)."
|
||||
)
|
||||
.arguments("<flow_path:string>")
|
||||
.option(
|
||||
@@ -1087,22 +1083,11 @@ const command = new Command()
|
||||
"--remote",
|
||||
"Use deployed workspace scripts for PathScript steps instead of local files."
|
||||
)
|
||||
.option(
|
||||
"--step <step_id:string>",
|
||||
"Run only the named step instead of the whole flow. Honors --data as the step's args and --remote / local-PathScript resolution the same way the full-flow preview does."
|
||||
)
|
||||
.action(preview as any)
|
||||
.command(
|
||||
"test-step",
|
||||
"Test a single step of a local flow in isolation. Resolves the step by id (including nested branchone/branchall/forloopflow/whileloopflow and the failure/preprocessor modules), runs only that step's runnable. Supported step types: rawscript, script (PathScript), flow (PathFlow)."
|
||||
)
|
||||
.arguments("<flow_path:string> <step_id:string>")
|
||||
.option(
|
||||
"-d --data <data:string>",
|
||||
"Step inputs as a JSON string or a file using @<filename> or stdin using @-."
|
||||
)
|
||||
.option(
|
||||
"-s --silent",
|
||||
"Do not output anything other then the final output. Useful for scripting."
|
||||
)
|
||||
.option("--json", "Output the result as JSON (same as --silent)")
|
||||
.action(testStep as any)
|
||||
.command(
|
||||
"generate-locks",
|
||||
'DEPRECATED: re-generate flow lock files. Use "wmill generate-metadata" instead.'
|
||||
|
||||
@@ -5167,8 +5167,7 @@ Once the flow has real content, **offer** to open the visual preview as a one-se
|
||||
|
||||
After writing, tell the user which command fits what they want to do:
|
||||
|
||||
- \`wmill flow preview <flow_path>\` — **default when iterating on a local flow.** Runs the local \`flow.yaml\` against local inline scripts without deploying. Add \`--remote\` to use deployed workspace scripts for PathScript steps instead of local files.
|
||||
- \`wmill flow test-step <flow_path> <step_id>\` — runs a single step of the local flow in isolation. Use when iterating on one module (rawscript / script / flow types) and you don't want to wait for upstream steps. Supports nested steps inside branchone/branchall/forloopflow/whileloopflow, plus the special \`preprocessor\` and \`failure\` modules by id. Pass step args with \`-d '<json>'\`.
|
||||
- \`wmill flow preview <flow_path>\` — **default when iterating on a local flow.** Runs the local \`flow.yaml\` against local inline scripts without deploying. Add \`--remote\` to use deployed workspace scripts for PathScript steps instead of local files. Add \`--step <step_id>\` to run only one module in isolation (see "Single-step vs whole-flow preview" below).
|
||||
- \`wmill flow run <path>\` — runs the flow **already deployed** in the workspace. Use only when the user explicitly wants to test the deployed version, not local edits.
|
||||
- \`wmill generate-metadata\` — regenerate stale \`.lock\` and \`.script.yaml\` files. By default it scans **scripts, flows, and apps** across the workspace; pass \`--skip-flows --skip-apps\` (or run from a subdirectory) to limit the scope when you only care about the flow you edited.
|
||||
- \`wmill sync push\` — deploy local changes to the workspace. Only suggest/run this when the user explicitly asks to deploy/publish/push — not when they say "run", "try", or "test".
|
||||
@@ -5185,11 +5184,11 @@ Only use \`sync push\` when:
|
||||
- The user explicitly asks to deploy, publish, push, or ship.
|
||||
- The preview has already validated the change and the user wants it in the workspace.
|
||||
|
||||
### Test a single step vs preview the whole flow
|
||||
### Single-step vs whole-flow preview
|
||||
|
||||
Use \`flow test-step <flow_path> <step_id>\` when the user is iterating on one module and the flow's upstream steps aren't part of what they're trying to validate. It runs only that step's runnable (rawscript: the inline script; script: the PathScript fetched from the workspace; flow: the subflow by path) and is much faster than running the whole flow when previous steps are slow or expensive.
|
||||
Use \`flow preview <flow_path> --step <step_id>\` when the user is iterating on one module and the flow's upstream steps aren't part of what they're trying to validate. It runs only that step's runnable (rawscript: the inline script; script: the PathScript, locally if available; flow: the subflow by path) and is much faster than running the whole flow when previous steps are slow or expensive. The step id is resolved by walking nested branchone/branchall/forloopflow/whileloopflow modules and includes the special \`preprocessor\` and \`failure\` modules.
|
||||
|
||||
Use \`flow preview <flow_path>\` when steps depend on each other's outputs, when the user is validating the overall control flow, or when \`test-step\` doesn't apply (branchone, branchall, forloopflow, whileloopflow, identity, and AI agent steps cannot themselves be tested in isolation — for branchone/branchall/forloopflow/whileloopflow, the *contained* steps can, by passing the inner step's id).
|
||||
Use \`flow preview <flow_path>\` (no \`--step\`) when steps depend on each other's outputs, when the user is validating the overall control flow, or when \`--step\` doesn't apply (branchone, branchall, forloopflow, whileloopflow, identity, and AI agent steps cannot themselves be tested in isolation — for branchone/branchall/forloopflow/whileloopflow, the *contained* steps can, by passing the inner step's id).
|
||||
|
||||
### After writing — offer to run, don't wait passively
|
||||
|
||||
@@ -6845,14 +6844,11 @@ flow related commands
|
||||
- \`flow run <path:string>\` - run a flow by path.
|
||||
- \`-d --data <data:string>\` - Inputs specified as a JSON string or a file using @<filename> or stdin using @-.
|
||||
- \`-s --silent\` - Do not ouput anything other then the final output. Useful for scripting.
|
||||
- \`flow preview <flow_path:string>\` - preview a local flow without deploying it. Runs the flow definition from local files and uses local PathScripts by default.
|
||||
- \`flow preview <flow_path:string>\` - preview a local flow without deploying it. Runs the flow definition from local files and uses local PathScripts by default. Pass --step <id> to run only one module in isolation (resolves nested steps inside branchone/branchall/forloopflow/whileloopflow plus the special preprocessor/failure modules; supported step types: rawscript, script, flow).
|
||||
- \`-d --data <data:string>\` - Inputs specified as a JSON string or a file using @<filename> or stdin using @-.
|
||||
- \`-s --silent\` - Do not output anything other then the final output. Useful for scripting.
|
||||
- \`--remote\` - Use deployed workspace scripts for PathScript steps instead of local files.
|
||||
- \`flow test-step <flow_path:string> <step_id:string>\` - Test a single step of a local flow in isolation. Resolves the step by id (including nested branchone/branchall/forloopflow/whileloopflow and the failure/preprocessor modules), runs only that step's runnable. Supported step types: rawscript, script (PathScript), flow (PathFlow).
|
||||
- \`-d --data <data:string>\` - Step inputs as a JSON string or a file using @<filename> or stdin using @-.
|
||||
- \`-s --silent\` - Do not output anything other then the final output. Useful for scripting.
|
||||
- \`--json\` - Output the result as JSON (same as --silent)
|
||||
- \`--step <step_id:string>\` - Run only the named step instead of the whole flow. Honors --data as the step's args and --remote / local-PathScript resolution the same way the full-flow preview does.
|
||||
- \`flow new <flow_path:string>\` - create a new empty flow
|
||||
- \`--summary <summary:string>\` - flow summary
|
||||
- \`--description <description:string>\` - flow description
|
||||
|
||||
@@ -148,14 +148,11 @@ flow related commands
|
||||
- `flow run <path:string>` - run a flow by path.
|
||||
- `-d --data <data:string>` - Inputs specified as a JSON string or a file using @<filename> or stdin using @-.
|
||||
- `-s --silent` - Do not ouput anything other then the final output. Useful for scripting.
|
||||
- `flow preview <flow_path:string>` - preview a local flow without deploying it. Runs the flow definition from local files and uses local PathScripts by default.
|
||||
- `flow preview <flow_path:string>` - preview a local flow without deploying it. Runs the flow definition from local files and uses local PathScripts by default. Pass --step <id> to run only one module in isolation (resolves nested steps inside branchone/branchall/forloopflow/whileloopflow plus the special preprocessor/failure modules; supported step types: rawscript, script, flow).
|
||||
- `-d --data <data:string>` - Inputs specified as a JSON string or a file using @<filename> or stdin using @-.
|
||||
- `-s --silent` - Do not output anything other then the final output. Useful for scripting.
|
||||
- `--remote` - Use deployed workspace scripts for PathScript steps instead of local files.
|
||||
- `flow test-step <flow_path:string> <step_id:string>` - Test a single step of a local flow in isolation. Resolves the step by id (including nested branchone/branchall/forloopflow/whileloopflow and the failure/preprocessor modules), runs only that step's runnable. Supported step types: rawscript, script (PathScript), flow (PathFlow).
|
||||
- `-d --data <data:string>` - Step inputs as a JSON string or a file using @<filename> or stdin using @-.
|
||||
- `-s --silent` - Do not output anything other then the final output. Useful for scripting.
|
||||
- `--json` - Output the result as JSON (same as --silent)
|
||||
- `--step <step_id:string>` - Run only the named step instead of the whole flow. Honors --data as the step's args and --remote / local-PathScript resolution the same way the full-flow preview does.
|
||||
- `flow new <flow_path:string>` - create a new empty flow
|
||||
- `--summary <summary:string>` - flow summary
|
||||
- `--description <description:string>` - flow description
|
||||
|
||||
@@ -2698,14 +2698,11 @@ flow related commands
|
||||
- \`flow run <path:string>\` - run a flow by path.
|
||||
- \`-d --data <data:string>\` - Inputs specified as a JSON string or a file using @<filename> or stdin using @-.
|
||||
- \`-s --silent\` - Do not ouput anything other then the final output. Useful for scripting.
|
||||
- \`flow preview <flow_path:string>\` - preview a local flow without deploying it. Runs the flow definition from local files and uses local PathScripts by default.
|
||||
- \`flow preview <flow_path:string>\` - preview a local flow without deploying it. Runs the flow definition from local files and uses local PathScripts by default. Pass --step <id> to run only one module in isolation (resolves nested steps inside branchone/branchall/forloopflow/whileloopflow plus the special preprocessor/failure modules; supported step types: rawscript, script, flow).
|
||||
- \`-d --data <data:string>\` - Inputs specified as a JSON string or a file using @<filename> or stdin using @-.
|
||||
- \`-s --silent\` - Do not output anything other then the final output. Useful for scripting.
|
||||
- \`--remote\` - Use deployed workspace scripts for PathScript steps instead of local files.
|
||||
- \`flow test-step <flow_path:string> <step_id:string>\` - Test a single step of a local flow in isolation. Resolves the step by id (including nested branchone/branchall/forloopflow/whileloopflow and the failure/preprocessor modules), runs only that step's runnable. Supported step types: rawscript, script (PathScript), flow (PathFlow).
|
||||
- \`-d --data <data:string>\` - Step inputs as a JSON string or a file using @<filename> or stdin using @-.
|
||||
- \`-s --silent\` - Do not output anything other then the final output. Useful for scripting.
|
||||
- \`--json\` - Output the result as JSON (same as --silent)
|
||||
- \`--step <step_id:string>\` - Run only the named step instead of the whole flow. Honors --data as the step's args and --remote / local-PathScript resolution the same way the full-flow preview does.
|
||||
- \`flow new <flow_path:string>\` - create a new empty flow
|
||||
- \`--summary <summary:string>\` - flow summary
|
||||
- \`--description <description:string>\` - flow description
|
||||
|
||||
@@ -153,14 +153,11 @@ flow related commands
|
||||
- `flow run <path:string>` - run a flow by path.
|
||||
- `-d --data <data:string>` - Inputs specified as a JSON string or a file using @<filename> or stdin using @-.
|
||||
- `-s --silent` - Do not ouput anything other then the final output. Useful for scripting.
|
||||
- `flow preview <flow_path:string>` - preview a local flow without deploying it. Runs the flow definition from local files and uses local PathScripts by default.
|
||||
- `flow preview <flow_path:string>` - preview a local flow without deploying it. Runs the flow definition from local files and uses local PathScripts by default. Pass --step <id> to run only one module in isolation (resolves nested steps inside branchone/branchall/forloopflow/whileloopflow plus the special preprocessor/failure modules; supported step types: rawscript, script, flow).
|
||||
- `-d --data <data:string>` - Inputs specified as a JSON string or a file using @<filename> or stdin using @-.
|
||||
- `-s --silent` - Do not output anything other then the final output. Useful for scripting.
|
||||
- `--remote` - Use deployed workspace scripts for PathScript steps instead of local files.
|
||||
- `flow test-step <flow_path:string> <step_id:string>` - Test a single step of a local flow in isolation. Resolves the step by id (including nested branchone/branchall/forloopflow/whileloopflow and the failure/preprocessor modules), runs only that step's runnable. Supported step types: rawscript, script (PathScript), flow (PathFlow).
|
||||
- `-d --data <data:string>` - Step inputs as a JSON string or a file using @<filename> or stdin using @-.
|
||||
- `-s --silent` - Do not output anything other then the final output. Useful for scripting.
|
||||
- `--json` - Output the result as JSON (same as --silent)
|
||||
- `--step <step_id:string>` - Run only the named step instead of the whole flow. Honors --data as the step's args and --remote / local-PathScript resolution the same way the full-flow preview does.
|
||||
- `flow new <flow_path:string>` - create a new empty flow
|
||||
- `--summary <summary:string>` - flow summary
|
||||
- `--description <description:string>` - flow description
|
||||
|
||||
@@ -46,8 +46,7 @@ Once the flow has real content, **offer** to open the visual preview as a one-se
|
||||
|
||||
After writing, tell the user which command fits what they want to do:
|
||||
|
||||
- `wmill flow preview <flow_path>` — **default when iterating on a local flow.** Runs the local `flow.yaml` against local inline scripts without deploying. Add `--remote` to use deployed workspace scripts for PathScript steps instead of local files.
|
||||
- `wmill flow test-step <flow_path> <step_id>` — runs a single step of the local flow in isolation. Use when iterating on one module (rawscript / script / flow types) and you don't want to wait for upstream steps. Supports nested steps inside branchone/branchall/forloopflow/whileloopflow, plus the special `preprocessor` and `failure` modules by id. Pass step args with `-d '<json>'`.
|
||||
- `wmill flow preview <flow_path>` — **default when iterating on a local flow.** Runs the local `flow.yaml` against local inline scripts without deploying. Add `--remote` to use deployed workspace scripts for PathScript steps instead of local files. Add `--step <step_id>` to run only one module in isolation (see "Single-step vs whole-flow preview" below).
|
||||
- `wmill flow run <path>` — runs the flow **already deployed** in the workspace. Use only when the user explicitly wants to test the deployed version, not local edits.
|
||||
- `wmill generate-metadata` — regenerate stale `.lock` and `.script.yaml` files. By default it scans **scripts, flows, and apps** across the workspace; pass `--skip-flows --skip-apps` (or run from a subdirectory) to limit the scope when you only care about the flow you edited.
|
||||
- `wmill sync push` — deploy local changes to the workspace. Only suggest/run this when the user explicitly asks to deploy/publish/push — not when they say "run", "try", or "test".
|
||||
@@ -64,11 +63,11 @@ Only use `sync push` when:
|
||||
- The user explicitly asks to deploy, publish, push, or ship.
|
||||
- The preview has already validated the change and the user wants it in the workspace.
|
||||
|
||||
### Test a single step vs preview the whole flow
|
||||
### Single-step vs whole-flow preview
|
||||
|
||||
Use `flow test-step <flow_path> <step_id>` when the user is iterating on one module and the flow's upstream steps aren't part of what they're trying to validate. It runs only that step's runnable (rawscript: the inline script; script: the PathScript fetched from the workspace; flow: the subflow by path) and is much faster than running the whole flow when previous steps are slow or expensive.
|
||||
Use `flow preview <flow_path> --step <step_id>` when the user is iterating on one module and the flow's upstream steps aren't part of what they're trying to validate. It runs only that step's runnable (rawscript: the inline script; script: the PathScript, locally if available; flow: the subflow by path) and is much faster than running the whole flow when previous steps are slow or expensive. The step id is resolved by walking nested branchone/branchall/forloopflow/whileloopflow modules and includes the special `preprocessor` and `failure` modules.
|
||||
|
||||
Use `flow preview <flow_path>` when steps depend on each other's outputs, when the user is validating the overall control flow, or when `test-step` doesn't apply (branchone, branchall, forloopflow, whileloopflow, identity, and AI agent steps cannot themselves be tested in isolation — for branchone/branchall/forloopflow/whileloopflow, the *contained* steps can, by passing the inner step's id).
|
||||
Use `flow preview <flow_path>` (no `--step`) when steps depend on each other's outputs, when the user is validating the overall control flow, or when `--step` doesn't apply (branchone, branchall, forloopflow, whileloopflow, identity, and AI agent steps cannot themselves be tested in isolation — for branchone/branchall/forloopflow/whileloopflow, the *contained* steps can, by passing the inner step's id).
|
||||
|
||||
### After writing — offer to run, don't wait passively
|
||||
|
||||
|
||||
@@ -41,8 +41,7 @@ Once the flow has real content, **offer** to open the visual preview as a one-se
|
||||
|
||||
After writing, tell the user which command fits what they want to do:
|
||||
|
||||
- `wmill flow preview <flow_path>` — **default when iterating on a local flow.** Runs the local `flow.yaml` against local inline scripts without deploying. Add `--remote` to use deployed workspace scripts for PathScript steps instead of local files.
|
||||
- `wmill flow test-step <flow_path> <step_id>` — runs a single step of the local flow in isolation. Use when iterating on one module (rawscript / script / flow types) and you don't want to wait for upstream steps. Supports nested steps inside branchone/branchall/forloopflow/whileloopflow, plus the special `preprocessor` and `failure` modules by id. Pass step args with `-d '<json>'`.
|
||||
- `wmill flow preview <flow_path>` — **default when iterating on a local flow.** Runs the local `flow.yaml` against local inline scripts without deploying. Add `--remote` to use deployed workspace scripts for PathScript steps instead of local files. Add `--step <step_id>` to run only one module in isolation (see "Single-step vs whole-flow preview" below).
|
||||
- `wmill flow run <path>` — runs the flow **already deployed** in the workspace. Use only when the user explicitly wants to test the deployed version, not local edits.
|
||||
- `wmill generate-metadata` — regenerate stale `.lock` and `.script.yaml` files. By default it scans **scripts, flows, and apps** across the workspace; pass `--skip-flows --skip-apps` (or run from a subdirectory) to limit the scope when you only care about the flow you edited.
|
||||
- `wmill sync push` — deploy local changes to the workspace. Only suggest/run this when the user explicitly asks to deploy/publish/push — not when they say "run", "try", or "test".
|
||||
@@ -59,11 +58,11 @@ Only use `sync push` when:
|
||||
- The user explicitly asks to deploy, publish, push, or ship.
|
||||
- The preview has already validated the change and the user wants it in the workspace.
|
||||
|
||||
### Test a single step vs preview the whole flow
|
||||
### Single-step vs whole-flow preview
|
||||
|
||||
Use `flow test-step <flow_path> <step_id>` when the user is iterating on one module and the flow's upstream steps aren't part of what they're trying to validate. It runs only that step's runnable (rawscript: the inline script; script: the PathScript fetched from the workspace; flow: the subflow by path) and is much faster than running the whole flow when previous steps are slow or expensive.
|
||||
Use `flow preview <flow_path> --step <step_id>` when the user is iterating on one module and the flow's upstream steps aren't part of what they're trying to validate. It runs only that step's runnable (rawscript: the inline script; script: the PathScript, locally if available; flow: the subflow by path) and is much faster than running the whole flow when previous steps are slow or expensive. The step id is resolved by walking nested branchone/branchall/forloopflow/whileloopflow modules and includes the special `preprocessor` and `failure` modules.
|
||||
|
||||
Use `flow preview <flow_path>` when steps depend on each other's outputs, when the user is validating the overall control flow, or when `test-step` doesn't apply (branchone, branchall, forloopflow, whileloopflow, identity, and AI agent steps cannot themselves be tested in isolation — for branchone/branchall/forloopflow/whileloopflow, the *contained* steps can, by passing the inner step's id).
|
||||
Use `flow preview <flow_path>` (no `--step`) when steps depend on each other's outputs, when the user is validating the overall control flow, or when `--step` doesn't apply (branchone, branchall, forloopflow, whileloopflow, identity, and AI agent steps cannot themselves be tested in isolation — for branchone/branchall/forloopflow/whileloopflow, the *contained* steps can, by passing the inner step's id).
|
||||
|
||||
### After writing — offer to run, don't wait passively
|
||||
|
||||
|
||||
Reference in New Issue
Block a user