@vm0/cli 4.31.1 → 4.32.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 +832 -437
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -6,8 +6,8 @@ var __export = (target, all) => {
6
6
  };
7
7
 
8
8
  // src/index.ts
9
- import { Command as Command25 } from "commander";
10
- import chalk26 from "chalk";
9
+ import { Command as Command29 } from "commander";
10
+ import chalk31 from "chalk";
11
11
 
12
12
  // src/lib/auth.ts
13
13
  import chalk from "chalk";
@@ -984,15 +984,15 @@ function mergeDefs(...defs) {
984
984
  function cloneDef(schema) {
985
985
  return mergeDefs(schema._zod.def);
986
986
  }
987
- function getElementAtPath(obj, path12) {
988
- if (!path12)
987
+ function getElementAtPath(obj, path14) {
988
+ if (!path14)
989
989
  return obj;
990
- return path12.reduce((acc, key) => acc?.[key], obj);
990
+ return path14.reduce((acc, key) => acc?.[key], obj);
991
991
  }
992
992
  function promiseAllObject(promisesObj) {
993
993
  const keys = Object.keys(promisesObj);
994
- const promises5 = keys.map((key) => promisesObj[key]);
995
- return Promise.all(promises5).then((results) => {
994
+ const promises6 = keys.map((key) => promisesObj[key]);
995
+ return Promise.all(promises6).then((results) => {
996
996
  const resolvedObj = {};
997
997
  for (let i = 0; i < keys.length; i++) {
998
998
  resolvedObj[keys[i]] = results[i];
@@ -1346,11 +1346,11 @@ function aborted(x, startIndex = 0) {
1346
1346
  }
1347
1347
  return false;
1348
1348
  }
1349
- function prefixIssues(path12, issues) {
1349
+ function prefixIssues(path14, issues) {
1350
1350
  return issues.map((iss) => {
1351
1351
  var _a;
1352
1352
  (_a = iss).path ?? (_a.path = []);
1353
- iss.path.unshift(path12);
1353
+ iss.path.unshift(path14);
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, path12 = []) => {
1521
+ const processError = (error44, path14 = []) => {
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 = [...path12, ...issue2.path];
1531
+ const fullpath = [...path14, ...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 path12 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
1564
- for (const seg of path12) {
1563
+ const path14 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
1564
+ for (const seg of path14) {
1565
1565
  if (typeof seg === "number")
1566
1566
  segs.push(`[${seg}]`);
1567
1567
  else if (typeof seg === "symbol")
@@ -12879,6 +12879,28 @@ var storagesDownloadContract = c3.router({
12879
12879
  summary: "Get presigned download URL"
12880
12880
  }
12881
12881
  });
12882
+ var storagesListContract = c3.router({
12883
+ list: {
12884
+ method: "GET",
12885
+ path: "/api/storages/list",
12886
+ query: external_exports.object({
12887
+ type: storageTypeSchema
12888
+ }),
12889
+ responses: {
12890
+ 200: external_exports.array(
12891
+ external_exports.object({
12892
+ name: external_exports.string(),
12893
+ size: external_exports.number(),
12894
+ fileCount: external_exports.number(),
12895
+ updatedAt: external_exports.string()
12896
+ })
12897
+ ),
12898
+ 401: apiErrorSchema,
12899
+ 500: apiErrorSchema
12900
+ },
12901
+ summary: "List user storages by type"
12902
+ }
12903
+ });
12882
12904
 
12883
12905
  // ../../packages/core/src/contracts/webhooks.ts
12884
12906
  var c4 = initContract();
@@ -13911,7 +13933,7 @@ var ApiClient = class {
13911
13933
  /**
13912
13934
  * Generic GET request
13913
13935
  */
13914
- async get(path12) {
13936
+ async get(path14) {
13915
13937
  const baseUrl = await this.getBaseUrl();
13916
13938
  const token = await getToken();
13917
13939
  if (!token) {
@@ -13924,7 +13946,7 @@ var ApiClient = class {
13924
13946
  if (bypassSecret) {
13925
13947
  headers["x-vercel-protection-bypass"] = bypassSecret;
13926
13948
  }
13927
- return fetch(`${baseUrl}${path12}`, {
13949
+ return fetch(`${baseUrl}${path14}`, {
13928
13950
  method: "GET",
13929
13951
  headers
13930
13952
  });
@@ -13932,7 +13954,7 @@ var ApiClient = class {
13932
13954
  /**
13933
13955
  * Generic POST request
13934
13956
  */
13935
- async post(path12, options) {
13957
+ async post(path14, options) {
13936
13958
  const baseUrl = await this.getBaseUrl();
13937
13959
  const token = await getToken();
13938
13960
  if (!token) {
@@ -13948,7 +13970,7 @@ var ApiClient = class {
13948
13970
  if (bypassSecret) {
13949
13971
  headers["x-vercel-protection-bypass"] = bypassSecret;
13950
13972
  }
13951
- return fetch(`${baseUrl}${path12}`, {
13973
+ return fetch(`${baseUrl}${path14}`, {
13952
13974
  method: "POST",
13953
13975
  headers,
13954
13976
  body: options?.body
@@ -13957,7 +13979,7 @@ var ApiClient = class {
13957
13979
  /**
13958
13980
  * Generic DELETE request
13959
13981
  */
13960
- async delete(path12) {
13982
+ async delete(path14) {
13961
13983
  const baseUrl = await this.getBaseUrl();
13962
13984
  const token = await getToken();
13963
13985
  if (!token) {
@@ -13970,7 +13992,7 @@ var ApiClient = class {
13970
13992
  if (bypassSecret) {
13971
13993
  headers["x-vercel-protection-bypass"] = bypassSecret;
13972
13994
  }
13973
- return fetch(`${baseUrl}${path12}`, {
13995
+ return fetch(`${baseUrl}${path14}`, {
13974
13996
  method: "DELETE",
13975
13997
  headers
13976
13998
  });
@@ -14340,6 +14362,28 @@ import * as tar2 from "tar";
14340
14362
  import * as fs2 from "fs";
14341
14363
  import * as path2 from "path";
14342
14364
  import * as tar from "tar";
14365
+ function formatBytes(bytes) {
14366
+ if (bytes === 0) return "0 B";
14367
+ const k = 1024;
14368
+ const sizes = ["B", "KB", "MB", "GB"];
14369
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
14370
+ return `${(bytes / Math.pow(k, i)).toFixed(2)} ${sizes[i]}`;
14371
+ }
14372
+ function formatRelativeTime(isoDate) {
14373
+ const date5 = new Date(isoDate);
14374
+ const now = /* @__PURE__ */ new Date();
14375
+ const diffMs = now.getTime() - date5.getTime();
14376
+ const diffSec = Math.floor(diffMs / 1e3);
14377
+ const diffMin = Math.floor(diffSec / 60);
14378
+ const diffHour = Math.floor(diffMin / 60);
14379
+ const diffDay = Math.floor(diffHour / 24);
14380
+ const diffWeek = Math.floor(diffDay / 7);
14381
+ if (diffSec < 60) return "just now";
14382
+ if (diffMin < 60) return `${diffMin} minute${diffMin === 1 ? "" : "s"} ago`;
14383
+ if (diffHour < 24) return `${diffHour} hour${diffHour === 1 ? "" : "s"} ago`;
14384
+ if (diffDay < 7) return `${diffDay} day${diffDay === 1 ? "" : "s"} ago`;
14385
+ return `${diffWeek} week${diffWeek === 1 ? "" : "s"} ago`;
14386
+ }
14343
14387
  function excludeVm0Filter(filePath) {
14344
14388
  const shouldExclude = filePath === ".vm0" || filePath.startsWith(".vm0/") || filePath.startsWith("./.vm0");
14345
14389
  return !shouldExclude;
@@ -14679,6 +14723,11 @@ async function uploadSkill(skillUrl) {
14679
14723
  }
14680
14724
 
14681
14725
  // src/commands/compose.ts
14726
+ function getSecretsFromComposeContent(content) {
14727
+ const refs = extractVariableReferences(content);
14728
+ const grouped = groupVariablesBySource(refs);
14729
+ return new Set(grouped.secrets.map((r) => r.name));
14730
+ }
14682
14731
  function transformExperimentalShorthand(agent) {
14683
14732
  const experimentalSecrets = agent.experimental_secrets;
14684
14733
  const experimentalVars = agent.experimental_vars;
@@ -14843,6 +14892,15 @@ var composeCommand = new Command().name("compose").description("Create or update
14843
14892
  const newVars = [...skillVars.entries()].filter(
14844
14893
  ([name]) => !(name in environment)
14845
14894
  );
14895
+ let headSecrets = /* @__PURE__ */ new Set();
14896
+ try {
14897
+ const existingCompose = await apiClient.getComposeByName(agentName);
14898
+ if (existingCompose.content) {
14899
+ headSecrets = getSecretsFromComposeContent(existingCompose.content);
14900
+ }
14901
+ } catch {
14902
+ }
14903
+ const trulyNewSecrets = newSecrets.map(([name]) => name).filter((name) => !headSecrets.has(name));
14846
14904
  if (newSecrets.length > 0 || newVars.length > 0) {
14847
14905
  console.log();
14848
14906
  console.log(
@@ -14852,7 +14910,11 @@ var composeCommand = new Command().name("compose").description("Create or update
14852
14910
  if (newSecrets.length > 0) {
14853
14911
  console.log(chalk2.cyan(" Secrets:"));
14854
14912
  for (const [name, skills] of newSecrets) {
14855
- console.log(` ${name.padEnd(24)} <- ${skills.join(", ")}`);
14913
+ const isNew = trulyNewSecrets.includes(name);
14914
+ const newMarker = isNew ? chalk2.yellow(" (new)") : "";
14915
+ console.log(
14916
+ ` ${name.padEnd(24)}${newMarker} <- ${skills.join(", ")}`
14917
+ );
14856
14918
  }
14857
14919
  }
14858
14920
  if (newVars.length > 0) {
@@ -14862,24 +14924,31 @@ var composeCommand = new Command().name("compose").description("Create or update
14862
14924
  }
14863
14925
  }
14864
14926
  console.log();
14865
- if (!options.yes) {
14866
- if (!process.stdin.isTTY) {
14867
- console.error(
14868
- chalk2.red(
14869
- "\u2717 Non-interactive terminal. Use --yes flag to skip confirmation."
14870
- )
14871
- );
14872
- process.exit(1);
14873
- }
14874
- const response2 = await prompts({
14875
- type: "confirm",
14876
- name: "value",
14877
- message: "Proceed with compose?",
14878
- initial: true
14879
- });
14880
- if (!response2.value) {
14881
- console.log(chalk2.yellow("Compose cancelled."));
14882
- process.exit(0);
14927
+ if (trulyNewSecrets.length > 0) {
14928
+ if (!options.yes) {
14929
+ if (!process.stdin.isTTY) {
14930
+ console.error(
14931
+ chalk2.red(
14932
+ `\u2717 New secrets detected: ${trulyNewSecrets.join(", ")}`
14933
+ )
14934
+ );
14935
+ console.error(
14936
+ chalk2.dim(
14937
+ " Use --yes flag to approve new secrets in non-interactive mode."
14938
+ )
14939
+ );
14940
+ process.exit(1);
14941
+ }
14942
+ const response2 = await prompts({
14943
+ type: "confirm",
14944
+ name: "value",
14945
+ message: `Approve ${trulyNewSecrets.length} new secret(s)?`,
14946
+ initial: true
14947
+ });
14948
+ if (!response2.value) {
14949
+ console.log(chalk2.yellow("Compose cancelled."));
14950
+ process.exit(0);
14951
+ }
14883
14952
  }
14884
14953
  }
14885
14954
  for (const [name] of newSecrets) {
@@ -16127,7 +16196,7 @@ runCmd.command("continue").description(
16127
16196
  var runCommand = runCmd;
16128
16197
 
16129
16198
  // src/commands/volume/index.ts
16130
- import { Command as Command7 } from "commander";
16199
+ import { Command as Command9 } from "commander";
16131
16200
 
16132
16201
  // src/commands/volume/init.ts
16133
16202
  import { Command as Command3 } from "commander";
@@ -16181,8 +16250,53 @@ async function writeStorageConfig(storageName, basePath = process.cwd(), type =
16181
16250
  await writeFile4(configPath, yamlContent, "utf8");
16182
16251
  }
16183
16252
 
16253
+ // src/lib/prompt-utils.ts
16254
+ import prompts2 from "prompts";
16255
+ function isInteractive() {
16256
+ return process.stdout.isTTY === true;
16257
+ }
16258
+ async function promptText(message, initial, validate) {
16259
+ if (!isInteractive()) {
16260
+ return void 0;
16261
+ }
16262
+ const response = await prompts2(
16263
+ {
16264
+ type: "text",
16265
+ name: "value",
16266
+ message,
16267
+ initial,
16268
+ validate
16269
+ },
16270
+ {
16271
+ onCancel: () => {
16272
+ return false;
16273
+ }
16274
+ }
16275
+ );
16276
+ return response.value;
16277
+ }
16278
+ async function promptConfirm(message, initial = true) {
16279
+ if (!isInteractive()) {
16280
+ return void 0;
16281
+ }
16282
+ const response = await prompts2(
16283
+ {
16284
+ type: "confirm",
16285
+ name: "value",
16286
+ message,
16287
+ initial
16288
+ },
16289
+ {
16290
+ onCancel: () => {
16291
+ return false;
16292
+ }
16293
+ }
16294
+ );
16295
+ return response.value;
16296
+ }
16297
+
16184
16298
  // src/commands/volume/init.ts
16185
- var initCommand = new Command3().name("init").description("Initialize a volume in the current directory").action(async () => {
16299
+ var initCommand = new Command3().name("init").description("Initialize a volume in the current directory").option("-n, --name <name>", "Volume name (required in non-interactive mode)").action(async (options) => {
16186
16300
  try {
16187
16301
  const cwd = process.cwd();
16188
16302
  const dirName = path7.basename(cwd);
@@ -16196,9 +16310,37 @@ var initCommand = new Command3().name("init").description("Initialize a volume i
16196
16310
  );
16197
16311
  return;
16198
16312
  }
16199
- const volumeName = dirName;
16313
+ let volumeName;
16314
+ if (options.name) {
16315
+ volumeName = options.name;
16316
+ } else if (!isInteractive()) {
16317
+ console.error(
16318
+ chalk6.red("\u2717 --name flag is required in non-interactive mode")
16319
+ );
16320
+ console.error(
16321
+ chalk6.dim(" Usage: vm0 volume init --name <volume-name>")
16322
+ );
16323
+ process.exit(1);
16324
+ } else {
16325
+ const defaultName = isValidStorageName(dirName) ? dirName : void 0;
16326
+ const name = await promptText(
16327
+ "Enter volume name",
16328
+ defaultName,
16329
+ (value) => {
16330
+ if (!isValidStorageName(value)) {
16331
+ return "Must be 3-64 characters, lowercase alphanumeric with hyphens";
16332
+ }
16333
+ return true;
16334
+ }
16335
+ );
16336
+ if (name === void 0) {
16337
+ console.log(chalk6.dim("Cancelled"));
16338
+ return;
16339
+ }
16340
+ volumeName = name;
16341
+ }
16200
16342
  if (!isValidStorageName(volumeName)) {
16201
- console.error(chalk6.red(`\u2717 Invalid volume name: "${dirName}"`));
16343
+ console.error(chalk6.red(`\u2717 Invalid volume name: "${volumeName}"`));
16202
16344
  console.error(
16203
16345
  chalk6.dim(
16204
16346
  " Volume names must be 3-64 characters, lowercase alphanumeric with hyphens"
@@ -16228,7 +16370,7 @@ var initCommand = new Command3().name("init").description("Initialize a volume i
16228
16370
  // src/commands/volume/push.ts
16229
16371
  import { Command as Command4 } from "commander";
16230
16372
  import chalk7 from "chalk";
16231
- function formatBytes(bytes) {
16373
+ function formatBytes2(bytes) {
16232
16374
  if (bytes === 0) return "0 B";
16233
16375
  const k = 1024;
16234
16376
  const sizes = ["B", "KB", "MB", "GB"];
@@ -16264,7 +16406,7 @@ var pushCommand = new Command4().name("push").description("Push local files to c
16264
16406
  }
16265
16407
  console.log(chalk7.dim(` Version: ${shortVersion}`));
16266
16408
  console.log(chalk7.dim(` Files: ${result.fileCount.toLocaleString()}`));
16267
- console.log(chalk7.dim(` Size: ${formatBytes(result.size)}`));
16409
+ console.log(chalk7.dim(` Size: ${formatBytes2(result.size)}`));
16268
16410
  } catch (error43) {
16269
16411
  console.error(chalk7.red("\u2717 Push failed"));
16270
16412
  if (error43 instanceof Error) {
@@ -16295,7 +16437,7 @@ async function handleEmptyStorageResponse(cwd) {
16295
16437
  }
16296
16438
 
16297
16439
  // src/commands/volume/pull.ts
16298
- function formatBytes2(bytes) {
16440
+ function formatBytes3(bytes) {
16299
16441
  if (bytes === 0) return "0 B";
16300
16442
  const k = 1024;
16301
16443
  const sizes = ["B", "KB", "MB", "GB"];
@@ -16354,7 +16496,7 @@ var pullCommand = new Command5().name("pull").description("Pull cloud files to l
16354
16496
  }
16355
16497
  const arrayBuffer = await s3Response.arrayBuffer();
16356
16498
  const tarBuffer = Buffer.from(arrayBuffer);
16357
- console.log(chalk9.green(`\u2713 Downloaded ${formatBytes2(tarBuffer.length)}`));
16499
+ console.log(chalk9.green(`\u2713 Downloaded ${formatBytes3(tarBuffer.length)}`));
16358
16500
  const tmpDir = fs6.mkdtempSync(path8.join(os4.tmpdir(), "vm0-"));
16359
16501
  const tarPath = path8.join(tmpDir, "volume.tar.gz");
16360
16502
  await fs6.promises.writeFile(tarPath, tarBuffer);
@@ -16390,7 +16532,7 @@ var pullCommand = new Command5().name("pull").description("Pull cloud files to l
16390
16532
  // src/commands/volume/status.ts
16391
16533
  import { Command as Command6 } from "commander";
16392
16534
  import chalk10 from "chalk";
16393
- function formatBytes3(bytes) {
16535
+ function formatBytes4(bytes) {
16394
16536
  if (bytes === 0) return "0 B";
16395
16537
  const k = 1024;
16396
16538
  const sizes = ["B", "KB", "MB", "GB"];
@@ -16437,7 +16579,7 @@ var statusCommand = new Command6().name("status").description("Show status of cl
16437
16579
  console.log(chalk10.green("\u2713 Found"));
16438
16580
  console.log(chalk10.dim(` Version: ${shortVersion}`));
16439
16581
  console.log(chalk10.dim(` Files: ${info.fileCount.toLocaleString()}`));
16440
- console.log(chalk10.dim(` Size: ${formatBytes3(info.size)}`));
16582
+ console.log(chalk10.dim(` Size: ${formatBytes4(info.size)}`));
16441
16583
  }
16442
16584
  } catch (error43) {
16443
16585
  console.error(chalk10.red("\u2717 Status check failed"));
@@ -16448,85 +16590,275 @@ var statusCommand = new Command6().name("status").description("Show status of cl
16448
16590
  }
16449
16591
  });
16450
16592
 
16593
+ // src/commands/volume/list.ts
16594
+ import { Command as Command7 } from "commander";
16595
+ import chalk11 from "chalk";
16596
+ var listCommand = new Command7().name("list").alias("ls").description("List all remote volumes").action(async () => {
16597
+ try {
16598
+ const url2 = "/api/storages/list?type=volume";
16599
+ const response = await apiClient.get(url2);
16600
+ if (!response.ok) {
16601
+ const error43 = await response.json();
16602
+ throw new Error(error43.error?.message || "List failed");
16603
+ }
16604
+ const items = await response.json();
16605
+ if (items.length === 0) {
16606
+ console.log(chalk11.dim("No volumes found"));
16607
+ console.log(
16608
+ chalk11.dim(" Create one with: vm0 volume init && vm0 volume push")
16609
+ );
16610
+ return;
16611
+ }
16612
+ const nameWidth = Math.max(4, ...items.map((i) => i.name.length));
16613
+ const sizeWidth = Math.max(
16614
+ 4,
16615
+ ...items.map((i) => formatBytes(i.size).length)
16616
+ );
16617
+ const filesWidth = Math.max(
16618
+ 5,
16619
+ ...items.map((i) => i.fileCount.toString().length)
16620
+ );
16621
+ const header = [
16622
+ "NAME".padEnd(nameWidth),
16623
+ "SIZE".padStart(sizeWidth),
16624
+ "FILES".padStart(filesWidth),
16625
+ "UPDATED"
16626
+ ].join(" ");
16627
+ console.log(chalk11.dim(header));
16628
+ for (const item of items) {
16629
+ const row = [
16630
+ item.name.padEnd(nameWidth),
16631
+ formatBytes(item.size).padStart(sizeWidth),
16632
+ item.fileCount.toString().padStart(filesWidth),
16633
+ formatRelativeTime(item.updatedAt)
16634
+ ].join(" ");
16635
+ console.log(row);
16636
+ }
16637
+ } catch (error43) {
16638
+ console.error(chalk11.red("\u2717 Failed to list volumes"));
16639
+ if (error43 instanceof Error) {
16640
+ if (error43.message.includes("Not authenticated")) {
16641
+ console.error(chalk11.dim(" Run: vm0 auth login"));
16642
+ } else {
16643
+ console.error(chalk11.dim(` ${error43.message}`));
16644
+ }
16645
+ }
16646
+ process.exit(1);
16647
+ }
16648
+ });
16649
+
16650
+ // src/commands/volume/clone.ts
16651
+ import { Command as Command8 } from "commander";
16652
+ import chalk13 from "chalk";
16653
+
16654
+ // src/lib/clone-utils.ts
16655
+ import chalk12 from "chalk";
16656
+ import path9 from "path";
16657
+ import * as fs7 from "fs";
16658
+ import * as os5 from "os";
16659
+ import * as tar4 from "tar";
16660
+ async function cloneStorage(name, type, destination, options = {}) {
16661
+ const typeLabel = type === "artifact" ? "artifact" : "volume";
16662
+ if (fs7.existsSync(destination)) {
16663
+ throw new Error(`Directory "${destination}" already exists`);
16664
+ }
16665
+ console.log(chalk12.dim(`Checking remote ${typeLabel}...`));
16666
+ let url2 = `/api/storages/download?name=${encodeURIComponent(name)}&type=${type}`;
16667
+ if (options.version) {
16668
+ url2 += `&version=${encodeURIComponent(options.version)}`;
16669
+ }
16670
+ const response = await apiClient.get(url2);
16671
+ if (!response.ok) {
16672
+ if (response.status === 404) {
16673
+ throw new Error(
16674
+ `${typeLabel.charAt(0).toUpperCase() + typeLabel.slice(1)} "${name}" not found`
16675
+ );
16676
+ }
16677
+ const error43 = await response.json();
16678
+ throw new Error(error43.error?.message || "Clone failed");
16679
+ }
16680
+ const downloadInfo = await response.json();
16681
+ console.log(chalk12.dim(`Creating directory: ${destination}/`));
16682
+ await fs7.promises.mkdir(destination, { recursive: true });
16683
+ if (downloadInfo.empty) {
16684
+ await writeStorageConfig(name, destination, type);
16685
+ console.log(chalk12.green(`\u2713 Cloned empty ${typeLabel}: ${name}`));
16686
+ console.log(chalk12.dim(`\u2713 Initialized .vm0/storage.yaml`));
16687
+ return {
16688
+ success: true,
16689
+ fileCount: 0,
16690
+ size: 0,
16691
+ versionId: downloadInfo.versionId
16692
+ };
16693
+ }
16694
+ if (!downloadInfo.url) {
16695
+ throw new Error("No download URL returned");
16696
+ }
16697
+ console.log(chalk12.dim("Downloading from S3..."));
16698
+ const s3Response = await fetch(downloadInfo.url);
16699
+ if (!s3Response.ok) {
16700
+ await fs7.promises.rm(destination, { recursive: true, force: true });
16701
+ throw new Error(`S3 download failed: ${s3Response.status}`);
16702
+ }
16703
+ const arrayBuffer = await s3Response.arrayBuffer();
16704
+ const tarBuffer = Buffer.from(arrayBuffer);
16705
+ console.log(chalk12.green(`\u2713 Downloaded ${formatBytes(tarBuffer.length)}`));
16706
+ const tmpDir = fs7.mkdtempSync(path9.join(os5.tmpdir(), "vm0-clone-"));
16707
+ const tarPath = path9.join(tmpDir, "archive.tar.gz");
16708
+ await fs7.promises.writeFile(tarPath, tarBuffer);
16709
+ const files = await listTarFiles(tarPath);
16710
+ console.log(chalk12.dim("Extracting files..."));
16711
+ await tar4.extract({
16712
+ file: tarPath,
16713
+ cwd: destination,
16714
+ gzip: true
16715
+ });
16716
+ await fs7.promises.unlink(tarPath);
16717
+ await fs7.promises.rmdir(tmpDir);
16718
+ console.log(chalk12.green(`\u2713 Extracted ${files.length} files`));
16719
+ await writeStorageConfig(name, destination, type);
16720
+ console.log(chalk12.green(`\u2713 Initialized .vm0/storage.yaml`));
16721
+ return {
16722
+ success: true,
16723
+ fileCount: downloadInfo.fileCount,
16724
+ size: downloadInfo.size,
16725
+ versionId: downloadInfo.versionId
16726
+ };
16727
+ }
16728
+
16729
+ // src/commands/volume/clone.ts
16730
+ var cloneCommand = new Command8().name("clone").description("Clone a remote volume to local directory (latest version)").argument("<name>", "Volume name to clone").argument("[destination]", "Destination directory (default: volume name)").action(async (name, destination) => {
16731
+ try {
16732
+ const targetDir = destination || name;
16733
+ console.log(`Cloning volume: ${name}`);
16734
+ const result = await cloneStorage(name, "volume", targetDir);
16735
+ console.log(chalk13.green(`
16736
+ \u2713 Successfully cloned volume: ${name}`));
16737
+ console.log(chalk13.dim(` Location: ${targetDir}/`));
16738
+ console.log(chalk13.dim(` Version: ${result.versionId.slice(0, 8)}`));
16739
+ } catch (error43) {
16740
+ console.error(chalk13.red("\u2717 Clone failed"));
16741
+ if (error43 instanceof Error) {
16742
+ if (error43.message.includes("Not authenticated")) {
16743
+ console.error(chalk13.dim(" Run: vm0 auth login"));
16744
+ } else {
16745
+ console.error(chalk13.dim(` ${error43.message}`));
16746
+ }
16747
+ }
16748
+ process.exit(1);
16749
+ }
16750
+ });
16751
+
16451
16752
  // src/commands/volume/index.ts
16452
- var volumeCommand = new Command7().name("volume").description("Manage cloud volumes").addCommand(initCommand).addCommand(pushCommand).addCommand(pullCommand).addCommand(statusCommand);
16753
+ var volumeCommand = new Command9().name("volume").description("Manage cloud volumes").addCommand(initCommand).addCommand(pushCommand).addCommand(pullCommand).addCommand(statusCommand).addCommand(listCommand).addCommand(cloneCommand);
16453
16754
 
16454
16755
  // src/commands/artifact/index.ts
16455
- import { Command as Command12 } from "commander";
16756
+ import { Command as Command16 } from "commander";
16456
16757
 
16457
16758
  // src/commands/artifact/init.ts
16458
- import { Command as Command8 } from "commander";
16459
- import chalk11 from "chalk";
16460
- import path9 from "path";
16461
- var initCommand2 = new Command8().name("init").description("Initialize an artifact in the current directory").action(async () => {
16759
+ import { Command as Command10 } from "commander";
16760
+ import chalk14 from "chalk";
16761
+ import path10 from "path";
16762
+ var initCommand2 = new Command10().name("init").description("Initialize an artifact in the current directory").option(
16763
+ "-n, --name <name>",
16764
+ "Artifact name (required in non-interactive mode)"
16765
+ ).action(async (options) => {
16462
16766
  try {
16463
16767
  const cwd = process.cwd();
16464
- const dirName = path9.basename(cwd);
16768
+ const dirName = path10.basename(cwd);
16465
16769
  const existingConfig = await readStorageConfig(cwd);
16466
16770
  if (existingConfig) {
16467
16771
  if (existingConfig.type === "artifact") {
16468
16772
  console.log(
16469
- chalk11.yellow(
16773
+ chalk14.yellow(
16470
16774
  `Artifact already initialized: ${existingConfig.name}`
16471
16775
  )
16472
16776
  );
16473
16777
  } else {
16474
16778
  console.log(
16475
- chalk11.yellow(
16779
+ chalk14.yellow(
16476
16780
  `Directory already initialized as volume: ${existingConfig.name}`
16477
16781
  )
16478
16782
  );
16479
16783
  console.log(
16480
- chalk11.dim(
16784
+ chalk14.dim(
16481
16785
  " To change type, delete .vm0/storage.yaml and reinitialize"
16482
16786
  )
16483
16787
  );
16484
16788
  }
16485
16789
  console.log(
16486
- chalk11.dim(`Config file: ${path9.join(cwd, ".vm0", "storage.yaml")}`)
16790
+ chalk14.dim(`Config file: ${path10.join(cwd, ".vm0", "storage.yaml")}`)
16487
16791
  );
16488
16792
  return;
16489
16793
  }
16490
- const artifactName = dirName;
16794
+ let artifactName;
16795
+ if (options.name) {
16796
+ artifactName = options.name;
16797
+ } else if (!isInteractive()) {
16798
+ console.error(
16799
+ chalk14.red("\u2717 --name flag is required in non-interactive mode")
16800
+ );
16801
+ console.error(
16802
+ chalk14.dim(" Usage: vm0 artifact init --name <artifact-name>")
16803
+ );
16804
+ process.exit(1);
16805
+ } else {
16806
+ const defaultName = isValidStorageName(dirName) ? dirName : void 0;
16807
+ const name = await promptText(
16808
+ "Enter artifact name",
16809
+ defaultName,
16810
+ (value) => {
16811
+ if (!isValidStorageName(value)) {
16812
+ return "Must be 3-64 characters, lowercase alphanumeric with hyphens";
16813
+ }
16814
+ return true;
16815
+ }
16816
+ );
16817
+ if (name === void 0) {
16818
+ console.log(chalk14.dim("Cancelled"));
16819
+ return;
16820
+ }
16821
+ artifactName = name;
16822
+ }
16491
16823
  if (!isValidStorageName(artifactName)) {
16492
- console.error(chalk11.red(`\u2717 Invalid artifact name: "${dirName}"`));
16824
+ console.error(chalk14.red(`\u2717 Invalid artifact name: "${artifactName}"`));
16493
16825
  console.error(
16494
- chalk11.dim(
16826
+ chalk14.dim(
16495
16827
  " Artifact names must be 3-64 characters, lowercase alphanumeric with hyphens"
16496
16828
  )
16497
16829
  );
16498
16830
  console.error(
16499
- chalk11.dim(" Example: my-project, user-workspace, code-artifact")
16831
+ chalk14.dim(" Example: my-project, user-workspace, code-artifact")
16500
16832
  );
16501
16833
  process.exit(1);
16502
16834
  }
16503
16835
  await writeStorageConfig(artifactName, cwd, "artifact");
16504
- console.log(chalk11.green(`\u2713 Initialized artifact: ${artifactName}`));
16836
+ console.log(chalk14.green(`\u2713 Initialized artifact: ${artifactName}`));
16505
16837
  console.log(
16506
- chalk11.dim(
16507
- `\u2713 Config saved to ${path9.join(cwd, ".vm0", "storage.yaml")}`
16838
+ chalk14.dim(
16839
+ `\u2713 Config saved to ${path10.join(cwd, ".vm0", "storage.yaml")}`
16508
16840
  )
16509
16841
  );
16510
16842
  } catch (error43) {
16511
- console.error(chalk11.red("\u2717 Failed to initialize artifact"));
16843
+ console.error(chalk14.red("\u2717 Failed to initialize artifact"));
16512
16844
  if (error43 instanceof Error) {
16513
- console.error(chalk11.dim(` ${error43.message}`));
16845
+ console.error(chalk14.dim(` ${error43.message}`));
16514
16846
  }
16515
16847
  process.exit(1);
16516
16848
  }
16517
16849
  });
16518
16850
 
16519
16851
  // src/commands/artifact/push.ts
16520
- import { Command as Command9 } from "commander";
16521
- import chalk12 from "chalk";
16522
- function formatBytes4(bytes) {
16852
+ import { Command as Command11 } from "commander";
16853
+ import chalk15 from "chalk";
16854
+ function formatBytes5(bytes) {
16523
16855
  if (bytes === 0) return "0 B";
16524
16856
  const k = 1024;
16525
16857
  const sizes = ["B", "KB", "MB", "GB"];
16526
16858
  const i = Math.floor(Math.log(bytes) / Math.log(k));
16527
16859
  return `${(bytes / Math.pow(k, i)).toFixed(2)} ${sizes[i]}`;
16528
16860
  }
16529
- var pushCommand2 = new Command9().name("push").description("Push local files to cloud artifact").option(
16861
+ var pushCommand2 = new Command11().name("push").description("Push local files to cloud artifact").option(
16530
16862
  "-f, --force",
16531
16863
  "Force upload even if content unchanged (recreate archive)"
16532
16864
  ).action(async (options) => {
@@ -16534,76 +16866,76 @@ var pushCommand2 = new Command9().name("push").description("Push local files to
16534
16866
  const cwd = process.cwd();
16535
16867
  const config2 = await readStorageConfig(cwd);
16536
16868
  if (!config2) {
16537
- console.error(chalk12.red("\u2717 No artifact initialized in this directory"));
16538
- console.error(chalk12.dim(" Run: vm0 artifact init"));
16869
+ console.error(chalk15.red("\u2717 No artifact initialized in this directory"));
16870
+ console.error(chalk15.dim(" Run: vm0 artifact init"));
16539
16871
  process.exit(1);
16540
16872
  }
16541
16873
  if (config2.type !== "artifact") {
16542
16874
  console.error(
16543
- chalk12.red(
16875
+ chalk15.red(
16544
16876
  `\u2717 This directory is initialized as a volume, not an artifact`
16545
16877
  )
16546
16878
  );
16547
- console.error(chalk12.dim(" Use: vm0 volume push"));
16879
+ console.error(chalk15.dim(" Use: vm0 volume push"));
16548
16880
  process.exit(1);
16549
16881
  }
16550
16882
  console.log(`Pushing artifact: ${config2.name}`);
16551
16883
  const result = await directUpload(config2.name, "artifact", cwd, {
16552
16884
  onProgress: (message) => {
16553
- console.log(chalk12.dim(message));
16885
+ console.log(chalk15.dim(message));
16554
16886
  },
16555
16887
  force: options.force
16556
16888
  });
16557
16889
  const shortVersion = result.versionId.slice(0, 8);
16558
16890
  if (result.empty) {
16559
- console.log(chalk12.yellow("No files found (empty artifact)"));
16891
+ console.log(chalk15.yellow("No files found (empty artifact)"));
16560
16892
  } else if (result.deduplicated) {
16561
- console.log(chalk12.green("\u2713 Content unchanged (deduplicated)"));
16893
+ console.log(chalk15.green("\u2713 Content unchanged (deduplicated)"));
16562
16894
  } else {
16563
- console.log(chalk12.green("\u2713 Upload complete"));
16895
+ console.log(chalk15.green("\u2713 Upload complete"));
16564
16896
  }
16565
- console.log(chalk12.dim(` Version: ${shortVersion}`));
16566
- console.log(chalk12.dim(` Files: ${result.fileCount.toLocaleString()}`));
16567
- console.log(chalk12.dim(` Size: ${formatBytes4(result.size)}`));
16897
+ console.log(chalk15.dim(` Version: ${shortVersion}`));
16898
+ console.log(chalk15.dim(` Files: ${result.fileCount.toLocaleString()}`));
16899
+ console.log(chalk15.dim(` Size: ${formatBytes5(result.size)}`));
16568
16900
  } catch (error43) {
16569
- console.error(chalk12.red("\u2717 Push failed"));
16901
+ console.error(chalk15.red("\u2717 Push failed"));
16570
16902
  if (error43 instanceof Error) {
16571
- console.error(chalk12.dim(` ${error43.message}`));
16903
+ console.error(chalk15.dim(` ${error43.message}`));
16572
16904
  }
16573
16905
  process.exit(1);
16574
16906
  }
16575
16907
  });
16576
16908
 
16577
16909
  // src/commands/artifact/pull.ts
16578
- import { Command as Command10 } from "commander";
16579
- import chalk13 from "chalk";
16580
- import path10 from "path";
16581
- import * as fs7 from "fs";
16582
- import * as os5 from "os";
16583
- import * as tar4 from "tar";
16584
- function formatBytes5(bytes) {
16910
+ import { Command as Command12 } from "commander";
16911
+ import chalk16 from "chalk";
16912
+ import path11 from "path";
16913
+ import * as fs8 from "fs";
16914
+ import * as os6 from "os";
16915
+ import * as tar5 from "tar";
16916
+ function formatBytes6(bytes) {
16585
16917
  if (bytes === 0) return "0 B";
16586
16918
  const k = 1024;
16587
16919
  const sizes = ["B", "KB", "MB", "GB"];
16588
16920
  const i = Math.floor(Math.log(bytes) / Math.log(k));
16589
16921
  return `${(bytes / Math.pow(k, i)).toFixed(2)} ${sizes[i]}`;
16590
16922
  }
16591
- var pullCommand2 = new Command10().name("pull").description("Pull cloud artifact to local directory").argument("[versionId]", "Version ID to pull (default: latest)").action(async (versionId) => {
16923
+ var pullCommand2 = new Command12().name("pull").description("Pull cloud artifact to local directory").argument("[versionId]", "Version ID to pull (default: latest)").action(async (versionId) => {
16592
16924
  try {
16593
16925
  const cwd = process.cwd();
16594
16926
  const config2 = await readStorageConfig(cwd);
16595
16927
  if (!config2) {
16596
- console.error(chalk13.red("\u2717 No artifact initialized in this directory"));
16597
- console.error(chalk13.dim(" Run: vm0 artifact init"));
16928
+ console.error(chalk16.red("\u2717 No artifact initialized in this directory"));
16929
+ console.error(chalk16.dim(" Run: vm0 artifact init"));
16598
16930
  process.exit(1);
16599
16931
  }
16600
16932
  if (config2.type !== "artifact") {
16601
16933
  console.error(
16602
- chalk13.red(
16934
+ chalk16.red(
16603
16935
  `\u2717 This directory is initialized as a volume, not an artifact`
16604
16936
  )
16605
16937
  );
16606
- console.error(chalk13.dim(" Use: vm0 volume pull"));
16938
+ console.error(chalk16.dim(" Use: vm0 volume pull"));
16607
16939
  process.exit(1);
16608
16940
  }
16609
16941
  if (versionId) {
@@ -16611,7 +16943,7 @@ var pullCommand2 = new Command10().name("pull").description("Pull cloud artifact
16611
16943
  } else {
16612
16944
  console.log(`Pulling artifact: ${config2.name}`);
16613
16945
  }
16614
- console.log(chalk13.dim("Getting download URL..."));
16946
+ console.log(chalk16.dim("Getting download URL..."));
16615
16947
  let url2 = `/api/storages/download?name=${encodeURIComponent(config2.name)}&type=artifact`;
16616
16948
  if (versionId) {
16617
16949
  url2 += `&version=${encodeURIComponent(versionId)}`;
@@ -16619,14 +16951,14 @@ var pullCommand2 = new Command10().name("pull").description("Pull cloud artifact
16619
16951
  const response = await apiClient.get(url2);
16620
16952
  if (!response.ok) {
16621
16953
  if (response.status === 404) {
16622
- console.error(chalk13.red(`\u2717 Artifact "${config2.name}" not found`));
16954
+ console.error(chalk16.red(`\u2717 Artifact "${config2.name}" not found`));
16623
16955
  console.error(
16624
- chalk13.dim(
16956
+ chalk16.dim(
16625
16957
  " Make sure the artifact name is correct in .vm0/storage.yaml"
16626
16958
  )
16627
16959
  );
16628
16960
  console.error(
16629
- chalk13.dim(" Or push the artifact first with: vm0 artifact push")
16961
+ chalk16.dim(" Or push the artifact first with: vm0 artifact push")
16630
16962
  );
16631
16963
  } else {
16632
16964
  const error43 = await response.json();
@@ -16642,18 +16974,18 @@ var pullCommand2 = new Command10().name("pull").description("Pull cloud artifact
16642
16974
  if (!downloadInfo.url) {
16643
16975
  throw new Error("No download URL returned");
16644
16976
  }
16645
- console.log(chalk13.dim("Downloading from S3..."));
16977
+ console.log(chalk16.dim("Downloading from S3..."));
16646
16978
  const s3Response = await fetch(downloadInfo.url);
16647
16979
  if (!s3Response.ok) {
16648
16980
  throw new Error(`S3 download failed: ${s3Response.status}`);
16649
16981
  }
16650
16982
  const arrayBuffer = await s3Response.arrayBuffer();
16651
16983
  const tarBuffer = Buffer.from(arrayBuffer);
16652
- console.log(chalk13.green(`\u2713 Downloaded ${formatBytes5(tarBuffer.length)}`));
16653
- const tmpDir = fs7.mkdtempSync(path10.join(os5.tmpdir(), "vm0-"));
16654
- const tarPath = path10.join(tmpDir, "artifact.tar.gz");
16655
- await fs7.promises.writeFile(tarPath, tarBuffer);
16656
- console.log(chalk13.dim("Syncing local files..."));
16984
+ console.log(chalk16.green(`\u2713 Downloaded ${formatBytes6(tarBuffer.length)}`));
16985
+ const tmpDir = fs8.mkdtempSync(path11.join(os6.tmpdir(), "vm0-"));
16986
+ const tarPath = path11.join(tmpDir, "artifact.tar.gz");
16987
+ await fs8.promises.writeFile(tarPath, tarBuffer);
16988
+ console.log(chalk16.dim("Syncing local files..."));
16657
16989
  const remoteFiles = await listTarFiles(tarPath);
16658
16990
  const remoteFilesSet = new Set(
16659
16991
  remoteFiles.map((f) => f.replace(/\\/g, "/"))
@@ -16661,53 +16993,53 @@ var pullCommand2 = new Command10().name("pull").description("Pull cloud artifact
16661
16993
  const removedCount = await removeExtraFiles(cwd, remoteFilesSet);
16662
16994
  if (removedCount > 0) {
16663
16995
  console.log(
16664
- chalk13.green(`\u2713 Removed ${removedCount} files not in remote`)
16996
+ chalk16.green(`\u2713 Removed ${removedCount} files not in remote`)
16665
16997
  );
16666
16998
  }
16667
- console.log(chalk13.dim("Extracting files..."));
16668
- await tar4.extract({
16999
+ console.log(chalk16.dim("Extracting files..."));
17000
+ await tar5.extract({
16669
17001
  file: tarPath,
16670
17002
  cwd,
16671
17003
  gzip: true
16672
17004
  });
16673
- await fs7.promises.unlink(tarPath);
16674
- await fs7.promises.rmdir(tmpDir);
16675
- console.log(chalk13.green(`\u2713 Extracted ${remoteFiles.length} files`));
17005
+ await fs8.promises.unlink(tarPath);
17006
+ await fs8.promises.rmdir(tmpDir);
17007
+ console.log(chalk16.green(`\u2713 Extracted ${remoteFiles.length} files`));
16676
17008
  } catch (error43) {
16677
- console.error(chalk13.red("\u2717 Pull failed"));
17009
+ console.error(chalk16.red("\u2717 Pull failed"));
16678
17010
  if (error43 instanceof Error) {
16679
- console.error(chalk13.dim(` ${error43.message}`));
17011
+ console.error(chalk16.dim(` ${error43.message}`));
16680
17012
  }
16681
17013
  process.exit(1);
16682
17014
  }
16683
17015
  });
16684
17016
 
16685
17017
  // src/commands/artifact/status.ts
16686
- import { Command as Command11 } from "commander";
16687
- import chalk14 from "chalk";
16688
- function formatBytes6(bytes) {
17018
+ import { Command as Command13 } from "commander";
17019
+ import chalk17 from "chalk";
17020
+ function formatBytes7(bytes) {
16689
17021
  if (bytes === 0) return "0 B";
16690
17022
  const k = 1024;
16691
17023
  const sizes = ["B", "KB", "MB", "GB"];
16692
17024
  const i = Math.floor(Math.log(bytes) / Math.log(k));
16693
17025
  return `${(bytes / Math.pow(k, i)).toFixed(2)} ${sizes[i]}`;
16694
17026
  }
16695
- var statusCommand2 = new Command11().name("status").description("Show status of cloud artifact").action(async () => {
17027
+ var statusCommand2 = new Command13().name("status").description("Show status of cloud artifact").action(async () => {
16696
17028
  try {
16697
17029
  const cwd = process.cwd();
16698
17030
  const config2 = await readStorageConfig(cwd);
16699
17031
  if (!config2) {
16700
- console.error(chalk14.red("\u2717 No artifact initialized in this directory"));
16701
- console.error(chalk14.dim(" Run: vm0 artifact init"));
17032
+ console.error(chalk17.red("\u2717 No artifact initialized in this directory"));
17033
+ console.error(chalk17.dim(" Run: vm0 artifact init"));
16702
17034
  process.exit(1);
16703
17035
  }
16704
17036
  if (config2.type !== "artifact") {
16705
17037
  console.error(
16706
- chalk14.red(
17038
+ chalk17.red(
16707
17039
  "\u2717 This directory is initialized as a volume, not an artifact"
16708
17040
  )
16709
17041
  );
16710
- console.error(chalk14.dim(" Use: vm0 volume status"));
17042
+ console.error(chalk17.dim(" Use: vm0 volume status"));
16711
17043
  process.exit(1);
16712
17044
  }
16713
17045
  console.log(`Checking artifact: ${config2.name}`);
@@ -16715,8 +17047,8 @@ var statusCommand2 = new Command11().name("status").description("Show status of
16715
17047
  const response = await apiClient.get(url2);
16716
17048
  if (!response.ok) {
16717
17049
  if (response.status === 404) {
16718
- console.error(chalk14.red("\u2717 Not found on remote"));
16719
- console.error(chalk14.dim(" Run: vm0 artifact push"));
17050
+ console.error(chalk17.red("\u2717 Not found on remote"));
17051
+ console.error(chalk17.dim(" Run: vm0 artifact push"));
16720
17052
  } else {
16721
17053
  const error43 = await response.json();
16722
17054
  throw new Error(error43.error?.message || "Status check failed");
@@ -16726,32 +17058,116 @@ var statusCommand2 = new Command11().name("status").description("Show status of
16726
17058
  const info = await response.json();
16727
17059
  const shortVersion = info.versionId.slice(0, 8);
16728
17060
  if (info.empty) {
16729
- console.log(chalk14.green("\u2713 Found (empty)"));
16730
- console.log(chalk14.dim(` Version: ${shortVersion}`));
17061
+ console.log(chalk17.green("\u2713 Found (empty)"));
17062
+ console.log(chalk17.dim(` Version: ${shortVersion}`));
16731
17063
  } else {
16732
- console.log(chalk14.green("\u2713 Found"));
16733
- console.log(chalk14.dim(` Version: ${shortVersion}`));
16734
- console.log(chalk14.dim(` Files: ${info.fileCount.toLocaleString()}`));
16735
- console.log(chalk14.dim(` Size: ${formatBytes6(info.size)}`));
17064
+ console.log(chalk17.green("\u2713 Found"));
17065
+ console.log(chalk17.dim(` Version: ${shortVersion}`));
17066
+ console.log(chalk17.dim(` Files: ${info.fileCount.toLocaleString()}`));
17067
+ console.log(chalk17.dim(` Size: ${formatBytes7(info.size)}`));
16736
17068
  }
16737
17069
  } catch (error43) {
16738
- console.error(chalk14.red("\u2717 Status check failed"));
17070
+ console.error(chalk17.red("\u2717 Status check failed"));
16739
17071
  if (error43 instanceof Error) {
16740
- console.error(chalk14.dim(` ${error43.message}`));
17072
+ console.error(chalk17.dim(` ${error43.message}`));
17073
+ }
17074
+ process.exit(1);
17075
+ }
17076
+ });
17077
+
17078
+ // src/commands/artifact/list.ts
17079
+ import { Command as Command14 } from "commander";
17080
+ import chalk18 from "chalk";
17081
+ var listCommand2 = new Command14().name("list").alias("ls").description("List all remote artifacts").action(async () => {
17082
+ try {
17083
+ const url2 = "/api/storages/list?type=artifact";
17084
+ const response = await apiClient.get(url2);
17085
+ if (!response.ok) {
17086
+ const error43 = await response.json();
17087
+ throw new Error(error43.error?.message || "List failed");
17088
+ }
17089
+ const items = await response.json();
17090
+ if (items.length === 0) {
17091
+ console.log(chalk18.dim("No artifacts found"));
17092
+ console.log(
17093
+ chalk18.dim(
17094
+ " Create one with: vm0 artifact init && vm0 artifact push"
17095
+ )
17096
+ );
17097
+ return;
17098
+ }
17099
+ const nameWidth = Math.max(4, ...items.map((i) => i.name.length));
17100
+ const sizeWidth = Math.max(
17101
+ 4,
17102
+ ...items.map((i) => formatBytes(i.size).length)
17103
+ );
17104
+ const filesWidth = Math.max(
17105
+ 5,
17106
+ ...items.map((i) => i.fileCount.toString().length)
17107
+ );
17108
+ const header = [
17109
+ "NAME".padEnd(nameWidth),
17110
+ "SIZE".padStart(sizeWidth),
17111
+ "FILES".padStart(filesWidth),
17112
+ "UPDATED"
17113
+ ].join(" ");
17114
+ console.log(chalk18.dim(header));
17115
+ for (const item of items) {
17116
+ const row = [
17117
+ item.name.padEnd(nameWidth),
17118
+ formatBytes(item.size).padStart(sizeWidth),
17119
+ item.fileCount.toString().padStart(filesWidth),
17120
+ formatRelativeTime(item.updatedAt)
17121
+ ].join(" ");
17122
+ console.log(row);
17123
+ }
17124
+ } catch (error43) {
17125
+ console.error(chalk18.red("\u2717 Failed to list artifacts"));
17126
+ if (error43 instanceof Error) {
17127
+ if (error43.message.includes("Not authenticated")) {
17128
+ console.error(chalk18.dim(" Run: vm0 auth login"));
17129
+ } else {
17130
+ console.error(chalk18.dim(` ${error43.message}`));
17131
+ }
17132
+ }
17133
+ process.exit(1);
17134
+ }
17135
+ });
17136
+
17137
+ // src/commands/artifact/clone.ts
17138
+ import { Command as Command15 } from "commander";
17139
+ import chalk19 from "chalk";
17140
+ var cloneCommand2 = new Command15().name("clone").description("Clone a remote artifact to local directory (latest version)").argument("<name>", "Artifact name to clone").argument("[destination]", "Destination directory (default: artifact name)").action(async (name, destination) => {
17141
+ try {
17142
+ const targetDir = destination || name;
17143
+ console.log(`Cloning artifact: ${name}`);
17144
+ const result = await cloneStorage(name, "artifact", targetDir);
17145
+ console.log(chalk19.green(`
17146
+ \u2713 Successfully cloned artifact: ${name}`));
17147
+ console.log(chalk19.dim(` Location: ${targetDir}/`));
17148
+ console.log(chalk19.dim(` Version: ${result.versionId.slice(0, 8)}`));
17149
+ } catch (error43) {
17150
+ console.error(chalk19.red("\u2717 Clone failed"));
17151
+ if (error43 instanceof Error) {
17152
+ if (error43.message.includes("Not authenticated")) {
17153
+ console.error(chalk19.dim(" Run: vm0 auth login"));
17154
+ } else {
17155
+ console.error(chalk19.dim(` ${error43.message}`));
17156
+ }
16741
17157
  }
16742
17158
  process.exit(1);
16743
17159
  }
16744
17160
  });
16745
17161
 
16746
17162
  // src/commands/artifact/index.ts
16747
- var artifactCommand = new Command12().name("artifact").description("Manage cloud artifacts (work products)").addCommand(initCommand2).addCommand(pushCommand2).addCommand(pullCommand2).addCommand(statusCommand2);
17163
+ var artifactCommand = new Command16().name("artifact").description("Manage cloud artifacts (work products)").addCommand(initCommand2).addCommand(pushCommand2).addCommand(pullCommand2).addCommand(statusCommand2).addCommand(listCommand2).addCommand(cloneCommand2);
16748
17164
 
16749
17165
  // src/commands/cook.ts
16750
- import { Command as Command13 } from "commander";
16751
- import chalk16 from "chalk";
17166
+ import { Command as Command17 } from "commander";
17167
+ import chalk21 from "chalk";
16752
17168
  import { readFile as readFile7, mkdir as mkdir6, writeFile as writeFile6, appendFile } from "fs/promises";
16753
- import { existsSync as existsSync7, readFileSync } from "fs";
16754
- import path11 from "path";
17169
+ import { existsSync as existsSync8, readFileSync } from "fs";
17170
+ import path12 from "path";
16755
17171
  import { spawn as spawn2 } from "child_process";
16756
17172
  import { parse as parseYaml4 } from "yaml";
16757
17173
  import { config as dotenvConfig2 } from "dotenv";
@@ -16759,7 +17175,7 @@ import { config as dotenvConfig2 } from "dotenv";
16759
17175
  // src/lib/update-checker.ts
16760
17176
  import https from "https";
16761
17177
  import { spawn } from "child_process";
16762
- import chalk15 from "chalk";
17178
+ import chalk20 from "chalk";
16763
17179
  var PACKAGE_NAME = "@vm0/cli";
16764
17180
  var NPM_REGISTRY_URL = `https://registry.npmjs.org/${encodeURIComponent(PACKAGE_NAME)}/latest`;
16765
17181
  var TIMEOUT_MS = 5e3;
@@ -16824,21 +17240,21 @@ function performUpgrade(packageManager) {
16824
17240
  async function checkAndUpgrade(currentVersion, prompt) {
16825
17241
  const latestVersion = await getLatestVersion();
16826
17242
  if (latestVersion === null) {
16827
- console.log(chalk15.yellow("Warning: Could not check for updates"));
17243
+ console.log(chalk20.yellow("Warning: Could not check for updates"));
16828
17244
  console.log();
16829
17245
  return false;
16830
17246
  }
16831
17247
  if (latestVersion === currentVersion) {
16832
17248
  return false;
16833
17249
  }
16834
- console.log(chalk15.yellow("vm0 is currently in Early Access (EA)."));
17250
+ console.log(chalk20.yellow("vm0 is currently in Early Access (EA)."));
16835
17251
  console.log(
16836
- chalk15.yellow(
17252
+ chalk20.yellow(
16837
17253
  `Current version: ${currentVersion} -> Latest version: ${latestVersion}`
16838
17254
  )
16839
17255
  );
16840
17256
  console.log(
16841
- chalk15.yellow(
17257
+ chalk20.yellow(
16842
17258
  "Please always use the latest version for best compatibility."
16843
17259
  )
16844
17260
  );
@@ -16847,20 +17263,20 @@ async function checkAndUpgrade(currentVersion, prompt) {
16847
17263
  console.log(`Upgrading via ${packageManager}...`);
16848
17264
  const success2 = await performUpgrade(packageManager);
16849
17265
  if (success2) {
16850
- console.log(chalk15.green(`Upgraded to ${latestVersion}`));
17266
+ console.log(chalk20.green(`Upgraded to ${latestVersion}`));
16851
17267
  console.log();
16852
17268
  console.log("To continue, run:");
16853
- console.log(chalk15.cyan(` ${buildRerunCommand(prompt)}`));
17269
+ console.log(chalk20.cyan(` ${buildRerunCommand(prompt)}`));
16854
17270
  return true;
16855
17271
  }
16856
17272
  console.log();
16857
- console.log(chalk15.red("Upgrade failed. Please run manually:"));
16858
- console.log(chalk15.cyan(` npm install -g ${PACKAGE_NAME}@latest`));
16859
- console.log(chalk15.dim(" # or"));
16860
- console.log(chalk15.cyan(` pnpm add -g ${PACKAGE_NAME}@latest`));
17273
+ console.log(chalk20.red("Upgrade failed. Please run manually:"));
17274
+ console.log(chalk20.cyan(` npm install -g ${PACKAGE_NAME}@latest`));
17275
+ console.log(chalk20.dim(" # or"));
17276
+ console.log(chalk20.cyan(` pnpm add -g ${PACKAGE_NAME}@latest`));
16861
17277
  console.log();
16862
17278
  console.log("Then re-run:");
16863
- console.log(chalk15.cyan(` ${buildRerunCommand(prompt)}`));
17279
+ console.log(chalk20.cyan(` ${buildRerunCommand(prompt)}`));
16864
17280
  return true;
16865
17281
  }
16866
17282
 
@@ -16868,12 +17284,12 @@ async function checkAndUpgrade(currentVersion, prompt) {
16868
17284
  import { homedir as homedir2 } from "os";
16869
17285
  import { join as join6 } from "path";
16870
17286
  import { readFile as readFile6, writeFile as writeFile5, mkdir as mkdir5 } from "fs/promises";
16871
- import { existsSync as existsSync6 } from "fs";
17287
+ import { existsSync as existsSync7 } from "fs";
16872
17288
  var CONFIG_DIR3 = join6(homedir2(), ".vm0");
16873
17289
  var COOK_STATE_FILE = join6(CONFIG_DIR3, "cook.json");
16874
17290
  var STALE_THRESHOLD_MS = 48 * 60 * 60 * 1e3;
16875
17291
  async function loadCookStateFile() {
16876
- if (!existsSync6(COOK_STATE_FILE)) {
17292
+ if (!existsSync7(COOK_STATE_FILE)) {
16877
17293
  return { ppid: {} };
16878
17294
  }
16879
17295
  try {
@@ -16933,7 +17349,7 @@ async function saveCookState(state) {
16933
17349
  var CONFIG_FILE3 = "vm0.yaml";
16934
17350
  var ARTIFACT_DIR = "artifact";
16935
17351
  function printCommand(cmd) {
16936
- console.log(chalk16.dim(`> ${cmd}`));
17352
+ console.log(chalk21.dim(`> ${cmd}`));
16937
17353
  }
16938
17354
  function execVm0Command(args, options = {}) {
16939
17355
  return new Promise((resolve2, reject) => {
@@ -17034,7 +17450,7 @@ function extractRequiredVarNames(config2) {
17034
17450
  }
17035
17451
  function checkMissingVariables(varNames, envFilePath) {
17036
17452
  let dotenvValues = {};
17037
- if (existsSync7(envFilePath)) {
17453
+ if (existsSync8(envFilePath)) {
17038
17454
  const result = dotenvConfig2({ path: envFilePath, quiet: true });
17039
17455
  if (result.parsed) {
17040
17456
  dotenvValues = result.parsed;
@@ -17052,7 +17468,7 @@ function checkMissingVariables(varNames, envFilePath) {
17052
17468
  }
17053
17469
  async function generateEnvPlaceholders(missingVars, envFilePath) {
17054
17470
  const placeholders = missingVars.map((name) => `${name}=`).join("\n");
17055
- if (existsSync7(envFilePath)) {
17471
+ if (existsSync8(envFilePath)) {
17056
17472
  const existingContent = readFileSync(envFilePath, "utf8");
17057
17473
  const needsNewline = existingContent.length > 0 && !existingContent.endsWith("\n");
17058
17474
  const prefix = needsNewline ? "\n" : "";
@@ -17068,9 +17484,9 @@ async function autoPullArtifact(runOutput, artifactDir) {
17068
17484
  runOutput,
17069
17485
  ARTIFACT_DIR
17070
17486
  );
17071
- if (serverVersion && existsSync7(artifactDir)) {
17487
+ if (serverVersion && existsSync8(artifactDir)) {
17072
17488
  console.log();
17073
- console.log(chalk16.bold("Pulling updated artifact:"));
17489
+ console.log(chalk21.bold("Pulling updated artifact:"));
17074
17490
  printCommand(`cd ${ARTIFACT_DIR}`);
17075
17491
  printCommand(`vm0 artifact pull ${serverVersion}`);
17076
17492
  try {
@@ -17080,23 +17496,23 @@ async function autoPullArtifact(runOutput, artifactDir) {
17080
17496
  });
17081
17497
  printCommand("cd ..");
17082
17498
  } catch (error43) {
17083
- console.error(chalk16.red(`\u2717 Artifact pull failed`));
17499
+ console.error(chalk21.red(`\u2717 Artifact pull failed`));
17084
17500
  if (error43 instanceof Error) {
17085
- console.error(chalk16.dim(` ${error43.message}`));
17501
+ console.error(chalk21.dim(` ${error43.message}`));
17086
17502
  }
17087
17503
  }
17088
17504
  }
17089
17505
  }
17090
- var cookCmd = new Command13().name("cook").description("One-click agent preparation and execution from vm0.yaml");
17506
+ var cookCmd = new Command17().name("cook").description("One-click agent preparation and execution from vm0.yaml");
17091
17507
  cookCmd.argument("[prompt]", "Prompt for the agent").action(async (prompt) => {
17092
- const shouldExit = await checkAndUpgrade("4.31.1", prompt);
17508
+ const shouldExit = await checkAndUpgrade("4.32.0", prompt);
17093
17509
  if (shouldExit) {
17094
17510
  process.exit(0);
17095
17511
  }
17096
17512
  const cwd = process.cwd();
17097
- console.log(chalk16.bold(`Reading config: ${CONFIG_FILE3}`));
17098
- if (!existsSync7(CONFIG_FILE3)) {
17099
- console.error(chalk16.red(`\u2717 Config file not found: ${CONFIG_FILE3}`));
17513
+ console.log(chalk21.bold(`Reading config: ${CONFIG_FILE3}`));
17514
+ if (!existsSync8(CONFIG_FILE3)) {
17515
+ console.error(chalk21.red(`\u2717 Config file not found: ${CONFIG_FILE3}`));
17100
17516
  process.exit(1);
17101
17517
  }
17102
17518
  let config2;
@@ -17104,49 +17520,49 @@ cookCmd.argument("[prompt]", "Prompt for the agent").action(async (prompt) => {
17104
17520
  const content = await readFile7(CONFIG_FILE3, "utf8");
17105
17521
  config2 = parseYaml4(content);
17106
17522
  } catch (error43) {
17107
- console.error(chalk16.red("\u2717 Invalid YAML format"));
17523
+ console.error(chalk21.red("\u2717 Invalid YAML format"));
17108
17524
  if (error43 instanceof Error) {
17109
- console.error(chalk16.dim(` ${error43.message}`));
17525
+ console.error(chalk21.dim(` ${error43.message}`));
17110
17526
  }
17111
17527
  process.exit(1);
17112
17528
  }
17113
17529
  const validation = validateAgentCompose(config2);
17114
17530
  if (!validation.valid) {
17115
- console.error(chalk16.red(`\u2717 ${validation.error}`));
17531
+ console.error(chalk21.red(`\u2717 ${validation.error}`));
17116
17532
  process.exit(1);
17117
17533
  }
17118
17534
  const agentNames = Object.keys(config2.agents);
17119
17535
  const agentName = agentNames[0];
17120
17536
  const volumeCount = config2.volumes ? Object.keys(config2.volumes).length : 0;
17121
17537
  console.log(
17122
- chalk16.green(`\u2713 Config validated: 1 agent, ${volumeCount} volume(s)`)
17538
+ chalk21.green(`\u2713 Config validated: 1 agent, ${volumeCount} volume(s)`)
17123
17539
  );
17124
17540
  const requiredVarNames = extractRequiredVarNames(config2);
17125
17541
  if (requiredVarNames.length > 0) {
17126
- const envFilePath = path11.join(cwd, ".env");
17542
+ const envFilePath = path12.join(cwd, ".env");
17127
17543
  const missingVars = checkMissingVariables(requiredVarNames, envFilePath);
17128
17544
  if (missingVars.length > 0) {
17129
17545
  await generateEnvPlaceholders(missingVars, envFilePath);
17130
17546
  console.log();
17131
17547
  console.log(
17132
- chalk16.yellow(
17548
+ chalk21.yellow(
17133
17549
  `\u26A0 Missing environment variables. Please fill in values in .env file:`
17134
17550
  )
17135
17551
  );
17136
17552
  for (const varName of missingVars) {
17137
- console.log(chalk16.yellow(` ${varName}`));
17553
+ console.log(chalk21.yellow(` ${varName}`));
17138
17554
  }
17139
17555
  process.exit(1);
17140
17556
  }
17141
17557
  }
17142
17558
  if (config2.volumes && Object.keys(config2.volumes).length > 0) {
17143
17559
  console.log();
17144
- console.log(chalk16.bold("Processing volumes:"));
17560
+ console.log(chalk21.bold("Processing volumes:"));
17145
17561
  for (const volumeConfig of Object.values(config2.volumes)) {
17146
- const volumeDir = path11.join(cwd, volumeConfig.name);
17147
- if (!existsSync7(volumeDir)) {
17562
+ const volumeDir = path12.join(cwd, volumeConfig.name);
17563
+ if (!existsSync8(volumeDir)) {
17148
17564
  console.error(
17149
- chalk16.red(
17565
+ chalk21.red(
17150
17566
  `\u2717 Directory not found: ${volumeConfig.name}. Create the directory and add files first.`
17151
17567
  )
17152
17568
  );
@@ -17156,11 +17572,14 @@ cookCmd.argument("[prompt]", "Prompt for the agent").action(async (prompt) => {
17156
17572
  printCommand(`cd ${volumeConfig.name}`);
17157
17573
  const existingConfig = await readStorageConfig(volumeDir);
17158
17574
  if (!existingConfig) {
17159
- printCommand("vm0 volume init");
17160
- await execVm0Command(["volume", "init"], {
17161
- cwd: volumeDir,
17162
- silent: true
17163
- });
17575
+ printCommand(`vm0 volume init --name ${volumeConfig.name}`);
17576
+ await execVm0Command(
17577
+ ["volume", "init", "--name", volumeConfig.name],
17578
+ {
17579
+ cwd: volumeDir,
17580
+ silent: true
17581
+ }
17582
+ );
17164
17583
  }
17165
17584
  printCommand("vm0 volume push");
17166
17585
  await execVm0Command(["volume", "push"], {
@@ -17169,27 +17588,27 @@ cookCmd.argument("[prompt]", "Prompt for the agent").action(async (prompt) => {
17169
17588
  });
17170
17589
  printCommand("cd ..");
17171
17590
  } catch (error43) {
17172
- console.error(chalk16.red(`\u2717 Failed`));
17591
+ console.error(chalk21.red(`\u2717 Failed`));
17173
17592
  if (error43 instanceof Error) {
17174
- console.error(chalk16.dim(` ${error43.message}`));
17593
+ console.error(chalk21.dim(` ${error43.message}`));
17175
17594
  }
17176
17595
  process.exit(1);
17177
17596
  }
17178
17597
  }
17179
17598
  }
17180
17599
  console.log();
17181
- console.log(chalk16.bold("Processing artifact:"));
17182
- const artifactDir = path11.join(cwd, ARTIFACT_DIR);
17600
+ console.log(chalk21.bold("Processing artifact:"));
17601
+ const artifactDir = path12.join(cwd, ARTIFACT_DIR);
17183
17602
  try {
17184
- if (!existsSync7(artifactDir)) {
17603
+ if (!existsSync8(artifactDir)) {
17185
17604
  printCommand(`mkdir ${ARTIFACT_DIR}`);
17186
17605
  await mkdir6(artifactDir, { recursive: true });
17187
17606
  }
17188
17607
  printCommand(`cd ${ARTIFACT_DIR}`);
17189
17608
  const existingConfig = await readStorageConfig(artifactDir);
17190
17609
  if (!existingConfig) {
17191
- printCommand("vm0 artifact init");
17192
- await execVm0Command(["artifact", "init"], {
17610
+ printCommand(`vm0 artifact init --name ${ARTIFACT_DIR}`);
17611
+ await execVm0Command(["artifact", "init", "--name", ARTIFACT_DIR], {
17193
17612
  cwd: artifactDir,
17194
17613
  silent: true
17195
17614
  });
@@ -17201,29 +17620,29 @@ cookCmd.argument("[prompt]", "Prompt for the agent").action(async (prompt) => {
17201
17620
  });
17202
17621
  printCommand("cd ..");
17203
17622
  } catch (error43) {
17204
- console.error(chalk16.red(`\u2717 Failed`));
17623
+ console.error(chalk21.red(`\u2717 Failed`));
17205
17624
  if (error43 instanceof Error) {
17206
- console.error(chalk16.dim(` ${error43.message}`));
17625
+ console.error(chalk21.dim(` ${error43.message}`));
17207
17626
  }
17208
17627
  process.exit(1);
17209
17628
  }
17210
17629
  console.log();
17211
- console.log(chalk16.bold("Composing agent:"));
17630
+ console.log(chalk21.bold("Composing agent:"));
17212
17631
  printCommand(`vm0 compose ${CONFIG_FILE3}`);
17213
17632
  try {
17214
17633
  await execVm0Command(["compose", CONFIG_FILE3], {
17215
17634
  cwd
17216
17635
  });
17217
17636
  } catch (error43) {
17218
- console.error(chalk16.red(`\u2717 Compose failed`));
17637
+ console.error(chalk21.red(`\u2717 Compose failed`));
17219
17638
  if (error43 instanceof Error) {
17220
- console.error(chalk16.dim(` ${error43.message}`));
17639
+ console.error(chalk21.dim(` ${error43.message}`));
17221
17640
  }
17222
17641
  process.exit(1);
17223
17642
  }
17224
17643
  if (prompt) {
17225
17644
  console.log();
17226
- console.log(chalk16.bold("Running agent:"));
17645
+ console.log(chalk21.bold("Running agent:"));
17227
17646
  printCommand(
17228
17647
  `vm0 run ${agentName} --artifact-name ${ARTIFACT_DIR} "${prompt}"`
17229
17648
  );
@@ -17265,8 +17684,8 @@ cookCmd.command("logs").description("View logs from the last cook run").option("
17265
17684
  async (options) => {
17266
17685
  const state = await loadCookState();
17267
17686
  if (!state.lastRunId) {
17268
- console.error(chalk16.red("\u2717 No previous run found"));
17269
- console.error(chalk16.dim(" Run 'vm0 cook <prompt>' first"));
17687
+ console.error(chalk21.red("\u2717 No previous run found"));
17688
+ console.error(chalk21.dim(" Run 'vm0 cook <prompt>' first"));
17270
17689
  process.exit(1);
17271
17690
  }
17272
17691
  const args = ["logs", state.lastRunId];
@@ -17308,12 +17727,12 @@ cookCmd.command("continue").description(
17308
17727
  ).argument("<prompt>", "Prompt for the continued agent").action(async (prompt) => {
17309
17728
  const state = await loadCookState();
17310
17729
  if (!state.lastSessionId) {
17311
- console.error(chalk16.red("\u2717 No previous session found"));
17312
- console.error(chalk16.dim(" Run 'vm0 cook <prompt>' first"));
17730
+ console.error(chalk21.red("\u2717 No previous session found"));
17731
+ console.error(chalk21.dim(" Run 'vm0 cook <prompt>' first"));
17313
17732
  process.exit(1);
17314
17733
  }
17315
17734
  const cwd = process.cwd();
17316
- const artifactDir = path11.join(cwd, ARTIFACT_DIR);
17735
+ const artifactDir = path12.join(cwd, ARTIFACT_DIR);
17317
17736
  printCommand(`vm0 run continue ${state.lastSessionId} "${prompt}"`);
17318
17737
  console.log();
17319
17738
  let runOutput;
@@ -17340,12 +17759,12 @@ cookCmd.command("resume").description(
17340
17759
  ).argument("<prompt>", "Prompt for the resumed agent").action(async (prompt) => {
17341
17760
  const state = await loadCookState();
17342
17761
  if (!state.lastCheckpointId) {
17343
- console.error(chalk16.red("\u2717 No previous checkpoint found"));
17344
- console.error(chalk16.dim(" Run 'vm0 cook <prompt>' first"));
17762
+ console.error(chalk21.red("\u2717 No previous checkpoint found"));
17763
+ console.error(chalk21.dim(" Run 'vm0 cook <prompt>' first"));
17345
17764
  process.exit(1);
17346
17765
  }
17347
17766
  const cwd = process.cwd();
17348
- const artifactDir = path11.join(cwd, ARTIFACT_DIR);
17767
+ const artifactDir = path12.join(cwd, ARTIFACT_DIR);
17349
17768
  printCommand(`vm0 run resume ${state.lastCheckpointId} "${prompt}"`);
17350
17769
  console.log();
17351
17770
  let runOutput;
@@ -17370,13 +17789,13 @@ cookCmd.command("resume").description(
17370
17789
  var cookCommand = cookCmd;
17371
17790
 
17372
17791
  // src/commands/image/index.ts
17373
- import { Command as Command18 } from "commander";
17792
+ import { Command as Command22 } from "commander";
17374
17793
 
17375
17794
  // src/commands/image/build.ts
17376
- import { Command as Command14 } from "commander";
17377
- import chalk17 from "chalk";
17795
+ import { Command as Command18 } from "commander";
17796
+ import chalk22 from "chalk";
17378
17797
  import { readFile as readFile8 } from "fs/promises";
17379
- import { existsSync as existsSync8 } from "fs";
17798
+ import { existsSync as existsSync9 } from "fs";
17380
17799
 
17381
17800
  // src/lib/dockerfile-validator.ts
17382
17801
  var ALLOWED_INSTRUCTIONS = /* @__PURE__ */ new Set(["FROM", "RUN"]);
@@ -17410,17 +17829,17 @@ function validateDockerfile(content) {
17410
17829
 
17411
17830
  // src/commands/image/build.ts
17412
17831
  var sleep2 = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
17413
- var buildCommand = new Command14().name("build").description("Build a custom image from a Dockerfile").requiredOption("-f, --file <path>", "Path to Dockerfile").requiredOption("-n, --name <name>", "Name for the image").option("--delete-existing", "Delete existing image before building").action(
17832
+ var buildCommand = new Command18().name("build").description("Build a custom image from a Dockerfile").requiredOption("-f, --file <path>", "Path to Dockerfile").requiredOption("-n, --name <name>", "Name for the image").option("--delete-existing", "Delete existing image before building").action(
17414
17833
  async (options) => {
17415
17834
  const { file: file2, name, deleteExisting } = options;
17416
- if (!existsSync8(file2)) {
17417
- console.error(chalk17.red(`\u2717 Dockerfile not found: ${file2}`));
17835
+ if (!existsSync9(file2)) {
17836
+ console.error(chalk22.red(`\u2717 Dockerfile not found: ${file2}`));
17418
17837
  process.exit(1);
17419
17838
  }
17420
17839
  const nameRegex = /^[a-zA-Z0-9][a-zA-Z0-9-]{1,62}[a-zA-Z0-9]$/;
17421
17840
  if (!nameRegex.test(name)) {
17422
17841
  console.error(
17423
- chalk17.red(
17842
+ chalk22.red(
17424
17843
  "\u2717 Invalid name format. Must be 3-64 characters, letters, numbers, and hyphens only."
17425
17844
  )
17426
17845
  );
@@ -17428,7 +17847,7 @@ var buildCommand = new Command14().name("build").description("Build a custom ima
17428
17847
  }
17429
17848
  if (name.startsWith("vm0-")) {
17430
17849
  console.error(
17431
- chalk17.red(
17850
+ chalk22.red(
17432
17851
  '\u2717 Invalid name. Cannot start with "vm0-" (reserved prefix).'
17433
17852
  )
17434
17853
  );
@@ -17439,24 +17858,24 @@ var buildCommand = new Command14().name("build").description("Build a custom ima
17439
17858
  const dockerfile = await readFile8(file2, "utf8");
17440
17859
  const validation = validateDockerfile(dockerfile);
17441
17860
  if (!validation.valid) {
17442
- console.error(chalk17.red("\u2717 Dockerfile validation failed\n"));
17861
+ console.error(chalk22.red("\u2717 Dockerfile validation failed\n"));
17443
17862
  for (const error43 of validation.errors) {
17444
- console.error(chalk17.red(` ${error43}`));
17863
+ console.error(chalk22.red(` ${error43}`));
17445
17864
  }
17446
17865
  console.error();
17447
17866
  console.error(
17448
- chalk17.yellow(
17867
+ chalk22.yellow(
17449
17868
  " vm0 image build only supports FROM and RUN instructions."
17450
17869
  )
17451
17870
  );
17452
17871
  console.error(
17453
- chalk17.yellow(
17872
+ chalk22.yellow(
17454
17873
  " The purpose is to pre-install environment dependencies."
17455
17874
  )
17456
17875
  );
17457
17876
  process.exit(1);
17458
17877
  }
17459
- console.log(chalk17.bold(`Building image: ${scope.slug}/${name}`));
17878
+ console.log(chalk22.bold(`Building image: ${scope.slug}/${name}`));
17460
17879
  console.log();
17461
17880
  const buildInfo = await apiClient.createImage({
17462
17881
  dockerfile,
@@ -17464,7 +17883,7 @@ var buildCommand = new Command14().name("build").description("Build a custom ima
17464
17883
  deleteExisting
17465
17884
  });
17466
17885
  const { imageId, buildId, versionId } = buildInfo;
17467
- console.log(chalk17.dim(` Build ID: ${buildId}`));
17886
+ console.log(chalk22.dim(` Build ID: ${buildId}`));
17468
17887
  console.log();
17469
17888
  let logsOffset = 0;
17470
17889
  let status = "building";
@@ -17480,7 +17899,7 @@ var buildCommand = new Command14().name("build").description("Build a custom ima
17480
17899
  }
17481
17900
  const statusData = await statusResponse.json();
17482
17901
  for (const log of statusData.logs) {
17483
- console.log(chalk17.dim(` ${log}`));
17902
+ console.log(chalk22.dim(` ${log}`));
17484
17903
  }
17485
17904
  logsOffset = statusData.logsOffset;
17486
17905
  status = statusData.status;
@@ -17492,23 +17911,23 @@ var buildCommand = new Command14().name("build").description("Build a custom ima
17492
17911
  if (status === "ready") {
17493
17912
  const shortVersion = formatVersionIdForDisplay(versionId);
17494
17913
  console.log(
17495
- chalk17.green(`\u2713 Image built: ${scope.slug}/${name}:${shortVersion}`)
17914
+ chalk22.green(`\u2713 Image built: ${scope.slug}/${name}:${shortVersion}`)
17496
17915
  );
17497
17916
  } else {
17498
- console.error(chalk17.red(`\u2717 Build failed`));
17917
+ console.error(chalk22.red(`\u2717 Build failed`));
17499
17918
  process.exit(1);
17500
17919
  }
17501
17920
  } catch (error43) {
17502
17921
  if (error43 instanceof Error) {
17503
17922
  if (error43.message.includes("Not authenticated")) {
17504
17923
  console.error(
17505
- chalk17.red("\u2717 Not authenticated. Run: vm0 auth login")
17924
+ chalk22.red("\u2717 Not authenticated. Run: vm0 auth login")
17506
17925
  );
17507
17926
  } else {
17508
- console.error(chalk17.red(`\u2717 ${error43.message}`));
17927
+ console.error(chalk22.red(`\u2717 ${error43.message}`));
17509
17928
  }
17510
17929
  } else {
17511
- console.error(chalk17.red("\u2717 An unexpected error occurred"));
17930
+ console.error(chalk22.red("\u2717 An unexpected error occurred"));
17512
17931
  }
17513
17932
  process.exit(1);
17514
17933
  }
@@ -17516,9 +17935,9 @@ var buildCommand = new Command14().name("build").description("Build a custom ima
17516
17935
  );
17517
17936
 
17518
17937
  // src/commands/image/list.ts
17519
- import { Command as Command15 } from "commander";
17520
- import chalk18 from "chalk";
17521
- var listCommand = new Command15().name("list").alias("ls").description("List your custom images").action(async () => {
17938
+ import { Command as Command19 } from "commander";
17939
+ import chalk23 from "chalk";
17940
+ var listCommand3 = new Command19().name("list").alias("ls").description("List your custom images").action(async () => {
17522
17941
  try {
17523
17942
  const response = await apiClient.get("/api/images");
17524
17943
  if (!response.ok) {
@@ -17530,15 +17949,15 @@ var listCommand = new Command15().name("list").alias("ls").description("List you
17530
17949
  const data = await response.json();
17531
17950
  const { images } = data;
17532
17951
  if (images.length === 0) {
17533
- console.log(chalk18.dim("No images found."));
17952
+ console.log(chalk23.dim("No images found."));
17534
17953
  console.log();
17535
17954
  console.log("Build your first image:");
17536
17955
  console.log(
17537
- chalk18.cyan(" vm0 image build --file Dockerfile --name my-image")
17956
+ chalk23.cyan(" vm0 image build --file Dockerfile --name my-image")
17538
17957
  );
17539
17958
  return;
17540
17959
  }
17541
- console.log(chalk18.bold("Your images:"));
17960
+ console.log(chalk23.bold("Your images:"));
17542
17961
  console.log();
17543
17962
  const imagesByAlias = /* @__PURE__ */ new Map();
17544
17963
  for (const image of images) {
@@ -17552,50 +17971,49 @@ var listCommand = new Command15().name("list").alias("ls").description("List you
17552
17971
  latestVersions.set(alias, latestReady?.versionId || null);
17553
17972
  }
17554
17973
  console.log(
17555
- chalk18.dim(
17974
+ chalk23.dim(
17556
17975
  `${"NAME".padEnd(40)} ${"STATUS".padEnd(12)} ${"CREATED".padEnd(20)}`
17557
17976
  )
17558
17977
  );
17559
- console.log(chalk18.dim("-".repeat(72)));
17978
+ console.log(chalk23.dim("-".repeat(72)));
17560
17979
  for (const image of images) {
17561
- const statusColor = image.status === "ready" ? chalk18.green : image.status === "building" ? chalk18.yellow : chalk18.red;
17980
+ const statusColor = image.status === "ready" ? chalk23.green : image.status === "building" ? chalk23.yellow : chalk23.red;
17562
17981
  const createdAt = new Date(image.createdAt).toLocaleString();
17563
17982
  let displayName = image.alias;
17564
17983
  if (image.versionId) {
17565
17984
  const shortVersion = formatVersionIdForDisplay(image.versionId);
17566
17985
  displayName = `${image.alias}:${shortVersion}`;
17567
17986
  if (image.status === "ready" && latestVersions.get(image.alias) === image.versionId) {
17568
- displayName = `${displayName} ${chalk18.cyan("latest")}`;
17987
+ displayName = `${displayName} ${chalk23.cyan("latest")}`;
17569
17988
  }
17570
17989
  }
17571
17990
  console.log(
17572
17991
  `${displayName.padEnd(40)} ${statusColor(image.status.padEnd(12))} ${createdAt.padEnd(20)}`
17573
17992
  );
17574
17993
  if (image.status === "error" && image.errorMessage) {
17575
- console.log(chalk18.red(` Error: ${image.errorMessage}`));
17994
+ console.log(chalk23.red(` Error: ${image.errorMessage}`));
17576
17995
  }
17577
17996
  }
17578
17997
  console.log();
17579
- console.log(chalk18.dim(`Total: ${images.length} version(s)`));
17998
+ console.log(chalk23.dim(`Total: ${images.length} version(s)`));
17580
17999
  } catch (error43) {
17581
18000
  if (error43 instanceof Error) {
17582
18001
  if (error43.message.includes("Not authenticated")) {
17583
- console.error(chalk18.red("Not authenticated. Run: vm0 auth login"));
18002
+ console.error(chalk23.red("Not authenticated. Run: vm0 auth login"));
17584
18003
  } else {
17585
- console.error(chalk18.red(`Error: ${error43.message}`));
18004
+ console.error(chalk23.red(`Error: ${error43.message}`));
17586
18005
  }
17587
18006
  } else {
17588
- console.error(chalk18.red("An unexpected error occurred"));
18007
+ console.error(chalk23.red("An unexpected error occurred"));
17589
18008
  }
17590
18009
  process.exit(1);
17591
18010
  }
17592
18011
  });
17593
18012
 
17594
18013
  // src/commands/image/delete.ts
17595
- import { Command as Command16 } from "commander";
17596
- import chalk19 from "chalk";
17597
- import * as readline from "readline";
17598
- var deleteCommand = new Command16().name("delete").alias("rm").description("Delete a custom image or specific version").argument("<name>", "Image name or name:version to delete").option("-f, --force", "Skip confirmation prompt").option("--all", "Delete all versions of the image").action(
18014
+ import { Command as Command20 } from "commander";
18015
+ import chalk24 from "chalk";
18016
+ var deleteCommand = new Command20().name("delete").alias("rm").description("Delete a custom image or specific version").argument("<name>", "Image name or name:version to delete").option("-f, --force", "Skip confirmation prompt").option("--all", "Delete all versions of the image").action(
17599
18017
  async (nameArg, options) => {
17600
18018
  try {
17601
18019
  const colonIndex = nameArg.lastIndexOf(":");
@@ -17616,12 +18034,12 @@ var deleteCommand = new Command16().name("delete").alias("rm").description("Dele
17616
18034
  (img) => img.alias === name && img.versionId && img.versionId.startsWith(versionId.toLowerCase())
17617
18035
  );
17618
18036
  if (matchingVersions.length === 0) {
17619
- console.error(chalk19.red(`Image version not found: ${nameArg}`));
18037
+ console.error(chalk24.red(`Image version not found: ${nameArg}`));
17620
18038
  process.exit(1);
17621
18039
  }
17622
18040
  if (matchingVersions.length > 1) {
17623
18041
  console.error(
17624
- chalk19.red(
18042
+ chalk24.red(
17625
18043
  `Ambiguous version prefix "${versionId}". Please use more characters.`
17626
18044
  )
17627
18045
  );
@@ -17631,7 +18049,7 @@ var deleteCommand = new Command16().name("delete").alias("rm").description("Dele
17631
18049
  } else if (options.all) {
17632
18050
  imagesToDelete = data.images.filter((img) => img.alias === name);
17633
18051
  if (imagesToDelete.length === 0) {
17634
- console.error(chalk19.red(`Image not found: ${name}`));
18052
+ console.error(chalk24.red(`Image not found: ${name}`));
17635
18053
  process.exit(1);
17636
18054
  }
17637
18055
  } else {
@@ -17639,7 +18057,7 @@ var deleteCommand = new Command16().name("delete").alias("rm").description("Dele
17639
18057
  (img) => img.alias === name
17640
18058
  );
17641
18059
  if (matchingImages.length === 0) {
17642
- console.error(chalk19.red(`Image not found: ${name}`));
18060
+ console.error(chalk24.red(`Image not found: ${name}`));
17643
18061
  process.exit(1);
17644
18062
  }
17645
18063
  const latestReady = matchingImages.find(
@@ -17655,18 +18073,9 @@ var deleteCommand = new Command16().name("delete").alias("rm").description("Dele
17655
18073
  const firstVersionDisplay = firstImage.versionId ? `:${formatVersionIdForDisplay(firstImage.versionId)}` : "";
17656
18074
  const confirmMsg = imagesToDelete.length === 1 ? `Delete image "${firstImage.alias}${firstVersionDisplay}"?` : `Delete ${imagesToDelete.length} versions of "${name}"?`;
17657
18075
  if (!options.force) {
17658
- const rl = readline.createInterface({
17659
- input: process.stdin,
17660
- output: process.stdout
17661
- });
17662
- const answer = await new Promise((resolve2) => {
17663
- rl.question(chalk19.yellow(`${confirmMsg} [y/N] `), (answer2) => {
17664
- rl.close();
17665
- resolve2(answer2);
17666
- });
17667
- });
17668
- if (answer.toLowerCase() !== "y" && answer.toLowerCase() !== "yes") {
17669
- console.log(chalk19.dim("Cancelled."));
18076
+ const confirmed = await promptConfirm(confirmMsg, false);
18077
+ if (!confirmed) {
18078
+ console.log(chalk24.dim("Cancelled."));
17670
18079
  return;
17671
18080
  }
17672
18081
  }
@@ -17681,17 +18090,17 @@ var deleteCommand = new Command16().name("delete").alias("rm").description("Dele
17681
18090
  );
17682
18091
  }
17683
18092
  const displayName = image.versionId ? `${image.alias}:${formatVersionIdForDisplay(image.versionId)}` : image.alias;
17684
- console.log(chalk19.green(`Deleted image: ${displayName}`));
18093
+ console.log(chalk24.green(`Deleted image: ${displayName}`));
17685
18094
  }
17686
18095
  } catch (error43) {
17687
18096
  if (error43 instanceof Error) {
17688
18097
  if (error43.message.includes("Not authenticated")) {
17689
- console.error(chalk19.red("Not authenticated. Run: vm0 auth login"));
18098
+ console.error(chalk24.red("Not authenticated. Run: vm0 auth login"));
17690
18099
  } else {
17691
- console.error(chalk19.red(`Error: ${error43.message}`));
18100
+ console.error(chalk24.red(`Error: ${error43.message}`));
17692
18101
  }
17693
18102
  } else {
17694
- console.error(chalk19.red("An unexpected error occurred"));
18103
+ console.error(chalk24.red("An unexpected error occurred"));
17695
18104
  }
17696
18105
  process.exit(1);
17697
18106
  }
@@ -17699,9 +18108,9 @@ var deleteCommand = new Command16().name("delete").alias("rm").description("Dele
17699
18108
  );
17700
18109
 
17701
18110
  // src/commands/image/versions.ts
17702
- import { Command as Command17 } from "commander";
17703
- import chalk20 from "chalk";
17704
- var versionsCommand = new Command17().name("versions").description("List all versions of an image").argument("<name>", "Name of the image").action(async (name) => {
18111
+ import { Command as Command21 } from "commander";
18112
+ import chalk25 from "chalk";
18113
+ var versionsCommand = new Command21().name("versions").description("List all versions of an image").argument("<name>", "Name of the image").action(async (name) => {
17705
18114
  try {
17706
18115
  const response = await apiClient.get("/api/images");
17707
18116
  if (!response.ok) {
@@ -17713,42 +18122,42 @@ var versionsCommand = new Command17().name("versions").description("List all ver
17713
18122
  const data = await response.json();
17714
18123
  const versions = data.images.filter((img) => img.alias === name);
17715
18124
  if (versions.length === 0) {
17716
- console.error(chalk20.red(`Image not found: ${name}`));
18125
+ console.error(chalk25.red(`Image not found: ${name}`));
17717
18126
  process.exit(1);
17718
18127
  }
17719
18128
  const latestReady = versions.find((v) => v.status === "ready");
17720
18129
  const latestVersionId = latestReady?.versionId || null;
17721
- console.log(chalk20.bold(`Versions of ${name}:`));
18130
+ console.log(chalk25.bold(`Versions of ${name}:`));
17722
18131
  console.log();
17723
18132
  console.log(
17724
- chalk20.dim(
18133
+ chalk25.dim(
17725
18134
  `${"VERSION".padEnd(20)} ${"STATUS".padEnd(12)} ${"CREATED".padEnd(24)}`
17726
18135
  )
17727
18136
  );
17728
- console.log(chalk20.dim("-".repeat(56)));
18137
+ console.log(chalk25.dim("-".repeat(56)));
17729
18138
  for (const version2 of versions) {
17730
- const statusColor = version2.status === "ready" ? chalk20.green : version2.status === "building" ? chalk20.yellow : chalk20.red;
18139
+ const statusColor = version2.status === "ready" ? chalk25.green : version2.status === "building" ? chalk25.yellow : chalk25.red;
17731
18140
  const createdAt = new Date(version2.createdAt).toLocaleString();
17732
18141
  let versionDisplay = version2.versionId ? formatVersionIdForDisplay(version2.versionId) : "(legacy)";
17733
18142
  if (version2.status === "ready" && version2.versionId === latestVersionId) {
17734
- versionDisplay = `${versionDisplay} ${chalk20.cyan("latest")}`;
18143
+ versionDisplay = `${versionDisplay} ${chalk25.cyan("latest")}`;
17735
18144
  }
17736
18145
  console.log(
17737
18146
  `${versionDisplay.padEnd(20)} ${statusColor(version2.status.padEnd(12))} ${createdAt.padEnd(24)}`
17738
18147
  );
17739
18148
  if (version2.status === "error" && version2.errorMessage) {
17740
- console.log(chalk20.red(` Error: ${version2.errorMessage}`));
18149
+ console.log(chalk25.red(` Error: ${version2.errorMessage}`));
17741
18150
  }
17742
18151
  }
17743
18152
  console.log();
17744
- console.log(chalk20.dim(`Total: ${versions.length} version(s)`));
18153
+ console.log(chalk25.dim(`Total: ${versions.length} version(s)`));
17745
18154
  console.log();
17746
- console.log(chalk20.dim("Usage:"));
17747
- console.log(chalk20.dim(` image: "${name}" # uses latest`));
18155
+ console.log(chalk25.dim("Usage:"));
18156
+ console.log(chalk25.dim(` image: "${name}" # uses latest`));
17748
18157
  if (latestVersionId) {
17749
18158
  const shortVersion = formatVersionIdForDisplay(latestVersionId);
17750
18159
  console.log(
17751
- chalk20.dim(
18160
+ chalk25.dim(
17752
18161
  ` image: "${name}:${shortVersion}" # pin to specific version`
17753
18162
  )
17754
18163
  );
@@ -17756,23 +18165,23 @@ var versionsCommand = new Command17().name("versions").description("List all ver
17756
18165
  } catch (error43) {
17757
18166
  if (error43 instanceof Error) {
17758
18167
  if (error43.message.includes("Not authenticated")) {
17759
- console.error(chalk20.red("Not authenticated. Run: vm0 auth login"));
18168
+ console.error(chalk25.red("Not authenticated. Run: vm0 auth login"));
17760
18169
  } else {
17761
- console.error(chalk20.red(`Error: ${error43.message}`));
18170
+ console.error(chalk25.red(`Error: ${error43.message}`));
17762
18171
  }
17763
18172
  } else {
17764
- console.error(chalk20.red("An unexpected error occurred"));
18173
+ console.error(chalk25.red("An unexpected error occurred"));
17765
18174
  }
17766
18175
  process.exit(1);
17767
18176
  }
17768
18177
  });
17769
18178
 
17770
18179
  // src/commands/image/index.ts
17771
- var imageCommand = new Command18().name("image").description("Manage custom images").addCommand(buildCommand).addCommand(listCommand).addCommand(deleteCommand).addCommand(versionsCommand);
18180
+ var imageCommand = new Command22().name("image").description("Manage custom images").addCommand(buildCommand).addCommand(listCommand3).addCommand(deleteCommand).addCommand(versionsCommand);
17772
18181
 
17773
18182
  // src/commands/logs/index.ts
17774
- import { Command as Command19 } from "commander";
17775
- import chalk21 from "chalk";
18183
+ import { Command as Command23 } from "commander";
18184
+ import chalk26 from "chalk";
17776
18185
 
17777
18186
  // src/lib/time-parser.ts
17778
18187
  function parseTime(timeStr) {
@@ -17819,7 +18228,7 @@ function parseRelativeTime(value, unit) {
17819
18228
  }
17820
18229
 
17821
18230
  // src/commands/logs/index.ts
17822
- function formatBytes7(bytes) {
18231
+ function formatBytes8(bytes) {
17823
18232
  if (bytes === 0) return "0 B";
17824
18233
  const k = 1024;
17825
18234
  const sizes = ["B", "KB", "MB", "GB"];
@@ -17829,28 +18238,28 @@ function formatBytes7(bytes) {
17829
18238
  function formatMetric(metric) {
17830
18239
  const memPercent = (metric.mem_used / metric.mem_total * 100).toFixed(1);
17831
18240
  const diskPercent = (metric.disk_used / metric.disk_total * 100).toFixed(1);
17832
- return `[${metric.ts}] CPU: ${metric.cpu.toFixed(1)}% | Mem: ${formatBytes7(metric.mem_used)}/${formatBytes7(metric.mem_total)} (${memPercent}%) | Disk: ${formatBytes7(metric.disk_used)}/${formatBytes7(metric.disk_total)} (${diskPercent}%)`;
18241
+ return `[${metric.ts}] CPU: ${metric.cpu.toFixed(1)}% | Mem: ${formatBytes8(metric.mem_used)}/${formatBytes8(metric.mem_total)} (${memPercent}%) | Disk: ${formatBytes8(metric.disk_used)}/${formatBytes8(metric.disk_total)} (${diskPercent}%)`;
17833
18242
  }
17834
18243
  function formatNetworkLog(entry) {
17835
18244
  let statusColor;
17836
18245
  if (entry.status >= 200 && entry.status < 300) {
17837
- statusColor = chalk21.green;
18246
+ statusColor = chalk26.green;
17838
18247
  } else if (entry.status >= 300 && entry.status < 400) {
17839
- statusColor = chalk21.yellow;
18248
+ statusColor = chalk26.yellow;
17840
18249
  } else if (entry.status >= 400) {
17841
- statusColor = chalk21.red;
18250
+ statusColor = chalk26.red;
17842
18251
  } else {
17843
- statusColor = chalk21.gray;
18252
+ statusColor = chalk26.gray;
17844
18253
  }
17845
18254
  let latencyColor;
17846
18255
  if (entry.latency_ms < 500) {
17847
- latencyColor = chalk21.green;
18256
+ latencyColor = chalk26.green;
17848
18257
  } else if (entry.latency_ms < 2e3) {
17849
- latencyColor = chalk21.yellow;
18258
+ latencyColor = chalk26.yellow;
17850
18259
  } else {
17851
- latencyColor = chalk21.red;
18260
+ latencyColor = chalk26.red;
17852
18261
  }
17853
- return `[${entry.timestamp}] ${entry.method.padEnd(6)} ${statusColor(entry.status)} ${latencyColor(entry.latency_ms + "ms")} ${formatBytes7(entry.request_size)}/${formatBytes7(entry.response_size)} ${chalk21.dim(entry.url)}`;
18262
+ return `[${entry.timestamp}] ${entry.method.padEnd(6)} ${statusColor(entry.status)} ${latencyColor(entry.latency_ms + "ms")} ${formatBytes8(entry.request_size)}/${formatBytes8(entry.response_size)} ${chalk26.dim(entry.url)}`;
17854
18263
  }
17855
18264
  function renderAgentEvent(event, provider) {
17856
18265
  const eventData = event.eventData;
@@ -17873,7 +18282,7 @@ function getLogType(options) {
17873
18282
  ].filter(Boolean).length;
17874
18283
  if (selected > 1) {
17875
18284
  console.error(
17876
- chalk21.red(
18285
+ chalk26.red(
17877
18286
  "Options --agent, --system, --metrics, and --network are mutually exclusive"
17878
18287
  )
17879
18288
  );
@@ -17884,7 +18293,7 @@ function getLogType(options) {
17884
18293
  if (options.network) return "network";
17885
18294
  return "agent";
17886
18295
  }
17887
- var logsCommand = new Command19().name("logs").description("View logs for an agent run").argument("<runId>", "Run ID to fetch logs for").option("-a, --agent", "Show agent events (default)").option("-s, --system", "Show system log").option("-m, --metrics", "Show metrics").option("-n, --network", "Show network logs (proxy traffic)").option(
18296
+ var logsCommand = new Command23().name("logs").description("View logs for an agent run").argument("<runId>", "Run ID to fetch logs for").option("-a, --agent", "Show agent events (default)").option("-s, --system", "Show system log").option("-m, --metrics", "Show metrics").option("-n, --network", "Show network logs (proxy traffic)").option(
17888
18297
  "--since <time>",
17889
18298
  "Show logs since timestamp (e.g., 5m, 2h, 1d, 2024-01-15T10:30:00Z, 1705312200)"
17890
18299
  ).option("--tail <n>", "Show last N entries (default: 5, max: 100)").option("--head <n>", "Show first N entries (max: 100)").action(
@@ -17893,7 +18302,7 @@ var logsCommand = new Command19().name("logs").description("View logs for an age
17893
18302
  const logType = getLogType(options);
17894
18303
  if (options.tail !== void 0 && options.head !== void 0) {
17895
18304
  console.error(
17896
- chalk21.red("Options --tail and --head are mutually exclusive")
18305
+ chalk26.red("Options --tail and --head are mutually exclusive")
17897
18306
  );
17898
18307
  process.exit(1);
17899
18308
  }
@@ -17930,7 +18339,7 @@ var logsCommand = new Command19().name("logs").description("View logs for an age
17930
18339
  async function showAgentEvents(runId, options) {
17931
18340
  const response = await apiClient.getAgentEvents(runId, options);
17932
18341
  if (response.events.length === 0) {
17933
- console.log(chalk21.yellow("No agent events found for this run."));
18342
+ console.log(chalk26.yellow("No agent events found for this run."));
17934
18343
  return;
17935
18344
  }
17936
18345
  const events = options.order === "desc" ? [...response.events].reverse() : response.events;
@@ -17940,7 +18349,7 @@ async function showAgentEvents(runId, options) {
17940
18349
  if (response.hasMore) {
17941
18350
  console.log();
17942
18351
  console.log(
17943
- chalk21.dim(
18352
+ chalk26.dim(
17944
18353
  `Showing ${response.events.length} events. Use --tail to see more.`
17945
18354
  )
17946
18355
  );
@@ -17949,21 +18358,21 @@ async function showAgentEvents(runId, options) {
17949
18358
  async function showSystemLog(runId, options) {
17950
18359
  const response = await apiClient.getSystemLog(runId, options);
17951
18360
  if (!response.systemLog) {
17952
- console.log(chalk21.yellow("No system log found for this run."));
18361
+ console.log(chalk26.yellow("No system log found for this run."));
17953
18362
  return;
17954
18363
  }
17955
18364
  console.log(response.systemLog);
17956
18365
  if (response.hasMore) {
17957
18366
  console.log();
17958
18367
  console.log(
17959
- chalk21.dim("More log entries available. Use --tail to see more.")
18368
+ chalk26.dim("More log entries available. Use --tail to see more.")
17960
18369
  );
17961
18370
  }
17962
18371
  }
17963
18372
  async function showMetrics(runId, options) {
17964
18373
  const response = await apiClient.getMetrics(runId, options);
17965
18374
  if (response.metrics.length === 0) {
17966
- console.log(chalk21.yellow("No metrics found for this run."));
18375
+ console.log(chalk26.yellow("No metrics found for this run."));
17967
18376
  return;
17968
18377
  }
17969
18378
  const metrics = options.order === "desc" ? [...response.metrics].reverse() : response.metrics;
@@ -17973,7 +18382,7 @@ async function showMetrics(runId, options) {
17973
18382
  if (response.hasMore) {
17974
18383
  console.log();
17975
18384
  console.log(
17976
- chalk21.dim(
18385
+ chalk26.dim(
17977
18386
  `Showing ${response.metrics.length} metrics. Use --tail to see more.`
17978
18387
  )
17979
18388
  );
@@ -17983,7 +18392,7 @@ async function showNetworkLogs(runId, options) {
17983
18392
  const response = await apiClient.getNetworkLogs(runId, options);
17984
18393
  if (response.networkLogs.length === 0) {
17985
18394
  console.log(
17986
- chalk21.yellow(
18395
+ chalk26.yellow(
17987
18396
  "No network logs found for this run. Network logs are only captured when beta_network_security is enabled."
17988
18397
  )
17989
18398
  );
@@ -17996,7 +18405,7 @@ async function showNetworkLogs(runId, options) {
17996
18405
  if (response.hasMore) {
17997
18406
  console.log();
17998
18407
  console.log(
17999
- chalk21.dim(
18408
+ chalk26.dim(
18000
18409
  `Showing ${response.networkLogs.length} network logs. Use --tail to see more.`
18001
18410
  )
18002
18411
  );
@@ -18005,31 +18414,31 @@ async function showNetworkLogs(runId, options) {
18005
18414
  function handleError(error43, runId) {
18006
18415
  if (error43 instanceof Error) {
18007
18416
  if (error43.message.includes("Not authenticated")) {
18008
- console.error(chalk21.red("Not authenticated. Run: vm0 auth login"));
18417
+ console.error(chalk26.red("Not authenticated. Run: vm0 auth login"));
18009
18418
  } else if (error43.message.includes("not found")) {
18010
- console.error(chalk21.red(`Run not found: ${runId}`));
18419
+ console.error(chalk26.red(`Run not found: ${runId}`));
18011
18420
  } else if (error43.message.includes("Invalid time format")) {
18012
- console.error(chalk21.red(error43.message));
18421
+ console.error(chalk26.red(error43.message));
18013
18422
  } else {
18014
- console.error(chalk21.red("Failed to fetch logs"));
18015
- console.error(chalk21.dim(` ${error43.message}`));
18423
+ console.error(chalk26.red("Failed to fetch logs"));
18424
+ console.error(chalk26.dim(` ${error43.message}`));
18016
18425
  }
18017
18426
  } else {
18018
- console.error(chalk21.red("An unexpected error occurred"));
18427
+ console.error(chalk26.red("An unexpected error occurred"));
18019
18428
  }
18020
18429
  }
18021
18430
 
18022
18431
  // src/commands/scope/index.ts
18023
- import { Command as Command22 } from "commander";
18432
+ import { Command as Command26 } from "commander";
18024
18433
 
18025
18434
  // src/commands/scope/status.ts
18026
- import { Command as Command20 } from "commander";
18027
- import chalk22 from "chalk";
18028
- var statusCommand3 = new Command20().name("status").description("View current scope status").action(async () => {
18435
+ import { Command as Command24 } from "commander";
18436
+ import chalk27 from "chalk";
18437
+ var statusCommand3 = new Command24().name("status").description("View current scope status").action(async () => {
18029
18438
  try {
18030
18439
  const scope = await apiClient.getScope();
18031
- console.log(chalk22.bold("Scope Information:"));
18032
- console.log(` Slug: ${chalk22.green(scope.slug)}`);
18440
+ console.log(chalk27.bold("Scope Information:"));
18441
+ console.log(` Slug: ${chalk27.green(scope.slug)}`);
18033
18442
  console.log(` Type: ${scope.type}`);
18034
18443
  if (scope.displayName) {
18035
18444
  console.log(` Display Name: ${scope.displayName}`);
@@ -18040,29 +18449,29 @@ var statusCommand3 = new Command20().name("status").description("View current sc
18040
18449
  } catch (error43) {
18041
18450
  if (error43 instanceof Error) {
18042
18451
  if (error43.message.includes("Not authenticated")) {
18043
- console.error(chalk22.red("\u2717 Not authenticated. Run: vm0 auth login"));
18452
+ console.error(chalk27.red("\u2717 Not authenticated. Run: vm0 auth login"));
18044
18453
  } else if (error43.message.includes("No scope configured")) {
18045
- console.log(chalk22.yellow("No scope configured."));
18454
+ console.log(chalk27.yellow("No scope configured."));
18046
18455
  console.log();
18047
18456
  console.log("Set your scope with:");
18048
- console.log(chalk22.cyan(" vm0 scope set <slug>"));
18457
+ console.log(chalk27.cyan(" vm0 scope set <slug>"));
18049
18458
  console.log();
18050
18459
  console.log("Example:");
18051
- console.log(chalk22.dim(" vm0 scope set myusername"));
18460
+ console.log(chalk27.dim(" vm0 scope set myusername"));
18052
18461
  } else {
18053
- console.error(chalk22.red(`\u2717 ${error43.message}`));
18462
+ console.error(chalk27.red(`\u2717 ${error43.message}`));
18054
18463
  }
18055
18464
  } else {
18056
- console.error(chalk22.red("\u2717 An unexpected error occurred"));
18465
+ console.error(chalk27.red("\u2717 An unexpected error occurred"));
18057
18466
  }
18058
18467
  process.exit(1);
18059
18468
  }
18060
18469
  });
18061
18470
 
18062
18471
  // src/commands/scope/set.ts
18063
- import { Command as Command21 } from "commander";
18064
- import chalk23 from "chalk";
18065
- var setCommand = new Command21().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(
18472
+ import { Command as Command25 } from "commander";
18473
+ import chalk28 from "chalk";
18474
+ var setCommand = new Command25().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(
18066
18475
  async (slug, options) => {
18067
18476
  try {
18068
18477
  let existingScope;
@@ -18074,56 +18483,56 @@ var setCommand = new Command21().name("set").description("Set your scope slug").
18074
18483
  if (existingScope) {
18075
18484
  if (!options.force) {
18076
18485
  console.error(
18077
- chalk23.yellow(`You already have a scope: ${existingScope.slug}`)
18486
+ chalk28.yellow(`You already have a scope: ${existingScope.slug}`)
18078
18487
  );
18079
18488
  console.error();
18080
18489
  console.error("To change your scope, use --force:");
18081
- console.error(chalk23.cyan(` vm0 scope set ${slug} --force`));
18490
+ console.error(chalk28.cyan(` vm0 scope set ${slug} --force`));
18082
18491
  console.error();
18083
18492
  console.error(
18084
- chalk23.yellow(
18493
+ chalk28.yellow(
18085
18494
  "Warning: Changing your scope may break existing image references."
18086
18495
  )
18087
18496
  );
18088
18497
  process.exit(1);
18089
18498
  }
18090
18499
  scope = await apiClient.updateScope({ slug, force: true });
18091
- console.log(chalk23.green(`\u2713 Scope updated to ${scope.slug}`));
18500
+ console.log(chalk28.green(`\u2713 Scope updated to ${scope.slug}`));
18092
18501
  } else {
18093
18502
  scope = await apiClient.createScope({
18094
18503
  slug,
18095
18504
  displayName: options.displayName
18096
18505
  });
18097
- console.log(chalk23.green(`\u2713 Scope created: ${scope.slug}`));
18506
+ console.log(chalk28.green(`\u2713 Scope created: ${scope.slug}`));
18098
18507
  }
18099
18508
  console.log();
18100
18509
  console.log("Your images will now be namespaced as:");
18101
- console.log(chalk23.cyan(` ${scope.slug}/<image-name>`));
18510
+ console.log(chalk28.cyan(` ${scope.slug}/<image-name>`));
18102
18511
  } catch (error43) {
18103
18512
  if (error43 instanceof Error) {
18104
18513
  if (error43.message.includes("Not authenticated")) {
18105
18514
  console.error(
18106
- chalk23.red("\u2717 Not authenticated. Run: vm0 auth login")
18515
+ chalk28.red("\u2717 Not authenticated. Run: vm0 auth login")
18107
18516
  );
18108
18517
  } else if (error43.message.includes("already exists")) {
18109
18518
  console.error(
18110
- chalk23.red(
18519
+ chalk28.red(
18111
18520
  `\u2717 Scope "${slug}" is already taken. Please choose a different slug.`
18112
18521
  )
18113
18522
  );
18114
18523
  } else if (error43.message.includes("reserved")) {
18115
- console.error(chalk23.red(`\u2717 ${error43.message}`));
18524
+ console.error(chalk28.red(`\u2717 ${error43.message}`));
18116
18525
  } else if (error43.message.includes("vm0")) {
18117
18526
  console.error(
18118
- chalk23.red(
18527
+ chalk28.red(
18119
18528
  "\u2717 Scope slugs cannot start with 'vm0' (reserved for system use)"
18120
18529
  )
18121
18530
  );
18122
18531
  } else {
18123
- console.error(chalk23.red(`\u2717 ${error43.message}`));
18532
+ console.error(chalk28.red(`\u2717 ${error43.message}`));
18124
18533
  }
18125
18534
  } else {
18126
- console.error(chalk23.red("\u2717 An unexpected error occurred"));
18535
+ console.error(chalk28.red("\u2717 An unexpected error occurred"));
18127
18536
  }
18128
18537
  process.exit(1);
18129
18538
  }
@@ -18131,13 +18540,13 @@ var setCommand = new Command21().name("set").description("Set your scope slug").
18131
18540
  );
18132
18541
 
18133
18542
  // src/commands/scope/index.ts
18134
- var scopeCommand = new Command22().name("scope").description("Manage your scope (namespace for images)").addCommand(statusCommand3).addCommand(setCommand);
18543
+ var scopeCommand = new Command26().name("scope").description("Manage your scope (namespace for images)").addCommand(statusCommand3).addCommand(setCommand);
18135
18544
 
18136
18545
  // src/commands/init.ts
18137
- import { Command as Command23 } from "commander";
18138
- import chalk24 from "chalk";
18139
- import * as readline2 from "readline";
18140
- import { existsSync as existsSync9 } from "fs";
18546
+ import { Command as Command27 } from "commander";
18547
+ import chalk29 from "chalk";
18548
+ import path13 from "path";
18549
+ import { existsSync as existsSync10 } from "fs";
18141
18550
  import { writeFile as writeFile7 } from "fs/promises";
18142
18551
  var VM0_YAML_FILE = "vm0.yaml";
18143
18552
  var AGENTS_MD_FILE = "AGENTS.md";
@@ -18172,76 +18581,76 @@ You are a HackerNews AI content curator.
18172
18581
  }
18173
18582
  function checkExistingFiles() {
18174
18583
  const existingFiles = [];
18175
- if (existsSync9(VM0_YAML_FILE)) existingFiles.push(VM0_YAML_FILE);
18176
- if (existsSync9(AGENTS_MD_FILE)) existingFiles.push(AGENTS_MD_FILE);
18584
+ if (existsSync10(VM0_YAML_FILE)) existingFiles.push(VM0_YAML_FILE);
18585
+ if (existsSync10(AGENTS_MD_FILE)) existingFiles.push(AGENTS_MD_FILE);
18177
18586
  return existingFiles;
18178
18587
  }
18179
- async function promptAgentName() {
18180
- const rl = readline2.createInterface({
18181
- input: process.stdin,
18182
- output: process.stdout
18183
- });
18184
- return new Promise((resolve2, reject) => {
18185
- rl.question(chalk24.cyan("? Enter agent name: "), (answer) => {
18186
- rl.close();
18187
- resolve2(answer.trim());
18188
- });
18189
- rl.on("SIGINT", () => {
18190
- rl.close();
18191
- console.log();
18192
- reject(new Error("User cancelled"));
18193
- });
18194
- });
18195
- }
18196
- var initCommand3 = new Command23().name("init").description("Initialize a new VM0 project in the current directory").option("-f, --force", "Overwrite existing files").option("-n, --name <name>", "Agent name (skips interactive prompt)").action(async (options) => {
18588
+ var initCommand3 = new Command27().name("init").description("Initialize a new VM0 project in the current directory").option("-f, --force", "Overwrite existing files").option("-n, --name <name>", "Agent name (required in non-interactive mode)").action(async (options) => {
18197
18589
  const existingFiles = checkExistingFiles();
18198
18590
  if (existingFiles.length > 0 && !options.force) {
18199
18591
  for (const file2 of existingFiles) {
18200
- console.log(chalk24.red(`\u2717 ${file2} already exists`));
18592
+ console.log(chalk29.red(`\u2717 ${file2} already exists`));
18201
18593
  }
18202
18594
  console.log();
18203
- console.log(`To overwrite: ${chalk24.cyan("vm0 init --force")}`);
18595
+ console.log(`To overwrite: ${chalk29.cyan("vm0 init --force")}`);
18204
18596
  process.exit(1);
18205
18597
  }
18206
18598
  let agentName;
18207
18599
  if (options.name) {
18208
18600
  agentName = options.name.trim();
18601
+ } else if (!isInteractive()) {
18602
+ console.error(
18603
+ chalk29.red("\u2717 --name flag is required in non-interactive mode")
18604
+ );
18605
+ console.error(chalk29.dim(" Usage: vm0 init --name <agent-name>"));
18606
+ process.exit(1);
18209
18607
  } else {
18210
- try {
18211
- agentName = await promptAgentName();
18212
- } catch {
18213
- process.exit(0);
18608
+ const dirName = path13.basename(process.cwd());
18609
+ const defaultName = validateAgentName(dirName) ? dirName : void 0;
18610
+ const name = await promptText(
18611
+ "Enter agent name",
18612
+ defaultName,
18613
+ (value) => {
18614
+ if (!validateAgentName(value)) {
18615
+ return "Must be 3-64 characters, alphanumeric and hyphens, start/end with letter or number";
18616
+ }
18617
+ return true;
18618
+ }
18619
+ );
18620
+ if (name === void 0) {
18621
+ console.log(chalk29.dim("Cancelled"));
18622
+ return;
18214
18623
  }
18624
+ agentName = name;
18215
18625
  }
18216
18626
  if (!agentName || !validateAgentName(agentName)) {
18217
- console.log(chalk24.red("\u2717 Invalid agent name"));
18627
+ console.log(chalk29.red("\u2717 Invalid agent name"));
18218
18628
  console.log(
18219
- chalk24.dim(" Must be 3-64 characters, alphanumeric and hyphens only")
18629
+ chalk29.dim(" Must be 3-64 characters, alphanumeric and hyphens only")
18220
18630
  );
18221
- console.log(chalk24.dim(" Must start and end with letter or number"));
18631
+ console.log(chalk29.dim(" Must start and end with letter or number"));
18222
18632
  process.exit(1);
18223
18633
  }
18224
18634
  await writeFile7(VM0_YAML_FILE, generateVm0Yaml(agentName));
18225
18635
  const vm0Status = existingFiles.includes(VM0_YAML_FILE) ? " (overwritten)" : "";
18226
- console.log(chalk24.green(`\u2713 Created ${VM0_YAML_FILE}${vm0Status}`));
18636
+ console.log(chalk29.green(`\u2713 Created ${VM0_YAML_FILE}${vm0Status}`));
18227
18637
  await writeFile7(AGENTS_MD_FILE, generateAgentsMd());
18228
18638
  const agentsStatus = existingFiles.includes(AGENTS_MD_FILE) ? " (overwritten)" : "";
18229
- console.log(chalk24.green(`\u2713 Created ${AGENTS_MD_FILE}${agentsStatus}`));
18639
+ console.log(chalk29.green(`\u2713 Created ${AGENTS_MD_FILE}${agentsStatus}`));
18230
18640
  console.log();
18231
18641
  console.log("Next steps:");
18232
18642
  console.log(
18233
- ` 1. Get your Claude Code token: ${chalk24.cyan("claude setup-token")}`
18643
+ ` 1. Get your Claude Code token: ${chalk29.cyan("claude setup-token")}`
18234
18644
  );
18235
18645
  console.log(` 2. Set the environment variable (or add to .env file):`);
18236
- console.log(chalk24.dim(` export CLAUDE_CODE_OAUTH_TOKEN=<your-token>`));
18237
- console.log(` 3. Run your agent: ${chalk24.cyan('vm0 cook "your prompt"')}`);
18646
+ console.log(chalk29.dim(` export CLAUDE_CODE_OAUTH_TOKEN=<your-token>`));
18647
+ console.log(` 3. Run your agent: ${chalk29.cyan('vm0 cook "your prompt"')}`);
18238
18648
  });
18239
18649
 
18240
18650
  // src/commands/setup-github.ts
18241
- import { Command as Command24 } from "commander";
18242
- import chalk25 from "chalk";
18243
- import * as readline3 from "readline";
18244
- import { existsSync as existsSync10 } from "fs";
18651
+ import { Command as Command28 } from "commander";
18652
+ import chalk30 from "chalk";
18653
+ import { existsSync as existsSync11 } from "fs";
18245
18654
  import { mkdir as mkdir7, readFile as readFile9, writeFile as writeFile8 } from "fs/promises";
18246
18655
  import { execSync, spawnSync } from "child_process";
18247
18656
  import { parse as parseYaml5 } from "yaml";
@@ -18264,57 +18673,57 @@ function isGhAuthenticated() {
18264
18673
  async function checkPrerequisites() {
18265
18674
  console.log("Checking prerequisites...");
18266
18675
  if (!isGhInstalled()) {
18267
- console.log(chalk25.red("\u2717 GitHub CLI (gh) is not installed"));
18676
+ console.log(chalk30.red("\u2717 GitHub CLI (gh) is not installed"));
18268
18677
  console.log();
18269
18678
  console.log("GitHub CLI is required for this command.");
18270
18679
  console.log();
18271
- console.log(` macOS: ${chalk25.cyan("brew install gh")}`);
18272
- console.log(` Other: ${chalk25.cyan("https://cli.github.com/")}`);
18680
+ console.log(` macOS: ${chalk30.cyan("brew install gh")}`);
18681
+ console.log(` Other: ${chalk30.cyan("https://cli.github.com/")}`);
18273
18682
  console.log();
18274
18683
  console.log("After installation, run:");
18275
- console.log(` ${chalk25.cyan("gh auth login")}`);
18684
+ console.log(` ${chalk30.cyan("gh auth login")}`);
18276
18685
  console.log();
18277
18686
  console.log("Then try again:");
18278
- console.log(` ${chalk25.cyan("vm0 setup-github")}`);
18687
+ console.log(` ${chalk30.cyan("vm0 setup-github")}`);
18279
18688
  process.exit(1);
18280
18689
  }
18281
- console.log(chalk25.green("\u2713 GitHub CLI (gh) is installed"));
18690
+ console.log(chalk30.green("\u2713 GitHub CLI (gh) is installed"));
18282
18691
  if (!isGhAuthenticated()) {
18283
- console.log(chalk25.red("\u2717 GitHub CLI is not authenticated"));
18692
+ console.log(chalk30.red("\u2717 GitHub CLI is not authenticated"));
18284
18693
  console.log();
18285
18694
  console.log("Please authenticate GitHub CLI first:");
18286
- console.log(` ${chalk25.cyan("gh auth login")}`);
18695
+ console.log(` ${chalk30.cyan("gh auth login")}`);
18287
18696
  console.log();
18288
18697
  console.log("Then try again:");
18289
- console.log(` ${chalk25.cyan("vm0 setup-github")}`);
18698
+ console.log(` ${chalk30.cyan("vm0 setup-github")}`);
18290
18699
  process.exit(1);
18291
18700
  }
18292
- console.log(chalk25.green("\u2713 GitHub CLI is authenticated"));
18701
+ console.log(chalk30.green("\u2713 GitHub CLI is authenticated"));
18293
18702
  const token = await getToken();
18294
18703
  if (!token) {
18295
- console.log(chalk25.red("\u2717 VM0 not authenticated"));
18704
+ console.log(chalk30.red("\u2717 VM0 not authenticated"));
18296
18705
  console.log();
18297
18706
  console.log("Please authenticate with VM0 first:");
18298
- console.log(` ${chalk25.cyan("vm0 auth login")}`);
18707
+ console.log(` ${chalk30.cyan("vm0 auth login")}`);
18299
18708
  console.log();
18300
18709
  console.log("Then try again:");
18301
- console.log(` ${chalk25.cyan("vm0 setup-github")}`);
18710
+ console.log(` ${chalk30.cyan("vm0 setup-github")}`);
18302
18711
  process.exit(1);
18303
18712
  }
18304
- console.log(chalk25.green("\u2713 VM0 authenticated"));
18305
- if (!existsSync10("vm0.yaml")) {
18306
- console.log(chalk25.red("\u2717 vm0.yaml not found"));
18713
+ console.log(chalk30.green("\u2713 VM0 authenticated"));
18714
+ if (!existsSync11("vm0.yaml")) {
18715
+ console.log(chalk30.red("\u2717 vm0.yaml not found"));
18307
18716
  console.log();
18308
18717
  console.log("This command requires a vm0.yaml configuration file.");
18309
18718
  console.log();
18310
18719
  console.log("To create one, run:");
18311
- console.log(` ${chalk25.cyan("vm0 init")}`);
18720
+ console.log(` ${chalk30.cyan("vm0 init")}`);
18312
18721
  console.log();
18313
18722
  console.log("Then try again:");
18314
- console.log(` ${chalk25.cyan("vm0 setup-github")}`);
18723
+ console.log(` ${chalk30.cyan("vm0 setup-github")}`);
18315
18724
  process.exit(1);
18316
18725
  }
18317
- console.log(chalk25.green("\u2713 vm0.yaml found"));
18726
+ console.log(chalk30.green("\u2713 vm0.yaml found"));
18318
18727
  return token;
18319
18728
  }
18320
18729
  function generatePublishYaml() {
@@ -18425,22 +18834,8 @@ function extractSecretsAndVars(config2) {
18425
18834
  };
18426
18835
  }
18427
18836
  async function promptYesNo(question, defaultYes) {
18428
- const hint = defaultYes ? "(Y/n)" : "(y/N)";
18429
- const rl = readline3.createInterface({
18430
- input: process.stdin,
18431
- output: process.stdout
18432
- });
18433
- return new Promise((resolve2) => {
18434
- rl.question(chalk25.cyan(`? ${question} ${hint} `), (answer) => {
18435
- rl.close();
18436
- const normalized = answer.trim().toLowerCase();
18437
- if (normalized === "") {
18438
- resolve2(defaultYes);
18439
- } else {
18440
- resolve2(normalized === "y" || normalized === "yes");
18441
- }
18442
- });
18443
- });
18837
+ const result = await promptConfirm(question, defaultYes);
18838
+ return result ?? false;
18444
18839
  }
18445
18840
  function setGitHubSecret(name, value) {
18446
18841
  const result = spawnSync("gh", ["secret", "set", name], {
@@ -18482,7 +18877,7 @@ function displaySecretsTable(secretStatuses, varStatuses) {
18482
18877
  if (secretStatuses.length > 0) {
18483
18878
  console.log("\u2502 Secrets: \u2502");
18484
18879
  for (const s of secretStatuses) {
18485
- const status = s.found ? chalk25.green("\u2713") : chalk25.red("\u2717");
18880
+ const status = s.found ? chalk30.green("\u2713") : chalk30.red("\u2717");
18486
18881
  const source = s.found ? `(from ${s.source})` : "not found";
18487
18882
  const paddedName = (s.name + " ").padEnd(23, ".");
18488
18883
  console.log(`\u2502 ${status} ${paddedName} ${source.padEnd(19)}\u2502`);
@@ -18491,7 +18886,7 @@ function displaySecretsTable(secretStatuses, varStatuses) {
18491
18886
  if (varStatuses.length > 0) {
18492
18887
  console.log("\u2502 Variables: \u2502");
18493
18888
  for (const v of varStatuses) {
18494
- const status = v.found ? chalk25.green("\u2713") : chalk25.red("\u2717");
18889
+ const status = v.found ? chalk30.green("\u2713") : chalk30.red("\u2717");
18495
18890
  const source = v.found ? `(from ${v.source})` : "not found";
18496
18891
  const paddedName = (v.name + " ").padEnd(23, ".");
18497
18892
  console.log(`\u2502 ${status} ${paddedName} ${source.padEnd(19)}\u2502`);
@@ -18503,17 +18898,17 @@ function showManualSetupInstructions(secrets, vars) {
18503
18898
  console.log("Skipped automatic setup. Configure secrets manually:");
18504
18899
  console.log();
18505
18900
  console.log(" Step 1: Get your VM0 token");
18506
- console.log(` ${chalk25.cyan("vm0 auth setup-token")}`);
18901
+ console.log(` ${chalk30.cyan("vm0 auth setup-token")}`);
18507
18902
  console.log();
18508
18903
  console.log(" Step 2: Set GitHub secrets");
18509
18904
  for (const s of secrets) {
18510
- console.log(` ${chalk25.cyan(`gh secret set ${s}`)}`);
18905
+ console.log(` ${chalk30.cyan(`gh secret set ${s}`)}`);
18511
18906
  }
18512
18907
  if (vars.length > 0) {
18513
18908
  console.log();
18514
18909
  console.log(" Step 3: Set GitHub variables");
18515
18910
  for (const v of vars) {
18516
- console.log(` ${chalk25.cyan(`gh variable set ${v}`)}`);
18911
+ console.log(` ${chalk30.cyan(`gh variable set ${v}`)}`);
18517
18912
  }
18518
18913
  }
18519
18914
  }
@@ -18556,7 +18951,7 @@ function showWorkflowsCreatedMessage() {
18556
18951
  console.log("\u2502 3. Push to main branch to trigger publish \u2502");
18557
18952
  console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518");
18558
18953
  }
18559
- var setupGithubCommand = new Command24().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(
18954
+ 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(
18560
18955
  async (options) => {
18561
18956
  const vm0Token = await checkPrerequisites();
18562
18957
  if (!vm0Token) {
@@ -18568,10 +18963,10 @@ var setupGithubCommand = new Command24().name("setup-github").description("Initi
18568
18963
  const config2 = parseYaml5(content);
18569
18964
  const agents = config2.agents;
18570
18965
  const agentName = Object.keys(agents)[0];
18571
- console.log(chalk25.green(`\u2713 Agent: ${agentName}`));
18966
+ console.log(chalk30.green(`\u2713 Agent: ${agentName}`));
18572
18967
  const { secrets, vars } = extractSecretsAndVars(config2);
18573
18968
  console.log(
18574
- chalk25.green(
18969
+ chalk30.green(
18575
18970
  `\u2713 Found ${secrets.length} secrets, ${vars.length} variables`
18576
18971
  )
18577
18972
  );
@@ -18579,10 +18974,10 @@ var setupGithubCommand = new Command24().name("setup-github").description("Initi
18579
18974
  const publishPath = ".github/workflows/publish.yml";
18580
18975
  const runPath = ".github/workflows/run.yml";
18581
18976
  const existingFiles = [];
18582
- if (existsSync10(publishPath)) existingFiles.push(publishPath);
18583
- if (existsSync10(runPath)) existingFiles.push(runPath);
18977
+ if (existsSync11(publishPath)) existingFiles.push(publishPath);
18978
+ if (existsSync11(runPath)) existingFiles.push(runPath);
18584
18979
  if (existingFiles.length > 0 && !options.force) {
18585
- console.log(chalk25.yellow("\u26A0 Existing workflow files detected:"));
18980
+ console.log(chalk30.yellow("\u26A0 Existing workflow files detected:"));
18586
18981
  for (const file2 of existingFiles) {
18587
18982
  console.log(` \u2022 ${file2}`);
18588
18983
  }
@@ -18595,7 +18990,7 @@ var setupGithubCommand = new Command24().name("setup-github").description("Initi
18595
18990
  if (!overwrite) {
18596
18991
  console.log();
18597
18992
  console.log("Aborted. To force overwrite, run:");
18598
- console.log(` ${chalk25.cyan("vm0 setup-github --force")}`);
18993
+ console.log(` ${chalk30.cyan("vm0 setup-github --force")}`);
18599
18994
  process.exit(0);
18600
18995
  }
18601
18996
  }
@@ -18605,13 +19000,13 @@ var setupGithubCommand = new Command24().name("setup-github").description("Initi
18605
19000
  await mkdir7(".github/workflows", { recursive: true });
18606
19001
  await writeFile8(publishPath, generatePublishYaml());
18607
19002
  const publishStatus = existingFiles.includes(publishPath) ? "Overwrote" : "Created";
18608
- console.log(chalk25.green(`\u2713 ${publishStatus} ${publishPath}`));
19003
+ console.log(chalk30.green(`\u2713 ${publishStatus} ${publishPath}`));
18609
19004
  await writeFile8(runPath, generateRunYaml(agentName, secrets, vars));
18610
19005
  const runStatus = existingFiles.includes(runPath) ? "Overwrote" : "Created";
18611
- console.log(chalk25.green(`\u2713 ${runStatus} ${runPath}`));
19006
+ console.log(chalk30.green(`\u2713 ${runStatus} ${runPath}`));
18612
19007
  console.log();
18613
19008
  if (options.skipSecrets) {
18614
- console.log(chalk25.green("\u2713 Done (secrets setup skipped)"));
19009
+ console.log(chalk30.green("\u2713 Done (secrets setup skipped)"));
18615
19010
  return;
18616
19011
  }
18617
19012
  const { secretStatuses, varStatuses } = await detectSecretValues(
@@ -18651,14 +19046,14 @@ var setupGithubCommand = new Command24().name("setup-github").description("Initi
18651
19046
  if (s.found && s.value) {
18652
19047
  const success2 = setGitHubSecret(s.name, s.value);
18653
19048
  if (success2) {
18654
- console.log(` ${chalk25.green("\u2713")} ${s.name}`);
19049
+ console.log(` ${chalk30.green("\u2713")} ${s.name}`);
18655
19050
  } else {
18656
- console.log(` ${chalk25.red("\u2717")} ${s.name} (failed)`);
19051
+ console.log(` ${chalk30.red("\u2717")} ${s.name} (failed)`);
18657
19052
  failedSecrets.push(s.name);
18658
19053
  }
18659
19054
  } else {
18660
19055
  console.log(
18661
- ` ${chalk25.yellow("\u26A0")} ${s.name} (skipped - not found)`
19056
+ ` ${chalk30.yellow("\u26A0")} ${s.name} (skipped - not found)`
18662
19057
  );
18663
19058
  }
18664
19059
  }
@@ -18670,14 +19065,14 @@ var setupGithubCommand = new Command24().name("setup-github").description("Initi
18670
19065
  if (v.found && v.value) {
18671
19066
  const success2 = setGitHubVariable(v.name, v.value);
18672
19067
  if (success2) {
18673
- console.log(` ${chalk25.green("\u2713")} ${v.name}`);
19068
+ console.log(` ${chalk30.green("\u2713")} ${v.name}`);
18674
19069
  } else {
18675
- console.log(` ${chalk25.red("\u2717")} ${v.name} (failed)`);
19070
+ console.log(` ${chalk30.red("\u2717")} ${v.name} (failed)`);
18676
19071
  failedVars.push(v.name);
18677
19072
  }
18678
19073
  } else {
18679
19074
  console.log(
18680
- ` ${chalk25.yellow("\u26A0")} ${v.name} (skipped - not found)`
19075
+ ` ${chalk30.yellow("\u26A0")} ${v.name} (skipped - not found)`
18681
19076
  );
18682
19077
  }
18683
19078
  }
@@ -18700,10 +19095,10 @@ var setupGithubCommand = new Command24().name("setup-github").description("Initi
18700
19095
  );
18701
19096
 
18702
19097
  // src/index.ts
18703
- var program = new Command25();
18704
- program.name("vm0").description("VM0 CLI - A modern build tool").version("4.31.1");
19098
+ var program = new Command29();
19099
+ program.name("vm0").description("VM0 CLI - A modern build tool").version("4.32.0");
18705
19100
  program.command("info").description("Display environment information").action(async () => {
18706
- console.log(chalk26.bold("System Information:"));
19101
+ console.log(chalk31.bold("System Information:"));
18707
19102
  console.log(`Node Version: ${process.version}`);
18708
19103
  console.log(`Platform: ${process.platform}`);
18709
19104
  console.log(`Architecture: ${process.arch}`);