@vm0/cli 9.4.1 → 9.5.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/index.js +475 -439
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -4382,175 +4382,201 @@ function getSecretsFromComposeContent(content) {
4382
4382
  const grouped = groupVariablesBySource(refs);
4383
4383
  return new Set(grouped.secrets.map((r) => r.name));
4384
4384
  }
4385
- var composeCommand = new Command7().name("compose").description("Create or update agent compose (e.g., vm0.yaml)").argument("<agent-yaml>", "Path to agent YAML file").option("-y, --yes", "Skip confirmation prompts for skill requirements").action(async (configFile, options) => {
4385
+ async function loadAndValidateConfig(configFile) {
4386
+ if (!existsSync3(configFile)) {
4387
+ console.error(chalk3.red(`\u2717 Config file not found: ${configFile}`));
4388
+ process.exit(1);
4389
+ }
4390
+ const content = await readFile4(configFile, "utf8");
4391
+ let config;
4386
4392
  try {
4387
- if (!existsSync3(configFile)) {
4388
- console.error(chalk3.red(`\u2717 Config file not found: ${configFile}`));
4389
- process.exit(1);
4390
- }
4391
- const content = await readFile4(configFile, "utf8");
4392
- let config;
4393
- try {
4394
- config = parseYaml2(content);
4395
- } catch (error) {
4396
- console.error(chalk3.red("\u2717 Invalid YAML format"));
4397
- if (error instanceof Error) {
4398
- console.error(chalk3.dim(` ${error.message}`));
4399
- }
4400
- process.exit(1);
4401
- }
4402
- const validation = validateAgentCompose(config);
4403
- if (!validation.valid) {
4404
- console.error(chalk3.red(`\u2717 ${validation.error}`));
4405
- process.exit(1);
4393
+ config = parseYaml2(content);
4394
+ } catch (error) {
4395
+ console.error(chalk3.red("\u2717 Invalid YAML format"));
4396
+ if (error instanceof Error) {
4397
+ console.error(chalk3.dim(` ${error.message}`));
4406
4398
  }
4407
- const cfg = config;
4408
- const agentsConfig = cfg.agents;
4409
- for (const [name, agentConfig] of Object.entries(agentsConfig)) {
4410
- const image = agentConfig.image;
4411
- if (image) {
4412
- console.log(
4413
- chalk3.yellow(
4414
- `\u26A0 Agent "${name}": 'image' field is deprecated. Use 'apps' field for pre-installed tools.`
4415
- )
4416
- );
4417
- const warning = getLegacySystemTemplateWarning(image);
4418
- if (warning) {
4419
- console.log(chalk3.yellow(` ${warning}`));
4420
- }
4399
+ process.exit(1);
4400
+ }
4401
+ const validation = validateAgentCompose(config);
4402
+ if (!validation.valid) {
4403
+ console.error(chalk3.red(`\u2717 ${validation.error}`));
4404
+ process.exit(1);
4405
+ }
4406
+ const cfg = config;
4407
+ const agentsConfig = cfg.agents;
4408
+ const agentName = Object.keys(agentsConfig)[0];
4409
+ const agent = agentsConfig[agentName];
4410
+ const basePath = dirname2(configFile);
4411
+ return { config, agentName, agent, basePath };
4412
+ }
4413
+ function checkLegacyImageFormat(config) {
4414
+ const cfg = config;
4415
+ const agentsConfig = cfg.agents;
4416
+ for (const [name, agentConfig] of Object.entries(agentsConfig)) {
4417
+ const image = agentConfig.image;
4418
+ if (image) {
4419
+ console.log(
4420
+ chalk3.yellow(
4421
+ `\u26A0 Agent "${name}": 'image' field is deprecated. Use 'apps' field for pre-installed tools.`
4422
+ )
4423
+ );
4424
+ const warning = getLegacySystemTemplateWarning(image);
4425
+ if (warning) {
4426
+ console.log(chalk3.yellow(` ${warning}`));
4421
4427
  }
4422
4428
  }
4423
- const agents = agentsConfig;
4424
- const agentName = Object.keys(agents)[0];
4425
- const agent = agents[agentName];
4426
- const basePath = dirname2(configFile);
4427
- if (agent.instructions) {
4428
- const instructionsPath = agent.instructions;
4429
- const framework = agent.framework;
4430
- console.log(`Uploading instructions: ${instructionsPath}`);
4431
- const result = await uploadInstructions(
4432
- agentName,
4433
- instructionsPath,
4434
- basePath,
4435
- framework
4436
- );
4429
+ }
4430
+ }
4431
+ async function uploadAssets(agentName, agent, basePath) {
4432
+ if (agent.instructions) {
4433
+ console.log(`Uploading instructions: ${agent.instructions}`);
4434
+ const result = await uploadInstructions(
4435
+ agentName,
4436
+ agent.instructions,
4437
+ basePath,
4438
+ agent.framework
4439
+ );
4440
+ console.log(
4441
+ chalk3.green(
4442
+ `\u2713 Instructions ${result.action === "deduplicated" ? "(unchanged)" : "uploaded"}: ${result.versionId.slice(0, 8)}`
4443
+ )
4444
+ );
4445
+ }
4446
+ const skillResults = [];
4447
+ if (agent.skills && Array.isArray(agent.skills)) {
4448
+ console.log(`Uploading ${agent.skills.length} skill(s)...`);
4449
+ for (const skillUrl of agent.skills) {
4450
+ console.log(chalk3.dim(` Downloading: ${skillUrl}`));
4451
+ const result = await uploadSkill(skillUrl);
4452
+ skillResults.push(result);
4437
4453
  console.log(
4438
4454
  chalk3.green(
4439
- `\u2713 Instructions ${result.action === "deduplicated" ? "(unchanged)" : "uploaded"}: ${result.versionId.slice(0, 8)}`
4455
+ ` \u2713 Skill ${result.action === "deduplicated" ? "(unchanged)" : "uploaded"}: ${result.skillName} (${result.versionId.slice(0, 8)})`
4440
4456
  )
4441
4457
  );
4442
4458
  }
4443
- const skillResults = [];
4444
- if (agent.skills && Array.isArray(agent.skills)) {
4445
- const skillUrls = agent.skills;
4446
- console.log(`Uploading ${skillUrls.length} skill(s)...`);
4447
- for (const skillUrl of skillUrls) {
4448
- console.log(chalk3.dim(` Downloading: ${skillUrl}`));
4449
- const result = await uploadSkill(skillUrl);
4450
- skillResults.push(result);
4451
- console.log(
4452
- chalk3.green(
4453
- ` \u2713 Skill ${result.action === "deduplicated" ? "(unchanged)" : "uploaded"}: ${result.skillName} (${result.versionId.slice(0, 8)})`
4454
- )
4455
- );
4456
- }
4457
- }
4458
- const skillSecrets = /* @__PURE__ */ new Map();
4459
- const skillVars = /* @__PURE__ */ new Map();
4460
- for (const result of skillResults) {
4461
- const { frontmatter, skillName } = result;
4462
- if (frontmatter.vm0_secrets) {
4463
- for (const secret of frontmatter.vm0_secrets) {
4464
- if (!skillSecrets.has(secret)) {
4465
- skillSecrets.set(secret, []);
4466
- }
4467
- skillSecrets.get(secret).push(skillName);
4459
+ }
4460
+ return skillResults;
4461
+ }
4462
+ async function collectSkillVariables(skillResults, environment, agentName) {
4463
+ const skillSecrets = /* @__PURE__ */ new Map();
4464
+ const skillVars = /* @__PURE__ */ new Map();
4465
+ for (const result of skillResults) {
4466
+ const { frontmatter, skillName } = result;
4467
+ if (frontmatter.vm0_secrets) {
4468
+ for (const secret of frontmatter.vm0_secrets) {
4469
+ if (!skillSecrets.has(secret)) {
4470
+ skillSecrets.set(secret, []);
4468
4471
  }
4472
+ skillSecrets.get(secret).push(skillName);
4469
4473
  }
4470
- if (frontmatter.vm0_vars) {
4471
- for (const varName of frontmatter.vm0_vars) {
4472
- if (!skillVars.has(varName)) {
4473
- skillVars.set(varName, []);
4474
- }
4475
- skillVars.get(varName).push(skillName);
4474
+ }
4475
+ if (frontmatter.vm0_vars) {
4476
+ for (const varName of frontmatter.vm0_vars) {
4477
+ if (!skillVars.has(varName)) {
4478
+ skillVars.set(varName, []);
4476
4479
  }
4480
+ skillVars.get(varName).push(skillName);
4477
4481
  }
4478
4482
  }
4479
- const environment = agent.environment || {};
4480
- const newSecrets = [...skillSecrets.entries()].filter(
4481
- ([name]) => !(name in environment)
4482
- );
4483
- const newVars = [...skillVars.entries()].filter(
4484
- ([name]) => !(name in environment)
4485
- );
4486
- let headSecrets = /* @__PURE__ */ new Set();
4487
- const existingCompose = await getComposeByName(agentName);
4488
- if (existingCompose?.content) {
4489
- headSecrets = getSecretsFromComposeContent(existingCompose.content);
4483
+ }
4484
+ const newSecrets = [...skillSecrets.entries()].filter(
4485
+ ([name]) => !(name in environment)
4486
+ );
4487
+ const newVars = [...skillVars.entries()].filter(
4488
+ ([name]) => !(name in environment)
4489
+ );
4490
+ let headSecrets = /* @__PURE__ */ new Set();
4491
+ const existingCompose = await getComposeByName(agentName);
4492
+ if (existingCompose?.content) {
4493
+ headSecrets = getSecretsFromComposeContent(existingCompose.content);
4494
+ }
4495
+ const trulyNewSecrets = newSecrets.map(([name]) => name).filter((name) => !headSecrets.has(name));
4496
+ return { newSecrets, newVars, trulyNewSecrets };
4497
+ }
4498
+ async function displayAndConfirmVariables(variables, options) {
4499
+ const { newSecrets, newVars, trulyNewSecrets } = variables;
4500
+ if (newSecrets.length === 0 && newVars.length === 0) {
4501
+ return true;
4502
+ }
4503
+ console.log();
4504
+ console.log(
4505
+ chalk3.bold("Skills require the following environment variables:")
4506
+ );
4507
+ console.log();
4508
+ if (newSecrets.length > 0) {
4509
+ console.log(chalk3.cyan(" Secrets:"));
4510
+ for (const [name, skills] of newSecrets) {
4511
+ const isNew = trulyNewSecrets.includes(name);
4512
+ const newMarker = isNew ? chalk3.yellow(" (new)") : "";
4513
+ console.log(` ${name.padEnd(24)}${newMarker} <- ${skills.join(", ")}`);
4490
4514
  }
4491
- const trulyNewSecrets = newSecrets.map(([name]) => name).filter((name) => !headSecrets.has(name));
4492
- if (newSecrets.length > 0 || newVars.length > 0) {
4493
- console.log();
4494
- console.log(
4495
- chalk3.bold("Skills require the following environment variables:")
4515
+ }
4516
+ if (newVars.length > 0) {
4517
+ console.log(chalk3.cyan(" Vars:"));
4518
+ for (const [name, skills] of newVars) {
4519
+ console.log(` ${name.padEnd(24)} <- ${skills.join(", ")}`);
4520
+ }
4521
+ }
4522
+ console.log();
4523
+ if (trulyNewSecrets.length > 0 && !options.yes) {
4524
+ if (!isInteractive()) {
4525
+ console.error(
4526
+ chalk3.red(`\u2717 New secrets detected: ${trulyNewSecrets.join(", ")}`)
4496
4527
  );
4497
- console.log();
4498
- if (newSecrets.length > 0) {
4499
- console.log(chalk3.cyan(" Secrets:"));
4500
- for (const [name, skills] of newSecrets) {
4501
- const isNew = trulyNewSecrets.includes(name);
4502
- const newMarker = isNew ? chalk3.yellow(" (new)") : "";
4503
- console.log(
4504
- ` ${name.padEnd(24)}${newMarker} <- ${skills.join(", ")}`
4505
- );
4506
- }
4507
- }
4508
- if (newVars.length > 0) {
4509
- console.log(chalk3.cyan(" Vars:"));
4510
- for (const [name, skills] of newVars) {
4511
- console.log(` ${name.padEnd(24)} <- ${skills.join(", ")}`);
4512
- }
4513
- }
4514
- console.log();
4515
- if (trulyNewSecrets.length > 0) {
4516
- if (!options.yes) {
4517
- if (!isInteractive()) {
4518
- console.error(
4519
- chalk3.red(
4520
- `\u2717 New secrets detected: ${trulyNewSecrets.join(", ")}`
4521
- )
4522
- );
4523
- console.error(
4524
- chalk3.dim(
4525
- " Use --yes flag to approve new secrets in non-interactive mode."
4526
- )
4527
- );
4528
- process.exit(1);
4529
- }
4530
- const confirmed = await promptConfirm(
4531
- `Approve ${trulyNewSecrets.length} new secret(s)?`,
4532
- true
4533
- );
4534
- if (!confirmed) {
4535
- console.log(chalk3.yellow("Compose cancelled"));
4536
- process.exit(0);
4537
- }
4538
- }
4539
- }
4540
- for (const [name] of newSecrets) {
4541
- environment[name] = `\${{ secrets.${name} }}`;
4542
- }
4543
- for (const [name] of newVars) {
4544
- environment[name] = `\${{ vars.${name} }}`;
4545
- }
4546
- if (Object.keys(environment).length > 0) {
4547
- agent.environment = environment;
4548
- }
4528
+ console.error(
4529
+ chalk3.dim(
4530
+ " Use --yes flag to approve new secrets in non-interactive mode."
4531
+ )
4532
+ );
4533
+ process.exit(1);
4534
+ }
4535
+ const confirmed = await promptConfirm(
4536
+ `Approve ${trulyNewSecrets.length} new secret(s)?`,
4537
+ true
4538
+ );
4539
+ if (!confirmed) {
4540
+ console.log(chalk3.yellow("Compose cancelled"));
4541
+ return false;
4549
4542
  }
4543
+ }
4544
+ return true;
4545
+ }
4546
+ function mergeSkillVariables(agent, variables) {
4547
+ const { newSecrets, newVars } = variables;
4548
+ if (newSecrets.length === 0 && newVars.length === 0) {
4549
+ return;
4550
+ }
4551
+ const environment = agent.environment || {};
4552
+ for (const [name] of newSecrets) {
4553
+ environment[name] = `\${{ secrets.${name} }}`;
4554
+ }
4555
+ for (const [name] of newVars) {
4556
+ environment[name] = `\${{ vars.${name} }}`;
4557
+ }
4558
+ if (Object.keys(environment).length > 0) {
4559
+ agent.environment = environment;
4560
+ }
4561
+ }
4562
+ var composeCommand = new Command7().name("compose").description("Create or update agent compose (e.g., vm0.yaml)").argument("<agent-yaml>", "Path to agent YAML file").option("-y, --yes", "Skip confirmation prompts for skill requirements").action(async (configFile, options) => {
4563
+ try {
4564
+ const { config, agentName, agent, basePath } = await loadAndValidateConfig(configFile);
4565
+ checkLegacyImageFormat(config);
4566
+ const skillResults = await uploadAssets(agentName, agent, basePath);
4567
+ const environment = agent.environment || {};
4568
+ const variables = await collectSkillVariables(
4569
+ skillResults,
4570
+ environment,
4571
+ agentName
4572
+ );
4573
+ const confirmed = await displayAndConfirmVariables(variables, options);
4574
+ if (!confirmed) {
4575
+ process.exit(0);
4576
+ }
4577
+ mergeSkillVariables(agent, variables);
4550
4578
  console.log("Uploading compose...");
4551
- const response = await createOrUpdateCompose({
4552
- content: config
4553
- });
4579
+ const response = await createOrUpdateCompose({ content: config });
4554
4580
  const scopeResponse = await getScope();
4555
4581
  const shortVersionId = response.versionId.slice(0, 8);
4556
4582
  const displayName = `${scopeResponse.slug}/${response.name}`;
@@ -4571,9 +4597,6 @@ var composeCommand = new Command7().name("compose").description("Create or updat
4571
4597
  if (error instanceof Error) {
4572
4598
  if (error.message.includes("Not authenticated")) {
4573
4599
  console.error(chalk3.red("\u2717 Not authenticated. Run: vm0 auth login"));
4574
- } else if (error.message.includes("Failed to create compose")) {
4575
- console.error(chalk3.red("\u2717 Failed to create compose"));
4576
- console.error(chalk3.dim(` ${error.message}`));
4577
4600
  } else {
4578
4601
  console.error(chalk3.red("\u2717 Failed to create compose"));
4579
4602
  console.error(chalk3.dim(` ${error.message}`));
@@ -7960,135 +7983,89 @@ function checkMissingVariables(varNames, envFilePath) {
7960
7983
  }
7961
7984
  return missing;
7962
7985
  }
7963
- var cookAction = new Command27().name("cook").description("Quick start: prepare, compose and run agent from vm0.yaml").argument("[prompt]", "Prompt for the agent").option(
7964
- "--env-file <path>",
7965
- "Load environment variables from file (priority: CLI flags > file > env vars)"
7966
- ).option("-y, --yes", "Skip confirmation prompts").addOption(new Option4("--debug-no-mock-claude").hideHelp()).addOption(new Option4("--no-auto-update").hideHelp()).action(
7967
- // eslint-disable-next-line complexity -- TODO: refactor complex function
7968
- async (prompt, options) => {
7969
- if (!options.noAutoUpdate) {
7970
- const shouldExit = await checkAndUpgrade("9.4.1", prompt);
7971
- if (shouldExit) {
7972
- process.exit(0);
7973
- }
7974
- }
7975
- const cwd = process.cwd();
7976
- console.log(chalk28.bold(`Reading config: ${CONFIG_FILE2}`));
7977
- if (!existsSync9(CONFIG_FILE2)) {
7978
- console.error(chalk28.red(`\u2717 Config file not found: ${CONFIG_FILE2}`));
7979
- process.exit(1);
7986
+ async function loadAndValidateConfig2() {
7987
+ console.log(chalk28.bold(`Reading config: ${CONFIG_FILE2}`));
7988
+ if (!existsSync9(CONFIG_FILE2)) {
7989
+ console.error(chalk28.red(`\u2717 Config file not found: ${CONFIG_FILE2}`));
7990
+ process.exit(1);
7991
+ }
7992
+ let config;
7993
+ try {
7994
+ const content = await readFile7(CONFIG_FILE2, "utf8");
7995
+ config = parseYaml4(content);
7996
+ } catch (error) {
7997
+ console.error(chalk28.red("\u2717 Invalid YAML format"));
7998
+ if (error instanceof Error) {
7999
+ console.error(chalk28.dim(` ${error.message}`));
7980
8000
  }
7981
- let config;
7982
- try {
7983
- const content = await readFile7(CONFIG_FILE2, "utf8");
7984
- config = parseYaml4(content);
7985
- } catch (error) {
7986
- console.error(chalk28.red("\u2717 Invalid YAML format"));
7987
- if (error instanceof Error) {
7988
- console.error(chalk28.dim(` ${error.message}`));
8001
+ process.exit(1);
8002
+ }
8003
+ const validation = validateAgentCompose(config);
8004
+ if (!validation.valid) {
8005
+ console.error(chalk28.red(`\u2717 ${validation.error}`));
8006
+ process.exit(1);
8007
+ }
8008
+ const agentNames = Object.keys(config.agents);
8009
+ const agentName = agentNames[0];
8010
+ const volumeCount = config.volumes ? Object.keys(config.volumes).length : 0;
8011
+ console.log(
8012
+ chalk28.green(`\u2713 Config validated: 1 agent, ${volumeCount} volume(s)`)
8013
+ );
8014
+ return { config, agentName, volumeCount };
8015
+ }
8016
+ function validateEnvVariables(config, envFile) {
8017
+ const requiredVarNames = extractRequiredVarNames(config);
8018
+ if (requiredVarNames.length === 0) {
8019
+ return;
8020
+ }
8021
+ try {
8022
+ const missingVars = checkMissingVariables(requiredVarNames, envFile);
8023
+ if (missingVars.length > 0) {
8024
+ console.log();
8025
+ console.error(chalk28.red("\u2717 Missing required variables:"));
8026
+ for (const varName of missingVars) {
8027
+ console.error(chalk28.red(` ${varName}`));
7989
8028
  }
8029
+ console.error(
8030
+ chalk28.dim(
8031
+ "\n Provide via --env-file, or set as environment variables"
8032
+ )
8033
+ );
7990
8034
  process.exit(1);
7991
8035
  }
7992
- const validation = validateAgentCompose(config);
7993
- if (!validation.valid) {
7994
- console.error(chalk28.red(`\u2717 ${validation.error}`));
7995
- process.exit(1);
7996
- }
7997
- const agentNames = Object.keys(config.agents);
7998
- const agentName = agentNames[0];
7999
- const volumeCount = config.volumes ? Object.keys(config.volumes).length : 0;
8000
- console.log(
8001
- chalk28.green(`\u2713 Config validated: 1 agent, ${volumeCount} volume(s)`)
8002
- );
8003
- const requiredVarNames = extractRequiredVarNames(config);
8004
- if (requiredVarNames.length > 0) {
8005
- try {
8006
- const missingVars = checkMissingVariables(
8007
- requiredVarNames,
8008
- options.envFile
8009
- );
8010
- if (missingVars.length > 0) {
8011
- console.log();
8012
- console.error(chalk28.red("\u2717 Missing required variables:"));
8013
- for (const varName of missingVars) {
8014
- console.error(chalk28.red(` ${varName}`));
8015
- }
8016
- console.error(
8017
- chalk28.dim(
8018
- "\n Provide via --env-file, or set as environment variables"
8019
- )
8020
- );
8021
- process.exit(1);
8022
- }
8023
- } catch (error) {
8024
- if (error instanceof Error) {
8025
- console.error(chalk28.red(`\u2717 ${error.message}`));
8026
- }
8027
- process.exit(1);
8028
- }
8036
+ } catch (error) {
8037
+ if (error instanceof Error) {
8038
+ console.error(chalk28.red(`\u2717 ${error.message}`));
8029
8039
  }
8030
- if (config.volumes && Object.keys(config.volumes).length > 0) {
8031
- console.log();
8032
- console.log(chalk28.bold("Processing volumes:"));
8033
- for (const volumeConfig of Object.values(config.volumes)) {
8034
- const volumeDir = path11.join(cwd, volumeConfig.name);
8035
- if (!existsSync9(volumeDir)) {
8036
- console.error(
8037
- chalk28.red(`\u2717 Directory not found: ${volumeConfig.name}`)
8038
- );
8039
- console.error(
8040
- chalk28.dim(" Create the directory and add files first")
8041
- );
8042
- process.exit(1);
8043
- }
8044
- try {
8045
- printCommand(`cd ${volumeConfig.name}`);
8046
- const existingConfig = await readStorageConfig(volumeDir);
8047
- if (!existingConfig) {
8048
- printCommand(`vm0 volume init --name ${volumeConfig.name}`);
8049
- await execVm0Command(
8050
- ["volume", "init", "--name", volumeConfig.name],
8051
- {
8052
- cwd: volumeDir,
8053
- silent: true
8054
- }
8055
- );
8056
- }
8057
- printCommand("vm0 volume push");
8058
- await execVm0Command(["volume", "push"], {
8059
- cwd: volumeDir,
8060
- silent: true
8061
- });
8062
- printCommand("cd ..");
8063
- } catch (error) {
8064
- console.error(chalk28.red(`\u2717 Failed`));
8065
- if (error instanceof Error) {
8066
- console.error(chalk28.dim(` ${error.message}`));
8067
- }
8068
- process.exit(1);
8069
- }
8070
- }
8040
+ process.exit(1);
8041
+ }
8042
+ }
8043
+ async function processVolumes(config, cwd) {
8044
+ if (!config.volumes || Object.keys(config.volumes).length === 0) {
8045
+ return;
8046
+ }
8047
+ console.log();
8048
+ console.log(chalk28.bold("Processing volumes:"));
8049
+ for (const volumeConfig of Object.values(config.volumes)) {
8050
+ const volumeDir = path11.join(cwd, volumeConfig.name);
8051
+ if (!existsSync9(volumeDir)) {
8052
+ console.error(chalk28.red(`\u2717 Directory not found: ${volumeConfig.name}`));
8053
+ console.error(chalk28.dim(" Create the directory and add files first"));
8054
+ process.exit(1);
8071
8055
  }
8072
- console.log();
8073
- console.log(chalk28.bold("Processing artifact:"));
8074
- const artifactDir = path11.join(cwd, ARTIFACT_DIR);
8075
8056
  try {
8076
- if (!existsSync9(artifactDir)) {
8077
- printCommand(`mkdir ${ARTIFACT_DIR}`);
8078
- await mkdir6(artifactDir, { recursive: true });
8079
- }
8080
- printCommand(`cd ${ARTIFACT_DIR}`);
8081
- const existingConfig = await readStorageConfig(artifactDir);
8057
+ printCommand(`cd ${volumeConfig.name}`);
8058
+ const existingConfig = await readStorageConfig(volumeDir);
8082
8059
  if (!existingConfig) {
8083
- printCommand(`vm0 artifact init --name ${ARTIFACT_DIR}`);
8084
- await execVm0Command(["artifact", "init", "--name", ARTIFACT_DIR], {
8085
- cwd: artifactDir,
8060
+ printCommand(`vm0 volume init --name ${volumeConfig.name}`);
8061
+ await execVm0Command(["volume", "init", "--name", volumeConfig.name], {
8062
+ cwd: volumeDir,
8086
8063
  silent: true
8087
8064
  });
8088
8065
  }
8089
- printCommand("vm0 artifact push");
8090
- await execVm0Command(["artifact", "push"], {
8091
- cwd: artifactDir,
8066
+ printCommand("vm0 volume push");
8067
+ await execVm0Command(["volume", "push"], {
8068
+ cwd: volumeDir,
8092
8069
  silent: true
8093
8070
  });
8094
8071
  printCommand("cd ..");
@@ -8099,51 +8076,112 @@ var cookAction = new Command27().name("cook").description("Quick start: prepare,
8099
8076
  }
8100
8077
  process.exit(1);
8101
8078
  }
8102
- console.log();
8103
- console.log(chalk28.bold("Composing agent:"));
8104
- const composeArgs = options.yes ? ["compose", "--yes", CONFIG_FILE2] : ["compose", CONFIG_FILE2];
8105
- printCommand(`vm0 ${composeArgs.join(" ")}`);
8106
- try {
8107
- await execVm0Command(composeArgs, {
8108
- cwd
8079
+ }
8080
+ }
8081
+ async function processArtifact(cwd) {
8082
+ console.log();
8083
+ console.log(chalk28.bold("Processing artifact:"));
8084
+ const artifactDir = path11.join(cwd, ARTIFACT_DIR);
8085
+ try {
8086
+ if (!existsSync9(artifactDir)) {
8087
+ printCommand(`mkdir ${ARTIFACT_DIR}`);
8088
+ await mkdir6(artifactDir, { recursive: true });
8089
+ }
8090
+ printCommand(`cd ${ARTIFACT_DIR}`);
8091
+ const existingConfig = await readStorageConfig(artifactDir);
8092
+ if (!existingConfig) {
8093
+ printCommand(`vm0 artifact init --name ${ARTIFACT_DIR}`);
8094
+ await execVm0Command(["artifact", "init", "--name", ARTIFACT_DIR], {
8095
+ cwd: artifactDir,
8096
+ silent: true
8109
8097
  });
8110
- } catch (error) {
8111
- console.error(chalk28.red(`\u2717 Compose failed`));
8112
- if (error instanceof Error) {
8113
- console.error(chalk28.dim(` ${error.message}`));
8098
+ }
8099
+ printCommand("vm0 artifact push");
8100
+ await execVm0Command(["artifact", "push"], {
8101
+ cwd: artifactDir,
8102
+ silent: true
8103
+ });
8104
+ printCommand("cd ..");
8105
+ } catch (error) {
8106
+ console.error(chalk28.red(`\u2717 Failed`));
8107
+ if (error instanceof Error) {
8108
+ console.error(chalk28.dim(` ${error.message}`));
8109
+ }
8110
+ process.exit(1);
8111
+ }
8112
+ return artifactDir;
8113
+ }
8114
+ async function composeAgent(cwd, skipConfirm) {
8115
+ console.log();
8116
+ console.log(chalk28.bold("Composing agent:"));
8117
+ const composeArgs = skipConfirm ? ["compose", "--yes", CONFIG_FILE2] : ["compose", CONFIG_FILE2];
8118
+ printCommand(`vm0 ${composeArgs.join(" ")}`);
8119
+ try {
8120
+ await execVm0Command(composeArgs, { cwd });
8121
+ } catch (error) {
8122
+ console.error(chalk28.red(`\u2717 Compose failed`));
8123
+ if (error instanceof Error) {
8124
+ console.error(chalk28.dim(` ${error.message}`));
8125
+ }
8126
+ process.exit(1);
8127
+ }
8128
+ }
8129
+ async function runAgent(agentName, artifactDir, prompt, cwd, debugNoMockClaude) {
8130
+ console.log();
8131
+ console.log(chalk28.bold("Running agent:"));
8132
+ printCommand(
8133
+ `vm0 run ${agentName} --artifact-name ${ARTIFACT_DIR} "${prompt}"`
8134
+ );
8135
+ console.log();
8136
+ let runOutput;
8137
+ try {
8138
+ const runArgs = [
8139
+ "run",
8140
+ agentName,
8141
+ "--artifact-name",
8142
+ ARTIFACT_DIR,
8143
+ ...debugNoMockClaude ? ["--debug-no-mock-claude"] : [],
8144
+ prompt
8145
+ ];
8146
+ runOutput = await execVm0RunWithCapture(runArgs, { cwd });
8147
+ } catch {
8148
+ process.exit(1);
8149
+ }
8150
+ const runIds = parseRunIdsFromOutput(runOutput);
8151
+ if (runIds.runId || runIds.sessionId || runIds.checkpointId) {
8152
+ await saveCookState({
8153
+ lastRunId: runIds.runId,
8154
+ lastSessionId: runIds.sessionId,
8155
+ lastCheckpointId: runIds.checkpointId
8156
+ });
8157
+ }
8158
+ await autoPullArtifact(runOutput, artifactDir);
8159
+ }
8160
+ var cookAction = new Command27().name("cook").description("Quick start: prepare, compose and run agent from vm0.yaml").argument("[prompt]", "Prompt for the agent").option(
8161
+ "--env-file <path>",
8162
+ "Load environment variables from file (priority: CLI flags > file > env vars)"
8163
+ ).option("-y, --yes", "Skip confirmation prompts").addOption(new Option4("--debug-no-mock-claude").hideHelp()).addOption(new Option4("--no-auto-update").hideHelp()).action(
8164
+ async (prompt, options) => {
8165
+ if (!options.noAutoUpdate) {
8166
+ const shouldExit = await checkAndUpgrade("9.5.0", prompt);
8167
+ if (shouldExit) {
8168
+ process.exit(0);
8114
8169
  }
8115
- process.exit(1);
8116
8170
  }
8171
+ const cwd = process.cwd();
8172
+ const { config, agentName } = await loadAndValidateConfig2();
8173
+ validateEnvVariables(config, options.envFile);
8174
+ await processVolumes(config, cwd);
8175
+ const artifactDir = await processArtifact(cwd);
8176
+ await composeAgent(cwd, options.yes ?? false);
8117
8177
  if (prompt) {
8118
- console.log();
8119
- console.log(chalk28.bold("Running agent:"));
8120
- printCommand(
8121
- `vm0 run ${agentName} --artifact-name ${ARTIFACT_DIR} "${prompt}"`
8178
+ await runAgent(
8179
+ agentName,
8180
+ artifactDir,
8181
+ prompt,
8182
+ cwd,
8183
+ options.debugNoMockClaude ?? false
8122
8184
  );
8123
- console.log();
8124
- let runOutput;
8125
- try {
8126
- const runArgs = [
8127
- "run",
8128
- agentName,
8129
- "--artifact-name",
8130
- ARTIFACT_DIR,
8131
- ...options.debugNoMockClaude ? ["--debug-no-mock-claude"] : [],
8132
- prompt
8133
- ];
8134
- runOutput = await execVm0RunWithCapture(runArgs, { cwd });
8135
- } catch {
8136
- process.exit(1);
8137
- }
8138
- const runIds = parseRunIdsFromOutput(runOutput);
8139
- if (runIds.runId || runIds.sessionId || runIds.checkpointId) {
8140
- await saveCookState({
8141
- lastRunId: runIds.runId,
8142
- lastSessionId: runIds.sessionId,
8143
- lastCheckpointId: runIds.checkpointId
8144
- });
8145
- }
8146
- await autoPullArtifact(runOutput, artifactDir);
8147
8185
  } else {
8148
8186
  console.log();
8149
8187
  console.log("To run your agent:");
@@ -10710,82 +10748,106 @@ import path16 from "path";
10710
10748
 
10711
10749
  // src/lib/ui/welcome-box.ts
10712
10750
  import chalk53 from "chalk";
10713
- function renderWelcomeBox(lines, width) {
10714
- const maxLineLength = Math.max(...lines.map((line) => line.length));
10715
- const boxWidth = width ?? maxLineLength + 4;
10716
- const innerWidth = boxWidth - 2;
10717
- const horizontalLine = "\u2500".repeat(innerWidth);
10718
- const topBorder = `\u250C${horizontalLine}\u2510`;
10719
- const bottomBorder = `\u2514${horizontalLine}\u2518`;
10720
- console.log(chalk53.cyan(topBorder));
10721
- for (const line of lines) {
10722
- const padding = innerWidth - line.length;
10723
- const leftPad = Math.floor(padding / 2);
10724
- const rightPad = padding - leftPad;
10725
- const centeredLine = " ".repeat(leftPad) + line + " ".repeat(rightPad);
10726
- console.log(chalk53.cyan("\u2502") + centeredLine + chalk53.cyan("\u2502"));
10727
- }
10728
- console.log(chalk53.cyan(bottomBorder));
10751
+ var gradientColors = [
10752
+ chalk53.hex("#FF9650"),
10753
+ // Line 1 - lightest
10754
+ chalk53.hex("#FF7832"),
10755
+ // Line 2
10756
+ chalk53.hex("#FF7832"),
10757
+ // Line 3
10758
+ chalk53.hex("#ED4E01"),
10759
+ // Line 4 - brand orange
10760
+ chalk53.hex("#ED4E01"),
10761
+ // Line 5
10762
+ chalk53.hex("#C83C00")
10763
+ // Line 6 - darkest
10764
+ ];
10765
+ 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\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557",
10768
+ "\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2588\u2588\u2588\u2588\u2554\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551",
10769
+ "\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
+ " \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
+ ];
10773
+ function renderVm0Banner() {
10774
+ console.log();
10775
+ for (let i = 0; i < vm0LogoLines.length; i++) {
10776
+ const color = gradientColors[i] ?? gradientColors[gradientColors.length - 1];
10777
+ console.log(` ${color?.(vm0LogoLines[i])}`);
10778
+ }
10779
+ console.log();
10729
10780
  }
10730
10781
  function renderOnboardWelcome() {
10731
- renderWelcomeBox([
10732
- "",
10733
- "Welcome to VM0!",
10734
- "",
10735
- "Let's create your first agent.",
10736
- ""
10737
- ]);
10782
+ renderVm0Banner();
10783
+ console.log(` ${chalk53.bold("Welcome to VM0!")}`);
10784
+ console.log(` ${chalk53.dim("Let's create your first agent.")}`);
10785
+ console.log();
10738
10786
  }
10739
10787
 
10740
10788
  // src/lib/ui/progress-line.ts
10741
10789
  import chalk54 from "chalk";
10742
- var STATUS_SYMBOLS = {
10743
- completed: "\u25CF",
10744
- "in-progress": "\u25D0",
10745
- pending: "\u25CB",
10746
- failed: "\u2717"
10747
- };
10748
- function getStatusColor(status) {
10749
- switch (status) {
10750
- case "completed":
10751
- return chalk54.green;
10752
- case "in-progress":
10753
- return chalk54.yellow;
10754
- case "failed":
10755
- return chalk54.red;
10756
- case "pending":
10757
- default:
10758
- return chalk54.dim;
10759
- }
10760
- }
10761
- function renderProgressLine(steps) {
10762
- for (let i = 0; i < steps.length; i++) {
10763
- const step = steps[i];
10764
- if (!step) continue;
10765
- const symbol = STATUS_SYMBOLS[step.status];
10766
- const color = getStatusColor(step.status);
10767
- console.log(color(`${symbol} ${step.label}`));
10768
- if (i < steps.length - 1) {
10769
- console.log(chalk54.dim("\u2502"));
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`);
10770
10804
  }
10771
- }
10772
- }
10773
- function createOnboardProgress() {
10774
- const steps = [
10775
- { label: "Authentication", status: "pending" },
10776
- { label: "Model Provider Setup", status: "pending" },
10777
- { label: "Create Agent", status: "pending" },
10778
- { label: "Claude Plugin Install", status: "pending" },
10779
- { label: "Complete", status: "pending" }
10780
- ];
10805
+ if (detailLineCount > 0) {
10806
+ process.stdout.write(`\x1B[${detailLineCount}A`);
10807
+ }
10808
+ };
10781
10809
  return {
10782
- steps,
10783
- render: () => renderProgressLine(steps),
10784
- update: (index, status) => {
10785
- const step = steps[index];
10786
- if (step) {
10787
- step.status = status;
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`);
10825
+ }
10826
+ console.log(chalk54.green(`\u25CF ${currentLabel}`));
10827
+ if (interactive && detailLineCount > 0) {
10828
+ clearDetailLines();
10788
10829
  }
10830
+ if (!isFinalStep) {
10831
+ console.log(chalk54.dim("\u2502"));
10832
+ }
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;
10848
+ },
10849
+ setFinalStep: () => {
10850
+ isFinalStep = true;
10789
10851
  }
10790
10852
  };
10791
10853
  }
@@ -11022,61 +11084,54 @@ async function installVm0Plugin(scope = "user", cwd) {
11022
11084
  // src/commands/onboard/index.ts
11023
11085
  var DEFAULT_AGENT_NAME = "my-vm0-agent";
11024
11086
  async function handleAuthentication(ctx) {
11025
- ctx.updateProgress(0, "in-progress");
11087
+ ctx.progress.startStep("Authentication");
11026
11088
  const authenticated = await isAuthenticated();
11027
11089
  if (authenticated) {
11028
- ctx.updateProgress(0, "completed");
11090
+ ctx.progress.completeStep();
11029
11091
  return;
11030
11092
  }
11031
11093
  if (!ctx.interactive) {
11094
+ ctx.progress.failStep();
11032
11095
  console.error(chalk56.red("Error: Not authenticated"));
11033
11096
  console.error("Run 'vm0 auth login' first or set VM0_TOKEN");
11034
11097
  process.exit(1);
11035
11098
  }
11036
- console.log(chalk56.dim("Authentication required..."));
11037
- console.log();
11038
11099
  await runAuthFlow({
11039
11100
  onInitiating: () => {
11040
- console.log("Initiating authentication...");
11041
11101
  },
11042
11102
  onDeviceCodeReady: (url, code, expiresIn) => {
11043
- console.log(chalk56.green("\nDevice code generated"));
11044
- console.log(chalk56.cyan(`
11045
- To authenticate, visit: ${url}`));
11046
- console.log(`And enter this code: ${chalk56.bold(code)}`);
11047
- console.log(`
11048
- The code expires in ${expiresIn} minutes.`);
11049
- console.log("\nWaiting for authentication...");
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...");
11050
11107
  },
11051
11108
  onPolling: () => {
11052
- process.stdout.write(chalk56.dim("."));
11053
11109
  },
11054
11110
  onSuccess: () => {
11055
- console.log(chalk56.green("\nAuthentication successful!"));
11056
- console.log("Your credentials have been saved.");
11057
11111
  },
11058
11112
  onError: (error) => {
11113
+ ctx.progress.failStep();
11059
11114
  console.error(chalk56.red(`
11060
11115
  ${error.message}`));
11061
11116
  process.exit(1);
11062
11117
  }
11063
11118
  });
11064
- ctx.updateProgress(0, "completed");
11119
+ ctx.progress.completeStep();
11065
11120
  }
11066
11121
  async function handleModelProvider(ctx) {
11067
- ctx.updateProgress(1, "in-progress");
11122
+ ctx.progress.startStep("Model Provider Setup");
11068
11123
  const providerStatus = await checkModelProviderStatus();
11069
11124
  if (providerStatus.hasProvider) {
11070
- ctx.updateProgress(1, "completed");
11125
+ ctx.progress.completeStep();
11071
11126
  return;
11072
11127
  }
11073
11128
  if (!ctx.interactive) {
11129
+ ctx.progress.failStep();
11074
11130
  console.error(chalk56.red("Error: No model provider configured"));
11075
11131
  console.error("Run 'vm0 model-provider setup' first");
11076
11132
  process.exit(1);
11077
11133
  }
11078
- console.log(chalk56.dim("Model provider setup required..."));
11079
- console.log();
11134
+ ctx.progress.detail("Setup required...");
11080
11135
  const choices = getProviderChoices();
11081
11136
  const providerType = await promptSelect(
11082
11137
  "Select provider type:",
@@ -11090,11 +11145,6 @@ async function handleModelProvider(ctx) {
11090
11145
  process.exit(0);
11091
11146
  }
11092
11147
  const selectedChoice = choices.find((c20) => c20.type === providerType);
11093
- if (selectedChoice) {
11094
- console.log();
11095
- console.log(chalk56.dim(selectedChoice.helpText));
11096
- console.log();
11097
- }
11098
11148
  const credential = await promptPassword(
11099
11149
  `Enter your ${selectedChoice?.credentialLabel ?? "credential"}:`
11100
11150
  );
@@ -11103,16 +11153,13 @@ async function handleModelProvider(ctx) {
11103
11153
  process.exit(0);
11104
11154
  }
11105
11155
  const result = await setupModelProvider(providerType, credential);
11106
- console.log(
11107
- chalk56.green(
11108
- `
11109
- \u2713 Model provider "${providerType}" ${result.created ? "created" : "updated"}${result.isDefault ? ` (default for ${result.framework})` : ""}`
11110
- )
11156
+ ctx.progress.detail(
11157
+ `${providerType} ${result.created ? "created" : "updated"}${result.isDefault ? ` (default for ${result.framework})` : ""}`
11111
11158
  );
11112
- ctx.updateProgress(1, "completed");
11159
+ ctx.progress.completeStep();
11113
11160
  }
11114
11161
  async function handleAgentCreation(ctx) {
11115
- ctx.updateProgress(2, "in-progress");
11162
+ ctx.progress.startStep("Create Agent");
11116
11163
  let agentName = ctx.options.name ?? DEFAULT_AGENT_NAME;
11117
11164
  if (!ctx.options.yes && !ctx.options.name && ctx.interactive) {
11118
11165
  const inputName = await promptText(
@@ -11131,6 +11178,7 @@ async function handleAgentCreation(ctx) {
11131
11178
  agentName = inputName;
11132
11179
  }
11133
11180
  if (!validateAgentName(agentName)) {
11181
+ ctx.progress.failStep();
11134
11182
  console.error(
11135
11183
  chalk56.red(
11136
11184
  "Invalid agent name: must be 3-64 chars, alphanumeric + hyphens"
@@ -11139,20 +11187,20 @@ async function handleAgentCreation(ctx) {
11139
11187
  process.exit(1);
11140
11188
  }
11141
11189
  if (existsSync11(agentName)) {
11142
- console.error(chalk56.red(`
11143
- \u2717 ${agentName}/ already exists`));
11190
+ ctx.progress.failStep();
11191
+ console.error(chalk56.red(`${agentName}/ already exists`));
11144
11192
  console.log();
11145
11193
  console.log("Remove it first or choose a different name:");
11146
11194
  console.log(chalk56.cyan(` rm -rf ${agentName}`));
11147
11195
  process.exit(1);
11148
11196
  }
11149
11197
  await mkdir7(agentName, { recursive: true });
11150
- console.log(chalk56.green(`\u2713 Created ${agentName}/`));
11151
- ctx.updateProgress(2, "completed");
11198
+ ctx.progress.detail(`Created ${agentName}/`);
11199
+ ctx.progress.completeStep();
11152
11200
  return agentName;
11153
11201
  }
11154
11202
  async function handlePluginInstallation(ctx, agentName) {
11155
- ctx.updateProgress(3, "in-progress");
11203
+ ctx.progress.startStep("Claude Plugin Install");
11156
11204
  let shouldInstall = true;
11157
11205
  if (!ctx.options.yes && ctx.interactive) {
11158
11206
  const confirmed = await promptConfirm(
@@ -11163,21 +11211,21 @@ async function handlePluginInstallation(ctx, agentName) {
11163
11211
  shouldInstall = confirmed ?? true;
11164
11212
  }
11165
11213
  if (!shouldInstall) {
11166
- console.log(chalk56.dim("Skipped plugin installation"));
11167
- ctx.updateProgress(3, "completed");
11214
+ ctx.progress.detail("Skipped");
11215
+ ctx.progress.completeStep();
11168
11216
  return;
11169
11217
  }
11170
11218
  const scope = "project";
11171
11219
  try {
11172
11220
  const agentDir = path16.resolve(process.cwd(), agentName);
11173
11221
  const result = await installVm0Plugin(scope, agentDir);
11174
- console.log(
11175
- chalk56.green(`\u2713 Installed ${result.pluginId} (scope: ${result.scope})`)
11222
+ ctx.progress.detail(
11223
+ `Installed ${result.pluginId} (scope: ${result.scope})`
11176
11224
  );
11177
11225
  } catch (error) {
11178
11226
  handlePluginError(error);
11179
11227
  }
11180
- ctx.updateProgress(3, "completed");
11228
+ ctx.progress.completeStep();
11181
11229
  }
11182
11230
  function printNextSteps(agentName) {
11183
11231
  console.log();
@@ -11195,27 +11243,15 @@ var onboardCommand = new Command56().name("onboard").description("Guided setup f
11195
11243
  renderOnboardWelcome();
11196
11244
  console.log();
11197
11245
  }
11198
- const progress = createOnboardProgress();
11199
- const updateProgress = (index, status) => {
11200
- progress.update(index, status);
11201
- if (interactive) {
11202
- console.clear();
11203
- renderOnboardWelcome();
11204
- console.log();
11205
- progress.render();
11206
- console.log();
11207
- }
11208
- };
11209
- if (interactive) {
11210
- progress.render();
11211
- console.log();
11212
- }
11213
- const ctx = { interactive, options, updateProgress };
11246
+ const progress = createProgressiveProgress(interactive);
11247
+ const ctx = { interactive, options, progress };
11214
11248
  await handleAuthentication(ctx);
11215
11249
  await handleModelProvider(ctx);
11216
11250
  const agentName = await handleAgentCreation(ctx);
11217
11251
  await handlePluginInstallation(ctx, agentName);
11218
- ctx.updateProgress(4, "completed");
11252
+ progress.startStep("Complete");
11253
+ progress.setFinalStep();
11254
+ progress.completeStep();
11219
11255
  printNextSteps(agentName);
11220
11256
  });
11221
11257
 
@@ -11245,7 +11281,7 @@ var setupClaudeCommand = new Command57().name("setup-claude").description("Insta
11245
11281
 
11246
11282
  // src/index.ts
11247
11283
  var program = new Command58();
11248
- program.name("vm0").description("VM0 CLI - Build and run agents with natural language").version("9.4.1");
11284
+ program.name("vm0").description("VM0 CLI - Build and run agents with natural language").version("9.5.0");
11249
11285
  program.addCommand(authCommand);
11250
11286
  program.addCommand(infoCommand);
11251
11287
  program.addCommand(composeCommand);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vm0/cli",
3
- "version": "9.4.1",
3
+ "version": "9.5.0",
4
4
  "description": "CLI application",
5
5
  "repository": {
6
6
  "type": "git",