@vm0/cli 1.0.0 → 1.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 +175 -5
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -12319,10 +12319,15 @@ var ApiClient = class {
12319
12319
  if (!token) {
12320
12320
  throw new Error("Not authenticated. Run: vm0 auth login");
12321
12321
  }
12322
- return {
12322
+ const headers = {
12323
12323
  Authorization: `Bearer ${token}`,
12324
12324
  "Content-Type": "application/json"
12325
12325
  };
12326
+ const bypassSecret = process.env.VERCEL_AUTOMATION_BYPASS_SECRET;
12327
+ if (bypassSecret) {
12328
+ headers["x-vercel-protection-bypass"] = bypassSecret;
12329
+ }
12330
+ return headers;
12326
12331
  }
12327
12332
  async getBaseUrl() {
12328
12333
  const apiUrl = await getApiUrl();
@@ -12393,6 +12398,20 @@ var ApiClient = class {
12393
12398
  }
12394
12399
  return await response.json();
12395
12400
  }
12401
+ async resumeRun(body) {
12402
+ const baseUrl = await this.getBaseUrl();
12403
+ const headers = await this.getHeaders();
12404
+ const response = await fetch(`${baseUrl}/api/agent/runs/resume`, {
12405
+ method: "POST",
12406
+ headers,
12407
+ body: JSON.stringify(body)
12408
+ });
12409
+ if (!response.ok) {
12410
+ const error43 = await response.json();
12411
+ throw new Error(error43.error || "Failed to resume run");
12412
+ }
12413
+ return await response.json();
12414
+ }
12396
12415
  };
12397
12416
  var apiClient = new ApiClient();
12398
12417
 
@@ -12428,6 +12447,29 @@ function validateAgentConfig(config2) {
12428
12447
  return { valid: true };
12429
12448
  }
12430
12449
 
12450
+ // src/lib/env-expander.ts
12451
+ function expandEnvVars(value) {
12452
+ return value.replace(/\$\{([^}]+)\}/g, (_, varName) => {
12453
+ return process.env[varName] ?? "";
12454
+ });
12455
+ }
12456
+ function expandEnvVarsInObject(obj) {
12457
+ if (typeof obj === "string") {
12458
+ return expandEnvVars(obj);
12459
+ }
12460
+ if (Array.isArray(obj)) {
12461
+ return obj.map((item) => expandEnvVarsInObject(item));
12462
+ }
12463
+ if (obj !== null && typeof obj === "object") {
12464
+ const result = {};
12465
+ for (const [key, value] of Object.entries(obj)) {
12466
+ result[key] = expandEnvVarsInObject(value);
12467
+ }
12468
+ return result;
12469
+ }
12470
+ return obj;
12471
+ }
12472
+
12431
12473
  // src/commands/build.ts
12432
12474
  var buildCommand = new Command().name("build").description("Create or update agent configuration").argument("<config-file>", "Path to config YAML file").action(async (configFile) => {
12433
12475
  try {
@@ -12446,6 +12488,7 @@ var buildCommand = new Command().name("build").description("Create or update age
12446
12488
  }
12447
12489
  process.exit(1);
12448
12490
  }
12491
+ config2 = expandEnvVarsInObject(config2);
12449
12492
  const validation = validateAgentConfig(config2);
12450
12493
  if (!validation.valid) {
12451
12494
  console.error(chalk2.red(`\u2717 ${validation.error}`));
@@ -12503,6 +12546,12 @@ var ClaudeEventParser = class {
12503
12546
  return this.parseUserMessage(rawEvent);
12504
12547
  case "result":
12505
12548
  return this.parseResultEvent(rawEvent);
12549
+ case "vm0_start":
12550
+ return this.parseVm0StartEvent(rawEvent);
12551
+ case "vm0_result":
12552
+ return this.parseVm0ResultEvent(rawEvent);
12553
+ case "vm0_error":
12554
+ return this.parseVm0ErrorEvent(rawEvent);
12506
12555
  default:
12507
12556
  return null;
12508
12557
  }
@@ -12585,6 +12634,42 @@ var ClaudeEventParser = class {
12585
12634
  }
12586
12635
  };
12587
12636
  }
12637
+ static parseVm0StartEvent(event) {
12638
+ return {
12639
+ type: "vm0_start",
12640
+ timestamp: new Date(event.timestamp),
12641
+ data: {
12642
+ runId: event.runId,
12643
+ agentConfigId: event.agentConfigId,
12644
+ agentName: event.agentName,
12645
+ prompt: event.prompt,
12646
+ dynamicVars: event.dynamicVars
12647
+ }
12648
+ };
12649
+ }
12650
+ static parseVm0ResultEvent(event) {
12651
+ return {
12652
+ type: "vm0_result",
12653
+ timestamp: new Date(event.timestamp),
12654
+ data: {
12655
+ runId: event.runId,
12656
+ checkpointId: event.checkpointId,
12657
+ volumeSnapshots: event.volumeSnapshots
12658
+ }
12659
+ };
12660
+ }
12661
+ static parseVm0ErrorEvent(event) {
12662
+ return {
12663
+ type: "vm0_error",
12664
+ timestamp: new Date(event.timestamp),
12665
+ data: {
12666
+ runId: event.runId,
12667
+ error: event.error,
12668
+ errorType: event.errorType,
12669
+ sandboxId: event.sandboxId
12670
+ }
12671
+ };
12672
+ }
12588
12673
  };
