@vm0/cli 9.25.0 → 9.26.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 +192 -144
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -61,7 +61,7 @@ if (DSN) {
61
61
  }
62
62
  });
63
63
  Sentry.setContext("cli", {
64
- version: "9.25.0",
64
+ version: "9.26.0",
65
65
  command: process.argv.slice(2).join(" ")
66
66
  });
67
67
  Sentry.setContext("runtime", {
@@ -198,7 +198,7 @@ The code expires in ${Math.floor(deviceAuth.expires_in / 60)} minutes.`
198
198
  apiUrl: targetApiUrl
199
199
  });
200
200
  console.log(chalk.green("\nAuthentication successful!"));
201
- console.log("Your credentials have been saved.");
201
+ console.log("Your credentials have been saved");
202
202
  return;
203
203
  }
204
204
  if (tokenResult.error === "authorization_pending") {
@@ -206,28 +206,26 @@ The code expires in ${Math.floor(deviceAuth.expires_in / 60)} minutes.`
206
206
  continue;
207
207
  }
208
208
  if (tokenResult.error === "expired_token") {
209
- console.log(
210
- chalk.red("\nThe device code has expired. Please try again.")
211
- );
209
+ console.error(chalk.red("\n\u2717 Device code expired, please try again"));
212
210
  process.exit(1);
213
211
  }
214
212
  if (tokenResult.error) {
215
- console.log(
213
+ console.error(
216
214
  chalk.red(
217
215
  `
218
- Authentication failed: ${tokenResult.error_description ?? tokenResult.error}`
216
+ \u2717 Authentication failed: ${tokenResult.error_description ?? tokenResult.error}`
219
217
  )
220
218
  );
221
219
  process.exit(1);
222
220
  }
223
221
  }
224
- console.log(chalk.red("\nAuthentication timed out. Please try again."));
222
+ console.error(chalk.red("\n\u2717 Authentication timed out, please try again"));
225
223
  process.exit(1);
226
224
  }
227
225
  async function logout() {
228
226
  await clearConfig();
229
227
  console.log(chalk.green("\u2713 Successfully logged out"));
230
- console.log("Your credentials have been cleared.");
228
+ console.log("Your credentials have been cleared");
231
229
  }
232
230
  async function checkAuthStatus() {
233
231
  const config = await loadConfig();
@@ -235,8 +233,8 @@ async function checkAuthStatus() {
235
233
  console.log(chalk.green("\u2713 Authenticated"));
236
234
  console.log("You are logged in to VM0.");
237
235
  } else {
238
- console.log(chalk.red("\u2717 Not authenticated"));
239
- console.log("Run 'vm0 auth login' to authenticate.");
236
+ console.error(chalk.red("\u2717 Not authenticated"));
237
+ console.error(chalk.dim(" Run: vm0 auth login"));
240
238
  }
241
239
  if (process.env.VM0_TOKEN) {
242
240
  console.log("Using token from VM0_TOKEN environment variable");
@@ -3263,6 +3261,29 @@ var CONNECTOR_TYPES = {
3263
3261
  }
3264
3262
  };
3265
3263
  var connectorTypeSchema = z24.enum(["github"]);
3264
+ function getConnectorDerivedNames(secretName) {
3265
+ const allTypes = Object.keys(CONNECTOR_TYPES);
3266
+ for (const type of allTypes) {
3267
+ const config = CONNECTOR_TYPES[type];
3268
+ const authMethods = config.authMethods;
3269
+ let found = false;
3270
+ for (const method of Object.values(authMethods)) {
3271
+ if (method.secrets && secretName in method.secrets) {
3272
+ found = true;
3273
+ break;
3274
+ }
3275
+ }
3276
+ if (!found) {
3277
+ continue;
3278
+ }
3279
+ const mapping = config.environmentMapping;
3280
+ const envVarNames = Object.entries(mapping).filter(([, valueRef]) => valueRef === `$secrets.${secretName}`).map(([envVar]) => envVar);
3281
+ if (envVarNames.length > 0) {
3282
+ return { connectorLabel: config.label, envVarNames };
3283
+ }
3284
+ }
3285
+ return null;
3286
+ }
3266
3287
  var connectorResponseSchema = z24.object({
3267
3288
  id: z24.string().uuid(),
3268
3289
  type: connectorTypeSchema,
@@ -5537,7 +5558,7 @@ function performUpgrade(packageManager) {
5537
5558
  async function checkAndUpgrade(currentVersion, prompt) {
5538
5559
  const latestVersion = await getLatestVersion();
5539
5560
  if (latestVersion === null) {
5540
- console.log(chalk3.yellow("Warning: Could not check for updates"));
5561
+ console.log(chalk3.yellow("\u26A0 Could not check for updates"));
5541
5562
  console.log();
5542
5563
  return false;
5543
5564
  }
@@ -5581,12 +5602,12 @@ async function checkAndUpgrade(currentVersion, prompt) {
5581
5602
  console.log(chalk3.cyan(` ${buildRerunCommand(prompt)}`));
5582
5603
  return true;
5583
5604
  }
5584
- console.log();
5585
- console.log(chalk3.red("Upgrade failed. Please run manually:"));
5586
- console.log(chalk3.cyan(` ${getManualUpgradeCommand(packageManager)}`));
5587
- console.log();
5588
- console.log("Then re-run:");
5589
- console.log(chalk3.cyan(` ${buildRerunCommand(prompt)}`));
5605
+ console.error();
5606
+ console.error(chalk3.red("\u2717 Upgrade failed. Please run manually:"));
5607
+ console.error(chalk3.cyan(` ${getManualUpgradeCommand(packageManager)}`));
5608
+ console.error();
5609
+ console.error("Then re-run:");
5610
+ console.error(chalk3.cyan(` ${buildRerunCommand(prompt)}`));
5590
5611
  return true;
5591
5612
  }
5592
5613
  async function silentUpgradeAfterCommand(currentVersion) {
@@ -5643,9 +5664,9 @@ function getSecretsFromComposeContent(content) {
5643
5664
  const grouped = groupVariablesBySource(refs);
5644
5665
  return new Set(grouped.secrets.map((r) => r.name));
5645
5666
  }
5646
- async function loadAndValidateConfig(configFile, porcelainMode) {
5667
+ async function loadAndValidateConfig(configFile, jsonMode) {
5647
5668
  if (!existsSync4(configFile)) {
5648
- if (porcelainMode) {
5669
+ if (jsonMode) {
5649
5670
  console.log(
5650
5671
  JSON.stringify({ error: `Config file not found: ${configFile}` })
5651
5672
  );
@@ -5660,7 +5681,7 @@ async function loadAndValidateConfig(configFile, porcelainMode) {
5660
5681
  config = parseYaml2(content);
5661
5682
  } catch (error) {
5662
5683
  const message = error instanceof Error ? error.message : "Unknown error";
5663
- if (porcelainMode) {
5684
+ if (jsonMode) {
5664
5685
  console.log(JSON.stringify({ error: `Invalid YAML format: ${message}` }));
5665
5686
  } else {
5666
5687
  console.error(chalk4.red("\u2717 Invalid YAML format"));
@@ -5670,7 +5691,7 @@ async function loadAndValidateConfig(configFile, porcelainMode) {
5670
5691
  }
5671
5692
  const validation = validateAgentCompose(config);
5672
5693
  if (!validation.valid) {
5673
- if (porcelainMode) {
5694
+ if (jsonMode) {
5674
5695
  console.log(JSON.stringify({ error: validation.error }));
5675
5696
  } else {
5676
5697
  console.error(chalk4.red(`\u2717 ${validation.error}`));
@@ -5710,9 +5731,9 @@ function checkLegacyImageFormat(config) {
5710
5731
  }
5711
5732
  }
5712
5733
  }
5713
- async function uploadAssets(agentName, agent, basePath, porcelainMode) {
5734
+ async function uploadAssets(agentName, agent, basePath, jsonMode) {
5714
5735
  if (agent.instructions) {
5715
- if (!porcelainMode) {
5736
+ if (!jsonMode) {
5716
5737
  console.log(`Uploading instructions: ${agent.instructions}`);
5717
5738
  }
5718
5739
  const result = await uploadInstructions(
@@ -5721,7 +5742,7 @@ async function uploadAssets(agentName, agent, basePath, porcelainMode) {
5721
5742
  basePath,
5722
5743
  agent.framework
5723
5744
  );
5724
- if (!porcelainMode) {
5745
+ if (!jsonMode) {
5725
5746
  console.log(
5726
5747
  chalk4.green(
5727
5748
  `\u2713 Instructions ${result.action === "deduplicated" ? "(unchanged)" : "uploaded"}: ${result.versionId.slice(0, 8)}`
@@ -5731,16 +5752,16 @@ async function uploadAssets(agentName, agent, basePath, porcelainMode) {
5731
5752
  }
5732
5753
  const skillResults = [];
5733
5754
  if (agent.skills && Array.isArray(agent.skills)) {
5734
- if (!porcelainMode) {
5755
+ if (!jsonMode) {
5735
5756
  console.log(`Uploading ${agent.skills.length} skill(s)...`);
5736
5757
  }
5737
5758
  for (const skillUrl of agent.skills) {
5738
- if (!porcelainMode) {
5759
+ if (!jsonMode) {
5739
5760
  console.log(chalk4.dim(` Downloading: ${skillUrl}`));
5740
5761
  }
5741
5762
  const result = await uploadSkill(skillUrl);
5742
5763
  skillResults.push(result);
5743
- if (!porcelainMode) {
5764
+ if (!jsonMode) {
5744
5765
  console.log(
5745
5766
  chalk4.green(
5746
5767
  ` \u2713 Skill ${result.action === "deduplicated" ? "(unchanged)" : "uploaded"}: ${result.skillName} (${result.versionId.slice(0, 8)})`
@@ -5792,7 +5813,7 @@ async function displayAndConfirmVariables(variables, options) {
5792
5813
  if (newSecrets.length === 0 && newVars.length === 0) {
5793
5814
  return true;
5794
5815
  }
5795
- if (!options.porcelain) {
5816
+ if (!options.json) {
5796
5817
  console.log();
5797
5818
  console.log(
5798
5819
  chalk4.bold("Skills require the following environment variables:")
@@ -5818,7 +5839,7 @@ async function displayAndConfirmVariables(variables, options) {
5818
5839
  }
5819
5840
  if (trulyNewSecrets.length > 0 && !options.yes) {
5820
5841
  if (!isInteractive()) {
5821
- if (options.porcelain) {
5842
+ if (options.json) {
5822
5843
  console.log(
5823
5844
  JSON.stringify({
5824
5845
  error: `New secrets detected: ${trulyNewSecrets.join(", ")}. Use --yes flag to approve.`
@@ -5841,7 +5862,7 @@ async function displayAndConfirmVariables(variables, options) {
5841
5862
  true
5842
5863
  );
5843
5864
  if (!confirmed) {
5844
- if (!options.porcelain) {
5865
+ if (!options.json) {
5845
5866
  console.log(chalk4.yellow("Compose cancelled"));
5846
5867
  }
5847
5868
  return false;
@@ -5871,7 +5892,7 @@ async function finalizeCompose(config, agent, variables, options) {
5871
5892
  process.exit(0);
5872
5893
  }
5873
5894
  mergeSkillVariables(agent, variables);
5874
- if (!options.porcelain) {
5895
+ if (!options.json) {
5875
5896
  console.log("Uploading compose...");
5876
5897
  }
5877
5898
  const response = await createOrUpdateCompose({ content: config });
@@ -5885,7 +5906,7 @@ async function finalizeCompose(config, agent, variables, options) {
5885
5906
  action: response.action,
5886
5907
  displayName
5887
5908
  };
5888
- if (!options.porcelain) {
5909
+ if (!options.json) {
5889
5910
  if (response.action === "created") {
5890
5911
  console.log(chalk4.green(`\u2713 Compose created: ${displayName}`));
5891
5912
  } else {
@@ -5901,19 +5922,19 @@ async function finalizeCompose(config, agent, variables, options) {
5901
5922
  );
5902
5923
  }
5903
5924
  if (options.autoUpdate !== false) {
5904
- await silentUpgradeAfterCommand("9.25.0");
5925
+ await silentUpgradeAfterCommand("9.26.0");
5905
5926
  }
5906
5927
  return result;
5907
5928
  }
5908
5929
  async function handleGitHubCompose(url, options) {
5909
- if (!options.porcelain) {
5930
+ if (!options.json) {
5910
5931
  console.log(`Downloading from GitHub: ${url}`);
5911
5932
  }
5912
5933
  const { dir: downloadedDir, tempRoot } = await downloadGitHubDirectory(url);
5913
5934
  const configFile = join6(downloadedDir, "vm0.yaml");
5914
5935
  try {
5915
5936
  if (!existsSync4(configFile)) {
5916
- if (options.porcelain) {
5937
+ if (options.json) {
5917
5938
  console.log(
5918
5939
  JSON.stringify({
5919
5940
  error: "vm0.yaml not found in the GitHub directory"
@@ -5929,11 +5950,11 @@ async function handleGitHubCompose(url, options) {
5929
5950
  }
5930
5951
  const { config, agentName, agent, basePath } = await loadAndValidateConfig(
5931
5952
  configFile,
5932
- options.porcelain
5953
+ options.json
5933
5954
  );
5934
5955
  const existingCompose = await getComposeByName(agentName);
5935
5956
  if (existingCompose) {
5936
- if (!options.porcelain) {
5957
+ if (!options.json) {
5937
5958
  console.log();
5938
5959
  console.log(
5939
5960
  chalk4.yellow(`\u26A0 An agent named "${agentName}" already exists.`)
@@ -5941,7 +5962,7 @@ async function handleGitHubCompose(url, options) {
5941
5962
  }
5942
5963
  if (!isInteractive()) {
5943
5964
  if (!options.yes) {
5944
- if (options.porcelain) {
5965
+ if (options.json) {
5945
5966
  console.log(
5946
5967
  JSON.stringify({
5947
5968
  error: "Cannot overwrite existing agent in non-interactive mode"
@@ -5967,7 +5988,7 @@ async function handleGitHubCompose(url, options) {
5967
5988
  false
5968
5989
  );
5969
5990
  if (!confirmed) {
5970
- if (!options.porcelain) {
5991
+ if (!options.json) {
5971
5992
  console.log(chalk4.yellow("Compose cancelled."));
5972
5993
  }
5973
5994
  process.exit(0);
@@ -5975,7 +5996,7 @@ async function handleGitHubCompose(url, options) {
5975
5996
  }
5976
5997
  }
5977
5998
  if (hasVolumes(config)) {
5978
- if (options.porcelain) {
5999
+ if (options.json) {
5979
6000
  console.log(
5980
6001
  JSON.stringify({
5981
6002
  error: "Volumes are not supported for GitHub URL compose"
@@ -5993,14 +6014,14 @@ async function handleGitHubCompose(url, options) {
5993
6014
  }
5994
6015
  process.exit(1);
5995
6016
  }
5996
- if (!options.porcelain) {
6017
+ if (!options.json) {
5997
6018
  checkLegacyImageFormat(config);
5998
6019
  }
5999
6020
  const skillResults = await uploadAssets(
6000
6021
  agentName,
6001
6022
  agent,
6002
6023
  basePath,
6003
- options.porcelain
6024
+ options.json
6004
6025
  );
6005
6026
  const environment = agent.environment || {};
6006
6027
  const variables = await collectSkillVariables(
@@ -6019,13 +6040,20 @@ var composeCommand = new Command7().name("compose").description("Create or updat
6019
6040
  ).option("-y, --yes", "Skip confirmation prompts for skill requirements").option(
6020
6041
  "--experimental-shared-compose",
6021
6042
  "Enable GitHub URL compose (experimental)"
6022
- ).option(
6043
+ ).option("--json", "Output JSON for scripts (suppresses interactive output)").option(
6023
6044
  "--porcelain",
6024
- "Output stable JSON for scripts (suppresses interactive output)"
6045
+ "[deprecated: use --json] Output JSON for scripts",
6046
+ false
6025
6047
  ).addOption(new Option("--no-auto-update").hideHelp()).action(
6026
6048
  async (configFile, options) => {
6027
6049
  const resolvedConfigFile = configFile ?? DEFAULT_CONFIG_FILE;
6028
- if (options.porcelain) {
6050
+ if (options.porcelain && !options.json) {
6051
+ console.error(
6052
+ chalk4.yellow("\u26A0 --porcelain is deprecated, use --json instead")
6053
+ );
6054
+ options.json = true;
6055
+ }
6056
+ if (options.json) {
6029
6057
  options.yes = true;
6030
6058
  options.autoUpdate = false;
6031
6059
  }
@@ -6033,7 +6061,7 @@ var composeCommand = new Command7().name("compose").description("Create or updat
6033
6061
  let result;
6034
6062
  if (isGitHubUrl(resolvedConfigFile)) {
6035
6063
  if (!options.experimentalSharedCompose) {
6036
- if (options.porcelain) {
6064
+ if (options.json) {
6037
6065
  console.log(
6038
6066
  JSON.stringify({
6039
6067
  error: "Composing shared agents requires --experimental-shared-compose flag"
@@ -6059,15 +6087,15 @@ var composeCommand = new Command7().name("compose").description("Create or updat
6059
6087
  }
6060
6088
  result = await handleGitHubCompose(resolvedConfigFile, options);
6061
6089
  } else {
6062
- const { config, agentName, agent, basePath } = await loadAndValidateConfig(resolvedConfigFile, options.porcelain);
6063
- if (!options.porcelain) {
6090
+ const { config, agentName, agent, basePath } = await loadAndValidateConfig(resolvedConfigFile, options.json);
6091
+ if (!options.json) {
6064
6092
  checkLegacyImageFormat(config);
6065
6093
  }
6066
6094
  const skillResults = await uploadAssets(
6067
6095
  agentName,
6068
6096
  agent,
6069
6097
  basePath,
6070
- options.porcelain
6098
+ options.json
6071
6099
  );
6072
6100
  const environment = agent.environment || {};
6073
6101
  const variables = await collectSkillVariables(
@@ -6077,11 +6105,11 @@ var composeCommand = new Command7().name("compose").description("Create or updat
6077
6105
  );
6078
6106
  result = await finalizeCompose(config, agent, variables, options);
6079
6107
  }
6080
- if (options.porcelain) {
6108
+ if (options.json) {
6081
6109
  console.log(JSON.stringify(result));
6082
6110
  }
6083
6111
  } catch (error) {
6084
- if (options.porcelain) {
6112
+ if (options.json) {
6085
6113
  const message = error instanceof Error ? error.message : "An unexpected error occurred";
6086
6114
  console.log(JSON.stringify({ error: message }));
6087
6115
  process.exit(1);
@@ -6424,10 +6452,10 @@ var EventRenderer = class _EventRenderer {
6424
6452
  * Note: This is run lifecycle status, not an event
6425
6453
  */
6426
6454
  static renderRunFailed(error, runId) {
6427
- console.log("");
6428
- console.log(chalk6.red("\u2717 Run failed"));
6429
- console.log(` Error: ${chalk6.red(error || "Unknown error")}`);
6430
- console.log(
6455
+ console.error("");
6456
+ console.error(chalk6.red("\u2717 Run failed"));
6457
+ console.error(` Error: ${chalk6.red(error || "Unknown error")}`);
6458
+ console.error(
6431
6459
  chalk6.dim(` (use "vm0 logs ${runId} --system" to view system logs)`)
6432
6460
  );
6433
6461
  }
@@ -8264,7 +8292,7 @@ var mainRunCommand = new Command8().name("run").description("Run an agent").argu
8264
8292
  " Running agent from other users carries security risks."
8265
8293
  )
8266
8294
  );
8267
- console.error(chalk9.dim(" Only run agents from users you trust."));
8295
+ console.error(chalk9.dim(" Only run agents from users you trust"));
8268
8296
  console.error();
8269
8297
  console.error("Example:");
8270
8298
  console.error(
@@ -8344,7 +8372,7 @@ var mainRunCommand = new Command8().name("run").description("Run an agent").argu
8344
8372
  }
8345
8373
  showNextSteps(result);
8346
8374
  if (options.autoUpdate !== false) {
8347
- await silentUpgradeAfterCommand("9.25.0");
8375
+ await silentUpgradeAfterCommand("9.26.0");
8348
8376
  }
8349
8377
  } catch (error) {
8350
8378
  handleRunError(error, identifier);
@@ -8524,7 +8552,7 @@ function formatRunStatus(status, width) {
8524
8552
  case "pending":
8525
8553
  return chalk12.yellow(paddedStatus);
8526
8554
  case "completed":
8527
- return chalk12.blue(paddedStatus);
8555
+ return chalk12.dim(paddedStatus);
8528
8556
  case "failed":
8529
8557
  case "timeout":
8530
8558
  return chalk12.red(paddedStatus);
@@ -8538,6 +8566,7 @@ var listCommand = new Command11().name("list").alias("ls").description("List act
8538
8566
  const activeRuns = response.runs;
8539
8567
  if (activeRuns.length === 0) {
8540
8568
  console.log(chalk12.dim("No active runs"));
8569
+ console.log(chalk12.dim(' Run: vm0 run <agent> "<prompt>"'));
8541
8570
  return;
8542
8571
  }
8543
8572
  const agentWidth = Math.max(
@@ -9702,7 +9731,7 @@ function validateEnvVariables(config, envFile) {
9702
9731
  try {
9703
9732
  const missingVars = checkMissingVariables(requiredVarNames, envFile);
9704
9733
  if (missingVars.length > 0) {
9705
- console.log();
9734
+ console.error();
9706
9735
  console.error(chalk29.red("\u2717 Missing required variables:"));
9707
9736
  for (const varName of missingVars) {
9708
9737
  console.error(chalk29.red(` ${varName}`));
@@ -9845,7 +9874,7 @@ var cookAction = new Command27().name("cook").description("Quick start: prepare,
9845
9874
  ).option("-y, --yes", "Skip confirmation prompts").option("-v, --verbose", "Show full tool inputs and outputs").addOption(new Option5("--debug-no-mock-claude").hideHelp()).addOption(new Option5("--no-auto-update").hideHelp()).action(
9846
9875
  async (prompt, options) => {
9847
9876
  if (options.autoUpdate !== false) {
9848
- const shouldExit = await checkAndUpgrade("9.25.0", prompt);
9877
+ const shouldExit = await checkAndUpgrade("9.26.0", prompt);
9849
9878
  if (shouldExit) {
9850
9879
  process.exit(0);
9851
9880
  }
@@ -10298,17 +10327,18 @@ async function showNetworkLogs(runId, options) {
10298
10327
  function handleError2(error, runId) {
10299
10328
  if (error instanceof Error) {
10300
10329
  if (error.message.includes("Not authenticated")) {
10301
- console.error(chalk33.red("Not authenticated. Run: vm0 auth login"));
10330
+ console.error(chalk33.red("\u2717 Not authenticated"));
10331
+ console.error(chalk33.dim(" Run: vm0 auth login"));
10302
10332
  } else if (error.message.includes("not found")) {
10303
- console.error(chalk33.red(`Run not found: ${runId}`));
10333
+ console.error(chalk33.red(`\u2717 Run not found: ${runId}`));
10304
10334
  } else if (error.message.includes("Invalid time format")) {
10305
- console.error(chalk33.red(error.message));
10335
+ console.error(chalk33.red(`\u2717 ${error.message}`));
10306
10336
  } else {
10307
- console.error(chalk33.red("Failed to fetch logs"));
10337
+ console.error(chalk33.red("\u2717 Failed to fetch logs"));
10308
10338
  console.error(chalk33.dim(` ${error.message}`));
10309
10339
  }
10310
10340
  } else {
10311
- console.error(chalk33.red("An unexpected error occurred"));
10341
+ console.error(chalk33.red("\u2717 An unexpected error occurred"));
10312
10342
  }
10313
10343
  }
10314
10344
 
@@ -11089,10 +11119,10 @@ var initCommand3 = new Command44().name("init").description("Initialize a new VM
11089
11119
  const existingFiles = checkExistingFiles();
11090
11120
  if (existingFiles.length > 0 && !options.force) {
11091
11121
  for (const file of existingFiles) {
11092
- console.log(chalk44.red(`\u2717 ${file} already exists`));
11122
+ console.error(chalk44.red(`\u2717 ${file} already exists`));
11093
11123
  }
11094
- console.log();
11095
- console.log(`To overwrite: ${chalk44.cyan("vm0 init --force")}`);
11124
+ console.error();
11125
+ console.error(`To overwrite: ${chalk44.cyan("vm0 init --force")}`);
11096
11126
  process.exit(1);
11097
11127
  }
11098
11128
  let agentName;
@@ -11124,11 +11154,11 @@ var initCommand3 = new Command44().name("init").description("Initialize a new VM
11124
11154
  agentName = name;
11125
11155
  }
11126
11156
  if (!agentName || !validateAgentName(agentName)) {
11127
- console.log(chalk44.red("\u2717 Invalid agent name"));
11128
- console.log(
11157
+ console.error(chalk44.red("\u2717 Invalid agent name"));
11158
+ console.error(
11129
11159
  chalk44.dim(" Must be 3-64 characters, alphanumeric and hyphens only")
11130
11160
  );
11131
- console.log(chalk44.dim(" Must start and end with letter or number"));
11161
+ console.error(chalk44.dim(" Must start and end with letter or number"));
11132
11162
  process.exit(1);
11133
11163
  }
11134
11164
  await writeFile7(VM0_YAML_FILE, generateVm0Yaml(agentName));
@@ -11805,7 +11835,7 @@ function formatRunStatus2(status) {
11805
11835
  case "timeout":
11806
11836
  return chalk47.red(status);
11807
11837
  case "running":
11808
- return chalk47.blue(status);
11838
+ return chalk47.cyan(status);
11809
11839
  case "pending":
11810
11840
  return chalk47.yellow(status);
11811
11841
  default:
@@ -12226,8 +12256,25 @@ var listCommand6 = new Command53().name("list").alias("ls").description("List al
12226
12256
  console.log(chalk52.bold("Secrets:"));
12227
12257
  console.log();
12228
12258
  for (const secret of result.secrets) {
12229
- const typeIndicator = secret.type === "model-provider" ? chalk52.dim(" [model-provider]") : "";
12259
+ let typeIndicator = "";
12260
+ let derivedLine = null;
12261
+ if (secret.type === "model-provider") {
12262
+ typeIndicator = chalk52.dim(" [model-provider]");
12263
+ } else if (secret.type === "connector") {
12264
+ const derived = getConnectorDerivedNames(secret.name);
12265
+ if (derived) {
12266
+ typeIndicator = chalk52.dim(` [${derived.connectorLabel} connector]`);
12267
+ derivedLine = chalk52.dim(
12268
+ `Available as: ${derived.envVarNames.join(", ")}`
12269
+ );
12270
+ } else {
12271
+ typeIndicator = chalk52.dim(" [connector]");
12272
+ }
12273
+ }
12230
12274
  console.log(` ${chalk52.cyan(secret.name)}${typeIndicator}`);
12275
+ if (derivedLine) {
12276
+ console.log(` ${derivedLine}`);
12277
+ }
12231
12278
  if (secret.description) {
12232
12279
  console.log(` ${chalk52.dim(secret.description)}`);
12233
12280
  }
@@ -12273,9 +12320,9 @@ var setCommand2 = new Command54().name("set").description("Create or update a se
12273
12320
  console.error(
12274
12321
  chalk53.red("\u2717 --body is required in non-interactive mode")
12275
12322
  );
12276
- console.log();
12277
- console.log("Usage:");
12278
- console.log(
12323
+ console.error();
12324
+ console.error("Usage:");
12325
+ console.error(
12279
12326
  chalk53.cyan(` vm0 secret set ${name} --body "your-secret-value"`)
12280
12327
  );
12281
12328
  process.exit(1);
@@ -12298,11 +12345,11 @@ var setCommand2 = new Command54().name("set").description("Create or update a se
12298
12345
  );
12299
12346
  } else if (error.message.includes("must contain only uppercase")) {
12300
12347
  console.error(chalk53.red(`\u2717 ${error.message}`));
12301
- console.log();
12302
- console.log("Examples of valid secret names:");
12303
- console.log(chalk53.dim(" MY_API_KEY"));
12304
- console.log(chalk53.dim(" GITHUB_TOKEN"));
12305
- console.log(chalk53.dim(" AWS_ACCESS_KEY_ID"));
12348
+ console.error();
12349
+ console.error("Examples of valid secret names:");
12350
+ console.error(chalk53.dim(" MY_API_KEY"));
12351
+ console.error(chalk53.dim(" GITHUB_TOKEN"));
12352
+ console.error(chalk53.dim(" AWS_ACCESS_KEY_ID"));
12306
12353
  } else {
12307
12354
  console.error(chalk53.red(`\u2717 ${error.message}`));
12308
12355
  }
@@ -12434,11 +12481,11 @@ var setCommand3 = new Command58().name("set").description("Create or update a va
12434
12481
  );
12435
12482
  } else if (error.message.includes("must contain only uppercase")) {
12436
12483
  console.error(chalk56.red(`\u2717 ${error.message}`));
12437
- console.log();
12438
- console.log("Examples of valid variable names:");
12439
- console.log(chalk56.dim(" MY_VAR"));
12440
- console.log(chalk56.dim(" API_URL"));
12441
- console.log(chalk56.dim(" DEBUG_MODE"));
12484
+ console.error();
12485
+ console.error("Examples of valid variable names:");
12486
+ console.error(chalk56.dim(" MY_VAR"));
12487
+ console.error(chalk56.dim(" API_URL"));
12488
+ console.error(chalk56.dim(" DEBUG_MODE"));
12442
12489
  } else {
12443
12490
  console.error(chalk56.red(`\u2717 ${error.message}`));
12444
12491
  }
@@ -12566,10 +12613,10 @@ import prompts2 from "prompts";
12566
12613
  function validateProviderType(typeStr) {
12567
12614
  if (!Object.keys(MODEL_PROVIDER_TYPES).includes(typeStr)) {
12568
12615
  console.error(chalk59.red(`\u2717 Invalid type "${typeStr}"`));
12569
- console.log();
12570
- console.log("Valid types:");
12616
+ console.error();
12617
+ console.error("Valid types:");
12571
12618
  for (const [t, config] of Object.entries(MODEL_PROVIDER_TYPES)) {
12572
- console.log(` ${chalk59.cyan(t)} - ${config.label}`);
12619
+ console.error(` ${chalk59.cyan(t)} - ${config.label}`);
12573
12620
  }
12574
12621
  process.exit(1);
12575
12622
  }
@@ -12582,10 +12629,10 @@ function validateModel(type, modelStr) {
12582
12629
  }
12583
12630
  if (models && !models.includes(modelStr)) {
12584
12631
  console.error(chalk59.red(`\u2717 Invalid model "${modelStr}"`));
12585
- console.log();
12586
- console.log("Valid models:");
12632
+ console.error();
12633
+ console.error("Valid models:");
12587
12634
  for (const m of models) {
12588
- console.log(` ${chalk59.cyan(m)}`);
12635
+ console.error(` ${chalk59.cyan(m)}`);
12589
12636
  }
12590
12637
  process.exit(1);
12591
12638
  }
@@ -12595,11 +12642,11 @@ function validateAuthMethod(type, authMethodStr) {
12595
12642
  const authMethods = getAuthMethodsForType(type);
12596
12643
  if (!authMethods || !(authMethodStr in authMethods)) {
12597
12644
  console.error(chalk59.red(`\u2717 Invalid auth method "${authMethodStr}"`));
12598
- console.log();
12599
- console.log("Valid auth methods:");
12645
+ console.error();
12646
+ console.error("Valid auth methods:");
12600
12647
  if (authMethods) {
12601
12648
  for (const [method, config] of Object.entries(authMethods)) {
12602
- console.log(` ${chalk59.cyan(method)} - ${config.label}`);
12649
+ console.error(` ${chalk59.cyan(method)} - ${config.label}`);
12603
12650
  }
12604
12651
  }
12605
12652
  process.exit(1);
@@ -12619,11 +12666,11 @@ function parseSecrets(type, authMethod, secretArgs) {
12619
12666
  console.error(
12620
12667
  chalk59.red("\u2717 Must use KEY=VALUE format for multi-secret auth methods")
12621
12668
  );
12622
- console.log();
12623
- console.log("Required secrets:");
12669
+ console.error();
12670
+ console.error("Required secrets:");
12624
12671
  for (const [name, fieldConfig] of Object.entries(secretsConfig)) {
12625
12672
  const requiredNote = fieldConfig.required ? " (required)" : "";
12626
- console.log(` ${chalk59.cyan(name)}${requiredNote}`);
12673
+ console.error(` ${chalk59.cyan(name)}${requiredNote}`);
12627
12674
  }
12628
12675
  process.exit(1);
12629
12676
  }
@@ -12639,8 +12686,8 @@ function parseSecrets(type, authMethod, secretArgs) {
12639
12686
  const eqIndex = arg.indexOf("=");
12640
12687
  if (eqIndex === -1) {
12641
12688
  console.error(chalk59.red(`\u2717 Invalid secret format "${arg}"`));
12642
- console.log();
12643
- console.log("Use KEY=VALUE format (e.g., AWS_REGION=us-east-1)");
12689
+ console.error();
12690
+ console.error("Use KEY=VALUE format (e.g., AWS_REGION=us-east-1)");
12644
12691
  process.exit(1);
12645
12692
  }
12646
12693
  const key = arg.slice(0, eqIndex);
@@ -12658,11 +12705,11 @@ function validateSecrets(type, authMethod, secrets) {
12658
12705
  for (const [name, fieldConfig] of Object.entries(secretsConfig)) {
12659
12706
  if (fieldConfig.required && !secrets[name]) {
12660
12707
  console.error(chalk59.red(`\u2717 Missing required secret: ${name}`));
12661
- console.log();
12662
- console.log("Required secrets:");
12708
+ console.error();
12709
+ console.error("Required secrets:");
12663
12710
  for (const [n, fc] of Object.entries(secretsConfig)) {
12664
12711
  if (fc.required) {
12665
- console.log(` ${chalk59.cyan(n)} - ${fc.label}`);
12712
+ console.error(` ${chalk59.cyan(n)} - ${fc.label}`);
12666
12713
  }
12667
12714
  }
12668
12715
  process.exit(1);
@@ -12671,11 +12718,11 @@ function validateSecrets(type, authMethod, secrets) {
12671
12718
  for (const name of Object.keys(secrets)) {
12672
12719
  if (!(name in secretsConfig)) {
12673
12720
  console.error(chalk59.red(`\u2717 Unknown secret: ${name}`));
12674
- console.log();
12675
- console.log("Valid secrets:");
12721
+ console.error();
12722
+ console.error("Valid secrets:");
12676
12723
  for (const [n, fc] of Object.entries(secretsConfig)) {
12677
12724
  const requiredNote = fc.required ? " (required)" : " (optional)";
12678
- console.log(` ${chalk59.cyan(n)}${requiredNote}`);
12725
+ console.error(` ${chalk59.cyan(n)}${requiredNote}`);
12679
12726
  }
12680
12727
  process.exit(1);
12681
12728
  }
@@ -12710,17 +12757,17 @@ function handleNonInteractiveMode(options) {
12710
12757
  `\u2717 --auth-method is required for "${type}" (multiple auth methods available)`
12711
12758
  )
12712
12759
  );
12713
- console.log();
12714
- console.log("Available auth methods:");
12760
+ console.error();
12761
+ console.error("Available auth methods:");
12715
12762
  for (const [method, config] of Object.entries(authMethods)) {
12716
12763
  const defaultNote = method === defaultAuthMethod ? " (default)" : "";
12717
- console.log(
12764
+ console.error(
12718
12765
  ` ${chalk59.cyan(method)} - ${config.label}${defaultNote}`
12719
12766
  );
12720
12767
  }
12721
- console.log();
12722
- console.log("Example:");
12723
- console.log(
12768
+ console.error();
12769
+ console.error("Example:");
12770
+ console.error(
12724
12771
  chalk59.cyan(
12725
12772
  ` vm0 model-provider setup --type ${type} --auth-method ${authMethodNames[0]} --secret KEY=VALUE`
12726
12773
  )
@@ -12877,9 +12924,9 @@ async function promptForSecrets(type, authMethod) {
12877
12924
  async function handleInteractiveMode() {
12878
12925
  if (!isInteractive()) {
12879
12926
  console.error(chalk59.red("\u2717 Interactive mode requires a TTY"));
12880
- console.log();
12881
- console.log("Use non-interactive mode:");
12882
- console.log(
12927
+ console.error();
12928
+ console.error("Use non-interactive mode:");
12929
+ console.error(
12883
12930
  chalk59.cyan(' vm0 model-provider setup --type <type> --secret "<value>"')
12884
12931
  );
12885
12932
  process.exit(1);
@@ -12916,7 +12963,7 @@ async function handleInteractiveMode() {
12916
12963
  const checkResult = await checkModelProviderSecret(type);
12917
12964
  if (checkResult.exists) {
12918
12965
  console.log();
12919
- console.log(`"${type}" is already configured.`);
12966
+ console.log(`"${type}" is already configured`);
12920
12967
  console.log();
12921
12968
  const actionResponse = await prompts2(
12922
12969
  {
@@ -12973,7 +13020,8 @@ async function handleInteractiveMode() {
12973
13020
  function handleSetupError2(error) {
12974
13021
  if (error instanceof Error) {
12975
13022
  if (error.message.includes("Not authenticated")) {
12976
- console.error(chalk59.red("\u2717 Not authenticated. Run: vm0 auth login"));
13023
+ console.error(chalk59.red("\u2717 Not authenticated"));
13024
+ console.error(chalk59.dim(" Run: vm0 auth login"));
12977
13025
  } else {
12978
13026
  console.error(chalk59.red(`\u2717 ${error.message}`));
12979
13027
  }
@@ -13184,7 +13232,7 @@ async function getHeaders2() {
13184
13232
  var connectCommand = new Command66().name("connect").description("Connect a third-party service (e.g., GitHub)").argument("<type>", "Connector type (e.g., github)").action(async (type) => {
13185
13233
  const parseResult = connectorTypeSchema.safeParse(type);
13186
13234
  if (!parseResult.success) {
13187
- console.error(chalk62.red(`Unknown connector type: ${type}`));
13235
+ console.error(chalk62.red(`\u2717 Unknown connector type: ${type}`));
13188
13236
  console.error("Available connectors: github");
13189
13237
  process.exit(1);
13190
13238
  }
@@ -13204,7 +13252,7 @@ var connectCommand = new Command66().name("connect").description("Connect a thir
13204
13252
  if (createResult.status !== 200) {
13205
13253
  const errorBody = createResult.body;
13206
13254
  console.error(
13207
- chalk62.red(`Failed to create session: ${errorBody.error?.message}`)
13255
+ chalk62.red(`\u2717 Failed to create session: ${errorBody.error?.message}`)
13208
13256
  );
13209
13257
  process.exit(1);
13210
13258
  }
@@ -13239,7 +13287,7 @@ The session expires in ${Math.floor(session.expiresIn / 60)} minutes.`
13239
13287
  const errorBody = statusResult.body;
13240
13288
  console.error(
13241
13289
  chalk62.red(`
13242
- Failed to check status: ${errorBody.error?.message}`)
13290
+ \u2717 Failed to check status: ${errorBody.error?.message}`)
13243
13291
  );
13244
13292
  process.exit(1);
13245
13293
  }
@@ -13251,14 +13299,14 @@ Failed to check status: ${errorBody.error?.message}`)
13251
13299
  ${type} connected successfully!`));
13252
13300
  return;
13253
13301
  case "expired":
13254
- console.log(chalk62.red("\nSession expired. Please try again."));
13302
+ console.error(chalk62.red("\n\u2717 Session expired, please try again"));
13255
13303
  process.exit(1);
13256
13304
  break;
13257
13305
  case "error":
13258
- console.log(
13306
+ console.error(
13259
13307
  chalk62.red(
13260
13308
  `
13261
- Connection failed: ${status.errorMessage || "Unknown error"}`
13309
+ \u2717 Connection failed: ${status.errorMessage || "Unknown error"}`
13262
13310
  )
13263
13311
  );
13264
13312
  process.exit(1);
@@ -13268,7 +13316,7 @@ Connection failed: ${status.errorMessage || "Unknown error"}`
13268
13316
  break;
13269
13317
  }
13270
13318
  }
13271
- console.log(chalk62.red("\nSession timed out. Please try again."));
13319
+ console.error(chalk62.red("\n\u2717 Session timed out, please try again"));
13272
13320
  process.exit(1);
13273
13321
  });
13274
13322
 
@@ -13322,10 +13370,10 @@ var statusCommand7 = new Command68().name("status").description("Show detailed s
13322
13370
  const parseResult = connectorTypeSchema.safeParse(type);
13323
13371
  if (!parseResult.success) {
13324
13372
  console.error(chalk64.red(`\u2717 Unknown connector type: ${type}`));
13325
- console.log();
13326
- console.log("Available connectors:");
13373
+ console.error();
13374
+ console.error("Available connectors:");
13327
13375
  for (const [t, config] of Object.entries(CONNECTOR_TYPES)) {
13328
- console.log(` ${chalk64.cyan(t)} - ${config.label}`);
13376
+ console.error(` ${chalk64.cyan(t)} - ${config.label}`);
13329
13377
  }
13330
13378
  process.exit(1);
13331
13379
  }
@@ -13388,10 +13436,10 @@ var disconnectCommand = new Command69().name("disconnect").description("Disconne
13388
13436
  const parseResult = connectorTypeSchema.safeParse(type);
13389
13437
  if (!parseResult.success) {
13390
13438
  console.error(chalk65.red(`\u2717 Unknown connector type: ${type}`));
13391
- console.log();
13392
- console.log("Available connectors:");
13439
+ console.error();
13440
+ console.error("Available connectors:");
13393
13441
  for (const [t, config] of Object.entries(CONNECTOR_TYPES)) {
13394
- console.log(` ${chalk65.cyan(t)} - ${config.label}`);
13442
+ console.error(` ${chalk65.cyan(t)} - ${config.label}`);
13395
13443
  }
13396
13444
  process.exit(1);
13397
13445
  }
@@ -13457,7 +13505,7 @@ function renderVm0Banner() {
13457
13505
  function renderOnboardWelcome() {
13458
13506
  renderVm0Banner();
13459
13507
  console.log(` Build agentic workflows using natural language.`);
13460
- console.log(` ${chalk66.dim("Currently in beta, enjoy it free.")}`);
13508
+ console.log(` ${chalk66.dim("Currently in beta, enjoy it free")}`);
13461
13509
  console.log(
13462
13510
  ` ${chalk66.dim("Star us on GitHub: https://github.com/vm0-ai/vm0")}`
13463
13511
  );
@@ -13714,9 +13762,9 @@ async function runClaudeCommand(args, cwd) {
13714
13762
  }
13715
13763
  function handlePluginError(error, context) {
13716
13764
  const displayContext = context ?? "Claude plugin";
13717
- console.error(chalk68.red(`Failed to install ${displayContext}`));
13765
+ console.error(chalk68.red(`\u2717 Failed to install ${displayContext}`));
13718
13766
  if (error instanceof Error) {
13719
- console.error(chalk68.red(error.message));
13767
+ console.error(chalk68.red(`\u2717 ${error.message}`));
13720
13768
  }
13721
13769
  console.error(
13722
13770
  chalk68.dim("Please ensure Claude CLI is installed and accessible.")
@@ -13800,7 +13848,7 @@ async function handleAuthentication(ctx) {
13800
13848
  return;
13801
13849
  }
13802
13850
  if (!ctx.interactive) {
13803
- console.error(chalk69.red("Error: Not authenticated"));
13851
+ console.error(chalk69.red("\u2717 Not authenticated"));
13804
13852
  console.error("Run 'vm0 auth login' first or set VM0_TOKEN");
13805
13853
  process.exit(1);
13806
13854
  }
@@ -13818,7 +13866,7 @@ async function handleAuthentication(ctx) {
13818
13866
  },
13819
13867
  onError: (error) => {
13820
13868
  console.error(chalk69.red(`
13821
- ${error.message}`));
13869
+ \u2717 ${error.message}`));
13822
13870
  process.exit(1);
13823
13871
  }
