@vm0/cli 8.1.1 → 9.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 +518 -97
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
- import { Command as Command45 } from "commander";
5
- import chalk46 from "chalk";
4
+ import { Command as Command47 } from "commander";
5
+ import chalk48 from "chalk";
6
6
 
7
7
  // src/lib/api/auth.ts
8
8
  import chalk from "chalk";
@@ -86,7 +86,7 @@ async function authenticate(apiUrl) {
86
86
  console.log("Initiating authentication...");
87
87
  const deviceAuth = await requestDeviceCode(targetApiUrl);
88
88
  console.log(chalk.green("\nDevice code generated"));
89
- const verificationUrl = `${targetApiUrl}/cli-auth`;
89
+ const verificationUrl = `${targetApiUrl}${deviceAuth.verification_path}`;
90
90
  console.log(chalk.cyan(`
91
91
  To authenticate, visit: ${verificationUrl}`));
92
92
  console.log(`And enter this code: ${chalk.bold(deviceAuth.user_code)}`);
@@ -1483,7 +1483,7 @@ var cliAuthDeviceContract = c6.router({
1483
1483
  200: z8.object({
1484
1484
  device_code: z8.string(),
1485
1485
  user_code: z8.string(),
1486
- verification_url: z8.string(),
1486
+ verification_path: z8.string(),
1487
1487
  expires_in: z8.number(),
1488
1488
  interval: z8.number()
1489
1489
  }),
@@ -2305,12 +2305,12 @@ var publicApiErrorSchema = z18.object({
2305
2305
  code: z18.string(),
2306
2306
  message: z18.string(),
2307
2307
  param: z18.string().optional(),
2308
- doc_url: z18.string().url().optional()
2308
+ docUrl: z18.string().url().optional()
2309
2309
  })
2310
2310
  });
2311
2311
  var paginationSchema = z18.object({
2312
- has_more: z18.boolean(),
2313
- next_cursor: z18.string().nullable()
2312
+ hasMore: z18.boolean(),
2313
+ nextCursor: z18.string().nullable()
2314
2314
  });
2315
2315
  function createPaginatedResponseSchema(dataSchema) {
2316
2316
  return z18.object({
@@ -2327,6 +2327,11 @@ var timestampSchema = z18.string().datetime();
2327
2327
 
2328
2328
  // ../../packages/core/src/contracts/platform.ts
2329
2329
  var c15 = initContract();
2330
+ var platformPaginationSchema = z19.object({
2331
+ hasMore: z19.boolean(),
2332
+ nextCursor: z19.string().nullable(),
2333
+ totalPages: z19.number()
2334
+ });
2330
2335
  var platformLogStatusSchema = z19.enum([
2331
2336
  "pending",
2332
2337
  "running",
@@ -2338,9 +2343,10 @@ var platformLogStatusSchema = z19.enum([
2338
2343
  var platformLogEntrySchema = z19.object({
2339
2344
  id: z19.string().uuid()
2340
2345
  });
2341
- var platformLogsListResponseSchema = createPaginatedResponseSchema(
2342
- platformLogEntrySchema
2343
- );
2346
+ var platformLogsListResponseSchema = z19.object({
2347
+ data: z19.array(platformLogEntrySchema),
2348
+ pagination: platformPaginationSchema
2349
+ });
2344
2350
  var artifactSchema = z19.object({
2345
2351
  name: z19.string().nullable(),
2346
2352
  version: z19.string().nullable()
@@ -2349,7 +2355,7 @@ var platformLogDetailSchema = z19.object({
2349
2355
  id: z19.string().uuid(),
2350
2356
  sessionId: z19.string().nullable(),
2351
2357
  agentName: z19.string(),
2352
- provider: z19.string(),
2358
+ framework: z19.string().nullable(),
2353
2359
  status: platformLogStatusSchema,
2354
2360
  prompt: z19.string(),
2355
2361
  error: z19.string().nullable(),
@@ -2387,6 +2393,26 @@ var platformLogsByIdContract = c15.router({
2387
2393
  summary: "Get agent run log details by ID"
2388
2394
  }
2389
2395
  });
2396
+ var artifactDownloadResponseSchema = z19.object({
2397
+ url: z19.string().url(),
2398
+ expiresAt: z19.string()
2399
+ });
2400
+ var platformArtifactDownloadContract = c15.router({
2401
+ getDownloadUrl: {
2402
+ method: "GET",
2403
+ path: "/api/platform/artifacts/download",
2404
+ query: z19.object({
2405
+ name: z19.string().min(1, "Artifact name is required"),
2406
+ version: z19.string().optional()
2407
+ }),
2408
+ responses: {
2409
+ 200: artifactDownloadResponseSchema,
2410
+ 401: apiErrorSchema,
2411
+ 404: apiErrorSchema
2412
+ },
2413
+ summary: "Get presigned URL for artifact download"
2414
+ }
2415
+ });
2390
2416
 
2391
2417
  // ../../packages/core/src/contracts/public/agents.ts
2392
2418
  import { z as z20 } from "zod";
@@ -2394,15 +2420,15 @@ var c16 = initContract();
2394
2420
  var publicAgentSchema = z20.object({
2395
2421
  id: z20.string(),
2396
2422
  name: z20.string(),
2397
- current_version_id: z20.string().nullable(),
2398
- created_at: timestampSchema,
2399
- updated_at: timestampSchema
2423
+ currentVersionId: z20.string().nullable(),
2424
+ createdAt: timestampSchema,
2425
+ updatedAt: timestampSchema
2400
2426
  });
2401
2427
  var agentVersionSchema = z20.object({
2402
2428
  id: z20.string(),
2403
- agent_id: z20.string(),
2404
- version_number: z20.number(),
2405
- created_at: timestampSchema
2429
+ agentId: z20.string(),
2430
+ versionNumber: z20.number(),
2431
+ createdAt: timestampSchema
2406
2432
  });
2407
2433
  var publicAgentDetailSchema = publicAgentSchema;
2408
2434
  var paginatedAgentsSchema = createPaginatedResponseSchema(publicAgentSchema);
@@ -2476,50 +2502,50 @@ var publicRunStatusSchema = z21.enum([
2476
2502
  ]);
2477
2503
  var publicRunSchema = z21.object({
2478
2504
  id: z21.string(),
2479
- agent_id: z21.string(),
2480
- agent_name: z21.string(),
2505
+ agentId: z21.string(),
2506
+ agentName: z21.string(),
2481
2507
  status: publicRunStatusSchema,
2482
2508
  prompt: z21.string(),
2483
- created_at: timestampSchema,
2484
- started_at: timestampSchema.nullable(),
2485
- completed_at: timestampSchema.nullable()
2509
+ createdAt: timestampSchema,
2510
+ startedAt: timestampSchema.nullable(),
2511
+ completedAt: timestampSchema.nullable()
2486
2512
  });
2487
2513
  var publicRunDetailSchema = publicRunSchema.extend({
2488
2514
  error: z21.string().nullable(),
2489
- execution_time_ms: z21.number().nullable(),
2490
- checkpoint_id: z21.string().nullable(),
2491
- session_id: z21.string().nullable(),
2492
- artifact_name: z21.string().nullable(),
2493
- artifact_version: z21.string().nullable(),
2515
+ executionTimeMs: z21.number().nullable(),
2516
+ checkpointId: z21.string().nullable(),
2517
+ sessionId: z21.string().nullable(),
2518
+ artifactName: z21.string().nullable(),
2519
+ artifactVersion: z21.string().nullable(),
2494
2520
  volumes: z21.record(z21.string(), z21.string()).optional()
2495
2521
  });
2496
2522
  var paginatedRunsSchema = createPaginatedResponseSchema(publicRunSchema);
2497
2523
  var createRunRequestSchema = z21.object({
2498
- // Agent identification (one of: agent, agent_id, session_id, checkpoint_id)
2524
+ // Agent identification (one of: agent, agentId, sessionId, checkpointId)
2499
2525
  agent: z21.string().optional(),
2500
2526
  // Agent name
2501
- agent_id: z21.string().optional(),
2527
+ agentId: z21.string().optional(),
2502
2528
  // Agent ID
2503
- agent_version: z21.string().optional(),
2529
+ agentVersion: z21.string().optional(),
2504
2530
  // Version specifier (e.g., "latest", "v1", specific ID)
2505
2531
  // Continue session
2506
- session_id: z21.string().optional(),
2532
+ sessionId: z21.string().optional(),
2507
2533
  // Resume from checkpoint
2508
- checkpoint_id: z21.string().optional(),
2534
+ checkpointId: z21.string().optional(),
2509
2535
  // Required
2510
2536
  prompt: z21.string().min(1, "Prompt is required"),
2511
2537
  // Optional configuration
2512
2538
  variables: z21.record(z21.string(), z21.string()).optional(),
2513
2539
  secrets: z21.record(z21.string(), z21.string()).optional(),
2514
- artifact_name: z21.string().optional(),
2540
+ artifactName: z21.string().optional(),
2515
2541
  // Artifact name to mount
2516
- artifact_version: z21.string().optional(),
2542
+ artifactVersion: z21.string().optional(),
2517
2543
  // Artifact version (defaults to latest)
2518
2544
  volumes: z21.record(z21.string(), z21.string()).optional()
2519
2545
  // volume_name -> version
2520
2546
  });
2521
2547
  var runListQuerySchema = listQuerySchema.extend({
2522
- agent_id: z21.string().optional(),
2548
+ agentId: z21.string().optional(),
2523
2549
  status: publicRunStatusSchema.optional(),
2524
2550
  since: timestampSchema.optional()
2525
2551
  });
@@ -2628,16 +2654,16 @@ var publicRunLogsContract = c17.router({
2628
2654
  });
2629
2655
  var metricPointSchema = z21.object({
2630
2656
  timestamp: timestampSchema,
2631
- cpu_percent: z21.number(),
2632
- memory_used_mb: z21.number(),
2633
- memory_total_mb: z21.number(),
2634
- disk_used_mb: z21.number(),
2635
- disk_total_mb: z21.number()
2657
+ cpuPercent: z21.number(),
2658
+ memoryUsedMb: z21.number(),
2659
+ memoryTotalMb: z21.number(),
2660
+ diskUsedMb: z21.number(),
2661
+ diskTotalMb: z21.number()
2636
2662
  });
2637
2663
  var metricsSummarySchema = z21.object({
2638
- avg_cpu_percent: z21.number(),
2639
- max_memory_used_mb: z21.number(),
2640
- total_duration_ms: z21.number().nullable()
2664
+ avgCpuPercent: z21.number(),
2665
+ maxMemoryUsedMb: z21.number(),
2666
+ totalDurationMs: z21.number().nullable()
2641
2667
  });
2642
2668
  var metricsResponseSchema2 = z21.object({
2643
2669
  data: z21.array(metricPointSchema),
@@ -2688,7 +2714,7 @@ var publicRunEventsContract = c17.router({
2688
2714
  id: z21.string().min(1, "Run ID is required")
2689
2715
  }),
2690
2716
  query: z21.object({
2691
- last_event_id: z21.string().optional()
2717
+ lastEventId: z21.string().optional()
2692
2718
  // For reconnection
2693
2719
  }),
2694
2720
  responses: {
@@ -2709,27 +2735,27 @@ var c18 = initContract();
2709
2735
  var publicArtifactSchema = z22.object({
2710
2736
  id: z22.string(),
2711
2737
  name: z22.string(),
2712
- current_version_id: z22.string().nullable(),
2738
+ currentVersionId: z22.string().nullable(),
2713
2739
  size: z22.number(),
2714
2740
  // Total size in bytes
2715
- file_count: z22.number(),
2716
- created_at: timestampSchema,
2717
- updated_at: timestampSchema
2741
+ fileCount: z22.number(),
2742
+ createdAt: timestampSchema,
2743
+ updatedAt: timestampSchema
2718
2744
  });
2719
2745
  var artifactVersionSchema = z22.object({
2720
2746
  id: z22.string(),
2721
2747
  // SHA-256 content hash
2722
- artifact_id: z22.string(),
2748
+ artifactId: z22.string(),
2723
2749
  size: z22.number(),
2724
2750
  // Size in bytes
2725
- file_count: z22.number(),
2751
+ fileCount: z22.number(),
2726
2752
  message: z22.string().nullable(),
2727
2753
  // Optional commit message
2728
- created_by: z22.string(),
2729
- created_at: timestampSchema
2754
+ createdBy: z22.string(),
2755
+ createdAt: timestampSchema
2730
2756
  });
2731
2757
  var publicArtifactDetailSchema = publicArtifactSchema.extend({
2732
- current_version: artifactVersionSchema.nullable()
2758
+ currentVersion: artifactVersionSchema.nullable()
2733
2759
  });
2734
2760
  var paginatedArtifactsSchema = createPaginatedResponseSchema(publicArtifactSchema);
2735
2761
  var paginatedArtifactVersionsSchema = createPaginatedResponseSchema(
@@ -2796,7 +2822,7 @@ var publicArtifactDownloadContract = c18.router({
2796
2822
  id: z22.string().min(1, "Artifact ID is required")
2797
2823
  }),
2798
2824
  query: z22.object({
2799
- version_id: z22.string().optional()
2825
+ versionId: z22.string().optional()
2800
2826
  // Defaults to current version
2801
2827
  }),
2802
2828
  responses: {
@@ -2817,27 +2843,27 @@ var c19 = initContract();
2817
2843
  var publicVolumeSchema = z23.object({
2818
2844
  id: z23.string(),
2819
2845
  name: z23.string(),
2820
- current_version_id: z23.string().nullable(),
2846
+ currentVersionId: z23.string().nullable(),
2821
2847
  size: z23.number(),
2822
2848
  // Total size in bytes
2823
- file_count: z23.number(),
2824
- created_at: timestampSchema,
2825
- updated_at: timestampSchema
2849
+ fileCount: z23.number(),
2850
+ createdAt: timestampSchema,
2851
+ updatedAt: timestampSchema
2826
2852
  });
2827
2853
  var volumeVersionSchema = z23.object({
2828
2854
  id: z23.string(),
2829
2855
  // SHA-256 content hash
2830
- volume_id: z23.string(),
2856
+ volumeId: z23.string(),
2831
2857
  size: z23.number(),
2832
2858
  // Size in bytes
2833
- file_count: z23.number(),
2859
+ fileCount: z23.number(),
2834
2860
  message: z23.string().nullable(),
2835
2861
  // Optional commit message
2836
- created_by: z23.string(),
2837
- created_at: timestampSchema
2862
+ createdBy: z23.string(),
2863
+ createdAt: timestampSchema
2838
2864
  });
2839
2865
  var publicVolumeDetailSchema = publicVolumeSchema.extend({
2840
- current_version: volumeVersionSchema.nullable()
2866
+ currentVersion: volumeVersionSchema.nullable()
2841
2867
  });
2842
2868
  var paginatedVolumesSchema = createPaginatedResponseSchema(publicVolumeSchema);
2843
2869
  var paginatedVolumeVersionsSchema = createPaginatedResponseSchema(volumeVersionSchema);
@@ -2902,7 +2928,7 @@ var publicVolumeDownloadContract = c19.router({
2902
2928
  id: z23.string().min(1, "Volume ID is required")
2903
2929
  }),
2904
2930
  query: z23.object({
2905
- version_id: z23.string().optional()
2931
+ versionId: z23.string().optional()
2906
2932
  // Defaults to current version
2907
2933
  }),
2908
2934
  responses: {
@@ -3094,10 +3120,10 @@ async function getRawHeaders() {
3094
3120
  }
3095
3121
  return headers;
3096
3122
  }
3097
- async function httpGet(path14) {
3123
+ async function httpGet(path15) {
3098
3124
  const baseUrl = await getBaseUrl();
3099
3125
  const headers = await getRawHeaders();
3100
- return fetch(`${baseUrl}${path14}`, {
3126
+ return fetch(`${baseUrl}${path15}`, {
3101
3127
  method: "GET",
3102
3128
  headers
3103
3129
  });
@@ -3577,49 +3603,49 @@ var cliComposeSchema = z24.object({
3577
3603
  function formatZodError(error) {
3578
3604
  const issue = error.issues[0];
3579
3605
  if (!issue) return "Validation failed";
3580
- const path14 = issue.path.join(".");
3606
+ const path15 = issue.path.join(".");
3581
3607
  const message = issue.message;
3582
- if (!path14) return message;
3608
+ if (!path15) return message;
3583
3609
  if (issue.code === "invalid_type") {
3584
3610
  const received = issue.received;
3585
3611
  const isMissing = received === "undefined" || message.includes("received undefined") || message === "Required";
3586
- if (path14 === "version" && isMissing) {
3612
+ if (path15 === "version" && isMissing) {
3587
3613
  return "Missing config.version";
3588
3614
  }
3589
- if (path14 === "agents" && isMissing) {
3615
+ if (path15 === "agents" && isMissing) {
3590
3616
  return "Missing agents object in config";
3591
3617
  }
3592
- if (path14.startsWith("volumes.") && path14.endsWith(".name")) {
3593
- const volumeKey = path14.split(".")[1];
3618
+ if (path15.startsWith("volumes.") && path15.endsWith(".name")) {
3619
+ const volumeKey = path15.split(".")[1];
3594
3620
  return `Volume "${volumeKey}" must have a 'name' field (string)`;
3595
3621
  }
3596
- if (path14.startsWith("volumes.") && path14.endsWith(".version")) {
3597
- const volumeKey = path14.split(".")[1];
3622
+ if (path15.startsWith("volumes.") && path15.endsWith(".version")) {
3623
+ const volumeKey = path15.split(".")[1];
3598
3624
  return `Volume "${volumeKey}" must have a 'version' field (string)`;
3599
3625
  }
3600
3626
  if (issue.expected === "array") {
3601
- const fieldName = path14.replace(/^agents\.[^.]+\./, "agent.");
3627
+ const fieldName = path15.replace(/^agents\.[^.]+\./, "agent.");
3602
3628
  return `${fieldName} must be an array`;
3603
3629
  }
3604
3630
  if (issue.expected === "string" && received === "number") {
3605
- const fieldName = path14.replace(/^agents\.[^.]+\./, "agent.");
3631
+ const fieldName = path15.replace(/^agents\.[^.]+\./, "agent.");
3606
3632
  const match = fieldName.match(/^(agent\.[^.]+)\.\d+$/);
3607
3633
  if (match) {
3608
3634
  return `Each entry in ${match[1]?.replace("agent.", "")} must be a string`;
3609
3635
  }
3610
3636
  }
3611
3637
  }
3612
- if (issue.code === "invalid_key" && path14.startsWith("agents.")) {
3638
+ if (issue.code === "invalid_key" && path15.startsWith("agents.")) {
3613
3639
  return "Invalid agent name format. Must be 3-64 characters, letters, numbers, and hyphens only. Must start and end with letter or number.";
3614
3640
  }
3615
- if (message === "Invalid key in record" && path14.startsWith("agents.")) {
3641
+ if (message === "Invalid key in record" && path15.startsWith("agents.")) {
3616
3642
  return "Invalid agent name format. Must be 3-64 characters, letters, numbers, and hyphens only. Must start and end with letter or number.";
3617
3643
  }
3618
3644
  if (issue.code === "custom") {
3619
3645
  return message;
3620
3646
  }
3621
- if (path14.startsWith("agents.")) {
3622
- const cleanPath = path14.replace(/^agents\.[^.]+\./, "agent.");
3647
+ if (path15.startsWith("agents.")) {
3648
+ const cleanPath = path15.replace(/^agents\.[^.]+\./, "agent.");
3623
3649
  if (message.startsWith("Invalid input:")) {
3624
3650
  const match = message.match(/expected (\w+), received (\w+)/);
3625
3651
  if (match && match[1] === "string" && match[2] === "number") {
@@ -3631,7 +3657,7 @@ function formatZodError(error) {
3631
3657
  }
3632
3658
  return `${cleanPath}: ${message}`;
3633
3659
  }
3634
- return `${path14}: ${message}`;
3660
+ return `${path15}: ${message}`;
3635
3661
  }
3636
3662
  function validateAgentName(name) {
3637
3663
  return cliAgentNameSchema.safeParse(name).success;
@@ -5834,7 +5860,7 @@ var ApiClient = class {
5834
5860
  /**
5835
5861
  * Generic GET request
5836
5862
  */
5837
- async get(path14) {
5863
+ async get(path15) {
5838
5864
  const baseUrl = await this.getBaseUrl();
5839
5865
  const token = await getToken();
5840
5866
  if (!token) {
@@ -5847,7 +5873,7 @@ var ApiClient = class {
5847
5873
  if (bypassSecret) {
5848
5874
  headers["x-vercel-protection-bypass"] = bypassSecret;
5849
5875
  }
5850
- return fetch(`${baseUrl}${path14}`, {
5876
+ return fetch(`${baseUrl}${path15}`, {
5851
5877
  method: "GET",
5852
5878
  headers
5853
5879
  });
@@ -5855,7 +5881,7 @@ var ApiClient = class {
5855
5881
  /**
5856
5882
  * Generic POST request
5857
5883
  */
5858
- async post(path14, options) {
5884
+ async post(path15, options) {
5859
5885
  const baseUrl = await this.getBaseUrl();
5860
5886
  const token = await getToken();
5861
5887
  if (!token) {
@@ -5871,7 +5897,7 @@ var ApiClient = class {
5871
5897
  if (bypassSecret) {
5872
5898
  headers["x-vercel-protection-bypass"] = bypassSecret;
5873
5899
  }
5874
- return fetch(`${baseUrl}${path14}`, {
5900
+ return fetch(`${baseUrl}${path15}`, {
5875
5901
  method: "POST",
5876
5902
  headers,
5877
5903
  body: options?.body
@@ -5880,7 +5906,7 @@ var ApiClient = class {
5880
5906
  /**
5881
5907
  * Generic DELETE request
5882
5908
  */
5883
- async delete(path14) {
5909
+ async delete(path15) {
5884
5910
  const baseUrl = await this.getBaseUrl();
5885
5911
  const token = await getToken();
5886
5912
  if (!token) {
@@ -5893,7 +5919,7 @@ var ApiClient = class {
5893
5919
  if (bypassSecret) {
5894
5920
  headers["x-vercel-protection-bypass"] = bypassSecret;
5895
5921
  }
5896
- return fetch(`${baseUrl}${path14}`, {
5922
+ return fetch(`${baseUrl}${path15}`, {
5897
5923
  method: "DELETE",
5898
5924
  headers
5899
5925
  });
@@ -7888,7 +7914,7 @@ cookCmd.argument("[prompt]", "Prompt for the agent").option(
7888
7914
  // eslint-disable-next-line complexity -- TODO: refactor complex function
7889
7915
  async (prompt, options) => {
7890
7916
  if (!options.noAutoUpdate) {
7891
- const shouldExit = await checkAndUpgrade("8.1.1", prompt);
7917
+ const shouldExit = await checkAndUpgrade("9.1.0", prompt);
7892
7918
  if (shouldExit) {
7893
7919
  process.exit(0);
7894
7920
  }
@@ -9568,7 +9594,7 @@ Deploying schedule for agent ${chalk32.cyan(params.agentName)}...`
9568
9594
  secrets: expandedSecrets,
9569
9595
  artifactName: params.artifactName
9570
9596
  });
9571
- displayDeployResult(params.agentName, deployResult);
9597
+ return deployResult;
9572
9598
  }
9573
9599
  function handleSetupError(error) {
9574
9600
  console.error(chalk32.red("\u2717 Failed to setup schedule"));
@@ -9608,14 +9634,53 @@ function displayDeployResult(agentName, deployResult) {
9608
9634
  );
9609
9635
  console.log(chalk32.dim(` At: ${atTimeFormatted}`));
9610
9636
  }
9611
- if (deployResult.created) {
9612
- console.log();
9637
+ }
9638
+ async function tryEnableSchedule(scheduleName, composeId, agentName) {
9639
+ try {
9640
+ await enableSchedule({ name: scheduleName, composeId });
9613
9641
  console.log(
9614
- ` To activate: ${chalk32.cyan(`vm0 schedule enable ${agentName}`)}`
9642
+ chalk32.green(`\u2713 Enabled schedule for agent ${chalk32.cyan(agentName)}`)
9643
+ );
9644
+ } catch (error) {
9645
+ console.error(chalk32.yellow("\u26A0 Failed to enable schedule"));
9646
+ if (error instanceof ApiRequestError) {
9647
+ if (error.code === "SCHEDULE_PAST") {
9648
+ console.error(chalk32.dim(" Scheduled time has already passed"));
9649
+ } else {
9650
+ console.error(chalk32.dim(` ${error.message}`));
9651
+ }
9652
+ } else if (error instanceof Error) {
9653
+ console.error(chalk32.dim(` ${error.message}`));
9654
+ }
9655
+ console.log(
9656
+ ` To enable manually: ${chalk32.cyan(`vm0 schedule enable ${agentName}`)}`
9615
9657
  );
9616
9658
  }
9617
9659
  }
9618
- 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) => {
9660
+ function showEnableHint(agentName) {
9661
+ console.log();
9662
+ console.log(` To enable: ${chalk32.cyan(`vm0 schedule enable ${agentName}`)}`);
9663
+ }
9664
+ async function handleScheduleEnabling(params) {
9665
+ const { scheduleName, composeId, agentName, enableFlag, shouldPromptEnable } = params;
9666
+ if (enableFlag) {
9667
+ await tryEnableSchedule(scheduleName, composeId, agentName);
9668
+ return;
9669
+ }
9670
+ if (shouldPromptEnable && isInteractive()) {
9671
+ const enableNow = await promptConfirm("Enable this schedule?", true);
9672
+ if (enableNow) {
9673
+ await tryEnableSchedule(scheduleName, composeId, agentName);
9674
+ } else {
9675
+ showEnableHint(agentName);
9676
+ }
9677
+ return;
9678
+ }
9679
+ if (shouldPromptEnable) {
9680
+ showEnableHint(agentName);
9681
+ }
9682
+ }
9683
+ 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").option("-e, --enable", "Enable schedule immediately after creation").action(async (agentName, options) => {
9619
9684
  try {
9620
9685
  const { composeId, scheduleName, composeContent } = await resolveAgent(agentName);
9621
9686
  const requiredConfig = extractRequiredConfiguration(composeContent);
@@ -9662,7 +9727,7 @@ var setupCommand = new Command28().name("setup").description("Create or edit a s
9662
9727
  optionVars: options.var || [],
9663
9728
  existingSchedule
9664
9729
  });
9665
- await buildAndDeploy({
9730
+ const deployResult = await buildAndDeploy({
9666
9731
  scheduleName,
9667
9732
  composeId,
9668
9733
  agentName,
@@ -9676,6 +9741,15 @@ var setupCommand = new Command28().name("setup").description("Create or edit a s
9676
9741
  secrets: config.preserveExistingSecrets ? void 0 : Object.keys(config.secrets).length > 0 ? config.secrets : void 0,
9677
9742
  artifactName: options.artifactName
9678
9743
  });
9744
+ displayDeployResult(agentName, deployResult);
9745
+ const shouldPromptEnable = deployResult.created || existingSchedule !== void 0 && !existingSchedule.enabled;
9746
+ await handleScheduleEnabling({
9747
+ scheduleName,
9748
+ composeId,
9749
+ agentName,
9750
+ enableFlag: options.enable ?? false,
9751
+ shouldPromptEnable
9752
+ });
9679
9753
  } catch (error) {
9680
9754
  handleSetupError(error);
9681
9755
  }
@@ -10555,11 +10629,356 @@ var setDefaultCommand = new Command43().name("set-default").description("Set a m
10555
10629
  // src/commands/model-provider/index.ts
10556
10630
  var modelProviderCommand = new Command44().name("model-provider").description("Manage model providers for agent runs").addCommand(listCommand6).addCommand(setupCommand2).addCommand(deleteCommand3).addCommand(setDefaultCommand);
10557
10631
 
10632
+ // src/commands/onboard.ts
10633
+ import { Command as Command46 } from "commander";
10634
+ import chalk47 from "chalk";
10635
+ import prompts3 from "prompts";
10636
+ import { mkdir as mkdir8 } from "fs/promises";
10637
+ import { existsSync as existsSync10 } from "fs";
10638
+
10639
+ // src/commands/setup-claude.ts
10640
+ import { Command as Command45 } from "commander";
10641
+ import chalk46 from "chalk";
10642
+ import { mkdir as mkdir7, writeFile as writeFile7 } from "fs/promises";
10643
+ import path14 from "path";
10644
+ var SKILL_DIR = ".claude/skills/vm0-agent-builder";
10645
+ var SKILL_CONTENT = `---
10646
+ name: vm0-agent-builder
10647
+ description: Guide for building VM0 agents with Claude's help. Use this skill when users want to create or improve their agent's AGENTS.md and vm0.yaml configuration.
10648
+ ---
10649
+
10650
+ # VM0 Agent Builder
10651
+
10652
+ Help users create effective AI agents using the VM0 platform. This skill guides the process of designing agent workflows, writing AGENTS.md instructions, and configuring vm0.yaml.
10653
+
10654
+ ## When to Use
10655
+
10656
+ - User wants to create a new VM0 agent from scratch
10657
+ - User wants to improve an existing agent's instructions
10658
+ - User needs help configuring vm0.yaml with skills
10659
+ - User is unsure how to structure their agent's workflow
10660
+
10661
+ ## Workflow
10662
+
10663
+ ### Step 1: Understand the Goal
10664
+
10665
+ Ask the user what they want their agent to accomplish:
10666
+ - What is the main task or problem to solve?
10667
+ - What inputs will the agent receive?
10668
+ - What outputs should the agent produce?
10669
+ - Are there any constraints or requirements?
10670
+
10671
+ ### Step 2: Design the Workflow
10672
+
10673
+ Break down the task into clear, sequential steps:
10674
+ 1. Each step should be a single, focused action
10675
+ 2. Steps should build on each other logically
10676
+ 3. Include error handling and edge cases
10677
+ 4. Consider what tools/skills the agent will need
10678
+
10679
+ ### Step 3: Write AGENTS.md
10680
+
10681
+ Create the agent instructions file with:
10682
+
10683
+ \`\`\`markdown
10684
+ # Agent Instructions
10685
+
10686
+ You are a [role description].
10687
+
10688
+ ## Goal
10689
+
10690
+ [Clear statement of what the agent should accomplish]
10691
+
10692
+ ## Workflow
10693
+
10694
+ 1. [First step with specific instructions]
10695
+ 2. [Second step with specific instructions]
10696
+ 3. [Continue with remaining steps...]
10697
+
10698
+ ## Output
10699
+
10700
+ [Describe the expected output format and location]
10701
+
10702
+ ## Constraints
10703
+
10704
+ [Any limitations or rules the agent should follow]
10705
+ \`\`\`
10706
+
10707
+ ### Step 4: Configure vm0.yaml
10708
+
10709
+ Update the vm0.yaml to include necessary skills:
10710
+
10711
+ \`\`\`yaml
10712
+ version: "1.0"
10713
+
10714
+ agents:
10715
+ agent-name:
10716
+ framework: claude-code
10717
+ instructions: AGENTS.md
10718
+ skills:
10719
+ - https://github.com/vm0-ai/vm0-skills/tree/main/skill-name
10720
+ environment:
10721
+ # Add any required environment variables
10722
+ API_KEY: "\${{ secrets.API_KEY }}"
10723
+ \`\`\`
10724
+
10725
+ ### Step 5: Test the Agent
10726
+
10727
+ Guide the user to test their agent:
10728
+
10729
+ \`\`\`bash
10730
+ # Deploy the agent configuration
10731
+ vm0 compose vm0.yaml
10732
+
10733
+ # Run the agent with a test prompt
10734
+ vm0 cook "start working on the task"
10735
+
10736
+ # Check the logs if needed
10737
+ vm0 logs <run-id>
10738
+ \`\`\`
10739
+
10740
+ ## Available Skills
10741
+
10742
+ Common skills from vm0-skills repository:
10743
+
10744
+ | Skill | Purpose |
10745
+ |-------|---------|
10746
+ | \`github\` | GitHub API operations (issues, PRs, repos) |
10747
+ | \`slack\` | Send messages to Slack channels |
10748
+ | \`notion\` | Read/write Notion pages and databases |
10749
+ | \`firecrawl\` | Web scraping and content extraction |
10750
+ | \`browserbase\` | Browser automation |
10751
+ | \`openai\` | OpenAI API for embeddings, completions |
10752
+ | \`supabase\` | Database operations with Supabase |
10753
+
10754
+ Browse all skills: https://github.com/vm0-ai/vm0-skills
10755
+
10756
+ ## Example Agents
10757
+
10758
+ ### Content Curator Agent
10759
+
10760
+ \`\`\`markdown
10761
+ # Agent Instructions
10762
+
10763
+ You are a content curator that monitors HackerNews for AI-related articles.
10764
+
10765
+ ## Workflow
10766
+
10767
+ 1. Go to HackerNews and read the top 30 stories
10768
+ 2. Filter for AI, ML, and LLM related content
10769
+ 3. For each relevant article, extract:
10770
+ - Title and URL
10771
+ - Key points (2-3 sentences)
10772
+ - Why it's interesting
10773
+ 4. Write a summary to \`daily-digest.md\`
10774
+
10775
+ ## Output
10776
+
10777
+ Create \`daily-digest.md\` with today's date as the header.
10778
+ \`\`\`
10779
+
10780
+ ### GitHub Issue Tracker Agent
10781
+
10782
+ \`\`\`markdown
10783
+ # Agent Instructions
10784
+
10785
+ You are a GitHub issue tracker that summarizes open issues.
10786
+
10787
+ ## Workflow
10788
+
10789
+ 1. List all open issues in the repository
10790
+ 2. Group issues by labels (bug, feature, docs)
10791
+ 3. For each group, summarize:
10792
+ - Number of issues
10793
+ - Oldest issue age
10794
+ - Most discussed issues
10795
+ 4. Create a report in \`issue-report.md\`
10796
+
10797
+ ## Skills Required
10798
+
10799
+ - github (for API access)
10800
+ \`\`\`
10801
+
10802
+ ### Data Pipeline Agent
10803
+
10804
+ \`\`\`markdown
10805
+ # Agent Instructions
10806
+
10807
+ You are a data pipeline agent that processes CSV files.
10808
+
10809
+ ## Workflow
10810
+
10811
+ 1. Read all CSV files from the input volume
10812
+ 2. For each file:
10813
+ - Validate the schema
10814
+ - Clean missing values
10815
+ - Transform dates to ISO format
10816
+ 3. Merge all files into \`combined.csv\`
10817
+ 4. Generate a summary report
10818
+
10819
+ ## Input
10820
+
10821
+ Files are provided via volume mount.
10822
+
10823
+ ## Output
10824
+
10825
+ Write results to the artifact directory.
10826
+ \`\`\`
10827
+
10828
+ ## Best Practices
10829
+
10830
+ 1. **Be Specific**: Vague instructions lead to unpredictable results
10831
+ 2. **One Task Per Step**: Keep workflow steps focused and atomic
10832
+ 3. **Define Output Clearly**: Specify exact file names and formats
10833
+ 4. **Handle Errors**: Include what to do when things go wrong
10834
+ 5. **Test Incrementally**: Start with simple workflows, add complexity
10835
+ 6. **Use Skills Wisely**: Only include skills the agent actually needs
10836
+
10837
+ ## Troubleshooting
10838
+
10839
+ ### Agent doesn't follow instructions
10840
+ - Make instructions more specific and explicit
10841
+ - Add examples of expected behavior
10842
+ - Break complex steps into smaller sub-steps
10843
+
10844
+ ### Agent uses wrong tools
10845
+ - Specify which tools/skills to use for each step
10846
+ - Add constraints about what NOT to do
10847
+
10848
+ ### Output format is wrong
10849
+ - Provide exact templates for output files
10850
+ - Include example output in the instructions
10851
+ `;
10852
+ var setupClaudeCommand = new Command45().name("setup-claude").description("Add/update Claude skill for agent building").action(async () => {
10853
+ console.log(chalk46.dim("Installing vm0-agent-builder skill..."));
10854
+ await mkdir7(SKILL_DIR, { recursive: true });
10855
+ await writeFile7(path14.join(SKILL_DIR, "SKILL.md"), SKILL_CONTENT);
10856
+ console.log(
10857
+ chalk46.green(`Done Installed vm0-agent-builder skill to ${SKILL_DIR}`)
10858
+ );
10859
+ console.log();
10860
+ console.log("Next step:");
10861
+ console.log(
10862
+ chalk46.cyan(
10863
+ ' claude /vm0-agent-builder "I want to build an agent that..."'
10864
+ )
10865
+ );
10866
+ });
10867
+
10868
+ // src/commands/onboard.ts
10869
+ var DEMO_AGENT_DIR = "vm0-demo-agent";
10870
+ var DEMO_AGENT_NAME = "vm0-demo-agent";
10871
+ var onboardCommand = new Command46().name("onboard").description("Guided setup for new VM0 users").option("-y, --yes", "Skip confirmation prompts").option(
10872
+ "--method <method>",
10873
+ "Agent building method: claude or manual",
10874
+ void 0
10875
+ ).action(async (options) => {
10876
+ const token = await getToken();
10877
+ if (token) {
10878
+ console.log(chalk47.green("Done Authenticated"));
10879
+ } else {
10880
+ console.log(chalk47.dim("Authentication required..."));
10881
+ console.log();
10882
+ await authenticate();
10883
+ }
10884
+ try {
10885
+ const result = await listModelProviders();
10886
+ if (result.modelProviders.length > 0) {
10887
+ console.log(chalk47.green("Done Model provider configured"));
10888
+ } else {
10889
+ console.log(chalk47.yellow("! No model provider configured"));
10890
+ console.log();
10891
+ console.log("Run the following to set up:");
10892
+ console.log(chalk47.cyan(" vm0 model-provider setup"));
10893
+ console.log();
10894
+ }
10895
+ } catch (error) {
10896
+ const message = error instanceof Error ? error.message : String(error);
10897
+ console.log(
10898
+ chalk47.yellow(`! Could not check model provider status: ${message}`)
10899
+ );
10900
+ console.log();
10901
+ }
10902
+ let createAgent = options.yes;
10903
+ if (!createAgent && isInteractive()) {
10904
+ const response = await prompts3(
10905
+ {
10906
+ type: "confirm",
10907
+ name: "create",
10908
+ message: `Create ${DEMO_AGENT_DIR}?`,
10909
+ initial: true
10910
+ },
10911
+ { onCancel: () => process.exit(0) }
10912
+ );
10913
+ createAgent = response.create;
10914
+ }
10915
+ if (!createAgent) {
10916
+ console.log(chalk47.dim("Skipped agent creation"));
10917
+ return;
10918
+ }
10919
+ if (existsSync10(DEMO_AGENT_DIR)) {
10920
+ console.log(chalk47.red(`x ${DEMO_AGENT_DIR}/ already exists`));
10921
+ console.log();
10922
+ console.log("Remove it first or use a different directory:");
10923
+ console.log(chalk47.cyan(` rm -rf ${DEMO_AGENT_DIR}`));
10924
+ process.exit(1);
10925
+ }
10926
+ await mkdir8(DEMO_AGENT_DIR, { recursive: true });
10927
+ const originalDir = process.cwd();
10928
+ process.chdir(DEMO_AGENT_DIR);
10929
+ try {
10930
+ await initCommand3.parseAsync(["--name", DEMO_AGENT_NAME], {
10931
+ from: "user"
10932
+ });
10933
+ } finally {
10934
+ process.chdir(originalDir);
10935
+ }
10936
+ console.log();
10937
+ let method = options.method;
10938
+ if (!method && isInteractive()) {
10939
+ const response = await prompts3(
10940
+ {
10941
+ type: "select",
10942
+ name: "method",
10943
+ message: "How would you like to build your agent?",
10944
+ choices: [
10945
+ {
10946
+ title: "Use `vm0 setup-claude` to let Claude help (Recommended)",
10947
+ value: "claude"
10948
+ },
10949
+ {
10950
+ title: "I will do it myself (Edit `AGENTS.md` and `vm0.yaml`)",
10951
+ value: "manual"
10952
+ }
10953
+ ]
10954
+ },
10955
+ { onCancel: () => process.exit(0) }
10956
+ );
10957
+ method = response.method;
10958
+ }
10959
+ if (method === "claude") {
10960
+ process.chdir(DEMO_AGENT_DIR);
10961
+ try {
10962
+ await setupClaudeCommand.parseAsync([], { from: "user" });
10963
+ } finally {
10964
+ process.chdir(originalDir);
10965
+ }
10966
+ } else {
10967
+ console.log("Next steps:");
10968
+ console.log(` 1. ${chalk47.cyan(`cd ${DEMO_AGENT_DIR}`)}`);
10969
+ console.log(
10970
+ ` 2. Edit ${chalk47.cyan("AGENTS.md")} to define your agent's workflow`
10971
+ );
10972
+ console.log(` 3. Edit ${chalk47.cyan("vm0.yaml")} to configure skills`);
10973
+ console.log(` 4. Run ${chalk47.cyan('vm0 cook "start working"')} to test`);
10974
+ }
10975
+ });
10976
+
10558
10977
  // src/index.ts
10559
- var program = new Command45();
10560
- program.name("vm0").description("VM0 CLI - Build and run agents with natural language").version("8.1.1");
10978
+ var program = new Command47();
10979
+ program.name("vm0").description("VM0 CLI - Build and run agents with natural language").version("9.1.0");
10561
10980
  program.command("info").description("Display environment information").action(async () => {
10562
- console.log(chalk46.bold("System Information:"));
10981
+ console.log(chalk48.bold("System Information:"));
10563
10982
  console.log(`Node Version: ${process.version}`);
10564
10983
  console.log(`Platform: ${process.platform}`);
10565
10984
  console.log(`Architecture: ${process.arch}`);
@@ -10592,6 +11011,8 @@ program.addCommand(scheduleCommand);
10592
11011
  program.addCommand(usageCommand);
10593
11012
  program.addCommand(credentialCommand);
10594
11013
  program.addCommand(modelProviderCommand);
11014
+ program.addCommand(onboardCommand);
11015
+ program.addCommand(setupClaudeCommand);
10595
11016
  if (process.argv[1]?.endsWith("index.js") || process.argv[1]?.endsWith("index.ts") || process.argv[1]?.endsWith("vm0")) {
10596
11017
  program.parse();
10597
11018
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vm0/cli",
3
- "version": "8.1.1",
3
+ "version": "9.1.0",
4
4
  "description": "CLI application",
5
5
  "repository": {
6
6
  "type": "git",