12589
12674
 
12590
12675
  // src/lib/event-renderer.ts
@@ -12610,6 +12695,15 @@ var EventRenderer = class {
12610
12695
  case "result":
12611
12696
  this.renderResult(event);
12612
12697
  break;
12698
+ case "vm0_start":
12699
+ this.renderVm0Start(event);
12700
+ break;
12701
+ case "vm0_result":
12702
+ this.renderVm0Result(event);
12703
+ break;
12704
+ case "vm0_error":
12705
+ this.renderVm0Error(event);
12706
+ break;
12613
12707
  }
12614
12708
  }
12615
12709
  static renderInit(event) {
@@ -12678,6 +12772,32 @@ var EventRenderer = class {
12678
12772
  );
12679
12773
  }
12680
12774
  }
12775
+ static renderVm0Start(event) {
12776
+ console.log(chalk3.cyan("[vm0_start]") + " Run starting");
12777
+ const prompt = String(event.data.prompt || "");
12778
+ const displayPrompt = prompt.length > 100 ? prompt.substring(0, 100) + "..." : prompt;
12779
+ console.log(` Prompt: ${chalk3.gray(displayPrompt)}`);
12780
+ if (event.data.agentName) {
12781
+ console.log(` Agent: ${chalk3.gray(String(event.data.agentName))}`);
12782
+ }
12783
+ }
12784
+ static renderVm0Result(event) {
12785
+ console.log(chalk3.green("[vm0_result]") + " \u2713 Run completed successfully");
12786
+ console.log(
12787
+ ` Checkpoint: ${chalk3.gray(String(event.data.checkpointId || ""))}`
12788
+ );
12789
+ const volumeSnapshots = Number(event.data.volumeSnapshots || 0);
12790
+ if (volumeSnapshots > 0) {
12791
+ console.log(` Volume snapshots: ${chalk3.gray(String(volumeSnapshots))}`);
12792
+ }
12793
+ }
12794
+ static renderVm0Error(event) {
12795
+ console.log(chalk3.red("[vm0_error]") + " \u2717 Run failed");
12796
+ console.log(` Error: ${chalk3.red(String(event.data.error || ""))}`);
12797
+ if (event.data.errorType) {
12798
+ console.log(` Type: ${chalk3.gray(String(event.data.errorType))}`);
12799
+ }
12800
+ }
12681
12801
  };
12682
12802
 
12683
12803
  // src/commands/run.ts
@@ -12693,19 +12813,32 @@ function isUUID(str) {
12693
12813
  return /^[0-9a-f-]{36}$/i.test(str);
12694
12814
  }