13824
13872
  });
@@ -13831,7 +13879,7 @@ async function handleModelProvider(ctx) {
13831
13879
  return;
13832
13880
  }
13833
13881
  if (!ctx.interactive) {
13834
- console.error(chalk69.red("Error: No model provider configured"));
13882
+ console.error(chalk69.red("\u2717 No model provider configured"));
13835
13883
  console.error("Run 'vm0 model-provider setup' first");
13836
13884
  process.exit(1);
13837
13885
  }
@@ -13935,10 +13983,10 @@ async function handleAgentCreation(ctx) {
13935
13983
  process.exit(1);
13936
13984
  }
13937
13985
  if (existsSync11(agentName)) {
13938
- console.error(chalk69.red(`${agentName}/ already exists`));
13939
- console.log();
13940
- console.log("Remove it first or choose a different name:");
13941
- console.log(chalk69.cyan(` rm -rf ${agentName}`));
13986
+ console.error(chalk69.red(`\u2717 ${agentName}/ already exists`));
13987
+ console.error();
13988
+ console.error("Remove it first or choose a different name:");
13989
+ console.error(chalk69.cyan(` rm -rf ${agentName}`));
13942
13990
  process.exit(1);
13943
13991
  }
13944
13992
  }
@@ -14182,9 +14230,9 @@ function displayResult(job) {
14182
14230
  }
