windmill-cli 1.710.1 → 1.712.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/esm/main.js +478 -23
  2. package/package.json +1 -1
package/esm/main.js CHANGED
@@ -16772,7 +16772,7 @@ var init_OpenAPI = __esm(() => {
16772
16772
  PASSWORD: undefined,
16773
16773
  TOKEN: getEnv3("WM_TOKEN"),
16774
16774
  USERNAME: undefined,
16775
- VERSION: "1.710.1",
16775
+ VERSION: "1.712.0",
16776
16776
  WITH_CREDENTIALS: true,
16777
16777
  interceptors: {
16778
16778
  request: new Interceptors,
@@ -67379,6 +67379,14 @@ async function pull(opts) {
67379
67379
  checkoutGitSyncDeployBranch(deployBranch);
67380
67380
  }
67381
67381
  if (opts.onlyCreateBranch) {
67382
+ gitSyncDeployPush({
67383
+ items: deployItems,
67384
+ authorName: process.env["WM_USERNAME"] || "windmill",
67385
+ authorEmail: process.env["WM_EMAIL"] || "windmill@windmill.dev",
67386
+ committerName: opts.gitCommitterName,
67387
+ committerEmail: opts.gitCommitterEmail,
67388
+ onlyCreateBranch: true
67389
+ });
67382
67390
  return;
67383
67391
  }
67384
67392
  }
@@ -67662,9 +67670,12 @@ function prettyChanges(changes, specificItems, branchOverride, folderDefaultAnno
67662
67670
  } else if (change.name === "deleted") {
67663
67671
  info(colors.red(`- ${getTypeStrFromPath(change.path)} ` + displayPath + colors.gray(wsNote)));
67664
67672
  } else if (change.name === "edited") {
67665
- info(colors.yellow(`~ ${getTypeStrFromPath(change.path)} ` + displayPath + colors.gray(wsNote) + (change.codebase ? ` (codebase changed)` : "")));
67673
+ const changeType = getTypeStrFromPath(change.path);
67674
+ info(colors.yellow(`~ ${changeType} ` + displayPath + colors.gray(wsNote) + (change.codebase ? ` (codebase changed)` : "")));
67666
67675
  if (change.before != change.after) {
67667
- if (change.path.endsWith(".yaml")) {
67676
+ if (changeType === "encryption_key") {
67677
+ showDiff(redactEncryptionKey(change.before), redactEncryptionKey(change.after));
67678
+ } else if (change.path.endsWith(".yaml")) {
67668
67679
  try {
67669
67680
  showDiff(import_yaml11.stringify(yamlParseContent(change.path, change.before), yamlOptions), import_yaml11.stringify(yamlParseContent(change.path, change.after), yamlOptions));
67670
67681
  } catch {
@@ -75804,11 +75815,35 @@ function showDiff(local, remote) {
75804
75815
  }
75805
75816
  function showConflict(path21, local, remote) {
75806
75817
  info(colors.yellow(`- ${path21}`));
75807
- showDiff(local, remote);
75818
+ let isEncryptionKey = false;
75819
+ try {
75820
+ isEncryptionKey = getTypeStrFromPath(path21) === "encryption_key";
75821
+ } catch {}
75822
+ if (isEncryptionKey) {
75823
+ showDiff(redactEncryptionKey(local), redactEncryptionKey(remote));
75824
+ } else {
75825
+ showDiff(local, remote);
75826
+ }
75808
75827
  info("\x1B[31mlocal\x1B[31m - \x1B[32mremote\x1B[32m");
75809
75828
  info(`
75810
75829
  `);
75811
75830
  }
75831
+ function redactEncryptionKey(content) {
75832
+ if (!content)
75833
+ return content;
75834
+ try {
75835
+ const parsed = JSON.parse(content);
75836
+ if (typeof parsed === "string") {
75837
+ return JSON.stringify(redactString(parsed));
75838
+ }
75839
+ } catch {}
75840
+ return redactString(content);
75841
+ }
75842
+ function redactString(s) {
75843
+ if (s.length <= 5)
75844
+ return s;
75845
+ return s.slice(0, 5) + "*".repeat(s.length - 5);
75846
+ }
75812
75847
  async function pushObj(workspace, p, befObj, newObj, plainSecrets, alreadySynced3, message, originalLocalPath, permissionedAsContext, wsSpecific) {
75813
75848
  const typeEnding = getTypeStrFromPath(p);
75814
75849
  if (typeEnding === "app") {
@@ -76130,7 +76165,7 @@ var init_local_path_scripts = __esm(async () => {
76130
76165
  });
76131
76166
 
76132
76167
  // src/commands/flow/flow.ts
76133
- import { sep as SEP20 } from "node:path";
76168
+ import { dirname as dirname17, sep as SEP20 } from "node:path";
76134
76169
  import { mkdirSync as mkdirSync5, writeFileSync as writeFileSync7 } from "node:fs";
76135
76170
  function normalizeOptionalString(value) {
76136
76171
  return typeof value === "string" && value.trim() === "" ? undefined : value ?? undefined;
@@ -76501,7 +76536,7 @@ async function preview2(opts, flowPath) {
76501
76536
  const isFlowDir = flowPath.endsWith(".flow") || flowPath.endsWith(".flow" + SEP20) || flowPath.endsWith("__flow") || flowPath.endsWith("__flow" + SEP20);
76502
76537
  if (!isFlowDir) {
76503
76538
  if (flowPath.endsWith("flow.yaml") || flowPath.endsWith("flow.json")) {
76504
- flowPath = flowPath.substring(0, flowPath.lastIndexOf(SEP20));
76539
+ flowPath = dirname17(flowPath);
76505
76540
  } else {
76506
76541
  throw new Error("Flow path must be a .flow/__flow directory or a flow.yaml file");
76507
76542
  }
@@ -76544,15 +76579,20 @@ async function preview2(opts, flowPath) {
76544
76579
  tempScriptRefs = await buildPreviewTempScriptRefs2(workspace, opts, resolvedCodebases, { kind: "flow", folder: flowPath });
76545
76580
  }
76546
76581
  const input = opts.data ? await resolve6(opts.data) : {};
76582
+ debug(`Flow value: ${JSON.stringify(localFlow.value, null, 2)}`);
76583
+ const flowWmPath = stripFlowSuffix(flowPath).replaceAll(SEP20, "/");
76584
+ if (opts.step) {
76585
+ await previewStep(opts.step, localFlow, flowWmPath, workspace, input, tempScriptRefs, opts.silent);
76586
+ return;
76587
+ }
76547
76588
  if (!opts.silent) {
76548
76589
  info(colors.yellow(`Running flow preview for ${flowPath}...`));
76549
76590
  }
76550
- debug(`Flow value: ${JSON.stringify(localFlow.value, null, 2)}`);
76551
76591
  const jobId = await runFlowPreview({
76552
76592
  workspace: workspace.workspaceId,
76553
76593
  requestBody: {
76554
76594
  value: localFlow.value,
76555
- path: flowPath.substring(0, flowPath.indexOf(".flow")).replaceAll(SEP20, "/"),
76595
+ path: flowWmPath,
76556
76596
  args: input,
76557
76597
  temp_script_refs: tempScriptRefs
76558
76598
  }
@@ -76575,6 +76615,151 @@ async function preview2(opts, flowPath) {
76575
76615
  info(JSON.stringify(result, null, 2));
76576
76616
  }
76577
76617
  }
76618
+ async function previewStep(stepId, localFlow, flowWmPath, workspace, baseArgs, tempScriptRefs, silent) {
76619
+ const module = findStepInFlowValue(localFlow.value, stepId);
76620
+ if (!module) {
76621
+ const available = collectStepIds(localFlow.value).join(", ") || "(none)";
76622
+ throw new Error(`Step '${stepId}' not found in flow. Available steps: ${available}`);
76623
+ }
76624
+ const args = stepId === "preprocessor" ? { _ENTRYPOINT_OVERRIDE: "preprocessor", ...baseArgs } : baseArgs;
76625
+ const moduleValue = module.value;
76626
+ let jobId;
76627
+ if (moduleValue?.type === "rawscript") {
76628
+ info(colors.yellow(`Previewing step '${stepId}' (rawscript, ${moduleValue.language})...`));
76629
+ jobId = await runScriptPreview({
76630
+ workspace: workspace.workspaceId,
76631
+ requestBody: {
76632
+ content: moduleValue.content ?? "",
76633
+ language: moduleValue.language,
76634
+ path: `${flowWmPath}/${stepId}`,
76635
+ flow_path: flowWmPath,
76636
+ args,
76637
+ temp_script_refs: tempScriptRefs
76638
+ }
76639
+ });
76640
+ } else if (moduleValue?.type === "script") {
76641
+ info(colors.yellow(`Previewing step '${stepId}' (script ${moduleValue.path})...`));
76642
+ const script = moduleValue.hash ? await getScriptByHash({
76643
+ workspace: workspace.workspaceId,
76644
+ hash: moduleValue.hash
76645
+ }) : await getScriptByPath({
76646
+ workspace: workspace.workspaceId,
76647
+ path: moduleValue.path
76648
+ });
76649
+ jobId = await runScriptPreview({
76650
+ workspace: workspace.workspaceId,
76651
+ requestBody: {
76652
+ content: script.content,
76653
+ language: script.language,
76654
+ path: moduleValue.path,
76655
+ flow_path: flowWmPath,
76656
+ args,
76657
+ temp_script_refs: tempScriptRefs
76658
+ }
76659
+ });
76660
+ } else if (moduleValue?.type === "flow") {
76661
+ info(colors.yellow(`Previewing step '${stepId}' (flow ${moduleValue.path})...`));
76662
+ jobId = await runFlowByPath({
76663
+ workspace: workspace.workspaceId,
76664
+ path: moduleValue.path,
76665
+ requestBody: args
76666
+ });
76667
+ } else {
76668
+ throw new Error(`Cannot preview step of type '${moduleValue?.type ?? "unknown"}'. Supported types: rawscript, script, flow.`);
76669
+ }
76670
+ const { result, success } = await pollForJobResult(workspace.workspaceId, jobId);
76671
+ if (!success) {
76672
+ if (silent) {
76673
+ console.log(JSON.stringify(result));
76674
+ } else {
76675
+ info(colors.red.bold(`Step '${stepId}' failed:`));
76676
+ info(JSON.stringify(result, null, 2));
76677
+ }
76678
+ process.exitCode = 1;
76679
+ return;
76680
+ }
76681
+ if (silent) {
76682
+ console.log(JSON.stringify(result));
76683
+ } else {
76684
+ info(colors.bold.underline.green(`Step '${stepId}' completed`));
76685
+ info(JSON.stringify(result, null, 2));
76686
+ }
76687
+ }
76688
+ function stripFlowSuffix(flowPath) {
76689
+ const stripped = flowPath.endsWith(SEP20) ? flowPath.slice(0, -SEP20.length) : flowPath;
76690
+ if (stripped.endsWith(".flow"))
76691
+ return stripped.slice(0, -".flow".length);
76692
+ if (stripped.endsWith("__flow"))
76693
+ return stripped.slice(0, -"__flow".length);
76694
+ return stripped;
76695
+ }
76696
+ function findStepInFlowValue(flowValue, stepId) {
76697
+ if (!flowValue)
76698
+ return;
76699
+ if (flowValue.failure_module?.id === stepId)
76700
+ return flowValue.failure_module;
76701
+ if (flowValue.preprocessor_module?.id === stepId)
76702
+ return flowValue.preprocessor_module;
76703
+ return findStepInModules(flowValue.modules ?? [], stepId);
76704
+ }
76705
+ function findStepInModules(modules, stepId) {
76706
+ for (const m of modules) {
76707
+ if (m?.id === stepId)
76708
+ return m;
76709
+ const v = m?.value;
76710
+ if (!v)
76711
+ continue;
76712
+ if (v.type === "forloopflow" || v.type === "whileloopflow") {
76713
+ const found = findStepInModules(v.modules ?? [], stepId);
76714
+ if (found)
76715
+ return found;
76716
+ } else if (v.type === "branchone") {
76717
+ for (const b of v.branches ?? []) {
76718
+ const found2 = findStepInModules(b.modules ?? [], stepId);
76719
+ if (found2)
76720
+ return found2;
76721
+ }
76722
+ const found = findStepInModules(v.default ?? [], stepId);
76723
+ if (found)
76724
+ return found;
76725
+ } else if (v.type === "branchall") {
76726
+ for (const b of v.branches ?? []) {
76727
+ const found = findStepInModules(b.modules ?? [], stepId);
76728
+ if (found)
76729
+ return found;
76730
+ }
76731
+ }
76732
+ }
76733
+ return;
76734
+ }
76735
+ function collectStepIds(flowValue) {
76736
+ const ids = [];
76737
+ const walkModules = (modules) => {
76738
+ for (const m of modules) {
76739
+ if (m?.id)
76740
+ ids.push(m.id);
76741
+ const v = m?.value;
76742
+ if (!v)
76743
+ continue;
76744
+ if (v.type === "forloopflow" || v.type === "whileloopflow") {
76745
+ walkModules(v.modules ?? []);
76746
+ } else if (v.type === "branchone") {
76747
+ for (const b of v.branches ?? [])
76748
+ walkModules(b.modules ?? []);
76749
+ walkModules(v.default ?? []);
76750
+ } else if (v.type === "branchall") {
76751
+ for (const b of v.branches ?? [])
76752
+ walkModules(b.modules ?? []);
76753
+ }
76754
+ }
76755
+ };
76756
+ if (flowValue?.preprocessor_module?.id)
76757
+ ids.push(flowValue.preprocessor_module.id);
76758
+ if (flowValue?.failure_module?.id)
76759
+ ids.push(flowValue.failure_module.id);
76760
+ walkModules(flowValue?.modules ?? []);
76761
+ return ids;
76762
+ }
76578
76763
  async function generateLocks(opts, folder) {
76579
76764
  warn(colors.yellow('This command is deprecated. Use "wmill generate-metadata" instead.'));
76580
76765
  const workspace = await resolveWorkspace(opts);
@@ -76711,7 +76896,7 @@ var init_flow = __esm(async () => {
76711
76896
  ]);
76712
76897
  import_yaml36 = __toESM(require_dist(), 1);
76713
76898
  alreadySynced3 = [];
76714
- command21 = new Command().description("flow related commands").option("--show-archived", "Enable archived flows in output").option("--json", "Output as JSON (for piping to jq)").action(list12).command("list", "list all flows").option("--show-archived", "Enable archived flows in output").option("--json", "Output as JSON (for piping to jq)").action(list12).command("get", "get a flow's details").arguments("<path:string>").option("--json", "Output as JSON (for piping to jq)").action(get9).command("push", "push a local flow spec. This overrides any remote versions.").arguments("<file_path:string> <remote_path:string>").option("--message <message:string>", "Deployment message").action(push11).command("run", "run a flow by path.").arguments("<path:string>").option("-d --data <data:string>", "Inputs specified as a JSON string or a file using @<filename> or stdin using @-.").option("-s --silent", "Do not ouput anything other then the final output. Useful for scripting.").action(run3).command("preview", "preview a local flow without deploying it. Runs the flow definition from local files and uses local PathScripts by default.").arguments("<flow_path:string>").option("-d --data <data:string>", "Inputs specified 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("--remote", "Use deployed workspace scripts for PathScript steps instead of local files.").action(preview2).command("generate-locks", 'DEPRECATED: re-generate flow lock files. Use "wmill generate-metadata" instead.').arguments("[flow:file]").option("--yes", "Skip confirmation prompt").option("--dry-run", "Perform a dry run without making changes").option("-i --includes <patterns:file[]>", "Comma separated patterns to specify which file to take into account (among files that are compatible with windmill). Patterns can include * (any string until '/') and ** (any string)").option("-e --excludes <patterns:file[]>", "Comma separated patterns to specify which file to NOT take into account.").action(generateLocks).command("new", "create a new empty flow").arguments("<flow_path:string>").option("--summary <summary:string>", "flow summary").option("--description <description:string>", "flow description").action(bootstrap2).command("bootstrap", "create a new empty flow (alias for new)").arguments("<flow_path:string>").option("--summary <summary:string>", "flow summary").option("--description <description:string>", "flow description").action(bootstrap2).command("history", "Show version history for a flow").arguments("<path:string>").option("--json", "Output as JSON (for piping to jq)").action(history2).command("show-version", "Show a specific version of a flow").arguments("<path:string> <version:string>").option("--json", "Output as JSON (for piping to jq)").action(showVersion).command("set-permissioned-as", "Set the on_behalf_of_email for a flow (requires admin or wm_deployers group)").arguments("<path:string> <email:string>").action(async (opts, flowPath, email) => {
76899
+ command21 = new Command().description("flow related commands").option("--show-archived", "Enable archived flows in output").option("--json", "Output as JSON (for piping to jq)").action(list12).command("list", "list all flows").option("--show-archived", "Enable archived flows in output").option("--json", "Output as JSON (for piping to jq)").action(list12).command("get", "get a flow's details").arguments("<path:string>").option("--json", "Output as JSON (for piping to jq)").action(get9).command("push", "push a local flow spec. This overrides any remote versions.").arguments("<file_path:string> <remote_path:string>").option("--message <message:string>", "Deployment message").action(push11).command("run", "run a flow by path.").arguments("<path:string>").option("-d --data <data:string>", "Inputs specified as a JSON string or a file using @<filename> or stdin using @-.").option("-s --silent", "Do not ouput anything other then the final output. Useful for scripting.").action(run3).command("preview", "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("-d --data <data:string>", "Inputs specified 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("--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(preview2).command("generate-locks", 'DEPRECATED: re-generate flow lock files. Use "wmill generate-metadata" instead.').arguments("[flow:file]").option("--yes", "Skip confirmation prompt").option("--dry-run", "Perform a dry run without making changes").option("-i --includes <patterns:file[]>", "Comma separated patterns to specify which file to take into account (among files that are compatible with windmill). Patterns can include * (any string until '/') and ** (any string)").option("-e --excludes <patterns:file[]>", "Comma separated patterns to specify which file to NOT take into account.").action(generateLocks).command("new", "create a new empty flow").arguments("<flow_path:string>").option("--summary <summary:string>", "flow summary").option("--description <description:string>", "flow description").action(bootstrap2).command("bootstrap", "create a new empty flow (alias for new)").arguments("<flow_path:string>").option("--summary <summary:string>", "flow summary").option("--description <description:string>", "flow description").action(bootstrap2).command("history", "Show version history for a flow").arguments("<path:string>").option("--json", "Output as JSON (for piping to jq)").action(history2).command("show-version", "Show a specific version of a flow").arguments("<path:string> <version:string>").option("--json", "Output as JSON (for piping to jq)").action(showVersion).command("set-permissioned-as", "Set the on_behalf_of_email for a flow (requires admin or wm_deployers group)").arguments("<path:string> <email:string>").action(async (opts, flowPath, email) => {
76715
76900
  const workspace = await resolveWorkspace(opts);
76716
76901
  await requireLogin(opts);
76717
76902
  const remote = await getFlowByPath({
@@ -82984,7 +83169,7 @@ Once the flow has real content, **offer** to open the visual preview as a one-se
82984
83169
 
82985
83170
  After writing, tell the user which command fits what they want to do:
82986
83171
 
82987
- - \`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.
83172
+ - \`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).
82988
83173
  - \`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.
82989
83174
  - \`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.
82990
83175
  - \`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".
@@ -83001,6 +83186,12 @@ Only use \`sync push\` when:
83001
83186
  - The user explicitly asks to deploy, publish, push, or ship.
83002
83187
  - The preview has already validated the change and the user wants it in the workspace.
83003
83188
 
83189
+ ### Single-step vs whole-flow preview
83190
+
83191
+ 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.
83192
+
83193
+ 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).
83194
+
83004
83195
  ### After writing — offer to run, don't wait passively
83005
83196
 
83006
83197
  This is about **programmatic execution** (\`wmill flow preview -d '<args>'\`), which actually runs the flow and has side effects. Visual preview (the \`preview\` skill) is offered separately — see "Visual preview" below.
@@ -84655,10 +84846,11 @@ flow related commands
84655
84846
  - \`flow run <path:string>\` - run a flow by path.
84656
84847
  - \`-d --data <data:string>\` - Inputs specified as a JSON string or a file using @<filename> or stdin using @-.
84657
84848
  - \`-s --silent\` - Do not ouput anything other then the final output. Useful for scripting.
84658
- - \`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.
84849
+ - \`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).
84659
84850
  - \`-d --data <data:string>\` - Inputs specified as a JSON string or a file using @<filename> or stdin using @-.
84660
84851
  - \`-s --silent\` - Do not output anything other then the final output. Useful for scripting.
84661
84852
  - \`--remote\` - Use deployed workspace scripts for PathScript steps instead of local files.
84853
+ - \`--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.
84662
84854
  - \`flow new <flow_path:string>\` - create a new empty flow
84663
84855
  - \`--summary <summary:string>\` - flow summary
84664
84856
  - \`--description <description:string>\` - flow description
@@ -84874,6 +85066,42 @@ Validate Windmill flow, schedule, and trigger YAML files in a directory
84874
85066
  - \`--locks-required\` - Fail if scripts or flow inline scripts that need locks have no locks
84875
85067
  - \`-w, --watch\` - Watch for file changes and re-lint automatically
84876
85068
 
85069
+ ### object-storage
85070
+
85071
+ **Alias:** \`s3\`
85072
+
85073
+ **Subcommands:**
85074
+
85075
+ - \`object-storage list\` - List configured object storages for the workspace (default + secondary).
85076
+ - \`--json\` - Output as JSON (for piping to jq)
85077
+ - \`object-storage files [prefix:string]\` - List files in an object storage. Optionally filter by prefix.
85078
+ - \`--json\` - Output as JSON (for piping to jq)
85079
+ - \`--max-keys <maxKeys:number>\` - Page size (default 100)
85080
+ - \`--marker <marker:string>\` - Pagination marker from a previous response
85081
+ - \`--storage <storage:string>\` - Secondary storage name (omit for the workspace default)
85082
+ - \`object-storage upload <local_path:string> <file_key:string>\` - Upload a local file to object storage at the given file key.
85083
+ - \`--storage <storage:string>\` - Secondary storage name
85084
+ - \`--content-type <contentType:string>\` - Content-Type header to set on the object
85085
+ - \`--content-disposition <contentDisposition:string>\` - Content-Disposition header to set on the object
85086
+ - \`object-storage download <file_key:string> [output_path:string]\` - Download an object to a local file (or stdout). Default output path is the basename of the file key in the current directory.
85087
+ - \`--storage <storage:string>\` - Secondary storage name
85088
+ - \`--stdout\` - Write file contents to stdout instead of a file
85089
+ - \`object-storage delete <file_key:string>\` - Delete an object from object storage. Prompts for confirmation unless --yes is set.
85090
+ - \`--storage <storage:string>\` - Secondary storage name
85091
+ - \`--yes\` - Skip the confirmation prompt
85092
+ - \`object-storage move <src_file_key:string> <dest_file_key:string>\` - Move an object within the same storage (rename or relocate by key).
85093
+ - \`--storage <storage:string>\` - Secondary storage name
85094
+ - \`object-storage info <file_key:string>\` - Show metadata (size, mime, last-modified) for an object.
85095
+ - \`--json\` - Output as JSON (for piping to jq)
85096
+ - \`--storage <storage:string>\` - Secondary storage name
85097
+ - \`object-storage preview <file_key:string>\` - Preview the contents of an object (text/CSV). Use --bytes-from / --bytes-length to peek at a slice of binary files.
85098
+ - \`--storage <storage:string>\` - Secondary storage name
85099
+ - \`--mime <mime:string>\` - Override the detected mime type (e.g. text/csv)
85100
+ - \`--bytes-from <bytesFrom:number>\` - Start offset in bytes
85101
+ - \`--bytes-length <bytesLength:number>\` - Number of bytes to read
85102
+ - \`--csv-separator <csvSeparator:string>\` - CSV column separator (default ,)
85103
+ - \`--csv-header\` - Treat the first CSV row as a header
85104
+
84877
85105
  ### protection-rules
84878
85106
 
84879
85107
  **Subcommands:**
@@ -85210,6 +85438,26 @@ workspace related commands
85210
85438
  - \`--team-name <team_name:string>\` - Slack team name
85211
85439
  - \`workspace disconnect-slack\`
85212
85440
 
85441
+
85442
+
85443
+ # Object Storage CLI
85444
+
85445
+ \`wmill object-storage\` (alias \`wmill s3\`) exposes the workspace's object storage (S3-compatible: AWS S3, MinIO, GCS, R2, Azure Blob) over the per-workspace \`/job_helpers/*\` endpoints.
85446
+
85447
+ ## Key concepts (not obvious from per-command --help)
85448
+
85449
+ - **\`file_key\` is the path inside the bucket** (e.g. \`reports/2026-05/orders.csv\`), not a Windmill path. Do NOT pass \`u/...\` or \`f/...\` here — those are Windmill paths to scripts/flows/resources, unrelated to objects in the bucket.
85450
+ - **Scope is the active workspace.** Object storage is configured per-workspace (default storage + optional secondary storages). Switching workspaces switches which bucket the commands target.
85451
+ - **\`--storage <name>\` targets a secondary storage** configured on the workspace. Omit it to use the workspace's default object storage. Use \`wmill object-storage list\` to discover configured storages.
85452
+ - **\`preview\` vs \`download\`**: \`preview\` returns a peek (CSV first rows, text content, or a byte slice via \`--bytes-from\`/\`--bytes-length\`) without writing to disk. Use \`download\` when you want the full file on disk.
85453
+
85454
+ ## Choosing a subcommand
85455
+
85456
+ - Look at what's there: \`wmill object-storage files [prefix]\` (alias \`ls\`) — paginated, use \`--marker\` to continue.
85457
+ - Inspect one file: \`wmill object-storage info <file_key>\` for size/mime/last-modified, \`wmill object-storage preview <file_key>\` for content peek.
85458
+ - Move data in: \`wmill object-storage upload <local_path> <file_key>\` — set \`--content-type\` if the receiver cares (e.g. \`text/csv\`).
85459
+ - Move data out: \`wmill object-storage download <file_key> [output_path]\` — \`--stdout\` to pipe.
85460
+ - Reorganize: \`wmill object-storage move <src> <dest>\` (same storage), \`wmill object-storage delete <file_key>\` (interactive confirm unless \`--yes\`).
85213
85461
  `,
85214
85462
  preview: `---
85215
85463
  name: preview
@@ -87946,13 +88194,13 @@ await __promiseAll([
87946
88194
  var import_yaml39 = __toESM(require_dist(), 1);
87947
88195
  import { existsSync as existsSync10 } from "node:fs";
87948
88196
  import { writeFile as writeFile19 } from "node:fs/promises";
87949
- import { dirname as dirname17, join as join18 } from "node:path";
88197
+ import { dirname as dirname18, join as join18 } from "node:path";
87950
88198
  var PROTECTION_RULES_FILENAME = "protection-rules.yaml";
87951
88199
  function getProtectionRulesPath() {
87952
88200
  const wmillPath = getWmillYamlPath();
87953
88201
  if (!wmillPath)
87954
88202
  return null;
87955
- return join18(dirname17(wmillPath), PROTECTION_RULES_FILENAME);
88203
+ return join18(dirname18(wmillPath), PROTECTION_RULES_FILENAME);
87956
88204
  }
87957
88205
  async function readProtectionRulesFile(path21) {
87958
88206
  if (!existsSync10(path21))
@@ -89948,7 +90196,11 @@ ${options.includeLine}
89948
90196
  }
89949
90197
  function referencesIncludeLine(content, includeLine) {
89950
90198
  for (const line of content.split(/\r?\n/)) {
89951
- if (line.trim() === includeLine) {
90199
+ const trimmed = line.trim();
90200
+ if (trimmed.startsWith("<!--") || trimmed.endsWith("-->")) {
90201
+ continue;
90202
+ }
90203
+ if (trimmed.split(/\s+/).includes(includeLine)) {
89952
90204
  return true;
89953
90205
  }
89954
90206
  }
@@ -93203,9 +93455,211 @@ async function run5(opts, sql) {
93203
93455
  var command40 = new Command().description("ducklake related commands").command("list", "list all ducklakes in the workspace").option("--json", "Output as JSON (for piping to jq)").action(list18).command("run", "run a SQL query on a ducklake").arguments("<sql:string>").option("-n --name <name:string>", "Ducklake name (default: main)").option("-s --silent", "Output only the final result as JSON. Useful for scripting.").action(run5);
93204
93456
  var ducklake_default = command40;
93205
93457
 
93458
+ // src/commands/object-storage/object-storage.ts
93459
+ init_mod3();
93460
+ init_mod6();
93461
+ init_colors2();
93462
+ init_log();
93463
+ init_services_gen();
93464
+ await __promiseAll([
93465
+ init_auth(),
93466
+ init_context(),
93467
+ init_confirm(),
93468
+ init_utils()
93469
+ ]);
93470
+ import { Buffer as Buffer5 } from "node:buffer";
93471
+ import { readFile as readFile3, writeFile as writeFile25 } from "node:fs/promises";
93472
+ import { basename as basename10 } from "node:path";
93473
+ function formatBytes(n2) {
93474
+ if (n2 == null)
93475
+ return "-";
93476
+ if (n2 < 1024)
93477
+ return `${n2}B`;
93478
+ if (n2 < 1024 * 1024)
93479
+ return `${(n2 / 1024).toFixed(1)}K`;
93480
+ if (n2 < 1024 * 1024 * 1024)
93481
+ return `${(n2 / (1024 * 1024)).toFixed(1)}M`;
93482
+ return `${(n2 / (1024 * 1024 * 1024)).toFixed(2)}G`;
93483
+ }
93484
+ async function listStorages(opts) {
93485
+ if (opts.json)
93486
+ setSilent(true);
93487
+ const workspace = await resolveWorkspace(opts);
93488
+ await requireLogin(opts);
93489
+ const names = await getSecondaryStorageNames({
93490
+ workspace: workspace.workspaceId,
93491
+ includeDefault: true
93492
+ });
93493
+ if (opts.json) {
93494
+ console.log(JSON.stringify(names));
93495
+ return;
93496
+ }
93497
+ if (names.length === 0) {
93498
+ info("No object storage configured for this workspace.");
93499
+ return;
93500
+ }
93501
+ for (const name of names) {
93502
+ console.log(name === "_default_" ? `${name} ${colors.dim("(default)")}` : name);
93503
+ }
93504
+ }
93505
+ async function listFiles(opts, prefix) {
93506
+ if (opts.json)
93507
+ setSilent(true);
93508
+ const workspace = await resolveWorkspace(opts);
93509
+ await requireLogin(opts);
93510
+ const result2 = await listStoredFiles({
93511
+ workspace: workspace.workspaceId,
93512
+ maxKeys: opts.maxKeys ?? 100,
93513
+ marker: opts.marker,
93514
+ prefix,
93515
+ storage: opts.storage
93516
+ });
93517
+ if (opts.json) {
93518
+ console.log(JSON.stringify(result2));
93519
+ return;
93520
+ }
93521
+ const files = result2.windmill_large_files ?? [];
93522
+ if (files.length === 0) {
93523
+ info("No files found.");
93524
+ return;
93525
+ }
93526
+ new Table2().header(["Key"]).padding(2).border(true).body(files.map((f3) => [f3.s3])).render();
93527
+ if (result2.next_marker) {
93528
+ info(`
93529
+ More results available. Use --marker '${result2.next_marker}' to paginate.`);
93530
+ }
93531
+ }
93532
+ async function upload(opts, localPath, fileKey) {
93533
+ const workspace = await resolveWorkspace(opts);
93534
+ await requireLogin(opts);
93535
+ const buf = await readFile3(localPath);
93536
+ const blob = new Blob([buf], { type: opts.contentType ?? "application/octet-stream" });
93537
+ await fileUpload({
93538
+ workspace: workspace.workspaceId,
93539
+ fileKey,
93540
+ storage: opts.storage,
93541
+ contentType: opts.contentType,
93542
+ contentDisposition: opts.contentDisposition,
93543
+ requestBody: blob
93544
+ });
93545
+ info(colors.green(`Uploaded ${localPath} -> ${fileKey}`));
93546
+ }
93547
+ async function download(opts, fileKey, outputPath) {
93548
+ if (opts.stdout)
93549
+ setSilent(true);
93550
+ const workspace = await resolveWorkspace(opts);
93551
+ await requireLogin(opts);
93552
+ const body = await fileDownload({
93553
+ workspace: workspace.workspaceId,
93554
+ fileKey,
93555
+ storage: opts.storage
93556
+ });
93557
+ let buf;
93558
+ if (typeof body === "string") {
93559
+ buf = Buffer5.from(body, "utf-8");
93560
+ } else if (body instanceof Blob) {
93561
+ buf = Buffer5.from(await body.arrayBuffer());
93562
+ } else if (body instanceof ArrayBuffer) {
93563
+ buf = Buffer5.from(body);
93564
+ } else if (body == null) {
93565
+ buf = Buffer5.alloc(0);
93566
+ } else {
93567
+ buf = Buffer5.from(JSON.stringify(body), "utf-8");
93568
+ }
93569
+ if (opts.stdout) {
93570
+ process.stdout.write(buf);
93571
+ return;
93572
+ }
93573
+ const dest = outputPath ?? basename10(fileKey);
93574
+ await writeFile25(dest, buf);
93575
+ info(colors.green(`Downloaded ${fileKey} -> ${dest}`));
93576
+ }
93577
+ async function del(opts, fileKey) {
93578
+ const workspace = await resolveWorkspace(opts);
93579
+ await requireLogin(opts);
93580
+ if (!opts.yes) {
93581
+ const confirmed = await Confirm.prompt({
93582
+ message: `Delete '${fileKey}' from object storage${opts.storage ? ` (storage: ${opts.storage})` : ""}?`,
93583
+ default: false
93584
+ });
93585
+ if (!confirmed) {
93586
+ info("Aborted.");
93587
+ return;
93588
+ }
93589
+ }
93590
+ await deleteS3File({
93591
+ workspace: workspace.workspaceId,
93592
+ fileKey,
93593
+ storage: opts.storage
93594
+ });
93595
+ info(colors.green(`Deleted ${fileKey}`));
93596
+ }
93597
+ async function move(opts, srcFileKey, destFileKey) {
93598
+ const workspace = await resolveWorkspace(opts);
93599
+ await requireLogin(opts);
93600
+ await moveS3File({
93601
+ workspace: workspace.workspaceId,
93602
+ srcFileKey,
93603
+ destFileKey,
93604
+ storage: opts.storage
93605
+ });
93606
+ info(colors.green(`Moved ${srcFileKey} -> ${destFileKey}`));
93607
+ }
93608
+ async function info2(opts, fileKey) {
93609
+ if (opts.json)
93610
+ setSilent(true);
93611
+ const workspace = await resolveWorkspace(opts);
93612
+ await requireLogin(opts);
93613
+ const metadata = await loadFileMetadata({
93614
+ workspace: workspace.workspaceId,
93615
+ fileKey,
93616
+ storage: opts.storage
93617
+ });
93618
+ if (opts.json) {
93619
+ console.log(JSON.stringify(metadata));
93620
+ return;
93621
+ }
93622
+ console.log(colors.bold("Key:") + " " + fileKey);
93623
+ console.log(colors.bold("Size:") + " " + formatBytes(metadata.size_in_bytes));
93624
+ console.log(colors.bold("Mime:") + " " + (metadata.mime_type ?? "-"));
93625
+ console.log(colors.bold("Last Modified:") + " " + (metadata.last_modified ? formatTimestamp(metadata.last_modified) : "-"));
93626
+ if (metadata.expires) {
93627
+ console.log(colors.bold("Expires:") + " " + formatTimestamp(metadata.expires));
93628
+ }
93629
+ if (metadata.version_id) {
93630
+ console.log(colors.bold("Version Id:") + " " + metadata.version_id);
93631
+ }
93632
+ }
93633
+ async function preview3(opts, fileKey) {
93634
+ const workspace = await resolveWorkspace(opts);
93635
+ await requireLogin(opts);
93636
+ const result2 = await loadFilePreview({
93637
+ workspace: workspace.workspaceId,
93638
+ fileKey,
93639
+ storage: opts.storage,
93640
+ fileMimeType: opts.mime,
93641
+ readBytesFrom: opts.bytesFrom ?? 0,
93642
+ readBytesLength: opts.bytesLength ?? 128 * 1024,
93643
+ csvSeparator: opts.csvSeparator,
93644
+ csvHasHeader: opts.csvHeader
93645
+ });
93646
+ if (result2.msg) {
93647
+ info(colors.yellow(result2.msg));
93648
+ }
93649
+ if (result2.content != null) {
93650
+ process.stdout.write(result2.content);
93651
+ if (!result2.content.endsWith(`
93652
+ `))
93653
+ process.stdout.write(`
93654
+ `);
93655
+ }
93656
+ }
93657
+ var command41 = new Command().alias("s3").description("Object storage (S3) related commands. Operates on the workspace's default object storage; use --storage to target a configured secondary storage.").action(listStorages).command("list", "List configured object storages for the workspace (default + secondary).").option("--json", "Output as JSON (for piping to jq)").action(listStorages).command("files", "List files in an object storage. Optionally filter by prefix.").alias("ls").arguments("[prefix:string]").option("--json", "Output as JSON (for piping to jq)").option("--max-keys <maxKeys:number>", "Page size (default 100)").option("--marker <marker:string>", "Pagination marker from a previous response").option("--storage <storage:string>", "Secondary storage name (omit for the workspace default)").action(listFiles).command("upload", "Upload a local file to object storage at the given file key.").arguments("<local_path:string> <file_key:string>").option("--storage <storage:string>", "Secondary storage name").option("--content-type <contentType:string>", "Content-Type header to set on the object").option("--content-disposition <contentDisposition:string>", "Content-Disposition header to set on the object").action(upload).command("download", "Download an object to a local file (or stdout). Default output path is the basename of the file key in the current directory.").arguments("<file_key:string> [output_path:string]").option("--storage <storage:string>", "Secondary storage name").option("--stdout", "Write file contents to stdout instead of a file").action(download).command("delete", "Delete an object from object storage. Prompts for confirmation unless --yes is set.").arguments("<file_key:string>").option("--storage <storage:string>", "Secondary storage name").option("--yes", "Skip the confirmation prompt").action(del).command("move", "Move an object within the same storage (rename or relocate by key).").arguments("<src_file_key:string> <dest_file_key:string>").option("--storage <storage:string>", "Secondary storage name").action(move).command("info", "Show metadata (size, mime, last-modified) for an object.").arguments("<file_key:string>").option("--json", "Output as JSON (for piping to jq)").option("--storage <storage:string>", "Secondary storage name").action(info2).command("preview", "Preview the contents of an object (text/CSV). Use --bytes-from / --bytes-length to peek at a slice of binary files.").arguments("<file_key:string>").option("--storage <storage:string>", "Secondary storage name").option("--mime <mime:string>", "Override the detected mime type (e.g. text/csv)").option("--bytes-from <bytesFrom:number>", "Start offset in bytes").option("--bytes-length <bytesLength:number>", "Number of bytes to read").option("--csv-separator <csvSeparator:string>", "CSV column separator (default ,)").option("--csv-header", "Treat the first CSV row as a header").action(preview3);
93658
+ var object_storage_default = command41;
93659
+
93206
93660
  // src/main.ts
93207
93661
  await init_context();
93208
- var VERSION = "1.710.1";
93662
+ var VERSION = "1.712.0";
93209
93663
  async function checkVersionSafe(cmd) {
93210
93664
  const mainCommand = cmd.getMainCommand();
93211
93665
  const upgradeCommand = mainCommand.getCommand("upgrade");
@@ -93222,7 +93676,7 @@ async function checkVersionSafe(cmd) {
93222
93676
  }
93223
93677
  mainCommand.version(`${currentVersion} (New version available: ${latestVersion}. Run '${mainCommand.getName()} upgrade' to upgrade to the latest version!)`);
93224
93678
  }
93225
- var command41 = new Command().name("wmill").action(() => info(`Welcome to Windmill CLI ${VERSION}. Use -h for help.`)).description("Windmill CLI").globalOption("--workspace <workspace:string>", "Specify the target workspace. This overrides the default workspace.").globalOption("--debug --verbose", "Show debug/verbose logs").globalOption("--show-diffs", "Show diff informations when syncing (may show sensitive informations)").globalOption("--token <token:string>", "Specify an API token. This will override any stored token.").globalOption("--base-url <baseUrl:string>", "Specify the base URL of the API. If used, --token and --workspace are required and no local remote/workspace already set will be used.").globalOption("--config-dir <configDir:string>", "Specify a custom config directory. Overrides WMILL_CONFIG_DIR environment variable and default ~/.config location.").env("HEADERS <headers:string>", `Specify headers to use for all requests. e.g: "HEADERS='h1: v1, h2: v2'"`).version(VERSION).versionOption(false).helpOption("-h, --help", "Show this help.", {
93679
+ var command42 = new Command().name("wmill").action(() => info(`Welcome to Windmill CLI ${VERSION}. Use -h for help.`)).description("Windmill CLI").globalOption("--workspace <workspace:string>", "Specify the target workspace. This overrides the default workspace.").globalOption("--debug --verbose", "Show debug/verbose logs").globalOption("--show-diffs", "Show diff informations when syncing (may show sensitive informations)").globalOption("--token <token:string>", "Specify an API token. This will override any stored token.").globalOption("--base-url <baseUrl:string>", "Specify the base URL of the API. If used, --token and --workspace are required and no local remote/workspace already set will be used.").globalOption("--config-dir <configDir:string>", "Specify a custom config directory. Overrides WMILL_CONFIG_DIR environment variable and default ~/.config location.").env("HEADERS <headers:string>", `Specify headers to use for all requests. e.g: "HEADERS='h1: v1, h2: v2'"`).version(VERSION).versionOption(false).helpOption("-h, --help", "Show this help.", {
93226
93680
  action: async function() {
93227
93681
  const self2 = this;
93228
93682
  const long = self2.getRawArgs().includes(`--${self2.getHelpOption()?.name}`);
@@ -93234,7 +93688,7 @@ var command41 = new Command().name("wmill").action(() => info(`Welcome to Windmi
93234
93688
  self2.showHelp({ long });
93235
93689
  self2.exit();
93236
93690
  }
93237
- }).command("init", init_default).command("refresh", refresh_default).command("app", app_default).command("flow", flow_default).command("script", script_default).command("workspace", workspace_default).command("resource", resource_default).command("resource-type", resource_type_default).command("user", user_default).command("variable", variable_default).command("hub", hub_default).command("folder", folder_default).command("schedule", schedule_default).command("trigger", trigger_default).command("dev", dev_default2).command("sync", sync_default).command("lint", lint_default).command("gitsync-settings", gitsync_settings_default).command("protection-rules", protection_rules_default).command("instance", instance_default).command("worker-groups", worker_groups_default).command("workers", workers_default).command("queues", queues_default).command("dependencies", dependencies_default).command("jobs", jobs_default).command("job", job_default).command("group", group_default).command("audit", audit_default).command("token", token_default).command("generate-metadata", generate_metadata_default).command("docs", docs_default).command("config", config_default).command("datatable", datatable_default).command("ducklake", ducklake_default).command("version --version", "Show version information").action(async (opts) => {
93691
+ }).command("init", init_default).command("refresh", refresh_default).command("app", app_default).command("flow", flow_default).command("script", script_default).command("workspace", workspace_default).command("resource", resource_default).command("resource-type", resource_type_default).command("user", user_default).command("variable", variable_default).command("hub", hub_default).command("folder", folder_default).command("schedule", schedule_default).command("trigger", trigger_default).command("dev", dev_default2).command("sync", sync_default).command("lint", lint_default).command("gitsync-settings", gitsync_settings_default).command("protection-rules", protection_rules_default).command("instance", instance_default).command("worker-groups", worker_groups_default).command("workers", workers_default).command("queues", queues_default).command("dependencies", dependencies_default).command("jobs", jobs_default).command("job", job_default).command("group", group_default).command("audit", audit_default).command("token", token_default).command("generate-metadata", generate_metadata_default).command("docs", docs_default).command("config", config_default).command("datatable", datatable_default).command("ducklake", ducklake_default).command("object-storage", object_storage_default).command("version --version", "Show version information").action(async (opts) => {
93238
93692
  console.log("CLI version: " + VERSION);
93239
93693
  try {
93240
93694
  const provider2 = new NpmProvider({ package: "windmill-cli" });
@@ -93264,20 +93718,20 @@ var command41 = new Command().name("wmill").action(() => info(`Welcome to Windmi
93264
93718
  error(e2);
93265
93719
  info("Try running with sudo and otherwise check the result of the command: npm uninstall windmill-cli && npm install -g windmill-cli");
93266
93720
  })).command("completions", new Command().description("Generate shell completions.").command("bash", new Command().description("Generate bash completions.").action(() => {
93267
- process.stdout.write(generateShellCompletions(command41, "bash") + `
93721
+ process.stdout.write(generateShellCompletions(command42, "bash") + `
93268
93722
  `);
93269
93723
  })).command("zsh", new Command().description("Generate zsh completions.").action(() => {
93270
- process.stdout.write(generateShellCompletions(command41, "zsh") + `
93724
+ process.stdout.write(generateShellCompletions(command42, "zsh") + `
93271
93725
  `);
93272
93726
  })).command("fish", new Command().description("Generate fish completions.").action(() => {
93273
- process.stdout.write(generateShellCompletions(command41, "fish") + `
93727
+ process.stdout.write(generateShellCompletions(command42, "fish") + `
93274
93728
  `);
93275
93729
  })));
93276
93730
  async function main2() {
93277
93731
  try {
93278
93732
  const args = process.argv.slice(2);
93279
93733
  if (args.length === 0) {
93280
- command41.showHelp();
93734
+ command42.showHelp();
93281
93735
  }
93282
93736
  const LOG_LEVEL = args.includes("--verbose") || args.includes("--debug") ? "DEBUG" : "INFO";
93283
93737
  setShowDiffs(args.includes("--show-diffs"));
@@ -93295,7 +93749,7 @@ async function main2() {
93295
93749
  const { warnIfPromptsStale: warnIfPromptsStale2 } = await init_freshness().then(() => exports_freshness);
93296
93750
  await warnIfPromptsStale2({ argv: process.argv }).catch(() => {});
93297
93751
  }
93298
- await command41.parse(args);
93752
+ await command42.parse(args);
93299
93753
  } catch (e2) {
93300
93754
  if (e2 && typeof e2 === "object" && "name" in e2 && e2.name === "ApiError") {
93301
93755
  const body = e2.body;
@@ -93331,7 +93785,7 @@ if (isMain()) {
93331
93785
  process.stdin.destroy();
93332
93786
  });
93333
93787
  }
93334
- var main_default = command41;
93788
+ var main_default = command42;
93335
93789
  export {
93336
93790
  add as workspaceAdd,
93337
93791
  workspace_default as workspace,
@@ -93347,6 +93801,7 @@ export {
93347
93801
  push4 as push,
93348
93802
  pull,
93349
93803
  protection_rules_default as protectionRules,
93804
+ object_storage_default as objectStorage,
93350
93805
  lint_default as lint,
93351
93806
  job_default as job,
93352
93807
  instance_default as instance,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "windmill-cli",
3
- "version": "1.710.1",
3
+ "version": "1.712.0",
4
4
  "description": "CLI for Windmill",
5
5
  "license": "Apache 2.0",
6
6
  "type": "module",