12695
12815
  async function pollEvents(runId) {
12696
- let nextSequence = 0;
12816
+ let nextSequence = -1;
12697
12817
  let complete = false;
12698
12818
  const pollIntervalMs = 500;
12819
+ const timeoutMs = 3 * 60 * 1e3;
12820
+ const startTime = Date.now();
12699
12821
  while (!complete) {
12822
+ const elapsed = Date.now() - startTime;
12823
+ if (elapsed > timeoutMs) {
12824
+ console.error(
12825
+ chalk4.red(
12826
+ "\n\u2717 Agent execution timed out after 3 minutes without receiving events"
12827
+ )
12828
+ );
12829
+ throw new Error("Agent execution timed out");
12830
+ }
12700
12831
  try {
12701
12832
  const response = await apiClient.getEvents(runId, {
12702
12833
  since: nextSequence
12703
12834
  });
12704
12835
  for (const event of response.events) {
12705
- const parsed = ClaudeEventParser.parse(event.eventData);
12836
+ const parsed = ClaudeEventParser.parse(
12837
+ event.eventData
12838
+ );
12706
12839
  if (parsed) {
12707
12840
  EventRenderer.render(parsed);
12708
- if (parsed.type === "result") {
12841
+ if (parsed.type === "vm0_result" || parsed.type === "vm0_error") {
12709
12842
  complete = true;
12710
12843
  }
12711
12844
  }
@@ -12723,7 +12856,7 @@ async function pollEvents(runId) {
12723
12856
  }
12724
12857
  }
12725
12858
  }
12726
- var runCommand = new Command2().name("run").description("Execute an agent").argument(
12859
+ var runCmd = new Command2().name("run").description("Execute an agent").argument(
12727
12860
  "<identifier>",
12728
12861
  "Agent name or config ID (e.g., 'my-agent' or 'cfg-abc-123')"
12729
12862
  ).argument("<prompt>", "Prompt for the agent").option(
@@ -12794,6 +12927,43 @@ var runCommand = new Command2().name("run").description("Execute an agent").argu
12794
12927
  }
12795
12928
  }
12796
12929
  );
12930
+ runCmd.command("resume").description("Resume an agent run from a checkpoint").argument("<checkpointId>", "Checkpoint ID to resume from").argument("<prompt>", "Prompt for the resumed agent").action(async (checkpointId, prompt) => {
12931
+ try {
12932
+ if (!isUUID(checkpointId)) {
12933
+ console.error(
12934
+ chalk4.red(`\u2717 Invalid checkpoint ID format: ${checkpointId}`)
12935
+ );
12936
+ console.error(chalk4.gray(" Checkpoint ID must be a valid UUID"));
12937
+ process.exit(1);
12938
+ }
12939
+ console.log(chalk4.blue("\nResuming agent run from checkpoint..."));
12940
+ console.log(chalk4.gray(` Checkpoint ID: ${checkpointId}`));
12941
+ console.log(chalk4.gray(` Prompt: ${prompt}`));
12942
+ console.log();
12943
+ console.log(chalk4.blue("Executing in sandbox..."));
12944
+ console.log();
12945
+ const response = await apiClient.resumeRun({
12946
+ checkpointId,
12947
+ prompt
12948
+ });
12949
+ await pollEvents(response.runId);
12950
+ } catch (error43) {
12951
+ if (error43 instanceof Error) {
12952
+ if (error43.message.includes("Not authenticated")) {
12953
+ console.error(chalk4.red("\u2717 Not authenticated. Run: vm0 auth login"));
12954
+ } else if (error43.message.includes("not found")) {
12955
+ console.error(chalk4.red(`\u2717 Checkpoint not found: ${checkpointId}`));
12956
+ } else {
12957
+ console.error(chalk4.red("\u2717 Resume failed"));
12958
+ console.error(chalk4.gray(` ${error43.message}`));
12959
+ }
12960
+ } else {
12961
+ console.error(chalk4.red("\u2717 An unexpected error occurred"));
12962
+ }
12963
+ process.exit(1);
12964
+ }
12965
+ });
12966
+ var runCommand = runCmd;
12797
12967
 
12798
12968
  // src/index.ts
12799
12969
  var program = new Command3();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vm0/cli",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "CLI application",
5
5
  "type": "module",
6
6
  "bin": {