@vm0/cli 9.5.0 → 9.5.1

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/index.js +252 -228
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -1878,7 +1878,7 @@ var credentialsByNameContract = c10.router({
1878
1878
  name: credentialNameSchema
1879
1879
  }),
1880
1880
  responses: {
1881
- 204: z13.undefined(),
1881
+ 204: c10.noBody(),
1882
1882
  401: apiErrorSchema,
1883
1883
  404: apiErrorSchema,
1884
1884
  500: apiErrorSchema
@@ -1990,7 +1990,7 @@ var modelProvidersByTypeContract = c11.router({
1990
1990
  type: modelProviderTypeSchema
1991
1991
  }),
1992
1992
  responses: {
1993
- 204: z14.undefined(),
1993
+ 204: c11.noBody(),
1994
1994
  401: apiErrorSchema,
1995
1995
  404: apiErrorSchema,
1996
1996
  500: apiErrorSchema
@@ -2275,7 +2275,7 @@ var schedulesByNameContract = c13.router({
2275
2275
  composeId: z16.string().uuid("Compose ID required")
2276
2276
  }),
2277
2277
  responses: {
2278
- 204: z16.undefined(),
2278
+ 204: c13.noBody(),
2279
2279
  401: apiErrorSchema,
2280
2280
  404: apiErrorSchema
2281
2281
  },
@@ -3246,10 +3246,10 @@ async function getRawHeaders() {
3246
3246
  }
3247
3247
  return headers;
3248
3248
  }
3249
- async function httpGet(path17) {
3249
+ async function httpGet(path16) {
3250
3250
  const baseUrl = await getBaseUrl();
3251
3251
  const headers = await getRawHeaders();
3252
- return fetch(`${baseUrl}${path17}`, {
3252
+ return fetch(`${baseUrl}${path16}`, {
3253
3253
  method: "GET",
3254
3254
  headers
3255
3255
  });
@@ -3754,49 +3754,49 @@ var cliComposeSchema = z24.object({
3754
3754
  function formatZodError(error) {
3755
3755
  const issue = error.issues[0];
3756
3756
  if (!issue) return "Validation failed";
3757
- const path17 = issue.path.join(".");
3757
+ const path16 = issue.path.join(".");
3758
3758
  const message = issue.message;
3759
- if (!path17) return message;
3759
+ if (!path16) return message;
3760
3760
  if (issue.code === "invalid_type") {
3761
3761
  const received = issue.received;
3762
3762
  const isMissing = received === "undefined" || message.includes("received undefined") || message === "Required";
3763
- if (path17 === "version" && isMissing) {
3763
+ if (path16 === "version" && isMissing) {
3764
3764
  return "Missing config.version";
3765
3765
  }
3766
- if (path17 === "agents" && isMissing) {
3766
+ if (path16 === "agents" && isMissing) {
3767
3767
  return "Missing agents object in config";
3768
3768
  }
3769
- if (path17.startsWith("volumes.") && path17.endsWith(".name")) {
3770
- const volumeKey = path17.split(".")[1];
3769
+ if (path16.startsWith("volumes.") && path16.endsWith(".name")) {
3770
+ const volumeKey = path16.split(".")[1];
3771
3771
  return `Volume "${volumeKey}" must have a 'name' field (string)`;
3772
3772
  }
3773
- if (path17.startsWith("volumes.") && path17.endsWith(".version")) {
3774
- const volumeKey = path17.split(".")[1];
3773
+ if (path16.startsWith("volumes.") && path16.endsWith(".version")) {
3774
+ const volumeKey = path16.split(".")[1];
3775
3775
  return `Volume "${volumeKey}" must have a 'version' field (string)`;
3776
3776
  }
3777
3777
  if (issue.expected === "array") {
3778
- const fieldName = path17.replace(/^agents\.[^.]+\./, "agent.");
3778
+ const fieldName = path16.replace(/^agents\.[^.]+\./, "agent.");
3779
3779
  return `${fieldName} must be an array`;
3780
3780
  }
3781
3781
  if (issue.expected === "string" && received === "number") {
3782
- const fieldName = path17.replace(/^agents\.[^.]+\./, "agent.");
3782
+ const fieldName = path16.replace(/^agents\.[^.]+\./, "agent.");
3783
3783
  const match = fieldName.match(/^(agent\.[^.]+)\.\d+$/);
3784
3784
  if (match) {
3785
3785
  return `Each entry in ${match[1]?.replace("agent.", "")} must be a string`;
3786
3786
  }
3787
3787
  }
3788
3788
  }
3789
- if (issue.code === "invalid_key" && path17.startsWith("agents.")) {
3789
+ if (issue.code === "invalid_key" && path16.startsWith("agents.")) {
3790
3790
  return "Invalid agent name format. Must be 3-64 characters, letters, numbers, and hyphens only. Must start and end with letter or number.";
3791
3791
  }
3792
- if (message === "Invalid key in record" && path17.startsWith("agents.")) {
3792
+ if (message === "Invalid key in record" && path16.startsWith("agents.")) {
3793
3793
  return "Invalid agent name format. Must be 3-64 characters, letters, numbers, and hyphens only. Must start and end with letter or number.";
3794
3794
  }
3795
3795
  if (issue.code === "custom") {
3796
3796
  return message;
3797
3797
  }
3798
- if (path17.startsWith("agents.")) {
3799
- const cleanPath = path17.replace(/^agents\.[^.]+\./, "agent.");
3798
+ if (path16.startsWith("agents.")) {
3799
+ const cleanPath = path16.replace(/^agents\.[^.]+\./, "agent.");
3800
3800
  if (message.startsWith("Invalid input:")) {
3801
3801
  const match = message.match(/expected (\w+), received (\w+)/);
3802
3802
  if (match && match[1] === "string" && match[2] === "number") {
@@ -3808,7 +3808,7 @@ function formatZodError(error) {
3808
3808
  }
3809
3809
  return `${cleanPath}: ${message}`;
3810
3810
  }
3811
- return `${path17}: ${message}`;
3811
+ return `${path16}: ${message}`;
3812
3812
  }
3813
3813
  function validateAgentName(name) {
3814
3814
  return cliAgentNameSchema.safeParse(name).success;
@@ -6007,7 +6007,7 @@ var ApiClient = class {
6007
6007
  /**
6008
6008
  * Generic GET request
6009
6009
  */
6010
- async get(path17) {
6010
+ async get(path16) {
6011
6011
  const baseUrl = await this.getBaseUrl();
6012
6012
  const token = await getToken();
6013
6013
  if (!token) {
@@ -6020,7 +6020,7 @@ var ApiClient = class {
6020
6020
  if (bypassSecret) {
6021
6021
  headers["x-vercel-protection-bypass"] = bypassSecret;
6022
6022
  }
6023
- return fetch(`${baseUrl}${path17}`, {
6023
+ return fetch(`${baseUrl}${path16}`, {
6024
6024
  method: "GET",
6025
6025
  headers
6026
6026
  });
@@ -6028,7 +6028,7 @@ var ApiClient = class {
6028
6028
  /**
6029
6029
  * Generic POST request
6030
6030
  */
6031
- async post(path17, options) {
6031
+ async post(path16, options) {
6032
6032
  const baseUrl = await this.getBaseUrl();
6033
6033
  const token = await getToken();
6034
6034
  if (!token) {
@@ -6044,7 +6044,7 @@ var ApiClient = class {
6044
6044
  if (bypassSecret) {
6045
6045
  headers["x-vercel-protection-bypass"] = bypassSecret;
6046
6046
  }
6047
- return fetch(`${baseUrl}${path17}`, {
6047
+ return fetch(`${baseUrl}${path16}`, {
6048
6048
  method: "POST",
6049
6049
  headers,
6050
6050
  body: options?.body
@@ -6053,7 +6053,7 @@ var ApiClient = class {
6053
6053
  /**
6054
6054
  * Generic DELETE request
6055
6055
  */
6056
- async delete(path17) {
6056
+ async delete(path16) {
6057
6057
  const baseUrl = await this.getBaseUrl();
6058
6058
  const token = await getToken();
6059
6059
  if (!token) {
@@ -6066,7 +6066,7 @@ var ApiClient = class {
6066
6066
  if (bypassSecret) {
6067
6067
  headers["x-vercel-protection-bypass"] = bypassSecret;
6068
6068
  }
6069
- return fetch(`${baseUrl}${path17}`, {
6069
+ return fetch(`${baseUrl}${path16}`, {
6070
6070
  method: "DELETE",
6071
6071
  headers
6072
6072
  });
@@ -7871,8 +7871,10 @@ function execVm0Command(args, options = {}) {
7871
7871
  }
7872
7872
  function execVm0RunWithCapture(args, options = {}) {
7873
7873
  return new Promise((resolve, reject) => {
7874
+ const env = process.stdout.isTTY ? { ...process.env, FORCE_COLOR: "1" } : process.env;
7874
7875
  const proc = spawn2("vm0", args, {
7875
7876
  cwd: options.cwd,
7877
+ env,
7876
7878
  stdio: ["inherit", "pipe", "pipe"],
7877
7879
  shell: process.platform === "win32"
7878
7880
  });
@@ -8163,7 +8165,7 @@ var cookAction = new Command27().name("cook").description("Quick start: prepare,
8163
8165
  ).option("-y, --yes", "Skip confirmation prompts").addOption(new Option4("--debug-no-mock-claude").hideHelp()).addOption(new Option4("--no-auto-update").hideHelp()).action(
8164
8166
  async (prompt, options) => {
8165
8167
  if (!options.noAutoUpdate) {
8166
- const shouldExit = await checkAndUpgrade("9.5.0", prompt);
8168
+ const shouldExit = await checkAndUpgrade("9.5.1", prompt);
8167
8169
  if (shouldExit) {
8168
8170
  process.exit(0);
8169
8171
  }
@@ -10744,31 +10746,30 @@ import { Command as Command56 } from "commander";
10744
10746
  import chalk56 from "chalk";
10745
10747
  import { mkdir as mkdir7 } from "fs/promises";
10746
10748
  import { existsSync as existsSync11 } from "fs";
10747
- import path16 from "path";
10748
10749
 
10749
10750
  // src/lib/ui/welcome-box.ts
10750
10751
  import chalk53 from "chalk";
10751
10752
  var gradientColors = [
10752
- chalk53.hex("#FF9650"),
10753
+ chalk53.hex("#FFAB5E"),
10753
10754
  // Line 1 - lightest
10754
- chalk53.hex("#FF7832"),
10755
+ chalk53.hex("#FF9642"),
10755
10756
  // Line 2
10756
- chalk53.hex("#FF7832"),
10757
+ chalk53.hex("#FF8228"),
10757
10758
  // Line 3
10758
- chalk53.hex("#ED4E01"),
10759
- // Line 4 - brand orange
10760
- chalk53.hex("#ED4E01"),
10759
+ chalk53.hex("#FF6D0A"),
10760
+ // Line 4
10761
+ chalk53.hex("#E85D00"),
10761
10762
  // Line 5
10762
- chalk53.hex("#C83C00")
10763
+ chalk53.hex("#CC4E00")
10763
10764
  // Line 6 - darkest
10764
10765
  ];
10765
10766
  var vm0LogoLines = [
10766
- "\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557",
10767
+ "\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 ",
10767
10768
  "\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557",
10768
10769
  "\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2588\u2588\u2588\u2588\u2554\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551",
10769
10770
  "\u255A\u2588\u2588\u2557 \u2588\u2588\u2554\u255D\u2588\u2588\u2551\u255A\u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551",
10770
10771
  " \u255A\u2588\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2551 \u255A\u2550\u255D \u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D",
10771
- " \u255A\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D"
10772
+ " \u255A\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D "
10772
10773
  ];
10773
10774
  function renderVm0Banner() {
10774
10775
  console.log();
@@ -10781,73 +10782,79 @@ function renderVm0Banner() {
10781
10782
  function renderOnboardWelcome() {
10782
10783
  renderVm0Banner();
10783
10784
  console.log(` ${chalk53.bold("Welcome to VM0!")}`);
10784
- console.log(` ${chalk53.dim("Let's create your first agent.")}`);
10785
+ console.log(
10786
+ ` ${chalk53.dim("Build agentic workflows using natural language.")}`
10787
+ );
10785
10788
  console.log();
10786
10789
  }
10787
10790
 
10788
- // src/lib/ui/progress-line.ts
10791
+ // src/lib/ui/step-runner.ts
10789
10792
  import chalk54 from "chalk";
10790
- function createProgressiveProgress(interactive = true) {
10791
- let currentLabel = "";
10792
- let detailLineCount = 0;
10793
- let isFinalStep = false;
10794
- const clearDetails = () => {
10795
- if (!interactive || detailLineCount === 0) return;
10796
- process.stdout.write(`\x1B[${detailLineCount + 1}A`);
10797
- process.stdout.write(`\x1B[K`);
10798
- };
10799
- const clearDetailLines = () => {
10800
- if (!interactive) return;
10801
- for (let i = 0; i < detailLineCount; i++) {
10802
- process.stdout.write(`
10803
- \x1B[K`);
10804
- }
10805
- if (detailLineCount > 0) {
10806
- process.stdout.write(`\x1B[${detailLineCount}A`);
10793
+ function createStepRunner(options = true) {
10794
+ const opts = typeof options === "boolean" ? { interactive: options } : options;
10795
+ const interactive = opts.interactive ?? true;
10796
+ const headerFn = opts.header;
10797
+ const completedSteps = [];
10798
+ function redrawCompletedSteps(isFinal) {
10799
+ process.stdout.write("\x1B[2J\x1B[H");
10800
+ if (headerFn) {
10801
+ console.log();
10802
+ headerFn();
10803
+ console.log();
10807
10804
  }
10808
- };
10809
- return {
10810
- startStep: (label) => {
10811
- currentLabel = label;
10812
- detailLineCount = 0;
10813
- isFinalStep = false;
10814
- console.log(chalk54.yellow(`\u25CB ${label}`));
10815
- },
10816
- detail: (message) => {
10817
- console.log(chalk54.dim(`\u2502 ${message}`));
10818
- detailLineCount++;
10819
- },
10820
- completeStep: () => {
10821
- if (interactive && detailLineCount > 0) {
10822
- clearDetails();
10823
- } else if (interactive) {
10824
- process.stdout.write(`\x1B[1A\x1B[K`);
10805
+ for (const [i, step] of completedSteps.entries()) {
10806
+ if (step.failed) {
10807
+ console.log(chalk54.red(`\u2717 ${step.label}`));
10808
+ } else {
10809
+ console.log(chalk54.green(`\u25CF ${step.label}`));
10825
10810
  }
10826
- console.log(chalk54.green(`\u25CF ${currentLabel}`));
10827
- if (interactive && detailLineCount > 0) {
10828
- clearDetailLines();
10811
+ const isLastStep = i === completedSteps.length - 1;
10812
+ if (!isLastStep || !isFinal) {
10813
+ console.log(chalk54.dim("\u2502"));
10829
10814
  }
10830
- if (!isFinalStep) {
10815
+ }
10816
+ }
10817
+ async function executeStep(label, fn, isFinal) {
10818
+ let stepFailed = false;
10819
+ console.log(chalk54.yellow(`\u25CB ${label}`));
10820
+ const ctx = {
10821
+ connector() {
10831
10822
  console.log(chalk54.dim("\u2502"));
10823
+ },
10824
+ detail(message) {
10825
+ console.log(`${chalk54.dim("\u2502")} ${message}`);
10826
+ },
10827
+ async prompt(promptFn) {
10828
+ return await promptFn();
10832
10829
  }
10833
- currentLabel = "";
10834
- detailLineCount = 0;
10835
- },
10836
- failStep: () => {
10837
- if (interactive && detailLineCount > 0) {
10838
- clearDetails();
10839
- } else if (interactive) {
10840
- process.stdout.write(`\x1B[1A\x1B[K`);
10841
- }
10842
- console.log(chalk54.red(`\u2717 ${currentLabel}`));
10843
- if (interactive && detailLineCount > 0) {
10844
- clearDetailLines();
10845
- }
10846
- currentLabel = "";
10847
- detailLineCount = 0;
10830
+ };
10831
+ try {
10832
+ await fn(ctx);
10833
+ } catch (error) {
10834
+ stepFailed = true;
10835
+ throw error;
10836
+ } finally {
10837
+ completedSteps.push({ label, failed: stepFailed });
10838
+ if (interactive) {
10839
+ redrawCompletedSteps(isFinal);
10840
+ } else {
10841
+ if (stepFailed) {
10842
+ console.log(chalk54.red(`\u2717 ${label}`));
10843
+ } else {
10844
+ console.log(chalk54.green(`\u25CF ${label}`));
10845
+ }
10846
+ if (!isFinal) {
10847
+ console.log(chalk54.dim("\u2502"));
10848
+ }
10849
+ }
10850
+ }
10851
+ }
10852
+ return {
10853
+ async step(label, fn) {
10854
+ await executeStep(label, fn, false);
10848
10855
  },
10849
- setFinalStep: () => {
10850
- isFinalStep = true;
10856
+ async finalStep(label, fn) {
10857
+ await executeStep(label, fn, true);
10851
10858
  }
10852
10859
  };
10853
10860
  }
@@ -11084,148 +11091,162 @@ async function installVm0Plugin(scope = "user", cwd) {
11084
11091
  // src/commands/onboard/index.ts
11085
11092
  var DEFAULT_AGENT_NAME = "my-vm0-agent";
11086
11093
  async function handleAuthentication(ctx) {
11087
- ctx.progress.startStep("Authentication");
11088
- const authenticated = await isAuthenticated();
11089
- if (authenticated) {
11090
- ctx.progress.completeStep();
11091
- return;
11092
- }
11093
- if (!ctx.interactive) {
11094
- ctx.progress.failStep();
11095
- console.error(chalk56.red("Error: Not authenticated"));
11096
- console.error("Run 'vm0 auth login' first or set VM0_TOKEN");
11097
- process.exit(1);
11098
- }
11099
- await runAuthFlow({
11100
- onInitiating: () => {
11101
- },
11102
- onDeviceCodeReady: (url, code, expiresIn) => {
11103
- ctx.progress.detail(`Visit: ${url}`);
11104
- ctx.progress.detail(`Code: ${code}`);
11105
- ctx.progress.detail(`Expires in ${expiresIn} minutes`);
11106
- ctx.progress.detail("Waiting for confirmation...");
11107
- },
11108
- onPolling: () => {
11109
- },
11110
- onSuccess: () => {
11111
- },
11112
- onError: (error) => {
11113
- ctx.progress.failStep();
11114
- console.error(chalk56.red(`
11115
- ${error.message}`));
11094
+ await ctx.runner.step("Authenticate to vm0.ai", async (step) => {
11095
+ const authenticated = await isAuthenticated();
11096
+ if (authenticated) {
11097
+ return;
11098
+ }
11099
+ if (!ctx.interactive) {
11100
+ console.error(chalk56.red("Error: Not authenticated"));
11101
+ console.error("Run 'vm0 auth login' first or set VM0_TOKEN");
11116
11102
  process.exit(1);
11117
11103
  }
11104
+ await runAuthFlow({
11105
+ onInitiating: () => {
11106
+ },
11107
+ onDeviceCodeReady: (url, code, expiresIn) => {
11108
+ step.detail(`Copy code: ${chalk56.cyan.bold(code)}`);
11109
+ step.detail(`Open: ${chalk56.cyan(url)}`);
11110
+ step.detail(chalk56.dim(`Expires in ${expiresIn} minutes`));
11111
+ },
11112
+ onPolling: () => {
11113
+ },
11114
+ onSuccess: () => {
11115
+ },
11116
+ onError: (error) => {
11117
+ console.error(chalk56.red(`
11118
+ ${error.message}`));
11119
+ process.exit(1);
11120
+ }
11121
+ });
11118
11122
  });
11119
- ctx.progress.completeStep();
11120
11123
  }
11121
11124
  async function handleModelProvider(ctx) {
11122
- ctx.progress.startStep("Model Provider Setup");
11123
- const providerStatus = await checkModelProviderStatus();
11124
- if (providerStatus.hasProvider) {
11125
- ctx.progress.completeStep();
11126
- return;
11127
- }
11128
- if (!ctx.interactive) {
11129
- ctx.progress.failStep();
11130
- console.error(chalk56.red("Error: No model provider configured"));
11131
- console.error("Run 'vm0 model-provider setup' first");
11132
- process.exit(1);
11133
- }
11134
- ctx.progress.detail("Setup required...");
11135
- const choices = getProviderChoices();
11136
- const providerType = await promptSelect(
11137
- "Select provider type:",
11138
- choices.map((c20) => ({
11139
- title: c20.label,
11140
- value: c20.type,
11141
- description: c20.helpText
11142
- }))
11143
- );
11144
- if (!providerType) {
11145
- process.exit(0);
11146
- }
11147
- const selectedChoice = choices.find((c20) => c20.type === providerType);
11148
- const credential = await promptPassword(
11149
- `Enter your ${selectedChoice?.credentialLabel ?? "credential"}:`
11150
- );
11151
- if (!credential) {
11152
- console.log(chalk56.dim("Cancelled"));
11153
- process.exit(0);
11154
- }
11155
- const result = await setupModelProvider(providerType, credential);
11156
- ctx.progress.detail(
11157
- `${providerType} ${result.created ? "created" : "updated"}${result.isDefault ? ` (default for ${result.framework})` : ""}`
11158
- );
11159
- ctx.progress.completeStep();
11160
- }
11161
- async function handleAgentCreation(ctx) {
11162
- ctx.progress.startStep("Create Agent");
11163
- let agentName = ctx.options.name ?? DEFAULT_AGENT_NAME;
11164
- if (!ctx.options.yes && !ctx.options.name && ctx.interactive) {
11165
- const inputName = await promptText(
11166
- "Enter agent name:",
11167
- DEFAULT_AGENT_NAME,
11168
- (value) => {
11169
- if (!validateAgentName(value)) {
11170
- return "Invalid name: 3-64 chars, alphanumeric + hyphens, start/end with letter/number";
11171
- }
11172
- return true;
11125
+ await ctx.runner.step("Set Up Model Provider", async (step) => {
11126
+ const providerStatus = await checkModelProviderStatus();
11127
+ if (providerStatus.hasProvider) {
11128
+ return;
11129
+ }
11130
+ if (!ctx.interactive) {
11131
+ console.error(chalk56.red("Error: No model provider configured"));
11132
+ console.error("Run 'vm0 model-provider setup' first");
11133
+ process.exit(1);
11134
+ }
11135
+ const choices = getProviderChoices();
11136
+ step.connector();
11137
+ const providerType = await step.prompt(
11138
+ () => promptSelect(
11139
+ "Select provider type:",
11140
+ choices.map((c20) => ({
11141
+ title: c20.label,
11142
+ value: c20.type
11143
+ }))
11144
+ )
11145
+ );
11146
+ if (!providerType) {
11147
+ process.exit(0);
11148
+ }
11149
+ const selectedChoice = choices.find((c20) => c20.type === providerType);
11150
+ if (selectedChoice?.helpText) {
11151
+ for (const line of selectedChoice.helpText.split("\n")) {
11152
+ step.detail(chalk56.dim(line));
11173
11153
  }
11154
+ }
11155
+ const credential = await step.prompt(
11156
+ () => promptPassword(
11157
+ `Enter your ${selectedChoice?.credentialLabel ?? "credential"}:`
11158
+ )
11174
11159
  );
11175
- if (!inputName) {
11160
+ if (!credential) {
11161
+ console.log(chalk56.dim("Cancelled"));
11176
11162
  process.exit(0);
11177
11163
  }
11178
- agentName = inputName;
11179
- }
11180
- if (!validateAgentName(agentName)) {
11181
- ctx.progress.failStep();
11182
- console.error(
11183
- chalk56.red(
11184
- "Invalid agent name: must be 3-64 chars, alphanumeric + hyphens"
11164
+ const result = await setupModelProvider(providerType, credential);
11165
+ step.detail(
11166
+ chalk56.green(
11167
+ `${providerType} ${result.created ? "created" : "updated"}${result.isDefault ? ` (default for ${result.framework})` : ""}`
11185
11168
  )
11186
11169
  );
11187
- process.exit(1);
11188
- }
11189
- if (existsSync11(agentName)) {
11190
- ctx.progress.failStep();
11191
- console.error(chalk56.red(`${agentName}/ already exists`));
11192
- console.log();
11193
- console.log("Remove it first or choose a different name:");
11194
- console.log(chalk56.cyan(` rm -rf ${agentName}`));
11195
- process.exit(1);
11196
- }
11197
- await mkdir7(agentName, { recursive: true });
11198
- ctx.progress.detail(`Created ${agentName}/`);
11199
- ctx.progress.completeStep();
11170
+ });
11171
+ }
11172
+ async function handleAgentCreation(ctx) {
11173
+ let agentName = ctx.options.name ?? DEFAULT_AGENT_NAME;
11174
+ await ctx.runner.step("Create New Project", async (step) => {
11175
+ if (!ctx.options.yes && !ctx.options.name && ctx.interactive) {
11176
+ let folderExists = true;
11177
+ while (folderExists) {
11178
+ step.connector();
11179
+ const inputName = await step.prompt(
11180
+ () => promptText(
11181
+ "Enter project name:",
11182
+ DEFAULT_AGENT_NAME,
11183
+ (value) => {
11184
+ if (!validateAgentName(value)) {
11185
+ return "Invalid name: 3-64 chars, alphanumeric + hyphens, start/end with letter/number";
11186
+ }
11187
+ return true;
11188
+ }
11189
+ )
11190
+ );
11191
+ if (!inputName) {
11192
+ process.exit(0);
11193
+ }
11194
+ agentName = inputName;
11195
+ if (existsSync11(agentName)) {
11196
+ step.detail(
11197
+ chalk56.yellow(`${agentName}/ already exists, choose another name`)
11198
+ );
11199
+ } else {
11200
+ folderExists = false;
11201
+ }
11202
+ }
11203
+ } else {
11204
+ if (!validateAgentName(agentName)) {
11205
+ console.error(
11206
+ chalk56.red(
11207
+ "Invalid agent name: must be 3-64 chars, alphanumeric + hyphens"
11208
+ )
11209
+ );
11210
+ process.exit(1);
11211
+ }
11212
+ if (existsSync11(agentName)) {
11213
+ console.error(chalk56.red(`${agentName}/ already exists`));
11214
+ console.log();
11215
+ console.log("Remove it first or choose a different name:");
11216
+ console.log(chalk56.cyan(` rm -rf ${agentName}`));
11217
+ process.exit(1);
11218
+ }
11219
+ }
11220
+ await mkdir7(agentName, { recursive: true });
11221
+ step.detail(chalk56.green(`Created ${agentName}/`));
11222
+ });
11200
11223
  return agentName;
11201
11224
  }
11202
11225
  async function handlePluginInstallation(ctx, agentName) {
11203
- ctx.progress.startStep("Claude Plugin Install");
11204
- let shouldInstall = true;
11205
- if (!ctx.options.yes && ctx.interactive) {
11206
- const confirmed = await promptConfirm(
11207
- "Install VM0 Claude Plugin?",
11208
- true
11209
- // default: Yes
11210
- );
11211
- shouldInstall = confirmed ?? true;
11212
- }
11213
- if (!shouldInstall) {
11214
- ctx.progress.detail("Skipped");
11215
- ctx.progress.completeStep();
11216
- return;
11217
- }
11218
- const scope = "project";
11219
- try {
11220
- const agentDir = path16.resolve(process.cwd(), agentName);
11221
- const result = await installVm0Plugin(scope, agentDir);
11222
- ctx.progress.detail(
11223
- `Installed ${result.pluginId} (scope: ${result.scope})`
11224
- );
11225
- } catch (error) {
11226
- handlePluginError(error);
11227
- }
11228
- ctx.progress.completeStep();
11226
+ await ctx.runner.step("Install Claude Plugin", async (step) => {
11227
+ let shouldInstall = true;
11228
+ if (!ctx.options.yes && ctx.interactive) {
11229
+ step.connector();
11230
+ const confirmed = await step.prompt(
11231
+ () => promptConfirm("Install VM0 Claude Plugin?", true)
11232
+ );
11233
+ shouldInstall = confirmed ?? true;
11234
+ }
11235
+ if (!shouldInstall) {
11236
+ step.detail(chalk56.dim("Skipped"));
11237
+ return;
11238
+ }
11239
+ const scope = "project";
11240
+ try {
11241
+ const agentDir = `${process.cwd()}/${agentName}`;
11242
+ const result = await installVm0Plugin(scope, agentDir);
11243
+ step.detail(
11244
+ chalk56.green(`Installed ${result.pluginId} (scope: ${result.scope})`)
11245
+ );
11246
+ } catch (error) {
11247
+ handlePluginError(error);
11248
+ }
11249
+ });
11229
11250
  }
11230
11251
  function printNextSteps(agentName) {
11231
11252
  console.log();
@@ -11239,19 +11260,22 @@ function printNextSteps(agentName) {
11239
11260
  var onboardCommand = new Command56().name("onboard").description("Guided setup for new VM0 users").option("-y, --yes", "Skip confirmation prompts").option("--name <name>", `Agent name (default: ${DEFAULT_AGENT_NAME})`).action(async (options) => {
11240
11261
  const interactive = isInteractive();
11241
11262
  if (interactive) {
11263
+ process.stdout.write("\x1B[2J\x1B[H");
11242
11264
  console.log();
11243
11265
  renderOnboardWelcome();
11244
11266
  console.log();
11245
11267
  }
11246
- const progress = createProgressiveProgress(interactive);
11247
- const ctx = { interactive, options, progress };
11268
+ const runner = createStepRunner({
11269
+ interactive,
11270
+ header: interactive ? renderOnboardWelcome : void 0
11271
+ });
11272
+ const ctx = { interactive, options, runner };
11248
11273
  await handleAuthentication(ctx);
11249
11274
  await handleModelProvider(ctx);
11250
11275
  const agentName = await handleAgentCreation(ctx);
11251
11276
  await handlePluginInstallation(ctx, agentName);
11252
- progress.startStep("Complete");
11253
- progress.setFinalStep();
11254
- progress.completeStep();
11277
+ await ctx.runner.finalStep("Completed", async () => {
11278
+ });
11255
11279
  printNextSteps(agentName);
11256
11280
  });
11257
11281
 
@@ -11281,7 +11305,7 @@ var setupClaudeCommand = new Command57().name("setup-claude").description("Insta
11281
11305
 
11282
11306
  // src/index.ts
11283
11307
  var program = new Command58();
11284
- program.name("vm0").description("VM0 CLI - Build and run agents with natural language").version("9.5.0");
11308
+ program.name("vm0").description("VM0 CLI - Build and run agents with natural language").version("9.5.1");
11285
11309
  program.addCommand(authCommand);
11286
11310
  program.addCommand(infoCommand);
11287
11311
  program.addCommand(composeCommand);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vm0/cli",
3
- "version": "9.5.0",
3
+ "version": "9.5.1",
4
4
  "description": "CLI application",
5
5
  "repository": {
6
6
  "type": "git",