@vm0/cli 4.34.0 → 4.35.1

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 +191 -45
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -984,10 +984,10 @@ function mergeDefs(...defs) {
984
984
  function cloneDef(schema) {
985
985
  return mergeDefs(schema._zod.def);
986
986
  }
987
- function getElementAtPath(obj, path14) {
988
- if (!path14)
987
+ function getElementAtPath(obj, path15) {
988
+ if (!path15)
989
989
  return obj;
990
- return path14.reduce((acc, key) => acc?.[key], obj);
990
+ return path15.reduce((acc, key) => acc?.[key], obj);
991
991
  }
992
992
  function promiseAllObject(promisesObj) {
993
993
  const keys = Object.keys(promisesObj);
@@ -1346,11 +1346,11 @@ function aborted(x, startIndex = 0) {
1346
1346
  }
1347
1347
  return false;
1348
1348
  }
1349
- function prefixIssues(path14, issues) {
1349
+ function prefixIssues(path15, issues) {
1350
1350
  return issues.map((iss) => {
1351
1351
  var _a;
1352
1352
  (_a = iss).path ?? (_a.path = []);
1353
- iss.path.unshift(path14);
1353
+ iss.path.unshift(path15);
1354
1354
  return iss;
1355
1355
  });
1356
1356
  }
@@ -1518,7 +1518,7 @@ function treeifyError(error43, _mapper) {
1518
1518
  return issue2.message;
1519
1519
  };
1520
1520
  const result = { errors: [] };
1521
- const processError = (error44, path14 = []) => {
1521
+ const processError = (error44, path15 = []) => {
1522
1522
  var _a, _b;
1523
1523
  for (const issue2 of error44.issues) {
1524
1524
  if (issue2.code === "invalid_union" && issue2.errors.length) {
@@ -1528,7 +1528,7 @@ function treeifyError(error43, _mapper) {
1528
1528
  } else if (issue2.code === "invalid_element") {
1529
1529
  processError({ issues: issue2.issues }, issue2.path);
1530
1530
  } else {
1531
- const fullpath = [...path14, ...issue2.path];
1531
+ const fullpath = [...path15, ...issue2.path];
1532
1532
  if (fullpath.length === 0) {
1533
1533
  result.errors.push(mapper(issue2));
1534
1534
  continue;
@@ -1560,8 +1560,8 @@ function treeifyError(error43, _mapper) {
1560
1560
  }
1561
1561
  function toDotPath(_path) {
1562
1562
  const segs = [];
1563
- const path14 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
1564
- for (const seg of path14) {
1563
+ const path15 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
1564
+ for (const seg of path15) {
1565
1565
  if (typeof seg === "number")
1566
1566
  segs.push(`[${seg}]`);
1567
1567
  else if (typeof seg === "symbol")
@@ -2760,7 +2760,7 @@ var $ZodBase64 = /* @__PURE__ */ $constructor("$ZodBase64", (inst, def) => {
2760
2760
  function isValidBase64URL(data) {
2761
2761
  if (!base64url.test(data))
2762
2762
  return false;
2763
- const base643 = data.replace(/[-_]/g, (c11) => c11 === "-" ? "+" : "/");
2763
+ const base643 = data.replace(/[-_]/g, (c12) => c12 === "-" ? "+" : "/");
2764
2764
  const padded = base643.padEnd(Math.ceil(base643.length / 4) * 4, "=");
2765
2765
  return isValidBase64(padded);
2766
2766
  }
@@ -11672,9 +11672,9 @@ var ZodDate = /* @__PURE__ */ $constructor("ZodDate", (inst, def) => {
11672
11672
  ZodType.init(inst, def);
11673
11673
  inst.min = (value, params) => inst.check(_gte(value, params));
11674
11674
  inst.max = (value, params) => inst.check(_lte(value, params));
11675
- const c11 = inst._zod.bag;
11676
- inst.minDate = c11.minimum ? new Date(c11.minimum) : null;
11677
- inst.maxDate = c11.maximum ? new Date(c11.maximum) : null;
11675
+ const c12 = inst._zod.bag;
11676
+ inst.minDate = c12.minimum ? new Date(c12.minimum) : null;
11677
+ inst.maxDate = c12.maximum ? new Date(c12.maximum) : null;
11678
11678
  });
11679
11679
  function date3(params) {
11680
11680
  return _date(ZodDate, params);
@@ -12302,7 +12302,17 @@ var agentDefinitionSchema = external_exports.object({
12302
12302
  * Array of GitHub tree URLs for agent skills.
12303
12303
  * Each skill is auto-downloaded and mounted at /home/user/.claude/skills/{skillName}/
12304
12304
  */
12305
- skills: external_exports.array(external_exports.string()).optional()
12305
+ skills: external_exports.array(external_exports.string()).optional(),
12306
+ /**
12307
+ * Route this agent to a self-hosted runner instead of E2B.
12308
+ * When specified, runs will be queued for the specified runner group.
12309
+ */
12310
+ experimental_runner: external_exports.object({
12311
+ group: external_exports.string().regex(
12312
+ /^[a-z0-9-]+\/[a-z0-9-]+$/,
12313
+ "Runner group must be in scope/name format (e.g., acme/production)"
12314
+ )
12315
+ }).optional()
12306
12316
  });
12307
12317
  var agentComposeContentSchema = external_exports.object({
12308
12318
  version: external_exports.string().min(1, "Version is required"),
@@ -13602,6 +13612,106 @@ var checkpointsByIdContract = c10.router({
13602
13612
  }
13603
13613
  });
13604
13614
 
13615
+ // ../../packages/core/src/contracts/runners.ts
13616
+ var c11 = initContract();
13617
+ var runnerGroupSchema = external_exports.string().regex(
13618
+ /^[a-z0-9-]+\/[a-z0-9-]+$/,
13619
+ "Runner group must be in scope/name format (e.g., acme/production)"
13620
+ );
13621
+ var jobSchema = external_exports.object({
13622
+ runId: external_exports.string().uuid(),
13623
+ prompt: external_exports.string(),
13624
+ agentComposeVersionId: external_exports.string(),
13625
+ vars: external_exports.record(external_exports.string(), external_exports.string()).nullable(),
13626
+ secretNames: external_exports.array(external_exports.string()).nullable(),
13627
+ checkpointId: external_exports.string().uuid().nullable()
13628
+ });
13629
+ var runnersPollContract = c11.router({
13630
+ poll: {
13631
+ method: "POST",
13632
+ path: "/api/runners/poll",
13633
+ body: external_exports.object({
13634
+ group: runnerGroupSchema
13635
+ }),
13636
+ responses: {
13637
+ 200: external_exports.object({
13638
+ job: jobSchema.nullable()
13639
+ }),
13640
+ 400: apiErrorSchema,
13641
+ 401: apiErrorSchema,
13642
+ 500: apiErrorSchema
13643
+ },
13644
+ summary: "Poll for pending jobs (long-polling with 30s timeout)"
13645
+ }
13646
+ });
13647
+ var storageEntrySchema = external_exports.object({
13648
+ mountPath: external_exports.string(),
13649
+ archiveUrl: external_exports.string().nullable()
13650
+ });
13651
+ var artifactEntrySchema = external_exports.object({
13652
+ mountPath: external_exports.string(),
13653
+ archiveUrl: external_exports.string().nullable(),
13654
+ vasStorageName: external_exports.string(),
13655
+ vasVersionId: external_exports.string()
13656
+ });
13657
+ var storageManifestSchema = external_exports.object({
13658
+ storages: external_exports.array(storageEntrySchema),
13659
+ artifact: artifactEntrySchema.nullable()
13660
+ });
13661
+ var resumeSessionSchema = external_exports.object({
13662
+ sessionId: external_exports.string(),
13663
+ sessionHistory: external_exports.string()
13664
+ });
13665
+ var storedExecutionContextSchema = external_exports.object({
13666
+ workingDir: external_exports.string(),
13667
+ storageManifest: storageManifestSchema.nullable(),
13668
+ environment: external_exports.record(external_exports.string(), external_exports.string()).nullable(),
13669
+ resumeSession: resumeSessionSchema.nullable(),
13670
+ encryptedSecrets: external_exports.string().nullable(),
13671
+ // AES-256-GCM encrypted secrets
13672
+ cliAgentType: external_exports.string(),
13673
+ experimentalNetworkSecurity: external_exports.boolean().optional()
13674
+ });
13675
+ var executionContextSchema = external_exports.object({
13676
+ runId: external_exports.string().uuid(),
13677
+ prompt: external_exports.string(),
13678
+ agentComposeVersionId: external_exports.string(),
13679
+ vars: external_exports.record(external_exports.string(), external_exports.string()).nullable(),
13680
+ secretNames: external_exports.array(external_exports.string()).nullable(),
13681
+ checkpointId: external_exports.string().uuid().nullable(),
13682
+ sandboxToken: external_exports.string(),
13683
+ apiUrl: external_exports.string(),
13684
+ // New fields for E2B parity:
13685
+ workingDir: external_exports.string(),
13686
+ storageManifest: storageManifestSchema.nullable(),
13687
+ environment: external_exports.record(external_exports.string(), external_exports.string()).nullable(),
13688
+ resumeSession: resumeSessionSchema.nullable(),
13689
+ secretValues: external_exports.array(external_exports.string()).nullable(),
13690
+ cliAgentType: external_exports.string()
13691
+ });
13692
+ var runnersJobClaimContract = c11.router({
13693
+ claim: {
13694
+ method: "POST",
13695
+ path: "/api/runners/jobs/:id/claim",
13696
+ pathParams: external_exports.object({
13697
+ id: external_exports.string().uuid()
13698
+ }),
13699
+ body: external_exports.object({}),
13700
+ responses: {
13701
+ 200: executionContextSchema,
13702
+ 400: apiErrorSchema,
13703
+ 401: apiErrorSchema,
13704
+ 403: apiErrorSchema,
13705
+ // Job does not belong to user
13706
+ 404: apiErrorSchema,
13707
+ 409: apiErrorSchema,
13708
+ // Already claimed
13709
+ 500: apiErrorSchema
13710
+ },
13711
+ summary: "Claim a pending job for execution"
13712
+ }
13713
+ });
13714
+
13605
13715
  // ../../packages/core/src/scope-reference.ts
13606
13716
  function getLegacySystemTemplateWarning(legacyFormat) {
13607
13717
  if (!isLegacySystemTemplate(legacyFormat)) {
@@ -14050,7 +14160,7 @@ var ApiClient = class {
14050
14160
  /**
14051
14161
  * Generic GET request
14052
14162
  */
14053
- async get(path14) {
14163
+ async get(path15) {
14054
14164
  const baseUrl = await this.getBaseUrl();
14055
14165
  const token = await getToken();
14056
14166
  if (!token) {
@@ -14063,7 +14173,7 @@ var ApiClient = class {
14063
14173
  if (bypassSecret) {
14064
14174
  headers["x-vercel-protection-bypass"] = bypassSecret;
14065
14175
  }
14066
- return fetch(`${baseUrl}${path14}`, {
14176
+ return fetch(`${baseUrl}${path15}`, {
14067
14177
  method: "GET",
14068
14178
  headers
14069
14179
  });
@@ -14071,7 +14181,7 @@ var ApiClient = class {
14071
14181
  /**
14072
14182
  * Generic POST request
14073
14183
  */
14074
- async post(path14, options) {
14184
+ async post(path15, options) {
14075
14185
  const baseUrl = await this.getBaseUrl();
14076
14186
  const token = await getToken();
14077
14187
  if (!token) {
@@ -14087,7 +14197,7 @@ var ApiClient = class {
14087
14197
  if (bypassSecret) {
14088
14198
  headers["x-vercel-protection-bypass"] = bypassSecret;
14089
14199
  }
14090
- return fetch(`${baseUrl}${path14}`, {
14200
+ return fetch(`${baseUrl}${path15}`, {
14091
14201
  method: "POST",
14092
14202
  headers,
14093
14203
  body: options?.body
@@ -14096,7 +14206,7 @@ var ApiClient = class {
14096
14206
  /**
14097
14207
  * Generic DELETE request
14098
14208
  */
14099
- async delete(path14) {
14209
+ async delete(path15) {
14100
14210
  const baseUrl = await this.getBaseUrl();
14101
14211
  const token = await getToken();
14102
14212
  if (!token) {
@@ -14109,7 +14219,7 @@ var ApiClient = class {
14109
14219
  if (bypassSecret) {
14110
14220
  headers["x-vercel-protection-bypass"] = bypassSecret;
14111
14221
  }
14112
- return fetch(`${baseUrl}${path14}`, {
14222
+ return fetch(`${baseUrl}${path15}`, {
14113
14223
  method: "DELETE",
14114
14224
  headers
14115
14225
  });
@@ -15381,9 +15491,9 @@ var CodexEventParser = class {
15381
15491
  }
15382
15492
  }
15383
15493
  if (itemType === "file_change" && item.changes && item.changes.length > 0) {
15384
- const changes = item.changes.map((c11) => {
15385
- const action = c11.kind === "add" ? "Created" : c11.kind === "modify" ? "Modified" : "Deleted";
15386
- return `${action}: ${c11.path}`;
15494
+ const changes = item.changes.map((c12) => {
15495
+ const action = c12.kind === "add" ? "Created" : c12.kind === "modify" ? "Modified" : "Deleted";
15496
+ return `${action}: ${c12.path}`;
15387
15497
  }).join("\n");
15388
15498
  return {
15389
15499
  type: "text",
@@ -15724,9 +15834,9 @@ var CodexEventRenderer = class {
15724
15834
  return;
15725
15835
  }
15726
15836
  if (itemType === "file_change" && item.changes && item.changes.length > 0) {
15727
- const summary = item.changes.map((c11) => {
15728
- const icon = c11.kind === "add" ? "+" : c11.kind === "delete" ? "-" : "~";
15729
- return `${icon}${c11.path}`;
15837
+ const summary = item.changes.map((c12) => {
15838
+ const icon = c12.kind === "add" ? "+" : c12.kind === "delete" ? "-" : "~";
15839
+ return `${icon}${c12.path}`;
15730
15840
  }).join(", ");
15731
15841
  console.log(chalk4.green("[files]") + ` ${summary}`);
15732
15842
  return;
@@ -17624,7 +17734,7 @@ async function autoPullArtifact(runOutput, artifactDir) {
17624
17734
  }
17625
17735
  var cookCmd = new Command17().name("cook").description("One-click agent preparation and execution from vm0.yaml");
17626
17736
  cookCmd.argument("[prompt]", "Prompt for the agent").option("-y, --yes", "Skip confirmation prompts").action(async (prompt, options) => {
17627
- const shouldExit = await checkAndUpgrade("4.34.0", prompt);
17737
+ const shouldExit = await checkAndUpgrade("4.35.1", prompt);
17628
17738
  if (shouldExit) {
17629
17739
  process.exit(0);
17630
17740
  }
@@ -18773,6 +18883,7 @@ import chalk30 from "chalk";
18773
18883
  import { existsSync as existsSync11 } from "fs";
18774
18884
  import { mkdir as mkdir7, readFile as readFile9, writeFile as writeFile8 } from "fs/promises";
18775
18885
  import { execSync, spawnSync } from "child_process";
18886
+ import path14 from "path";
18776
18887
  import { parse as parseYaml5 } from "yaml";
18777
18888
  function isGhInstalled() {
18778
18889
  try {
@@ -18790,8 +18901,36 @@ function isGhAuthenticated() {
18790
18901
  return false;
18791
18902
  }
18792
18903
  }
18904
+ function getGitRoot() {
18905
+ try {
18906
+ return execSync("git rev-parse --show-toplevel", {
18907
+ encoding: "utf8"
18908
+ }).trim();
18909
+ } catch {
18910
+ return null;
18911
+ }
18912
+ }
18913
+ function getRelativeWorkingDir(gitRoot) {
18914
+ const cwd = process.cwd();
18915
+ if (cwd === gitRoot) {
18916
+ return null;
18917
+ }
18918
+ const relativePath = path14.relative(gitRoot, cwd);
18919
+ return relativePath.replace(/\\/g, "/");
18920
+ }
18793
18921
  async function checkPrerequisites() {
18794
18922
  console.log("Checking prerequisites...");
18923
+ const gitRoot = getGitRoot();
18924
+ if (!gitRoot) {
18925
+ console.log(chalk30.red("\u2717 Not in a git repository"));
18926
+ console.log();
18927
+ console.log("This command must be run from within a git repository.");
18928
+ console.log();
18929
+ console.log("To initialize a git repository, run:");
18930
+ console.log(` ${chalk30.cyan("git init")}`);
18931
+ process.exit(1);
18932
+ }
18933
+ console.log(chalk30.green("\u2713 Git repository detected"));
18795
18934
  if (!isGhInstalled()) {
18796
18935
  console.log(chalk30.red("\u2717 GitHub CLI (gh) is not installed"));
18797
18936
  console.log();
@@ -18844,17 +18983,20 @@ async function checkPrerequisites() {
18844
18983
  process.exit(1);
18845
18984
  }
18846
18985
  console.log(chalk30.green("\u2713 vm0.yaml found"));
18847
- return token;
18986
+ return { token, gitRoot };
18848
18987
  }
18849
- function generatePublishYaml() {
18988
+ function generatePublishYaml(workingDir) {
18989
+ const pathPrefix = workingDir ? `${workingDir}/` : "";
18990
+ const workingDirYaml = workingDir ? ` working-directory: ${workingDir}
18991
+ ` : "";
18850
18992
  return `name: Publish Agent
18851
18993
 
18852
18994
  on:
18853
18995
  push:
18854
18996
  branches: [main]
18855
18997
  paths:
18856
- - 'vm0.yaml'
18857
- - 'AGENTS.md'
18998
+ - '${pathPrefix}vm0.yaml'
18999
+ - '${pathPrefix}AGENTS.md'
18858
19000
 
18859
19001
  jobs:
18860
19002
  publish:
@@ -18867,7 +19009,7 @@ jobs:
18867
19009
  id: compose
18868
19010
  with:
18869
19011
  vm0-token: \${{ secrets.VM0_TOKEN }}
18870
-
19012
+ ${workingDirYaml}
18871
19013
  - name: Show Results
18872
19014
  run: |
18873
19015
  echo "Agent: \${{ steps.compose.outputs.name }}"
@@ -19073,10 +19215,12 @@ function showWorkflowsCreatedMessage() {
19073
19215
  }
19074
19216
  var setupGithubCommand = new Command28().name("setup-github").description("Initialize GitHub Actions workflows for agent deployment").option("-f, --force", "Overwrite existing workflow files").option("-y, --yes", "Auto-confirm all prompts").option("--skip-secrets", "Skip automatic secrets/variables setup").action(
19075
19217
  async (options) => {
19076
- const vm0Token = await checkPrerequisites();
19077
- if (!vm0Token) {
19218
+ const prereqs = await checkPrerequisites();
19219
+ if (!prereqs) {
19078
19220
  process.exit(1);
19079
19221
  }
19222
+ const { token: vm0Token, gitRoot } = prereqs;
19223
+ const workingDir = getRelativeWorkingDir(gitRoot);
19080
19224
  console.log();
19081
19225
  console.log("Analyzing vm0.yaml...");
19082
19226
  const content = await readFile9("vm0.yaml", "utf8");
@@ -19091,11 +19235,13 @@ var setupGithubCommand = new Command28().name("setup-github").description("Initi
19091
19235
  )
19092
19236
  );
19093
19237
  console.log();
19094
- const publishPath = ".github/workflows/publish.yml";
19095
- const runPath = ".github/workflows/run.yml";
19238
+ const publishPath = path14.join(gitRoot, ".github/workflows/publish.yml");
19239
+ const runPath = path14.join(gitRoot, ".github/workflows/run.yml");
19240
+ const displayPublishPath = ".github/workflows/publish.yml";
19241
+ const displayRunPath = ".github/workflows/run.yml";
19096
19242
  const existingFiles = [];
19097
- if (existsSync11(publishPath)) existingFiles.push(publishPath);
19098
- if (existsSync11(runPath)) existingFiles.push(runPath);
19243
+ if (existsSync11(publishPath)) existingFiles.push(displayPublishPath);
19244
+ if (existsSync11(runPath)) existingFiles.push(displayRunPath);
19099
19245
  if (existingFiles.length > 0 && !options.force) {
19100
19246
  console.log(chalk30.yellow("\u26A0 Existing workflow files detected:"));
19101
19247
  for (const file2 of existingFiles) {
@@ -19117,13 +19263,13 @@ var setupGithubCommand = new Command28().name("setup-github").description("Initi
19117
19263
  console.log();
19118
19264
  }
19119
19265
  console.log("Creating workflow files...");
19120
- await mkdir7(".github/workflows", { recursive: true });
19121
- await writeFile8(publishPath, generatePublishYaml());
19122
- const publishStatus = existingFiles.includes(publishPath) ? "Overwrote" : "Created";
19123
- console.log(chalk30.green(`\u2713 ${publishStatus} ${publishPath}`));
19266
+ await mkdir7(path14.join(gitRoot, ".github/workflows"), { recursive: true });
19267
+ await writeFile8(publishPath, generatePublishYaml(workingDir));
19268
+ const publishStatus = existingFiles.includes(displayPublishPath) ? "Overwrote" : "Created";
19269
+ console.log(chalk30.green(`\u2713 ${publishStatus} ${displayPublishPath}`));
19124
19270
  await writeFile8(runPath, generateRunYaml(agentName, secrets, vars));
19125
- const runStatus = existingFiles.includes(runPath) ? "Overwrote" : "Created";
19126
- console.log(chalk30.green(`\u2713 ${runStatus} ${runPath}`));
19271
+ const runStatus = existingFiles.includes(displayRunPath) ? "Overwrote" : "Created";
19272
+ console.log(chalk30.green(`\u2713 ${runStatus} ${displayRunPath}`));
19127
19273
  console.log();
19128
19274
  if (options.skipSecrets) {
19129
19275
  console.log(chalk30.green("\u2713 Done (secrets setup skipped)"));
@@ -19216,7 +19362,7 @@ var setupGithubCommand = new Command28().name("setup-github").description("Initi
19216
19362
 
19217
19363
  // src/index.ts
19218
19364
  var program = new Command29();
19219
- program.name("vm0").description("VM0 CLI - A modern build tool").version("4.34.0");
19365
+ program.name("vm0").description("VM0 CLI - A modern build tool").version("4.35.1");
19220
19366
  program.command("info").description("Display environment information").action(async () => {
19221
19367
  console.log(chalk31.bold("System Information:"));
19222
19368
  console.log(`Node Version: ${process.version}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vm0/cli",
3
- "version": "4.34.0",
3
+ "version": "4.35.1",
4
4
  "description": "CLI application",
5
5
  "repository": {
6
6
  "type": "git",