14183
14231
  }
14184
14232
  } else if (job.status === "failed") {
14185
- console.log(chalk71.red("\u2717 Compose failed!"));
14233
+ console.error(chalk71.red("\u2717 Compose failed"));
14186
14234
  if (job.error) {
14187
- console.log(` Error: ${chalk71.red(job.error)}`);
14235
+ console.error(` Error: ${chalk71.red(job.error)}`);
14188
14236
  }
14189
14237
  } else {
14190
14238
  console.log(`Status: ${job.status}`);
@@ -14196,7 +14244,7 @@ var devToolCommand = new Command74().name("dev-tool").description("Developer too
14196
14244
 
14197
14245
  // src/index.ts
14198
14246
  var program = new Command75();
14199
- program.name("vm0").description("VM0 CLI - Build and run agents with natural language").version("9.25.0");
14247
+ program.name("vm0").description("VM0 CLI - Build and run agents with natural language").version("9.26.0");
14200
14248
  program.addCommand(authCommand);
14201
14249
  program.addCommand(infoCommand);
14202
14250
  program.addCommand(composeCommand);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vm0/cli",
3
- "version": "9.25.0",
3
+ "version": "9.26.0",
4
4
  "description": "CLI application",
5
5
  "repository": {
6
6
  "type": "git",