@vm0/cli 8.0.1 → 8.1.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 +107 -186
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -432,11 +432,6 @@ var appStringSchema = z4.string().superRefine((val, ctx) => {
432
432
  });
433
433
  var agentDefinitionSchema = z4.object({
434
434
  description: z4.string().optional(),
435
- /**
436
- * @deprecated Use `apps` field instead for pre-installed tools.
437
- * This field will be removed in a future version.
438
- */
439
- image: z4.string().optional(),
440
435
  framework: z4.string().min(1, "Framework is required"),
441
436
  /**
442
437
  * Array of pre-installed apps/tools for the agent environment.
@@ -446,8 +441,6 @@ var agentDefinitionSchema = z4.object({
446
441
  */
447
442
  apps: z4.array(appStringSchema).optional(),
448
443
  volumes: z4.array(z4.string()).optional(),
449
- working_dir: z4.string().optional(),
450
- // Optional when provider supports auto-config
451
444
  environment: z4.record(z4.string(), z4.string()).optional(),
452
445
  /**
453
446
  * Path to instructions file (e.g., AGENTS.md).
@@ -474,7 +467,17 @@ var agentDefinitionSchema = z4.object({
474
467
  * Requires experimental_runner to be configured.
475
468
  * When enabled, filters outbound traffic by domain/IP rules.
476
469
  */
477
- experimental_firewall: experimentalFirewallSchema.optional()
470
+ experimental_firewall: experimentalFirewallSchema.optional(),
471
+ /**
472
+ * @deprecated Server-resolved field. User input is ignored.
473
+ * @internal
474
+ */
475
+ image: z4.string().optional(),
476
+ /**
477
+ * @deprecated Server-resolved field. User input is ignored.
478
+ * @internal
479
+ */
480
+ working_dir: z4.string().optional()
478
481
  });
479
482
  var agentComposeContentSchema = z4.object({
480
483
  version: z4.string().min(1, "Version is required"),
@@ -1606,13 +1609,11 @@ var scopeResponseSchema = z12.object({
1606
1609
  id: z12.string().uuid(),
1607
1610
  slug: z12.string(),
1608
1611
  type: scopeTypeSchema,
1609
- displayName: z12.string().nullable(),
1610
1612
  createdAt: z12.string(),
1611
1613
  updatedAt: z12.string()
1612
1614
  });
1613
1615
  var createScopeRequestSchema = z12.object({
1614
- slug: scopeSlugSchema,
1615
- displayName: z12.string().max(128).optional()
1616
+ slug: scopeSlugSchema
1616
1617
  });
1617
1618
  var updateScopeRequestSchema = z12.object({
1618
1619
  slug: scopeSlugSchema,
@@ -2973,6 +2974,13 @@ var FEATURE_SWITCHES = {
2973
2974
  };
2974
2975
 
2975
2976
  // src/lib/api/core/client-factory.ts
2977
+ var ApiRequestError = class extends Error {
2978
+ constructor(message, code) {
2979
+ super(message);
2980
+ this.code = code;
2981
+ this.name = "ApiRequestError";
2982
+ }
2983
+ };
2976
2984
  async function getHeaders() {
2977
2985
  const token = await getToken();
2978
2986
  if (!token) {
@@ -3002,7 +3010,8 @@ async function getClientConfig() {
3002
3010
  function handleError(result, defaultMessage) {
3003
3011
  const errorBody = result.body;
3004
3012
  const message = errorBody.error?.message || defaultMessage;
3005
- throw new Error(message);
3013
+ const code = errorBody.error?.code || "UNKNOWN";
3014
+ throw new ApiRequestError(message, code);
3006
3015
  }
3007
3016
 
3008
3017
  // src/lib/api/core/http.ts
@@ -3421,72 +3430,6 @@ async function getUsage(options) {
3421
3430
 
3422
3431
  // src/lib/domain/yaml-validator.ts
3423
3432
  import { z as z23 } from "zod";
3424
-
3425
- // src/lib/domain/framework-config.ts
3426
- var FRAMEWORK_DEFAULTS = {
3427
- "claude-code": {
3428
- workingDir: "/home/user/workspace",
3429
- image: {
3430
- production: "vm0/claude-code:latest",
3431
- development: "vm0/claude-code:dev"
3432
- }
3433
- },
3434
- codex: {
3435
- workingDir: "/home/user/workspace",
3436
- image: {
3437
- production: "vm0/codex:latest",
3438
- development: "vm0/codex:dev"
3439
- }
3440
- }
3441
- };
3442
- function getFrameworkDefaults(framework) {
3443
- return FRAMEWORK_DEFAULTS[framework];
3444
- }
3445
- function isFrameworkSupported(framework) {
3446
- return framework in FRAMEWORK_DEFAULTS;
3447
- }
3448
- var FRAMEWORK_APPS_IMAGES = {
3449
- "claude-code": {
3450
- github: {
3451
- production: "vm0/claude-code-github:latest",
3452
- development: "vm0/claude-code-github:dev"
3453
- }
3454
- },
3455
- codex: {
3456
- github: {
3457
- production: "vm0/codex-github:latest",
3458
- development: "vm0/codex-github:dev"
3459
- }
3460
- }
3461
- };
3462
- function parseAppString(appString) {
3463
- const [app, tag] = appString.split(":");
3464
- return {
3465
- app: app ?? appString,
3466
- tag: tag === "dev" ? "dev" : "latest"
3467
- };
3468
- }
3469
- function getDefaultImageWithApps(framework, apps) {
3470
- const defaults = FRAMEWORK_DEFAULTS[framework];
3471
- if (!defaults) return void 0;
3472
- if (apps && apps.length > 0) {
3473
- const frameworkApps = FRAMEWORK_APPS_IMAGES[framework];
3474
- if (frameworkApps) {
3475
- const firstApp = apps[0];
3476
- if (firstApp) {
3477
- const { app, tag } = parseAppString(firstApp);
3478
- const appImage = frameworkApps[app];
3479
- if (appImage) {
3480
- return tag === "dev" ? appImage.development : appImage.production;
3481
- }
3482
- }
3483
- }
3484
- }
3485
- const isDevelopment = process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test";
3486
- return isDevelopment ? defaults.image.development : defaults.image.production;
3487
- }
3488
-
3489
- // src/lib/domain/yaml-validator.ts
3490
3433
  var cliAgentNameSchema = z23.string().min(3, "Agent name must be at least 3 characters").max(64, "Agent name must be 64 characters or less").regex(
3491
3434
  /^[a-zA-Z0-9]([a-zA-Z0-9-]{0,62}[a-zA-Z0-9])?$/,
3492
3435
  "Agent name must start and end with letter or number, and contain only letters, numbers, and hyphens"
@@ -3497,21 +3440,6 @@ function validateGitHubTreeUrl(url) {
3497
3440
  }
3498
3441
  var cliAgentDefinitionSchema = agentDefinitionSchema.superRefine(
3499
3442
  (agent, ctx) => {
3500
- const frameworkSupported = isFrameworkSupported(agent.framework);
3501
- if (!agent.image && !frameworkSupported) {
3502
- ctx.addIssue({
3503
- code: z23.ZodIssueCode.custom,
3504
- message: "Missing agent.image (required when framework is not auto-configured)",
3505
- path: ["image"]
3506
- });
3507
- }
3508
- if (!agent.working_dir && !frameworkSupported) {
3509
- ctx.addIssue({
3510
- code: z23.ZodIssueCode.custom,
3511
- message: "Missing agent.working_dir (required when framework is not auto-configured)",
3512
- path: ["working_dir"]
3513
- });
3514
- }
3515
3443
  if (agent.skills) {
3516
3444
  for (let i = 0; i < agent.skills.length; i++) {
3517
3445
  const skillUrl = agent.skills[i];
@@ -4171,24 +4099,6 @@ var composeCommand = new Command().name("compose").description("Create or update
4171
4099
  const agentName = Object.keys(agents)[0];
4172
4100
  const agent = agents[agentName];
4173
4101
  const basePath = dirname2(configFile);
4174
- if (agent.framework) {
4175
- const defaults = getFrameworkDefaults(agent.framework);
4176
- if (defaults) {
4177
- if (!agent.image) {
4178
- const apps = agent.apps;
4179
- const defaultImage = getDefaultImageWithApps(
4180
- agent.framework,
4181
- apps
4182
- );
4183
- if (defaultImage) {
4184
- agent.image = defaultImage;
4185
- }
4186
- }
4187
- if (!agent.working_dir) {
4188
- agent.working_dir = defaults.workingDir;
4189
- }
4190
- }
4191
- }
4192
4102
  if (agent.instructions) {
4193
4103
  const instructionsPath = agent.instructions;
4194
4104
  const framework = agent.framework;
@@ -7959,7 +7869,7 @@ cookCmd.argument("[prompt]", "Prompt for the agent").option(
7959
7869
  // eslint-disable-next-line complexity -- TODO: refactor complex function
7960
7870
  async (prompt, options) => {
7961
7871
  if (!options.noAutoUpdate) {
7962
- const shouldExit = await checkAndUpgrade("8.0.1", prompt);
7872
+ const shouldExit = await checkAndUpgrade("8.1.0", prompt);
7963
7873
  if (shouldExit) {
7964
7874
  process.exit(0);
7965
7875
  }
@@ -8558,9 +8468,6 @@ var statusCommand3 = new Command21().name("status").description("View current sc
8558
8468
  console.log(chalk26.bold("Scope Information:"));
8559
8469
  console.log(` Slug: ${chalk26.green(scope.slug)}`);
8560
8470
  console.log(` Type: ${scope.type}`);
8561
- if (scope.displayName) {
8562
- console.log(` Display Name: ${scope.displayName}`);
8563
- }
8564
8471
  console.log(
8565
8472
  ` Created: ${new Date(scope.createdAt).toLocaleDateString()}`
8566
8473
  );
@@ -8589,76 +8496,69 @@ var statusCommand3 = new Command21().name("status").description("View current sc
8589
8496
  // src/commands/scope/set.ts
8590
8497
  import { Command as Command22 } from "commander";
8591
8498
  import chalk27 from "chalk";
8592
- var setCommand = new Command22().name("set").description("Set your scope slug").argument("<slug>", "The scope slug (e.g., your username)").option("--force", "Force change existing scope (may break references)").option("--display-name <name>", "Display name for the scope").action(
8593
- async (slug, options) => {
8499
+ var setCommand = new Command22().name("set").description("Set your scope slug").argument("<slug>", "The scope slug (e.g., your username)").option("--force", "Force change existing scope (may break references)").action(async (slug, options) => {
8500
+ try {
8501
+ let existingScope;
8594
8502
  try {
8595
- let existingScope;
8596
- try {
8597
- existingScope = await getScope();
8598
- } catch (error) {
8599
- if (!(error instanceof Error) || !error.message.includes("No scope configured")) {
8600
- throw error;
8601
- }
8503
+ existingScope = await getScope();
8504
+ } catch (error) {
8505
+ if (!(error instanceof Error) || !error.message.includes("No scope configured")) {
8506
+ throw error;
8602
8507
  }
8603
- let scope;
8604
- if (existingScope) {
8605
- if (!options.force) {
8606
- console.error(
8607
- chalk27.yellow(`You already have a scope: ${existingScope.slug}`)
8608
- );
8609
- console.error();
8610
- console.error("To change your scope, use --force:");
8611
- console.error(chalk27.cyan(` vm0 scope set ${slug} --force`));
8612
- console.error();
8613
- console.error(
8614
- chalk27.yellow(
8615
- "Warning: Changing your scope may break existing agent references."
8616
- )
8617
- );
8618
- process.exit(1);
8619
- }
8620
- scope = await updateScope({ slug, force: true });
8621
- console.log(chalk27.green(`\u2713 Scope updated to ${scope.slug}`));
8622
- } else {
8623
- scope = await createScope({
8624
- slug,
8625
- displayName: options.displayName
8626
- });
8627
- console.log(chalk27.green(`\u2713 Scope created: ${scope.slug}`));
8508
+ }
8509
+ let scope;
8510
+ if (existingScope) {
8511
+ if (!options.force) {
8512
+ console.error(
8513
+ chalk27.yellow(`You already have a scope: ${existingScope.slug}`)
8514
+ );
8515
+ console.error();
8516
+ console.error("To change your scope, use --force:");
8517
+ console.error(chalk27.cyan(` vm0 scope set ${slug} --force`));
8518
+ console.error();
8519
+ console.error(
8520
+ chalk27.yellow(
8521
+ "Warning: Changing your scope may break existing agent references."
8522
+ )
8523
+ );
8524
+ process.exit(1);
8628
8525
  }
8629
- console.log();
8630
- console.log("Your agents will now be namespaced as:");
8631
- console.log(chalk27.cyan(` ${scope.slug}/<agent-name>`));
8632
- } catch (error) {
8633
- if (error instanceof Error) {
8634
- if (error.message.includes("Not authenticated")) {
8635
- console.error(
8636
- chalk27.red("\u2717 Not authenticated. Run: vm0 auth login")
8637
- );
8638
- } else if (error.message.includes("already exists")) {
8639
- console.error(
8640
- chalk27.red(
8641
- `\u2717 Scope "${slug}" is already taken. Please choose a different slug.`
8642
- )
8643
- );
8644
- } else if (error.message.includes("reserved")) {
8645
- console.error(chalk27.red(`\u2717 ${error.message}`));
8646
- } else if (error.message.includes("vm0")) {
8647
- console.error(
8648
- chalk27.red(
8649
- "\u2717 Scope slugs cannot start with 'vm0' (reserved for system use)"
8650
- )
8651
- );
8652
- } else {
8653
- console.error(chalk27.red(`\u2717 ${error.message}`));
8654
- }
8526
+ scope = await updateScope({ slug, force: true });
8527
+ console.log(chalk27.green(`\u2713 Scope updated to ${scope.slug}`));
8528
+ } else {
8529
+ scope = await createScope({ slug });
8530
+ console.log(chalk27.green(`\u2713 Scope created: ${scope.slug}`));
8531
+ }
8532
+ console.log();
8533
+ console.log("Your agents will now be namespaced as:");
8534
+ console.log(chalk27.cyan(` ${scope.slug}/<agent-name>`));
8535
+ } catch (error) {
8536
+ if (error instanceof Error) {
8537
+ if (error.message.includes("Not authenticated")) {
8538
+ console.error(chalk27.red("\u2717 Not authenticated. Run: vm0 auth login"));
8539
+ } else if (error.message.includes("already exists")) {
8540
+ console.error(
8541
+ chalk27.red(
8542
+ `\u2717 Scope "${slug}" is already taken. Please choose a different slug.`
8543
+ )
8544
+ );
8545
+ } else if (error.message.includes("reserved")) {
8546
+ console.error(chalk27.red(`\u2717 ${error.message}`));
8547
+ } else if (error.message.includes("vm0")) {
8548
+ console.error(
8549
+ chalk27.red(
8550
+ "\u2717 Scope slugs cannot start with 'vm0' (reserved for system use)"
8551
+ )
8552
+ );
8655
8553
  } else {
8656
- console.error(chalk27.red("\u2717 An unexpected error occurred"));
8554
+ console.error(chalk27.red(`\u2717 ${error.message}`));
8657
8555
  }
8658
- process.exit(1);
8556
+ } else {
8557
+ console.error(chalk27.red("\u2717 An unexpected error occurred"));
8659
8558
  }
8559
+ process.exit(1);
8660
8560
  }
8661
- );
8561
+ });
8662
8562
 
8663
8563
  // src/commands/scope/index.ts
8664
8564
  var scopeCommand = new Command23().name("scope").description("Manage your scope (namespace for agents)").addCommand(statusCommand3).addCommand(setCommand);
@@ -9506,11 +9406,11 @@ async function gatherSecrets(optionSecrets, existingSecretNames) {
9506
9406
  `Keep existing secrets? (${existingSecretNames.join(", ")})`,
9507
9407
  true
9508
9408
  );
9509
- if (!keepSecrets) {
9510
- console.log(
9511
- chalk31.dim(" Note: You'll need to provide new secret values")
9512
- );
9409
+ if (keepSecrets) {
9410
+ return void 0;
9513
9411
  }
9412
+ console.log(chalk31.dim(" Note: You'll need to provide new secret values"));
9413
+ return {};
9514
9414
  }
9515
9415
  return void 0;
9516
9416
  }
@@ -9671,6 +9571,12 @@ function displayDeployResult(agentName, deployResult) {
9671
9571
  );
9672
9572
  console.log(chalk31.dim(` At: ${atTimeFormatted}`));
9673
9573
  }
9574
+ if (deployResult.created) {
9575
+ console.log();
9576
+ console.log(
9577
+ ` To activate: ${chalk31.cyan(`vm0 schedule enable ${agentName}`)}`
9578
+ );
9579
+ }
9674
9580
  }
9675
9581
  var setupCommand = new Command28().name("setup").description("Create or edit a schedule for an agent").argument("<agent-name>", "Agent name to configure schedule for").option("-f, --frequency <type>", "Frequency: daily|weekly|monthly|once").option("-t, --time <HH:MM>", "Time to run (24-hour format)").option("-d, --day <day>", "Day of week (mon-sun) or day of month (1-31)").option("-z, --timezone <tz>", "IANA timezone").option("-p, --prompt <text>", "Prompt to run").option("--var <name=value>", "Variable (can be repeated)", collect, []).option("--secret <name=value>", "Secret (can be repeated)", collect, []).option("--artifact-name <name>", "Artifact name", "artifact").action(async (agentName, options) => {
9676
9582
  try {
@@ -9721,6 +9627,7 @@ var setupCommand = new Command28().name("setup").description("Create or edit a s
9721
9627
  options.secret || [],
9722
9628
  existingSchedule?.secretNames
9723
9629
  );
9630
+ const keepExistingSecrets = initialSecrets === void 0;
9724
9631
  const { secrets, vars } = await gatherMissingConfiguration(
9725
9632
  requiredConfig,
9726
9633
  initialSecrets ?? {},
@@ -9738,7 +9645,7 @@ var setupCommand = new Command28().name("setup").description("Create or edit a s
9738
9645
  timezone,
9739
9646
  prompt: promptText_,
9740
9647
  vars: Object.keys(vars).length > 0 ? vars : void 0,
9741
- secrets: Object.keys(secrets).length > 0 ? secrets : void 0,
9648
+ secrets: keepExistingSecrets ? void 0 : Object.keys(secrets).length > 0 ? secrets : void 0,
9742
9649
  artifactName: options.artifactName
9743
9650
  });
9744
9651
  } catch (error) {
@@ -9999,10 +9906,24 @@ var enableCommand = new Command32().name("enable").description("Enable a schedul
9999
9906
  );
10000
9907
  } catch (error) {
10001
9908
  console.error(chalk35.red("\u2717 Failed to enable schedule"));
10002
- if (error instanceof Error) {
9909
+ if (error instanceof ApiRequestError) {
9910
+ if (error.code === "SCHEDULE_PAST") {
9911
+ console.error(chalk35.dim(" Scheduled time has already passed"));
9912
+ console.error(chalk35.dim(` Run: vm0 schedule setup ${agentName}`));
9913
+ } else if (error.code === "NOT_FOUND") {
9914
+ console.error(
9915
+ chalk35.dim(` No schedule found for agent "${agentName}"`)
9916
+ );
9917
+ console.error(chalk35.dim(" Run: vm0 schedule list"));
9918
+ } else if (error.code === "UNAUTHORIZED") {
9919
+ console.error(chalk35.dim(" Run: vm0 auth login"));
9920
+ } else {
9921
+ console.error(chalk35.dim(` ${error.message}`));
9922
+ }
9923
+ } else if (error instanceof Error) {
10003
9924
  if (error.message.includes("Not authenticated")) {
10004
9925
  console.error(chalk35.dim(" Run: vm0 auth login"));
10005
- } else if (error.message.toLowerCase().includes("not found") || error.message.includes("No schedule found")) {
9926
+ } else if (error.message.includes("No schedule found")) {
10006
9927
  console.error(
10007
9928
  chalk35.dim(` No schedule found for agent "${agentName}"`)
10008
9929
  );
@@ -10621,7 +10542,7 @@ var modelProviderCommand = new Command44().name("model-provider").description("M
10621
10542
 
10622
10543
  // src/index.ts
10623
10544
  var program = new Command45();
10624
- program.name("vm0").description("VM0 CLI - Build and run agents with natural language").version("8.0.1");
10545
+ program.name("vm0").description("VM0 CLI - Build and run agents with natural language").version("8.1.0");
10625
10546
  program.command("info").description("Display environment information").action(async () => {
10626
10547
  console.log(chalk45.bold("System Information:"));
10627
10548
  console.log(`Node Version: ${process.version}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vm0/cli",
3
- "version": "8.0.1",
3
+ "version": "8.1.0",
4
4
  "description": "CLI application",
5
5
  "repository": {
6
6
  "type": "git",